Slightly OT: while trying to understand the vulnerability I came across a Rust question. Why can you do this? let mut outfd = File::create(&outpath); match outfd.write_all(&buffer[0 .. len]) { ... } According to `old_io::File`'s doc[0] it returns an `IoResult ` which is an alias `type IoResult = Result ` i.e. `Result `. How come you can do `write_all` directly on a `Result ` without unwrapping the `File` first? The e…
Heartbleed in Rust
11–20 of 140 posts
Re: Heartbleed in Rust
#12Earlier quoted context omitted.
It's because Writer (the trait write_all() is from) is implemented on IoResult. http://doc.rust-lang.org/std/old_io/trait.Writer.html#tymeth... impl Writer for IoResult From the `std::old_io` docs: http://doc.rust-lang.org/std/old_io/index.html > Common traits are implemented for IoResult, e.g. impl Reader > for IoResult , so that error values do not have to be 'unwrapped' before use.
Ah, remote implementation of traits bites me once again. Is there any reason behind not listing the implemented traits in IoResult's docs? Listing the implementors in the trait is not very useful since in the first place you have to know which traits are implemented to consult them. It's backwards and counterintuitive as I see it.
Re: Heartbleed in Rust
#13To 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.Re: Heartbleed in Rust
#14That being said I'm a bit more skeptical of this part: "code no true C programmer would write : heartbleed :: code no true rust programmer would write :: (exercise for the reader)"
If I look at the examples in the acticle, the C version doesn't look that terrible and contrieved to me. I wonder what the author means by "Survey says no true C programmer would ever write a program like that, either." That looks like a lot of C code I've read, there's nothing particularly weird about it.
On the other hand the rust version looks very foreign to me (and I've been writing quite a lot of rust lately). You basically have to go out of your way to create the same issue.
I guess my point is that while it's true that as long as there'll be coders there'll be bugs and security vulnerabilities it doesn't mean we shouldn't try to make things better. And in my opinion Rust makes it much more difficult to shoot yourself in the foot than plain C.
Re: Heartbleed in Rust
#15Wasn't the heartbleed issue that you could trick it into reading past the memory it had allocated? That's different to explicitly reusing memory you've allocated without clearing it in between. The original claim was that rust would prevent the class of errors that caused Heartbleed. No one claimed rust would prevent you from writing a program with a different bug that just happens to exhibit similar behavior. Buffer…
Re: Heartbleed in Rust
#16This is why I get a little uncomfortable when people suggest Rust fixes tons of security issues. Yes, it will fix some of them. No, just because a Rust program compiles doesn't mean that it won't have problems. Rust is _memory safe_. Nothing more, nothing less.
Rust's type system can be used to prevent high level attacks too. For instance, if an sql library is set up properly, it can prevent sql injection by requiring inputs be properly sanitized.
Re: Heartbleed in Rust
#17No 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…
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-heartblee...
[1] http://www.tedunangst.com/flak/post/heartbleed-vs-mallocconf
[2] http://www.tedunangst.com/flak/post/analysis-of-openssl-free...
Re: Heartbleed in Rust
#18Wasn't the heartbleed issue that you could trick it into reading past the memory it had allocated? That's different to explicitly reusing memory you've allocated without clearing it in between. The original claim was that rust would prevent the class of errors that caused Heartbleed. No one claimed rust would prevent you from writing a program with a different bug that just happens to exhibit similar behavior. Buffer…
Openssl uses their own memory allocator (since malloc is slow on big-endian x86 xenix or something) so they _do_ reuse memory without clearing it in between. Had they used the system malloc, it wouldn't have been vulnerable (on OpenBSD and probably elsewhere). Can rust prevent you from implementing your own (buggy) memory allocator?
Re: Heartbleed in Rust
#19I don't know that anyone claimed that a bug similar or analogous to heartbleed couldn't be reproduced in Rust. If they did, that was certainly an overstatement. I think more concretely people claimed that unreachable code yields a warning in Rust, which is absolutely true, but certainly not equivalent to saying something like a heartbleed bug would not happen. In general, Rust is fairly aggressive about linting for "…
In particular, while I of course agree with the author that one can write buggy code in any language, I also have found that following Rust's idioms leads to code that is less buggy. This is not unique to Rust: I've also had similar experiences in Scala and Ocaml. What Rust brings to the table is that it supports zero-cost-abstractions, doesn't require a virtual machine, and guarantees data-race-freedom (a rather useful propery).
Re: Heartbleed in Rust
#20Wasn't the heartbleed issue that you could trick it into reading past the memory it had allocated? That's different to explicitly reusing memory you've allocated without clearing it in between. The original claim was that rust would prevent the class of errors that caused Heartbleed. No one claimed rust would prevent you from writing a program with a different bug that just happens to exhibit similar behavior. Buffer…
Openssl uses their own memory allocator (since malloc is slow on big-endian x86 xenix or something) so they _do_ reuse memory without clearing it in between. Had they used the system malloc, it wouldn't have been vulnerable (on OpenBSD and probably elsewhere). Can rust prevent you from implementing your own (buggy) memory allocator?