Live data from Hacker News

Memory safety is necessary, not sufficient

steveklabnik.com

41–50 of 162 posts

Re: Memory safety is necessary, not sufficient

#41
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…

> I have a hard time not reading them as shibboleths for "Rust is the only safe language", which is manifestly false.

Given that quite simple classes of vulnerabilities are endemic to all other major languages, no, it's not "manifestly false". The state of software safety really is bad enough that "all major languages that aren't Rust are unsafe" is plausible.

> The vulnerabilities endemic to memory-safe languages (logic and higher-level vulnerabilities like SQLI, metacharacter quoting, filesystem traversal, and cryptography bugs) are common both to languages like Python and Java and also to Rust --- the only super-common class of vulnerability endemic to languages like Python and Java that Rust avoids is deserialization (you avoid deserialization vulnerabilities by not building hypercapable serialization formats).

SQLI at least should be a lot less common in ML-family languages like Rust where manipulating structured data is relatively easy (or at least, the ease advantage of string manipulation over structured data is smaller). Carefully distinguishing between character strings, file paths, and byte sequences, as Rust does, should also eliminate at least some common kinds of vulnerabilities.

> The data races aren't going to burn you.

Eh maybe. All we can really say so far is that they haven't reached low-hanging fruit level yet. There have been plenty of similarly unsafe things that weren't thought to be exploitable that have turned out to be major sources of vulnerabilities as the bar gets raised and more effort gets put in, e.g. there was a time when the conventional wisdom was that double-free() was only a reliability/resiliency concern and not a security issue.

Re: Memory safety is necessary, not sufficient

#42
post #27

Earlier quoted context omitted.

uh. No. Rust unsafe gives rust behavior a lot like C. If you at all break the rather subtle rules, then essentially anything can and will happen. So for example, there was recently a thread where someone had code that checked if a value was in range to safely coerce it directly to an enum then did so. But because of eager evaluation of an argument the unsafe cast happened first. From this the compiler reasoned that t…

> As a result, I don't think it can be taken for granted that rust as a whole is an advancement in software integrity-- it may be, but it's something that ought to be formally studied. In some cases rust might be replacing memory safety bugs with an even greater number of other defects which, depending on the application, may be worse. I’m sorry, but without any supporting evidence for this claim, this is just FUD. E…

Citation welcome to those case studies, because I've not seen them. It's on the advocates of rust to establish that it makes things better because it absolutely isn't unambiguous.

We really seem to be in the stone age in terms of what practices lead to higher quality software. We still have people who chant "goto harmful" against one simply forward jumps to on-error-cleanup code, yet still litter their C++ and java with exceptions which are a less safe and less clear version of the same thing.

I've personally found the rate of embarrassing errors in simple rust software is increased over comparable C code, but I freely admit that this experience is far from a formal study and may well be due to the lack of problem-domain competence or general haste in people participating in culty "re-implement in rust" exercises (and where the rust code is far more often someone's "learn rust" project). And at least where security w/ untrusted input is a concern the nature of the rust bugs is preferable to the bugs in comparable C code, but as mentioned that doesn't apply to a lot of software.

Another data-point is that the vast majority of firefox crashes I experience now are rust panics, even though the amount of rust code is small compared to C++ code. It's hard to reason from that however, since it can be said that the rust code is more complex and more heavily used than the bulk of the rest.

Re: Memory safety is necessary, not sufficient

#43
post #39

Earlier quoted context omitted.

Are you grouping kernel exploits in with user space sandboxes? Lots of local roots come from data races which I would not call exotic. And there's always https://portswigger.net/research/smashing-the-state-machine for web stuff.

Right, these aren't data races; they're distributed systems races, more akin to tempfile races from the 1990s than to memory corruption.

Okay, fair.

Re: Memory safety is necessary, not sufficient

#44
post #40
post #37

Earlier quoted context omitted.

> If you at all break the rather subtle rules, then essentially anything can and will happen. If by subtle rules you mean your invariants, that is missing fundamental assumptions. It's akin to making a building without foundation and load bearing structures. > So for example, there was recently a thread where someone had code that checked if a value was in range to safely coerce it directly to an enum then did so. Bu…

> If by subtle rules you mean your invariants, that is missing fundamental assumptions. > It's akin to making a building without foundation and load bearing structures. That's exactly how C approaches UB too. > However note the UB goes away if you never use any unsafe code. Or if you expand your unsafe to encompas some safe code. Right. The problem is that's untenable; any nontrivial program will have unsafe somewher…

Exactly. All-hope-lost behavior is possible in rust code unless there is no unsafe anywhere (and no compiler bugs, but I think its fair to ignore those when discussing the language in the abstract).

Rust potentially benefits from fewer opportunities to footgun yourself, but rust also comes with other costs (including a more complex syntax, a bad dependency culture, a lot more front-loaded cognitive load around lifetime management, etc.) which might offset those benefits. Some of those extra complexity costs seem hard (or impossible) to avoid when trying to keep memory safety from having a disproportional runtime cost, so I'm not necessarily faulting rust. But some of the sources of defects in rust code may also be entirely avoidable, which is why I think it's important to actually study it rather than axiomatically assume its behavior makes programs correct. It doesn't, even absent unsafe.

Re: Memory safety is necessary, not sufficient

