Slashdot Mirror


Gosling Claims Huge Security Hole in .NET

renai42 writes "Java creator James Gosling this week called Microsoft's decision to support C and C++ in the common language runtime in .NET one of the 'biggest and most offensive mistakes that they could have made.' Gosling further commented that by including the two languages into Microsoft's software development platform, the company 'has left open a security hole large enough to drive many, many large trucks through.'" Note that this isn't a particular vulnerability, just a system of typing that makes it easy to introduce vulnerabilities, which last time I checked, all C programmers deal with.

9 of 687 comments (clear)

  1. It's called unsafe code for a reason by jerometremblay · · Score: 4, Informative

    Unsafe code is not subject to security checks of the .NET virtual machine. To execute unsafe code, you have to specifically grant those rights to the executing program. It is not something automatic.

    Applications that require safety (for example running plugins downloaded from the net) simply don't allow those assemblies to be loaded.

    Where is the problem again?

  2. Re:Java is a type-safe language at the VM level... by patniemeyer · · Score: 4, Informative

    Yes, actually, it does. Have you checked it recently? The only overhead that natively compiled Java code would have over comparable C++ is that it always does array bounds checking. Other than that you just have to ask yourself, what kind of optimization can a static compiler (C/C++) do that a dynamic, profiling runtime compiler (Java) can't do?

    Garbage collection in Java has been faster than free/malloc in C for years. This is in large part due to the fact that the runtime can recognize very short lived objects and put them on a special part of the heap.

    It's not necessary to use unsafe languages to get performance any more.

    Pat Niemeyer

  3. Re:JNI by patniemeyer · · Score: 4, Informative

    But JNI is not Java... It's an API. For that matter you might consider sockets and network connections to make Java unsafe because they could invoke unsafe applications.

    It is completely fair to point out that .NET allows you to choose safe vs. unsafe code... but it is a little different from the Java scenario in that this is unsafe code that is run through the VM. It's just an odd choice to make.

    Pat Niemeyer
    Author of Learning Java, O'Reilly & Associates

  4. Re:Phew! by DrLZRDMN · · Score: 3, Informative

    Id like to see a kernel written in either language.

  5. Re:Java is a type-safe language at the VM level... by hobuddy · · Score: 4, Informative

    You're quite right that Java's speed is excellent these days (for non-GUI code, at least). I've spent a lot of time recently working with a large system that was first implemented in Java (by highly skilled developers) and then ported to C++ (by greenhorns). The C++ port is only 50-100% faster, which isn't worth the price in developer time that's been wasted on memory leaks and other forms of memory corruption that were never a factor in Java. Besides that, supporting multiple platforms with the C++ version is the #definition of pain.

    However, the C++ version uses only about 1/4 or 1/5 as much memory as the Java version, and starts up far more quickly. If a *desktop* application needs to be deployed on older machines, or if the application is so memory-intensive it taxes the limits of today's server hardware, Java still falls flat.

    --
    Erlang.org: wow
  6. Yay, more rhetoric from Sun by rabtech · · Score: 3, Informative

    Like we really need more Rhetoric from Sun... but I'll deal with his concerns anyway.

    In order to use "unsafe" code from managed C++ (or unsafe blocks in C#) you must have "FullTrust" security rights, otherwise the code fails to run.

    You could shoot yourself in the foot but the runtime is perfectly capable of detecting and coping with corruption of the managed heap (generally by closing down the offending AppDomain.) Of course you can write a COM component in C++ and call it from dotnet, which is (in effect) the same exact thing! (I dare you to try and stop me from trashing Java or dotnet once I'm loaded in process via JNI or COM...)

    CAS (Code Access Security) means that no other code can call your "unsafe" methods without FullTrust either, so there is no danger from code running off the web of doing this.

    JNI is the same thing, Sun just gets to hide behind the lie since the risks aren't known by or integrated with the platform. At least with unsafe code the runtime is fully aware of that pointer voodoo magic you are trying to pull and can deal with it appropriately.

    In other words Game Developer X can hand-tune the rendering algorithm inside the "unsafe" code areas, but develop the rest of the platform in fully managed code, making the development process much easier to write, test, and debug.

    (As an aside, thanks to the antitrust ruling Microsoft is not allowed to comment on a great many things, including competitors. I don't know if this falls under that heading, but in many cases Microsoft's employees can't just come out and call bullshit when they see it for legal reasons.)

    In conclusion: Sun should shut the hell up.

    --
    Natural != (nontoxic || beneficial)
  7. Re:Advertisement? by Bodrius · · Score: 3, Informative

    What are you talking about? Inner classes are fully supported in C#...

    Unless you're talking about anonymous inner classes (a different animal, typically with a different purpose altogether when it comes to design motivation).

    This seems to have been a matter of designer taste on the part of Hejlsberg. 2.0 should bring anonymous methods, which aims to solve the same type of problems anonymous classes did, in a neater way.

    --
    Freedom is the freedom to say 2+2=4, everything else follows...
  8. Re:Advertisement? by malfunct · · Score: 3, Informative

    Nope, at least not if it can't verify its safety and request permissions correctly. There is a chain of trust that needs to be developed before the .NET framework will allow the assembly to load. One thing that you should do if you don't want unsafe code to execute is remove that permission from your program (can be done with an attribute in your source code) and then these unsafe modules just won't load.

    Not saying this can't be defeated but there are tools in the languages to protect yourself.

    --

    "You can now flame me, I am full of love,"

  9. malloc+free: fast, simple, and can be even faster by nothings · · Score: 4, Informative
    Malloc and free are simple algorithms, and whoever told you otherwise was wrong.

    I don't know where you got your understanding of malloc, and especially free, but it's severely out of date. Knuth published about "Boundary Tags" no later than 1973 (citeseer is down, so no link). Saying that a coalesce operation "can be arbirarily slow" is just FUD. A boundary tag makes free() a fast O(1) operation: check the previous block in memory to see if it's free and if so join, a fast O(1) operation; check the next block in memory to see if it's free and if so coalesce; add free block to free-list, done. Yes, it's not zero work like a GC implementation sort-of is, but "arbitrarily slow"? It's basically at least as fast as malloc().

    Allocation requests can hit disk, sure, but so can GC allocations even if they're just bumping a pointer: it all depends on the working set size. GC compaction can reduce fragmentation to reduce working set size, but that is only a big win if there's a lot of fragmentation, and most apps using a good malloc() don't exhibit that much. (It is also possible for a GC to rearrange memory so more in-working-set data is on pages together, reducing the working set page count without changing the total memory used. I don't know of any in-use implementations of this, since you need hardware support to know what objects are more-in-use; generally this is only available at the page level, where it's no help. I think maybe an early microde-based Smalltalk implementation might have done this.)

    If your malloc has to walk giant free lists to find an open block, then sure, that can be slow. That's why people use trees of free lists based on size and such to make it more O(log N), and O(1) for small allocations. (On large allocations, actually using the memory amortizes the cost.) Read about dlmalloc, for example.

    Furthermore, let's not misrepresent GC. Stop-and-collect GCs have obvious extra costs beyond the free-of-charge free (or lack of need for one). Incremental GCs that don't pause are usually slower overall and only preferred for interactive programs. For example, incremental GCs usually require "write barriers" or "read barriers" which require several extra instruction on every fetch from memory or every write of a pointer variable in memory. This can add up across the entire program. Incremental GCs also tend to be conservative, and only end up collecting things that, say, were garbage at the start of the most recent collection round, and generational collectors allow garbage to collect in later generations for some time, so they don't actually necessarily have a smaller working set than a non-leaky malloc()/free() program.

    Another big win in non-GC systems is that you can use pointers that don't come off the heap. That way you can avoid allocation and deallocation and GC entirely. (You can actually do some of this in a GC system too if it's a 'conservative' GC that copes with pointers into the middle of blocks. Those pretty much only get used for adding GC to C and C++, though.) Here are some common ways this happens:

    • statically allocated arrays
    • small arrays and strcts on the stack
    • structs that are components of other structs, or arrays at the end of structs
    • use of special allocators:
      • slab allocators (it's even possible to embed this entirely inside the default allocator for all small allocations)
      • pool allocators (allocate a large block of memory, suballocate from it, deallocate all at once)
      • "stack" allocators (allocate a large block of memory, suballocate from one end, only allow freeing from the same end, so allocation is a adding to a pointer and deallocation is reseting that pointer)

    Of course, doing all these things requires that you balance your different types of malloc()s with the correct, matching type of free(). In practice, GC proponents overestimate the diffi