Live data from Hacker News

Heartbleed in Rust

tedunangst.com

111–120 of 140 posts

Re: Heartbleed in Rust

#111
post #70

Earlier quoted context omitted.

Others at Mozilla and I have done similar studies with our Gecko critical security bugs. The number of them that Rust would have prevented are staggering. I've always been careful not to claim that Servo will have no security flaws. It will, and some of them will be critical. But nobody denies that sandboxing is a powerful defense because Pinkie Pie found some sandbox escapes in the Pwnium contest. Likewise, let's no…

Of course. But subtextually: had you replaced C++ with Python, you'd have had the same outcome. Obviously, a significant advancement in Rust is that it's feasible to replace performant C++ programs with Rust, and not feasible to do that with Python. But that's perhaps a performance and logistical advance, not a security advance. I get that the combination of [memory-safe, non-garbage-collected, performant, natively-c…

> But subtextually: had you replaced C++ with Python, you'd have had the same outcome

Would you? http://pastebin.com/T5S0w708

Re: Heartbleed in Rust

#112

Type / memory safety != security. The Rust people also mistake "no segmentation faults" for "no crashes".

> Type / memory safety != security

Type and memory safety certainly does enhance security, by eliminating classes of vulnerabilities. Security isn't a binary thing.

> The Rust people also mistake "no segmentation faults" for "no crashes".

To a systems programmer the meaning of "no crashes" is pretty clear. A Web page (or your browser) doesn't crash because the JavaScript on the page threw an unhandled exception. Rust panics work like exceptions.

Re: Heartbleed in Rust

#113

Earlier quoted context omitted.

Java. Python. Golang. Lua.

(Just trying for clarity, not arguing against or opposing your point) In an earlier comment you used as an example of an unforced error "we wrote our custom database engine that only ever runs serverside in C". Are you saying (with this comment) that for such use cases, developers should use Java/Python/Go/Lua (vs C/C++)?

Yes, because you remove a whole class of errors that might be exploited. Might be hard, might even be impossible, but they are there waiting to be taken advantage of.

Interestingly enough, very high performance java is a bit like rust. Almost all memory safe, except a few (10-100) lines off crazy unsafe stuff.

Of course it is possible that your C code has no memory issues and is verified to be safe, but I would not bet any money on it.

Also at the moment custom code is the last entry point for a hacker, but once all other things are hardend its the last guaranteed leak in the ship.

I also understand where C semantics can lead to faster code than e.g. java today. But I suspect that edge to disappear within the next 3 years. Just like java is going to make heterogeneous compute easy its also going to improve streaming over memory for speed where needed.

Re: Heartbleed in Rust

#114

Earlier quoted context omitted.

> As the offending commentor, I apologize. Particularly to the Rust team for generating this negative publicity, and to the person I replied to, for asserting a lie. Realistically you're on the right side here. I just like to argue because it makes people justify their positions, which helps me (and hopefully other people) understand them better. Rust is one of the most promising languages I've seen in a long time. P…

But Rust does solve all memory safety issues, doesn't it? In the same way, say, F# does. Except I can use it without worrying about deployment or runtime costs. One scenario I am using Rust for is a packet capture parsing and forwarding daemon. With C, my biggest failure mode is "people can run code on your server by sending a packet across your network". With Rust, my biggest failure is "my code might be buggy so re…

Aren't we just talking about Heartbleed again? If you're forwarding packets the attacker could send you one with a forged length field.

Even if all you're doing is receiving packets and writing them to a file, what happens when you use the attacker-controlled reverse DNS of the packet's IP address as the file name?

Re: Heartbleed in Rust

#115
post #86
post #84

Earlier quoted context omitted.

"Don't write C/C++ in 2015" That's quite bold.

Some people have to write C/C++. Kernel developers, for instance. But most people who write C/C++ in 2015 don't really have to. For every low-level game programmer or RTOS embedded systems use case you'll cite, I'll cite an unforced error that occurs 5x as often, such as "we wrote our custom database engine that only ever runs serverside in C".