#45
post #41
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…

> I have a hard time not reading them as shibboleths for "Rust is the only safe language", which is manifestly false. Given that quite simple classes of vulnerabilities are endemic to all other major languages, no, it's not "manifestly false". The state of software safety really is bad enough that "all major languages that aren't Rust are unsafe" is plausible. > The vulnerabilities endemic to memory-safe languages (l…

Given that quite simple classes of vulnerabilities are endemic to all other major languages, no, it's not "manifestly false". The state of software safety really is bad enough that "all major languages that aren't Rust are unsafe" is plausible.

We're really very good at documenting vulnerabilities; the mere documentation of vulnerabilities is itself a 9-figure industry. So: cough up the examples. I can't think of any, so that's where I'm setting the bar for you.

A reminder that memory corruption bugs in FFI-bound libraries doesn't count --- Rust has plenty of those --- and neither do deserialization vulnerabilities, which were discussed upthread. It also doesn't matter if a condition makes it unsafe to run attacker-controlled code in a shared runtime; nobody does that (with native languages; they try, with Javascript, and it has been a disaster). You're looking for vulnerabilities that are widely exploited and intrinsic to a memory-safe language that isn't Rust. Not to a library, but to the language.

Re: Memory safety is necessary, not sufficient

#46
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…

> But in the main, data races have not empirically proved out as a source of exploited vulnerabilities.

Say what? Data races, otherwise lumped under the bucket “timing attacks”, are a common source of security exploits. A basic example is racing with code that is creating a file and applying an ACL in two steps. If I can “time” things right from a concurrent thread/process, I can get into this file before the ACL prevents me.

There are countless scenarios where multi-step operations that need to be treated atomically can be exploited by racing.

Re: Memory safety is necessary, not sufficient

#47
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…

> But in the main, data races have not empirically proved out as a source of exploited vulnerabilities. Say what? Data races, otherwise lumped under the bucket “timing attacks”, are a common source of security exploits. A basic example is racing with code that is creating a file and applying an ACL in two steps. If I can “time” things right from a concurrent thread/process, I can get into this file before the ACL pre…

That's not a vulnerability Rust prevents; it's an interaction between multiple competing runtimes. I'm not denying that race conditions (or timing attacks, another bug class Rust doesn't prevent) exist and are exploited! I'm denying that in-process data races that corrupt memory are a meaningful source of exploitable vulnerabilities.

For background, I've spent most of my career doing vulnerability research. I'm by no means a world expert on memory corruption vulnerabilities (I'm still impressed that I got my imapd shellcode to work with no uppercase ASCII characters), but you can safely assume I'm not just completely blowing off huge classes of exploitable vulnerabilities because I've never heard of them. Doesn't mean I'm right! But like, if you're going "say what", you're probably misconstruing me.

Re: Memory safety is necessary, not sufficient

#48
post #22

Our programs are growing so big by having so many (indirect) dependencies that we need a way to sandbox the libraries that we include from our main programs. This is the type of safety that I'm looking for, really.

Java can use SecurityManager to do this.

It's deprecated for removal.[0]

[0] https://openjdk.org/jeps/411

Re: Memory safety is necessary, not sufficient

#49
post #47

Earlier quoted context omitted.

> But in the main, data races have not empirically proved out as a source of exploited vulnerabilities. Say what? Data races, otherwise lumped under the bucket “timing attacks”, are a common source of security exploits. A basic example is racing with code that is creating a file and applying an ACL in two steps. If I can “time” things right from a concurrent thread/process, I can get into this file before the ACL pre…

That's not a vulnerability Rust prevents; it's an interaction between multiple competing runtimes. I'm not denying that race conditions (or timing attacks, another bug class Rust doesn't prevent) exist and are exploited! I'm denying that in-process data races that corrupt memory are a meaningful source of exploitable vulnerabilities. For background, I've spent most of my career doing vulnerability research. I'm by no…

OK, but I think you are moving the goal posts. You referred to “data races” and “security exploits” and suggested the two were not related. Memory corruption is only one (small) class of security exploits. Data races cause just as many in process, in memory, exploits as multi-step file operations (we are talking breaking application security models). Perhaps Rust can prevent most of these! (I don’t know rust).

Re: Memory safety is necessary, not sufficient

#50
post #47

Earlier quoted context omitted.

That's not a vulnerability Rust prevents; it's an interaction between multiple competing runtimes. I'm not denying that race conditions (or timing attacks, another bug class Rust doesn't prevent) exist and are exploited! I'm denying that in-process data races that corrupt memory are a meaningful source of exploitable vulnerabilities. For background, I've spent most of my career doing vulnerability research. I'm by no…

OK, but I think you are moving the goal posts. You referred to “data races” and “security exploits” and suggested the two were not related. Memory corruption is only one (small) class of security exploits. Data races cause just as many in process, in memory, exploits as multi-step file operations (we are talking breaking application security models). Perhaps Rust can prevent most of these! (I don’t know rust).

What are they? Show me the vulnerabilities you're talking about. I don't think I'm moving the goalposts here. The major distinction between Rust and (say) Java is Rust's type system formalisms to prevent in-process data race memory corruption. Those are real features, but they don't mitigate a major class of vulnerabilities.
Post reply on HN