top | item 44410979

(no title)

burakemir | 8 months ago

A definition of memory safety without data race freedom may be more precise but arguably less complete.

It is correct that data races in a garbage collected language are difficult to turn into exploits.

The problem is that data races in C and C++ do in fact get combined with other memory safety bugs into exploits.

A definition from first principles is still missing, but imagine it takes the form of "all memory access is free from UB". Then whether the pointer is in-bounds, or whether no thread is concurrently mutating the location seem to be quite similar constraints.

Rust does give ways to control concurrency, eg via expressing exclusive access through &mut reference. So there is also precedent that the same mechanisms can be used to ensure validity of reference (not dangling) as well as absence of concurrent access.

discuss

order

pizlonator|8 months ago

> The problem is that data races in C and C++ do in fact get combined with other memory safety bugs into exploits.

Because C and C++ are not memory safe.

> A definition from first principles is still missing, but imagine it takes the form of "all memory access is free from UB". Then whether the pointer is in-bounds, or whether no thread is concurrently mutating the location seem to be quite similar constraints.

I think it's useful to work backwards from the languages that security folks say are "memory safe", since what they're really saying is, "I cannot use the attacks I'm familiar with against programs written in these languages".

Based on that, saying "no UB" isn't enough, and only looking at memory accesses isn't enough.

WebAssembly has no UB, but pointers defined to just be integers (i.e. the UB-free structured assembly semantics of a C programmer's dreams). So, attackers can do OOB and UAF data attacks within the wasm memory. The only thing attackers cannot do is control the instruction pointer or escape the wasm memory (unless the wasm embedder has a weak sandbox policy, in which case they can do both). Overall, I think that memory-safety-in-the-sense-of-wasm isn't really memory safety at all. It's too exploitable.

To be memory safe like the "MSLs" that security folks speak of, you also need to consider stuff like function calls. Depending on the language, you might have to look at other stuff, too.

I think that what security folks consider "memory safe" is the combination of these things:

1) Absence of UB. Every outcome is well defined.

2) Pointers (or whatever pointer-like construct your language has) can only be used to access whatever allocation the originated from (i.e. pointers carry capabilities).

And it's important that these get "strongly" combined; i.e. there is no operation in the language that could be used to break a pointer's capability enforcement.

Java and Fil-C both have a strong combination of (1) and (2).

But, long story short, it's true that a definition of memory safety from first principles is missing in the sense that the field hasn't settled on a consensus for what the definition should be. It's controversial because you could argue that under my definition, Rust isn't memory safe (you can get to UB in Rust). And, you could argue that wasm meets (2) because "the allocation" is just "all of memory". I'm not even sure I like my own definition. At some point you have to say more words about what an allocation is.