"But most people who write C/C++ in 2015 don't really have to."

While greenfield projects might be able to start with a new language established products have quite a lot of inertia. Any production environment needs to factor in personnel training (or, hey, fire the tens of C++ developers and replace them with equally skilled Rust developers who are as famimiar with the domain requirements as the last lot..) and the costs and risks in architecture changes. Switching languages might not be even then feasible, given a common big ball of mud structure with computational modules, UI and domain logic cooked together into a delicious mess.

Even if the long term costs of a codebase written in Rust were, say, the tenth of the costs of a similar codebase written in C++ often the product development costs are not that large percentage for established ISV:s.

When the next greatest browser gets written in Rust, then industrial users start paying notice.

Why would I care of how organizations develop software? Because I need to get paid and I work inside an organization... I write C++ to earn my living, I don't want to write C++ home for fun.

So at home I wouldn't write C++ any way and at work I really don't have a choice :) - Of course, peoples situation vary.

Re: Heartbleed in Rust

#116
post #89

Earlier quoted context omitted.

I would argue that the whole Rust ecosystem pretty strongly discourages you from writing broken low-level infrastructure code. The idea behind unsafe code blocks, the generics system, and Cargo is to encourage you to use off-the-shelf tools instead of rolling your own, often broken, solutions. The C ecosystem, by contrast, tends to encourage rolling your own solutions because managing dependencies in a cross-platform…

I mostly agree, but "use somebody else's" doesn't really help if you're writing a crypto library in the first place.

They're referring to writing your own allocator.

Re: Heartbleed in Rust

#117

Earlier quoted context omitted.

> 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. Heartblee…

What he's done is actually very different to heartbleed. The heartbleed flaw was made much worse by the custom allocator used, but that wasn't the source of the flaw. The source was the fact that dynamically allocated memory in C is not bounds checked. That isn't true in Rust, and he had to basically implement a deliberately unsafe memory allocator to show this flaw. His argument that you can't say "no rust programme…

> The source was the fact that dynamically allocated memory in C is not bounds checked.

When you say "bounds-checked", what are you talking about? To me, it means that "x[somenumber]" make the program abort if somenumber is out of range. However, as you can see, the reads and writes were never out of range. As I see it, the issue is that uninitialized memory is being read. This is not "unsafe", cause it will never crash your program. I don't know the exact definition of "undefined behaviour", but since we are using a custom allocator, even if reading from freshly malloc'ed memory is undefined, it may not be in this case.

Rust doesn't let you get uninitialized memory without using "unsafe", so to construct a program with the issue, he had to reuse the buffer. I think it's a lot less likely to happen with Rust, since it is visible to anyone that it is the same buffer.

> If he had ignored the custom allocator and used the defaults in both languages (e.g. malloc in C, whatever it is in Rust)

How do you know the default allocator isn't using memory that was previously used for the private key? And why do you think the default allocator wasn't used in the Rust code?

PS: Taint analysis also has a much better chance of working in Rust, since we are not working with libraries, but standard language constructs. In C, your taint analysis would have to taint every byte straight from malloc.

Re: Heartbleed in Rust

#118

Earlier quoted context omitted.

But Rust does solve all memory safety issues, doesn't it? In the same way, say, F# does. Except I can use it without worrying about deployment or runtime costs. One scenario I am using Rust for is a packet capture parsing and forwarding daemon. With C, my biggest failure mode is "people can run code on your server by sending a packet across your network". With Rust, my biggest failure is "my code might be buggy so re…

Aren't we just talking about Heartbleed again? If you're forwarding packets the attacker could send you one with a forged length field. Even if all you're doing is receiving packets and writing them to a file, what happens when you use the attacker-controlled reverse DNS of the packet's IP address as the file name?

Heartbleed isn't a memory safety issue though, which is what kicked this off. You're right in your original reply to me that if you want to go reuse buffers with leftover data, you can do that in any language. If you want to create a byte array in Java, fill it with private key material, then reuse the same byte array for an output buffer... what can stop that?

