3 ms·
If your language (and program in Rust's case, since Rust has unsafe code) is memory safe, then the contents of deallocated memory shouldn't be internally observ
by cwzwarich 9y ago
If your language (and program in Rust's case, since Rust has unsafe code) is memory safe, then the contents of deallocated memory shouldn't be internally observable. Technically speaking, you could add an API to Rust that returns an Option of a buffer by virtual address, and this would be completely safe.
If you're truly concerned about the implications of preserving the contents of existing memory, you need to do it at a lower level in the allocator anyways. In the case that a pushing elements on a Vec causes the Vec's buffer to be reallocated, the allocator is free to either extent the existing allocation of the buffer or make a new allocation. If the allocator chooses the latter, then clearing the memory upon drop doesn't clear the old copy.
- mehrdadn 9y ago> then the contents of deallocated memory shouldn't be internally observable. Only as long as you can assume control flow integrity. As soon as the control-flow gets diverted then an attacker can read the memory. That's the root of the security concern to begin with.
- koverstreet 9y agoHuh? If memory safety isn't broken, no matter what the attacker does the memory is only going to be accessible through the container that allocated it. Parent's point still stands.
- mehrdadn 9y ago> If memory safety isn't broken You're missing the facts that (a) your unsafe code won't be safe, and (b) your program will generally invoke external code that can be also buggy and hence not memory-safe.
- koverstreet 9y agoHalf the point of Rust is to drive the amount of unsafe code as close to zero as possible so we don't have to worry about crap like that. Based on the code I've seen, I think you're simply protecting your experiences and fears from C++. You are of course free to use an allocator that zeroes on dealloc in your own code.
- Yoric 9y agoTo be fair, Rust code can link to (entirely unsafe) C/C++ code or even JIT-compiled code, in which case you also want some runtime guarantees to mitigate exploits in case they happen. In such a case, I believe a clearing allocator (or a set of custom allocators) sounds like the way to go. There may be a performance penalty, but you will be certain that all instances are covered, not just Vec<_>. Alternatively, a typed allocator (I wanted to link to a paper on the topic, but I can't find it) can, for a very small price, perform reasonably good mitigation on such exploits.
- cwzwarich 9y agoI was assuming memory safety, and that violation of control-flow integrity would also be a violation of memory safety.
- mehrdadn 9y agoYou cannot assume memory safety; the entire point of this security concern is that you cannot assume memory safety. There will in general be unsafe Rust code and non-Rust code that you cannot verify in external libraries, etc.
- Manishearth 9y agoIn which case you can always implement a hardened vec that clears itself, like the parent commenter said. That comment had two parts, it first said that if your code is memory safe (even explicitly calling out unsafe code!) then it's not a problem, and then saying you can do it at a lower level if you have to. You can do it at a lower level either by changing the allocator, or by having a hardened vec that does a volatile write in its destructor. Look again at the text right before your quote "then the contents of deallocated memory shouldn't be internally observable."; it explicitly addresses this exact concern.
- mehrdadn 9y agoWhat I am trying to say is that that "if the program is memory-safe" condition is never satisfied in reality. You will be calling unsafe code no matter what you do -- not only will any non-trivial program itself have unsafe code as already called out, but because even a trivial "hello, world" would need to invoke a syscall which will not be written in Rust (until the time comes when we get a Rust kernel...) and hence not proven memory-safe. Does this make sense? Yes, if your program was secure then you wouldn't need to worry about security, but that's not the world we live in.
- Manishearth 9y agoSure. At which point, again, there is still a solution, just that Vec itself won't help here. However, it's worth noting that at this level of "everything is unsafe" the problem is intractable. Just as you trust Rust's stdlib to have safely-crafted syscalls, you trust Rust's compiler to generate the right code if you tell it to do a volatile clear on a drop/resize. You have to define your trust level somewhere. For some, it is "I have audited my small amount of unsafe code (if any), and I trust Rust's stdlib". The parent's comment was addressing that level of trust. If you're not trusting the stdlib, you also probably don't trust the compiler to generate the right code; at which point the most you can do is try to keep things safe, you can never succeed short of auditing the generated asm extensively.
- dbrgn 9y agoIf you're worried about secrets leaking, you can also use crates like https://crates.io/crates/secrets https://crates.io/crates/secrets or https://crates.io/crates/secstr https://crates.io/crates/secstr that clear memory on drop and also prevent active memory from being swapped, and other things.