8 ms·
No true blogger would wilfully misunderstand a buffer overrun vulnerability in order to score some cheap pageviews. To put it simply, his examples are the equi
by stevejones 12y ago
No true blogger would wilfully misunderstand a buffer overrun vulnerability in order to score some cheap pageviews.
To put it simply, his examples are the equivalent of doing this:
unsigned char data[4096];
#define X (*(int *)(&data[0]))
#define Y (*(int *)(&data[4]))
...
Basically, he's explicitly re-using a buffer, no buffer was overrun. In Rust you will not read something out of a buffer you didn't put there first, in C you can, and you might even read several GB out of a 256 byte buffer.
- masklinn 12y ago> No true blogger would wilfully misunderstand a buffer overrun vulnerability in order to score some cheap pageviews. You may want to read up on Ted, and realise that when he writes > if we don’t actually understand what vulnerabilities like Heartbleed are he's probably talking about you. > Basically, he's explicitly re-using a buffer, no buffer was overrun. Which is essentially what happened in heartbleed. Heartbleed was not a buffer overrun at any point. Here's the tl;dr: during heartbeat, OpenSSL would malloc both input and output buffers at the caller-specified size (65536 bytes), copy a caller-provided input (1 byte) to the input buffer then copy the whole input buffer to the output buffer. Anything beside the overwritten byte would likely be previously written data since neither malloc nor free zero out their stuff by default[0], essentially leaking 65k of random data every time. This was compounded by OpenSSL doing its own memory management via freelists, making it even more likely interesting data would be present in the input "garbage" and precluding OS mitigations (such as BSD's malloc.conf framework[1]), not to mention the unmitigated (no freelist) codepath had bitrotted and didn't actually work even if you knew how to enable it[2]. Note that [1] and [2] are by TFAA, and that he's an OpenBSD and LibreSSL core contributor. [0] http://www.seancassidy.me/diagnosis-of-the-openssl-heartbleed-bug.html http://www.seancassidy.me/diagnosis-of-the-openssl-heartblee... [1] http://www.tedunangst.com/flak/post/heartbleed-vs-mallocconf http://www.tedunangst.com/flak/post/heartbleed-vs-mallocconf [2] http://www.tedunangst.com/flak/post/analysis-of-openssl-freelist-reuse http://www.tedunangst.com/flak/post/analysis-of-openssl-free...
- Jweb_Guru 12y agoIn Rust, you cannot ever read uninitialized memory (including allocated memory) without using unsafe code (as can be seen in the original code sample, the Rust buffer, unlike the C buffer, is initially zeroed out). So in safe Rust, what you are describing indeed could not happen. The unsafety would have to be explicit at the caller end: the unsafe within the allocator implementation isn't enough.
- masklinn 12y ago> So in safe Rust, what you are describing indeed could not happen. Read the last paragraph. OpenSSL has a buffer reuse system via a freelist (and the non-freelist code had bitrotted), it didn't release buffers to the system's allocator after use, buffers were initialised across calls. Otherwise while heartbleed would still have existed to a large extent, it would also have been mitigable by e.g. malloc.conf or shimming in a zeroing malloc.
- Jweb_Guru 12y agoI believe if it went through any of Rust's planned custom allocator system (i.e. worked through `box`) it would still not work, though. You could certainly rewrite exactly the same system from C, of course (though as I noted elsewhere, it seems less likely that OpenSSL would want to replace jemalloc than the often-slow system allocator), but I think it would be quite difficult to write a safe implementation that worked with Rust's borrow checker. The closest thing to a custom allocator that works in Rust right now is an arena with a free list, which requires you to explicitly initialize any newly allocated elements. As another commentor noted, you would really have to go quite far out of your way to reproduce the issue.
- eddyb 12y agoAn allocator like that would require unsafe code to write and could not expose a safe interface unless it couldn't be used to read uninitialized memory. `Vec::with_capacity` would still not let you read the data even if you had a custom allocator.