But more to my point: in C, I could end up executing arbitrary code by misparsing a network packet. In Rust, the worst I'll do is parse it wrong send invalid data onwards. That's just a massive reduction in scope.

I suppose if you have a tool that writes to arbitrary, attacker-supplied file locations, that could have a severe impact. Or it could pass an attacker-controlled value to the shell without escaping.

But things like the cpio[1] bug mentioned in the lessopen issue. Or the numerous compression libraries that require trusted inputs. Image manipulation code. And on and on. How many of them become simple crashes with a memory safe language? Cause from my unscientific (and flawed as this entire article is about) review, it seems like the great majority are these memory safety issues. Perhaps 90%? For widespread code, am I that far off the mark? (I understand that most intranet or custom software might just eval() every querystring given to it.)

1: http://seclists.org/fulldisclosure/2014/Nov/74

Re: Heartbleed in Rust

#119
post #110

Earlier quoted context omitted.

But Rust does solve all memory safety issues, doesn't it? In the same way, say, F# does. Except I can use it without worrying about deployment or runtime costs. One scenario I am using Rust for is a packet capture parsing and forwarding daemon. With C, my biggest failure mode is "people can run code on your server by sending a packet across your network". With Rust, my biggest failure is "my code might be buggy so re…

Rust can't solve all memory safety issues. Rust tries very hard to guarantee that safe code (i.e. not unsafe{}) will be memory safe and free of some race conditions. The hard part is making this possible - turns out you need unsafe in the core to be able to write safe implementations of those features in the general case. Attack surface is greatly lessened, but it's still there.

The difference is that in Rust not the whole source code but rather only the `unsafe` blocks and what they touch need to be verified for memory-safety.

Re: Heartbleed in Rust

#120
post #70

Earlier quoted context omitted.

Others at Mozilla and I have done similar studies with our Gecko critical security bugs. The number of them that Rust would have prevented are staggering. I've always been careful not to claim that Servo will have no security flaws. It will, and some of them will be critical. But nobody denies that sandboxing is a powerful defense because Pinkie Pie found some sandbox escapes in the Pwnium contest. Likewise, let's no…

Of course. But subtextually: had you replaced C++ with Python, you'd have had the same outcome. Obviously, a significant advancement in Rust is that it's feasible to replace performant C++ programs with Rust, and not feasible to do that with Python. But that's perhaps a performance and logistical advance, not a security advance. I get that the combination of [memory-safe, non-garbage-collected, performant, natively-c…

Isn't that setting up a straw-man?

Nobody sane would use C/C++ when they could get away with Python and nobody sane would use Python if they need to control the memory layout and access patterns like in C/C++.

Obvious candidates for such use-cases, besides kernel space, are games or video/audio systems or other stuff in which dropping frames is unacceptable, real time systems which includes some web services, or simply applications that have to use a lot of RAM, like databases, since even the most advanced mainstream garbage collectors are still awful at managing huge heap sizes.

And it seems to me like the target for Rust is pretty clear - that people are even considering it as a replacement for GC-ed languages is a pretty good achievement, but I don't think somebody wouldn't notice the stark contrast between what is a systems language and a GCed one right from the 10 minutes tutorial.

And btw, there are some instances in which Rust is safer than a language like Java in a multi-threading scenario. In Java or other JVM languages, you can happily capture a mutable object inside a closure and then mutate it asynchronously, possibly in another thread, while not synchronizing or releasing control in the thread in which the capturing happens. Even if you're using high-level abstractions, like actors, futures, streams and what not, this possibility of capturing mutable objects from the context by mistake in closures that execute asynchronously is always there, so to write safe code that protects against accidents you have to get religious with immutable data-structures and whatnot. This isn't to say that Rust is safer than Java - I doubt that. But it has some interesting ideas in it nonetheless.

Post reply on HN