Live data from Hacker News

Memory safety is necessary, not sufficient

steveklabnik.com

101–110 of 162 posts

Re: Memory safety is necessary, not sufficient

#101
post #35

I'm not sure I understand what this piece is trying to say about Python memory safety. Conventionally, in software security, Python is considered a memory-safe language. The piece makes the case that Python isn't memory safe when you FFI into a C library. But neither is Rust, nor is it when you use `unsafe`. What matters in both case is how little unsafe code you end up writing. Memory safety is a software security c…

Data races are definitely exploited! If we are considering TOCTOU issues then this is a very easy way to get fairly reliable and simple exploits. If we are talking about races of the “two threads access the same value” kind then it’s easy (well, assuming reliability is an exercise for the reader) to turn this into a UAF or OOB access by having one thread work with a stale version of an object that has been modified e…

TOCTOU isn't a data race. It's a race condition, but a "data race" is something much more specific. I think the terminology is confusing to be honest.

Re: Memory safety is necessary, not sufficient

#102
post #76

I think it’s worth emphasizing that the C spec’s love of undefined behavior—if you do X by accident, anything can happen—and the apparently massive amount of memory-unsafe software that has been written that will just allocate 16 bytes on the stack and then read from a file descriptor until it encounters a null byte… are examples of things that aren’t considered remotely sane or reasonable to a modern programmer or l…

Undefined behavior is critical for performance. Without undefined behavior, C compilers would not be able to optimize at all. You'd be running everything at -O0 or worse.

> Undefined behavior is critical for performance

Not only is this not true, it's trivially easy to prove it's not true. Both rustc and clang generate LLVM IR and use LLVM to optimise and generate machine code. The code that's generated is equally performant, as you'd expect since most of the optimisation is being done by LLVM, not the front end.

The difference between the two frontends is that rustc is stricter, rejecting programs where UB may arise.

Re: Memory safety is necessary, not sufficient

#103

Earlier quoted context omitted.

Data races are definitely exploited! If we are considering TOCTOU issues then this is a very easy way to get fairly reliable and simple exploits. If we are talking about races of the “two threads access the same value” kind then it’s easy (well, assuming reliability is an exercise for the reader) to turn this into a UAF or OOB access by having one thread work with a stale version of an object that has been modified e…

TOCTOU isn't a data race. It's a race condition, but a "data race" is something much more specific. I think the terminology is confusing to be honest.

Right, my understanding is that a data race is the second thing I mentioned. I was just so surprised to hear this viewpoint that I figured I’d throw it in just in case we were talking about different things.

Re: Memory safety is necessary, not sufficient

#104
post #9

Earlier quoted context omitted.

Just a small clarification here. The author isn’t just a fan of Rust. Steve was a member of the Rust Core Team for years and was co-author of the book “The Rust Programming Language,” which is the main recommended introductory text for the language.

I saw the authors credentials and I do respect them a lot. But to be fair, I'm sure the person who wrote the Go manual could have written the same blog post with the same outlook for the future only with Go in place of Rust. I'm trying to broaden the scope of conversation to a more holistic one, rather than just "this is our chance to take over the world!" Like my Gotek USB emulator reference. The device costs $50, a…

Go has absolutely zero interesting properties here. It has a shitty, inexpressive type system, dangerous concurrency, brain-dead error handling. It is a managed language, which provided memory-safety for many many decades now.

Re: Memory safety is necessary, not sufficient

#105
post #35

I'm not sure I understand what this piece is trying to say about Python memory safety. Conventionally, in software security, Python is considered a memory-safe language. The piece makes the case that Python isn't memory safe when you FFI into a C library. But neither is Rust, nor is it when you use `unsafe`. What matters in both case is how little unsafe code you end up writing. Memory safety is a software security c…

> logic bugs, SQL injection, quoting, filesystem traversal...

Actually Rust does go quite far in reducing the probability of these bugs, even if it doesn't have specific features for it. This is through a combination of:

