News for hackers. Stuff that matters.
Re:Why you should, actually, rewrite some of it in Rust by falcolas on Wednesday July 12, 2017 @12:03PM (#14753657)
Sigh. This again.

Not all security vulnerabilities are due to pointer arithmetic or out of bounds execution or pick-your-rust-is-better-idiom.

Heartbleed is a great example. It wasn't caused by an error with how C handles memory or strings or anything else. It was caused by failing to validate untrusted input. Rust isn't going to help you with that.

Could the affected parts be re-written in a way where the boundary checks would have worked? Yes. As they could have in C, C++, D, Fortran, or any number of other languages.

If memory safety and correctness was so truly valued above everything else, we'd be seeing a lot more Ada than we do today.

And this doesn't even cover the fact that not everything can be re-written in Rust, mainly due to compilation target restrictions.

Exasperated Edit: No, I'm not saying code should never be re-written. I'm not even saying that Rust is a bad tool if the decision to re-write is made. What I am saying is that Rust is not a silver bullet. Rust is not going to solve every problem ever. Rust is one of many choices for writing memory safe, C ABI compatible code.

The reasons provided by this article are insufficient to solely justify a re-write in Rust; the exact same arguments could be used as justification for rewriting everything in Ada. Or Haskell. Perhaps some thought will be put in the next "re-write everything in Rust" article that takes that into account.

Then again, none of the past articles have.

Re:Why you should, actually, rewrite some of it in Rust by ekidd on Wednesday July 12, 2017 @12:28PM (#14753900)
> Rust isn't going to help you with that.

As I noted elsewhere in this thread ( https://news.ycombinator.com/item?id=14753692 ), I've actually been working on a low-level media decoder in Rust. Compared to my earlier work in C (the xmlrpc-c library, for example), my Rust code has stood up very well to heavy fuzzing. My xmlrpc-c code, on the other hand, was written with ridiculous levels of paranoia, and it has been the subject of multiple CVEs thanks to a third-party XML parser I used.

So in terms of practical engineering reality, Rust seems to make a big difference. And even more importantly, it means I can trust other people's libraries a bit more.

Rust's practical advantages seem to be:

1. Runtime bounds checks! I wouldn't have thought that this was the most important thing, but when fuzzing, it's the last line of defense against quite a few potential exploits.

2. Debug-mode checks for integer overflow. Rust defines integer overflow as an error, and debug builds will actually check for it. This turns out to work really well with fuzzers.

3. The borrow checker. In my experience, this is actually less useful than (1) and (2) above in terms of preventing security bugs. But it does help.

So as somebody who's written parsers for untrusted data in both C and Rust, I definitely found that Rust helped me a lot. Of course, Rust can't help with some forms of stupidity, such as writing a bad custom memory allocator and using it to handle key material. OpenSSL's problems go well beyond the ordinary hazards of C.

Re:Why you should, actually, rewrite some of it in Rust by pjmlp on Wednesday July 12, 2017 @01:46PM (#14754704)
> 1. Runtime bounds checks! I wouldn't have thought that this was the most important thing, but when fuzzing, it's the last line of defense against quite a few potential exploits.

C.A.R Hoare talking in 1981 about how their Algol compiler customers reacted to the proposal of turning off bounds checking.

"Many years later we asked our customers whether they wished us to provide an option to switch off these checks in the interests of efficiency on production runs. Unanimously, they urged us not to--they already knew how frequently subscript errors occur on production runs where failure to detect them could be disastrous. I note with fear and horror that even in 1980, language designers and users have not learned this lesson. In any respectable branch of engineering, failure to observe such elementary precautions would have long been against the law."

The mainstream adoption of UNIX and with it, C, made many without the knowledge of how computing outside AT&T walls since the dawn of computing looked it, to cargo cult ideas that were proven wrong elsewhere.

But given that victorious get to re-write history and UNIX got adopted by the enterprise, those OSes written in safer systems programming languages get forgotten.

The recent example was to learn about PL/8 and how IBM used it, in a compiler framework similar to LLVM, to do the research that lead to RISC.

http://rsim.cs.illinois.edu/arch/qual_papers/compilers/ausla...

Imagine that! The RISC computer was designed using an OS written in a system programming language using Algol safety checks, including bounds checking, in the 70's.

EDIT: Added a link to the PL/8 research paper.

Re:Why you should, actually, rewrite some of it in Rust by fpgaminer on Wednesday July 12, 2017 @12:55PM (#14754186)
Sigh. This again.

The Rust language is more than just memory safety. Memory safety is certainly the most prominent and unique feature of Rust, but the language also includes a lot of features that make writing good, bug-free code easier.

For example:

`Result`, when returned, forces all callees to check for errors. It's all too easy to throw away error codes in C/C++. This is probably one of the most important features in Rust, besides memory safety.

To easily consume an `Enum`, you have to use `match`, which forces you to handle all members of the enum. In C/C++ it's easy to build a switch for an enum, and then later when a new member is added to the enum and you forget to update all your switches.

Support for multiple return values (through tuples) means being able to avoid the nightmare of output pointer arguments to functions.

No NULL pointers.

Unit testing built into the canonical tooling.

Documentation testing built into the canonical tooling.

The `Option` type, which lets you return "nothing". In C/C++ you'd have to return a bool, and again use a nightmarish output pointer argument.

`OsRng` in the rand crate (go ahead, try to write a function that safely reads urandom in C).

No undefined behavior.

The list goes on. The flavor of it, is that Rust makes it easier to write defensive code. Defensive code is code that is hard to use wrong. For example, for a backup solution I built using Rust, I made all the cryptographic types their own unique, opaque types. EncryptionKey, HmacKey, Salt, etc. For someone new to the codebase, these types make it obvious what each function is asking for, and make it really difficult to use the functions or the types the wrong way. And they are super easy to build and use in Rust, see my code: https://github.com/fpgaminer/preserve/blob/master/src/keysto...

C++ would require a whole set of classes, and require instantiating a new class every time I want to add a new cryptographic type. Rust only requires 3 lines per type.

TL;DR: The real magic is that it's easier to do the right thing in Rust.

Re:Why you should, actually, rewrite some of it in Rust by blub on Wednesday July 12, 2017 @01:21PM (#14754428)
Some corrections:

* option and result are also available in C++, the former is even standardised.

* random numbers support is quite good.

* C++ compilers will warn if not all members of an enum have been handled in a switch. It's also easy to assert/throw in the default case as a safety measure.

* tuples are likewise supported

* I believe something like your opaque types could be done with templates and tag classes in a similar amount of LOC.

But yes, in Rust it's generally easier to do the right thing. This is the big benefit of learning from others' mistakes and not having to maintain backwards compatibility with ancient decisions.

Re:Why you should, actually, rewrite some of it in Rust by Manishearth on Friday July 14, 2017 @12:57AM (#14767582)
std::optional don't enforce exhaustiveness; you can get away with accidentally unwrapping it. In Rust this requires an explicit check or explicit call to unwrap()/expect().

To me, this is super important. But yeah, it's still a good thing to have!

IIRC there are TMP-implemented versions of this that are safer (though a bit ugly to use) though.

Re:Why you should, actually, rewrite some of it in Rust by cesarb on Wednesday July 12, 2017 @01:12PM (#14754343)
> `OsRng` in the rand crate (go ahead, try to write a function that safely reads urandom in C).

Nowadays, you should just call getentropy (http://man7.org/linux/man-pages/man3/getentropy.3.html) instead of trying to read from /dev/urandom, unless you have special requirements.

Re:Why you should, actually, rewrite some of it in Rust by dbaupp on Wednesday July 12, 2017 @03:36PM (#14755863)
Great example! OsRng will use that system call, if it is available.
Re:Why you should, actually, rewrite some of it in Rust by sidlls on Wednesday July 12, 2017 @03:57PM (#14756066)
I mainly agree that Rust is more than about safety. I just wish these other features had a tenth of the vocal support as Safety.

It's even worse here on HN, where the a certain group seem to thrive on blasting not-Rust, especially if that not-Rust is C or C++. I've seen comments to the effect that anyone writing in C or C++ today is literally acting with reckless indifference to life and safety. It's terrible.

Re:Why you should, actually, rewrite some of it in Rust by fpgaminer on Wednesday July 12, 2017 @06:52PM (#14757370)
Criticism is just so much easier than constructive arguments. That's why it's rampant in communities, even HN. And controversial subjects (Bitcoin, health, food, Javascript) will magnify the problem.

It's easy to find fault in C/C++. It's easy to parrot the Rust marketing. It's not so easy to actually have spent the time to learn and use Rust, let alone articulate the subtle ways that its design, taken as a whole, is better than alternatives.

Building those constructive arguments is _hard_. I remember reading an article about error handling. It had to have been at least 10 pages worth of content, covering the history of error handling throughout all the old and modern languages, and using examples for where each fails or succeeds. It culminates, more or less, in explaining exactly why the error handling of languages like Rust outperforms in the field of systems programming.

(NOTE: The author of that article was actually arguing for the error system used in the language they developed for their OS, IIRC. But Rust was pretty darn close to the ideal the author was going for, and they pointed out as much.)

My point is that it took 10+ pages to make a solid argument for _just_ error handling. Not many people have the experience, wisdom, time, and willingness to write even a fraction of such insightful content in a comment on HN.

That said, well written, balanced comments still generally float to the top in even controversial HN threads.

EDIT: I would also like to point out something specifically in response to "I've seen comments to the effect that anyone writing in C or C++ today is literally acting with reckless indifference to life and safety."

There is a tremendous amount of pent up anger in the programming community against C/C++. The language should have been put our to pasture a _long_ time ago. Rust is the first language which has a real chance to displace it. So it's no wonder that a lot of us are willing to just burn C/C++ to the ground and jump ship.

Not to mention that as programmers we may be quickly approaching a time when security bugs become a governmental issue, and the _last_ thing we want is the government mandating how we write code. So it is in everyone's interest if we self regulate. Again, that would explain why everyone is kinda jumpy about C and security bugs.

Re:Why you should, actually, rewrite some of it in Rust by pjmlp on Thursday July 13, 2017 @02:58AM (#14759281)
The interesting bit is that it was already happening on the PC world, with C only being used for OS APIs on Windows and OS/2, but most people were actually using C++ (OWL, VCL, MFC), Turbo Pascal for Windows followed by Delphi, VB, Eiffel, Ada, Oberon, Component Pascal...

Then the UNIX FOSS, written mostly in C took over, and set us almost 20 years back in security and safety.

Re:Why you should, actually, rewrite some of it in Rust by jacquesm on Wednesday July 12, 2017 @04:37PM (#14756432)
It's actually harming Rust. And not just a little bit.
Re:Why you should, actually, rewrite some of it in Rust by sidlls on Wednesday July 12, 2017 @04:53PM (#14756571)
The official Rust community isn't helping itself, either, here. If they were even a little bit as eager to step on lazy "C is bad" comments as to point out how safe Rust is it might help. Lazy reasoning about competitor languages isn't helpful because it inhibits the ability to effectively tout Rust's benefits.

But I've basically stopped commenting in Rust threads. There's too much "not even wrong" as regards C and C++ to be bothered with.

Re:Why you should, actually, rewrite some of it in Rust by bandook_raja on Wednesday July 12, 2017 @01:19PM (#14754406)
> It's all too easy to throw away error codes in C/C++.

Warning is produced by nearly every good compiler. They aren't forced because sometimes I don't really want to check for return values.

> In C/C++ it's easy to build a switch for an enum, and then later when a new member is added to the enum and you forget to update all your switches.

why would you update all other enum values in accordance to addition to a new one? I understand you could possibly be skipping one switch case because you just added it in enum definition but didn't update switch case, but why would you update rest? Is this a forced requirement in Rust? This is bad if it is.

> Support for multiple return values (through tuples) means being able to avoid the nightmare of output pointer arguments to functions.

std::tuple?

> No NULL pointers.

but what if you need them? Lets say a type safe, non-zero nullptr? I understand some people want to bring up whole NULL is bad mistake argument but remember some of us work with maintaining large code where such changes are non-trivial.

> Unit testing built into the canonical tooling. Documentation testing built into the canonical tooling.

This is good argument :)

> The `Option` type, which lets you return "nothing". In C/C++ you'd have to return a bool, and again use a nightmarish output pointer argument.

std::optional? Or many other implementations of optional type? I've been using them since ages(before rust was even born) and writing them is no NP problem. Don't credit rust as if it brought the `Option` type.

> `OsRng` in the rand crate (go ahead, try to write a function that safely reads urandom in C).

Is this intended to be sarcasm? try <random> header and see if it fulfills your requirement, otherwise there are tons of libraries. But wait, what? This is another already solved problem unless I'm missing something.

> No undefined behavior.

Lol do you even unsafe bro?

> C++ would require a whole set of classes, and require instantiating a new class every time I want to add a new cryptographic type. Rust only requires 3 lines per type.

Depends on your cpp skills and judging by this post, they're certainly less than expected from a beginner. I hope you learn about certain languages (even the ones you are defending) before writing things on internet, since 90% of what you wrote won't even come near acceptable so I suggest doing your research properly.

Re:Why you should, actually, rewrite some of it in Rust by fuwafuwa on Wednesday July 12, 2017 @02:54PM (#14755407)
Your comment indicates that you don't really understand the value of ADTs as the switch, option type and NULL pointer comments overlap: in your new code(and it would be be new code since it's rewritten in Rust) you define it to have Some(pointer) or None. Then to access the value you have to switch on and evaluate the None case at any dereference site. NULL cannot happen but you can still pass around a None type.

Regarding safely reading urandom, you don't seem to be aware that concurrency issues occur when accessing it from multiple processes. This is something that the borrow system can aid with by formalizing access to a resource like urandom and not allowing contention for it to occur at runtime.

Also, nobody appreciates aggro kid language.

Re:Why you should, actually, rewrite some of it in Rust by sqeaky on Wednesday July 12, 2017 @12:33PM (#14753953)
I agree that there are technical limitations, but I think those should be sought to be overcome. I disagree with your implicit assertion that all languages are equal (or close enough). If it is possible to make a class of error completely disappear then it should be done when not cost prohibitive, and languages can be designed such that there is no cost to avoid certain errors.

Sure one boundary error could have been detected in any language, but there will always be fewer in a language that simply disallows them. Consider how infrequently Gotos are used now there are no longer errors with setting state before a jmp/goto, because modern constrol flow tools function, case, inheritance, generics and others tools have strong semantics with good implementations that work well and reduce complexity.

Unfortunately language adoption is not a pure meritocratic affair. Bad languages can stick around for far too long because of external factors. Consider that Ada never had real use outside the DoD when it was shiny and new. That group isn't exactly known for evangelizing. The Rust community has better marketing strategy and has chosen a highly meritocratic approach to language design.

Re:Why you should, actually, rewrite some of it in Rust by lilyball on Wednesday July 12, 2017 @01:33PM (#14754557)
> Heartbleed is a great example. It wasn't caused by an error with how C handles memory or strings or anything else. It was caused by failing to validate untrusted input. Rust isn't going to help you with that.

Yes, it would. In Rust, the server would have crashed when it overran the buffer instead of sending that potentially-secret memory back to the client. Heartbleed is a great example of why rewriting in Rust is good.

Re:Why you should, actually, rewrite some of it in Rust by legulere on Wednesday July 12, 2017 @12:58PM (#14754212)
Heartbleed included memory safety violation. A hand crafted Malloc replacement was used to manage buffers. Uninitialized memory of new buffers was able to be read which allowed the extraction of secrets.

Now the reason why some people claim that Rust would not have stopped it, is that a similar leaky buffer system is possible to be written in Rust. This however is just applicable if you just use byte buffers for everything. At that point you become close to emulation. Also if the system malloc is shit, you just use jemalloc which is the standard for Rust. So there is no need to roll your own malloc replacement in Rust

Re:Why you should, actually, rewrite some of it in Rust by jaas on Wednesday July 12, 2017 @12:31PM (#14753931)
So your argument is that because rust doesn't solve all problems people shouldn't strongly consider replacing C code with it, even though rust avoids entire classes of critical bug types in C?

I happen to like rust, though I would not suggest that it is the only solution to the classes of problems it avoids. I would, however, suggest that people very strongly consider using languages that avoid the problems that rust avoids whenever possible. Like, literally any time you're considering writing C or C++, at least strongly consider rust or another much safer option.

Re:Why you should, actually, rewrite some of it in Rust by atemerev on Wednesday July 12, 2017 @12:42PM (#14754033)
> It was caused by failing to validate untrusted input. Rust isn't going to help you with that.

Really?

Validation and sanitization are the last, not the first line of defense. It is not about erecting barriers, it is about failure modes. All your software components, from core to border, should fail fast, safe and in a predictable way -- the exact opposite of what happens in C.

In any sane programming language (e.g. Java -- not particularly sane, but boring enough) Heartbleed would have resulted, at worst, in OutOfBoundsException or similar, and the only damage would have been the denial of service. And to do bounds checking, you don't need to have garbage collector -- it is the most basic thing the runtime can do, and performance penalty is minimal. Why it is customary to skip this in C/C++, I don't know.

Lack of bounds checking, not pointer arithmetic or allocation lifecycle, is the major source of security issues with existing software.

Re:Why you should, actually, rewrite some of it in Rust by pcwalton on Wednesday July 12, 2017 @02:32PM (#14755201)
> Lack of bounds checking, not pointer arithmetic or allocation lifecycle, is the major source of security issues with existing software.

No, this is not true. Use after free is more pernicious nowadays.

Re:Why you should, actually, rewrite some of it in Rust by iso-8859-1 on Wednesday July 12, 2017 @01:56PM (#14754828)
Bounds checking is not customary because it is more work. It is more work because arrays in C degrade to pointers, which do not know their length. This is because C was designed on a PDP-7 with 8k RAM. Original Pascal had only fixed size arrays/strings and it was a problem.

http://cm.bell-labs.com/who/dmr/chist.html

Re:Why you should, actually, rewrite some of it in Rust by mamcx on Wednesday July 12, 2017 @12:47PM (#14754096)
Sometimes I wonder why developers are so masochist with his tools, and so MUCH AGAINST AUTOMATION.

If a language, for example, don't have NULLs and you need to use Sum Types (like ML or Swift) you have solved FOREVER and FOR ALL THE DEVELOPERS that problem.

But say that just because this is one problem among dozens, then is better FOREVER AND ALL THE DEVELOPERS to stay with the problem?

Instead, why not put as our goals to eliminate all the problems that are possible?

Re:Why you should, actually, rewrite some of it in Rust by erentz on Wednesday July 12, 2017 @01:10PM (#14754317)
Isn't this just the nirvana fallacy? You're basically arguing that because Rust can't solve all security problems, it's not worth using it to solve some security problems, and the better option is the status quo of using languages that expose all problems.
Re:Why you should, actually, rewrite some of it in Rust by pjmlp on Wednesday July 12, 2017 @01:39PM (#14754634)
> If memory safety and correctness was so truly valued above everything else, we'd be seeing a lot more Ada than we do today.

The problem was that many companies had certain problems paying for Ada compilers and rather used the free C compiler delivered with their OS SDK.

Re:Why you should, actually, rewrite some of it in Rust by petters on Wednesday July 12, 2017 @12:06PM (#14753681)
?? Surely Rust would have helped against heartbleed? I mean, some servers were leaking private keys because they sent random segments of memory back to clients.
Re:Why you should, actually, rewrite some of it in Rust by Manishearth on Wednesday July 12, 2017 @12:46PM (#14754086)
It's ... debatable.

Heartbleed implemented their own memory management system (and had a bug in their use of it). This is pretty unusual even in C. It's extremely unusual in Rust, but who's to say that a similar implementation in Rust would come across the same challenges and implement their own memory management too? And write the same bug? Ultimately this kind of system would be unsafe code anyway, so Rust won't help you there. The question is if a Rust programmer would design such a thing (it's very non-Rust-y). The answer is probably "no". However, the same can be said about C programmers and the heartbleed code, so you have a bit of a no-true-scotsman vibe happening here.

So, yes, heartbleed could have happened in Rust too. I do feel it's less likely (Rust more strongly forces you to compartmentalize unsafe abstractions), but all of that is really debatable.

Re:Why you should, actually, rewrite some of it in Rust by youdontknowtho on Wednesday July 12, 2017 @12:57PM (#14754201)
Yeah, the openssl codebase was pretty crazy due to cross platform support over multiple decades...I guess it grew organically and turned into a enough of a mess that the OpenBSD team started the libressl project. There are some pretty good youtube videos about the work that they did.
Re:Why you should, actually, rewrite some of it in Rust by petters on Thursday July 13, 2017 @02:16AM (#14759124)
Thank you for the clarification.
Re:Why you should, actually, rewrite some of it in Rust by gsnedders on Wednesday July 12, 2017 @12:07PM (#14753691)
The problem is they implementing their own memory management on top of the standard primitives; they never sent unallocated memory to the client.
Re:Why you should, actually, rewrite some of it in Rust by the8472 on Wednesday July 12, 2017 @12:41PM (#14754022)
rust can also help you make custom memory management safer, e.g. there are several arena crates which hand out allocations with lifetimes, which means the arenas won't be freed before all references went out of scope. And there also is no pointer arithmetic into the arena, you only interact with individual allocations. I don't know if it would have prevented heartbleed, but it enables 3rd-party allocators to provide the same safety guarantees as the rust standard lib does. Something that cannot be said about C because there are no safety guarantees in C in the first place.
Re:Why you should, actually, rewrite some of it in Rust by klodolph on Wednesday July 12, 2017 @12:44PM (#14754060)
There are some safety guarantees in C, it's just that Rust has more. Rust doesn't guarantee total safety, just like C doesn't mean no safety.
Re:Why you should, actually, rewrite some of it in Rust by thephyber on Wednesday July 12, 2017 @05:24PM (#14756819)
> The reasons provided by this article are insufficient to solely justify a re-write in Rust;

You didn't read the article. He acknowledged that the hyperbolic calls to "IMMEDIATELY REWRITE EVERYTHING IN RUST!!1!!1one" are silly. In bold, the author states:

> What I’m advocating for is much simpler: surgically replace weaker parts but keep most of the project intact.

Which, by the way, is exactly how Mozilla is applying Rust-written rewrites to Firefox (dogfooding their own programming language).

Re:Why you should, actually, rewrite some of it in Rust by jeffdavis on Wednesday July 12, 2017 @04:59PM (#14756634)
Haskell (and any other GC language) has big runtime requirements that rust does not. It's not just about the ABI.

Your argument does apply to Ada, but freeing from the heap in Ada is unsafe, which has made it difficult to use in a safe way for a lot of cases.

Rust really does make an advance in this regard: safety, and no significant runtime requirements.

D and modern C++ might work for disciplined teams, but seem a few steps behind rust safety-wise.

Re:Why you should, actually, rewrite some of it in Rust by Animats on Wednesday July 12, 2017 @03:50PM (#14755990)
Heartbleed came from allowing reads of uninitialized/out of bounds memory. Rust doesn't absolutely prohibit that, but it is an out of bounds memory access error. Python, Javascript, etc. catch that.
Re:Why you should, actually, rewrite some of it in Rust by Ar-Curunir on Wednesday July 12, 2017 @02:31PM (#14755191)
Actually, Rust would just have panicked in the Heartbleed case: you wouldn't have been able to perform an out of bounds memory access without causing a runtime panic.
Re:Why you should, actually, rewrite some of it in Rust by naasking on Wednesday July 12, 2017 @05:10PM (#14756712)
> Heartbleed is a great example. It wasn't caused by an error with how C handles memory or strings or anything else. It was caused by failing to validate untrusted input. Rust isn't going to help you with that.

I think you'll want to check your facts again:

https://tonyarcieri.com/would-rust-have-prevented-heartbleed...