On Sun, Apr 27, 2014 at 1:27 AM, Steve Haflich shaflich@gmail.com wrote:
At some point on any modern OS, reading or writing to a socket stream will involve passing to the OS (generally via a thin user-mode C API layer like *nix read() and write(), or some socket analogue). Neither Lisp nor C will provide any automatic bounds checking on such a call. The OS treats the application's address space as a mostly-contiguous undifferentiated sea of bytes(*). It doesn't matter that at the app level C also has this model of a sea of bytes, while in Lisp the ocean is run-time tagged into small plots. That distinction disappears once one calls write(fd,buf,len).
I think we've all understood that.
But here's the thing. If you're writing at the application level in Lisp (or Java, or Python, or Ruby, or ...) you're probably not going to code the foreign call to 'write' yourself. You're probably going to invoke some stream operation that was written either by the Lisp implementor or by the author of a portable library. This means the person who writes the foreign call (a) is probably more experienced and in more of a mindset to think about things like bounds checking; (b) is therefore likelier to insert a check that the number of bytes you want written is no greater than the length of the array you've provided; and (c) has the information available at that point in the code to make that check, because the array is not represented as just a raw byte pointer. The last point is the most important: the library writer _can_ make the check, which is not true the way things are usually done in C.
C, in contrast, has people writing dangerous low-level calls _all the time_, in _application_ code. The odds of it being done correctly every time are far poorer -- in practice, approximately zero, in any substantial program.
It certainly is possible to write better C libraries that relieve the application programmer of some of this burden; both Microsoft and Apple have done some of this. But the use of these libraries is not yet routine in portable POSIX code, and I don't know that they would have caught the Heartbleed bug anyway.
I'm not suggesting that bounds errors are the only source of security vulnerabilities -- William's list is a good one -- nor that use of a "safe" language is an absolute guarantee that one won't have them. But in practice, an attacker's time is not well spent looking for bounds errors in applications written in Lisp/Java/etc. It _is_ well spent looking for them in C code.
-- Scott