* really strong type system ("if it compiles it works")

* Better ergonomics, e.g. using prepared queries is much easier than in C.

* Library code being generally very high quality, and easy to obtain.

Re: Memory safety is necessary, not sufficient

#106
post #48

Earlier quoted context omitted.

Java can use SecurityManager to do this.

It's deprecated for removal.[0] [0] https://openjdk.org/jeps/411

GraalVM has Isolates that can do this on a much more fine-grained level and with multiple languages (it can also run LLVM-languages now).

Re: Memory safety is necessary, not sufficient

#107

I think it’s worth emphasizing that the C spec’s love of undefined behavior—if you do X by accident, anything can happen—and the apparently massive amount of memory-unsafe software that has been written that will just allocate 16 bytes on the stack and then read from a file descriptor until it encounters a null byte… are examples of things that aren’t considered remotely sane or reasonable to a modern programmer or l…

"Worse is better" is much older then "undefined behaviour". Undefined behaviour was invented for C standardization, when C was already mature and had been out of the Unix childhood home for a long time.

For example, many UB semantics in the standard come from allowing for C ports for strange non-unix hardware, and making bold decisions when developments in compiler optimization state of the art ran into underspecified corners of C semantics.

Re: Memory safety is necessary, not sufficient

#108
post #76

I think it’s worth emphasizing that the C spec’s love of undefined behavior—if you do X by accident, anything can happen—and the apparently massive amount of memory-unsafe software that has been written that will just allocate 16 bytes on the stack and then read from a file descriptor until it encounters a null byte… are examples of things that aren’t considered remotely sane or reasonable to a modern programmer or l…

Undefined behavior is critical for performance. Without undefined behavior, C compilers would not be able to optimize at all. You'd be running everything at -O0 or worse.

The main performance-critical undefined behavior in C is provenance. The rest can be removed without major performance impact. (Which is not to say they can't give you 10% on specific workloads, just they aren't what is taking you from -O0 to -O3.)

A related student poster from EuroLLVM 2023: https://llvm.org/devmtg/2023-05/slides/Posters/05-Popescu-Pe... It tests the performance impact of some of the secondary undefined behaviors, and the result is basically what you'd expect. They do have impact, but if you average over all benchmarks the improvement is, at best, in the low single digits.

Re: Memory safety is necessary, not sufficient

#109

Nobody has been able explain to me what would be lost if we defined data races to yield one of the values that had been written to the memory in the past, instead of being undefined. It is not as if any optimizer can see that you are racing and delete the code path that has it.

This is what Java does, so in a way, data races are safe.

Re: Memory safety is necessary, not sufficient

#110

Earlier quoted context omitted.

> compiler bugs... its fair to ignore those when discussing the language in the abstract When the language is defined as whatever the compiler does , as it is in the case of Rust, I'm not so sure. If there were a Rust standard with multiple compliant compilers, I'd be more convinced, but Rust isn't there yet. (And TRF's trademark policy may well prevent it from ever getting there.)

Having more implementations doesn’t really help you avoid bugs in the one you’re using.

Not entirely true. When there are multiple implementations disagreements between them in normative behavior prove one or the other (or the language itself) has a bug. This means you can run randomized tests in your software, hash the results, and the hash should be the same between compilers (and across platforms).

That's an option that doesn't exist when there aren't multiple, and even if you won't use the potential personally other people using it will eliminate bugs in the compiler. The csmith program was used to find an incredible amount of bugs in gcc and clang. This approach can also be applied to many pieces of ordinary code too.

Prior poster's point is also that when there is only one the language is the compiler and it's not useful to talk about them in isolation. I don't fully agree with that in theory since the language is supposed to be stable-ish while bugs in the compiler will get fixed. So to the extent that something in rust is a footgun due to the language we might be stuck with it, but if its due to a compiler bug it will probably be fixed.

Post reply on HN