Slashdot Mirror


Are Buffer Overflow Sploits Intel's Fault?

Bruce Perens submitted a story he wrote for his website on overflows and who's fault they are. I'm pretty skeptical of almost every point raised in this story, but it's an interesting read. [Updated 21:13 by t] As Sea Monkey points out, Bruce has now taken down the article, with a brief note: "I've withdrawn this article after enough people convinced me that I didn't know what I was talking about. It happens sometimes. Thanks." What if everyone displayed such grace?

13 of 269 comments (clear)

  1. Bull Pucky by nweaver · · Score: 4

    Buffer overflows are the fault of the LANGUAGE. Important system utilities need to be written in bounds-checked languages. Some compilers, no matter the architecture, will write executable code on the stack: "trampolines". Unfortunatly, this is common enough that the OS can't blindly turn off the executable bit on the stack pages. And non-executable stack pages don't stop all buffer overflow attacks, they just require a 2 part attack: A heap buffer to write the code, and a stack buffer to overwrite the return address. The heap buffer doesn't necessarily even need to be overflown, the attacker just needs to be able to deduce the address. And one can't set heap-addresses to be nonexecutable, simply because there are MANY language environments which do create code at runtime, such as interpreters, JITs, etc etc etc.


    Nicholas C Weaver
    nweaver@cs.berkeley.edu

    --
    Test your net with Netalyzr
  2. What a great great man -thanks Timothy by gad_zuki! · · Score: 4

    What if everyone displayed such grace?

    Or what if everyone bothered to do some research before writing and self-promoting some inane rant.

  3. Re:Its not intel's fault(history) by Stephen+Samuel · · Score: 5
    When intel came out with the 808[68], they wanted to make it as compatible with the 8085 as possible. It really was 16-bit. The data code and stack segments were 64K wide. Segment registers that gave you overlapping segments with a 16 byte granularity.

    If you used the segment registers, the result was basically a highly non-linear address space. In a lot of ways, it was an 8 bit processor with 16 bit registers and hardware bank switching (for those of you that remember bank switching).

    as a result, there were a few 'standard' memory models that programmers used:

    • Small address space: All segment registers the same. don't touch them. This gave you a flat 16bit (64k)address space, turning the machine into a glorified 8085/Z80 -- almost completely source code (assembler!) compatible. It also gave a slight speed advantage, since all pointers and integers were 16 bits wide.
    • Intermediate address space: segment registers point to disjoint spaces. not too much difference but you get some breathing space since the code and data don't share the same (tiny!) 64K address space.. pointers are still 16 bits, but you now have to remember which segment you're talking to.
    • 'large' address space: all pointers are 32 bits wide. (include both segment registers and then pointers within the segments). This gives you access to the full 1M address space. (the 640K limit was because 380K was reserved for I/O space).

      SERIOUS performance hit. If you allow arrays >64K then just about every array access requires you to calculate and load the segment register. address math sucks because if you have two 32 bit addresses A and B, A != B does not necessarily mean that they don't point to the same memory, and *X++ can require some serious work to do the exepected thing.

    The 80286 allowed people to break the 1M barrier without doing bank switching (EMS?), but it turned the segment register/pointer problem into a serious horror story. Unless you were seriously masochistic (or just plain desperate) you just made it look like an 8086 that ran a bit faster.

    When they came out with the '386 you now had segments of 4GB each. This was at a time when a 2GB ram module could have been camouflaged as a desk and would have required a 15KW watt power supply.

    Most programmers and OS designers just set all the segment registers the same (the '386 equivalent of the 'small memory model', and forget about them (I called this traumatic amnesia).

    So, yes: Intel has a Segment model that could be used to provide security, but few people are brave/stupid enough to risk the horror stories/ flashbacks that enabling it might entail.

    Intel: Just short of intelligent.

    --
    Free Software: Like love, it grows best when given away.
  4. It's the industry as a whole. by jetson123 · · Score: 4
    Buffer overflow exploits don't necessarily require you to be able to run code from the stack segment. Often, it's sufficient just to change the return address (which necessarily is stored on the stack) to some useful routine, or to change a bunch of bits that are used for a security check.

    The underlying problem is that C/C++/Objective-C do not have mechanisms to protect against these kinds of problems. In fact, it's impossible to write substantial programs in those languages that use only "safe" constructs. This is a peculiar and fundamental bug in the C-family language design.

    There are excellent alternatives around. Modula-3, Oberon, Ada, Sather, and Eiffel all have efficient, free, open source implementations around, they all provide access to unsafe features when needed, and one of them should satisfy anybody's programming needs. Java is an excellent applications and server programming language, although it has a bit more overhead and no access to low-level features.

    So, folks, get with the program and stop writing servers and other applications in C/C++.

  5. Its not intel's fault by bored · · Score: 5

    The problem isn't Intels fault because the arch has an execute bit in the segments. The original idea was you put your code in a separate code segment from your stack and data segments. The real problem is OS designers who for various reasons decide that the x86 arch's segmentation should be ignored and set the code segments equal in size to the data segments and stack segments. It then becomes a simple matter to just jump into the data or stack segment and begin executing code.

    Of course since most of the OS's don't properly use the protection mechanisms Intel has provided, I guess it becomes Intels fault if they don't extend the arch to support a feature and potentially break downward compatibility with other OS's using the current paging system.

  6. Blame the Language by Tom7 · · Score: 5

    Blame the language! C and C++ continue to be inappropriate for security-critical work.

    Aside from speed-critical stuff like kernels and Quake 3, I don't see the need to write programs in C and C++ any more.

    Let's start using modern languages with type safety. They're easier to write programs in (because debugging is easier) and not that slow.

    I know that I'd gladly take the 2x speed hit on my security-critical apps (mail daemon, web server, ssh, etc.) to know that they cannot have this kind of bug in them, because they were written in a language like ML, Eiffel, Haskell, or even Java.

    1. Re:Blame the Language by QuoteMstr · · Score: 5

      Like a system, and langauge can be as secure or insecure as you can make it. One can write an extremely tight program in C++ while writing one in Perl or Java that leaves gaping security holes open.

      Educate the programmer on *why* things like sprintf, strcpy, etc. are Bad Things, don't force them to use a Bondage and Discipline-style language like RPG or Java that forces the programmer to do what the *language designer* thought to be The Right Thing.

      Instead of using a new language that probably wouldn't be suited to the task, why not write something like lint, but for security holes?

      Also...

      *PEOPLE SHOULD ENABLE ALL WARNINGS ON THEIR COMPILERS. WARNING CATCH MANY BUGS AND OTHER NASTY THINGS THAT WOULD OTHERWISE BE IGNORED.*

    2. Re:Blame the Language by mikpos · · Score: 4

      You should be blaming the programmers from 10 years ago. The *only* C programs that I have seen that have one of:
      - gets()
      - scanf()
      - poor use of *scanf() or str*()
      are programs that have (a) been written 10 years ago; or (b) written by programmers who learned how to code in C 10 years ago. Yes, there are stupid technical school and high school teachers too, but normally, before anyone gets to a level where they can do something useful, they will have found a clueful reference to get rid of all that nonsense.

      There is a new breed of C programmers, though. They don't assume Unicisms, PDPisms or TheirPlatformisms, and their eyes actually burn a whole through their skull upon the mere sight of gets(), scanf(), or any of the other death traps.

      C is a good language. C++, of course, is not, though (hey, if you can get modded up for ignorant flamebait, why can't I?)

  7. The unsafe C library by Animats · · Score: 4
    One particular problem with C is a history of unsafe standard library functions, such as sprintf, strcat, and such, which just happily output into an array of char with no checking whatsoever. Those functions were deprecated back in the 1980s, and there are safe versions with output size limits like sprintf, but there is still far too much code that uses the old ones.

    They need to be deprecated more forcefully. All the unsafe functions should be pulled from the standard C library and moved to something like "deprecated_unsafe_library.h". All set-UID programs need to be purged of those functions. Now. Any manufacturer shipping a system with those functions in a security-critical program should be sued for gross negligence.

  8. Bounds checking is too Slow? by GGardner · · Score: 4
    I can't believe how many posts say that languages with automagic bounds checking (Java, Perl, Lisp, etc.) have too much overhead. Instead, these posters say, we should all manually insert bounds checking code by ourselves, and somehow that will magically have less overhead, and be more secure than having the compiler do it.

    Ick. That's just the sort of mundane task I want a compiler for. As a programmer, I already have too much to worry about -- bounds checking is one simple task that I'd just as soon have the compiler do.

    In most cases, the bounds check can be hoisted out of loops, so there's almost no overhead. In a perfect world, I'd like to see a compiler that, when given a high enough warning level, warns that it can't hoist bounds checks.

  9. PS, Not a Joke (+ more info) by Tom7 · · Score: 4


    Lest you be confused by the +1 funny on my post, let me say that I am not joking.

    2x slower is the most conservative estimate for the speed of modern safe languages against C code. (In practice I've seen much better. Does anyone trust benchmarks?) My point is, even if it is 2X slower, I'll gladly take it and sleep a little more soundly at night knowing that my linux box isn't being hacked due to 20 year-old issues. 99% of my box's CPU time is spent at Nice -19 trying to find big primes for the GIMPS project.

    Modern languages (take java if OO is your thing, but there are more intersting languages around) have SOLVED this problem with buffer checking (or static proofs that checking isn't needed). Without having to worry about this type of common security hole, programmers can spend more time on things we REALLY need: documentation, maintainable code, asymptotic speed increases, and the other possible security holes (ie, not escaping shell metacharacters in user input).

    See my thread on Functional Languages for what I think is a convincing argument about modern typed languages in general. I know my position is extreme, but that doesn't make it a joke.

    http://slashdot.org/comments.pl?sid=00/07/01/232 1210&threshold=1&commentsort=3&mode=thread &cid=145

  10. Re:Buffer Overflows by electricmonk · · Score: 4
    is it like sorta like going out with too many guys or something?

    No, I think that's more akin to what a packet sniffer does. But close!

    --
    Friends don't let friends use multiple inheritance.
  11. Blame the Programmer by adubey · · Score: 5

    Like a system, and langauge can be as secure or insecure as you can make it. One can write an extremely tight program in C++ while writing one in Perl or Java that leaves gaping security holes open.

    This statement troubles me. C/C++ addict who have little exposure to other languages have little knowledge of what they're missing.

    _Many_ (if not most?) security attacks involve buffer overflows. You have to _work_ and _think_ to free yourself of buffer overflows in C/C++. In other languages, this protection comes for free.

    Yes, it's possible to make a secure program in C/C++. But it's just a hell of a lot easier in bounds-checking languages.

    So there.