Hacker News new | ask | show | jobs
by nullc 1091 days ago
In security software like sudo you could argue that nearly all bugs are security bugs. But there are plenty of bugs in non-primarily-security software where it's really hard to argue that there is any security implication.

In any case the reason for the figure is because when there is a buffer overflow that allows overwriting the stack its almost always a security bug because it usually allows untrusted input to make the program do anything. So of all the kinds of bugs a program can have the memory safety ones are usually security bugs, while other logic bugs may or may not have meaningful security implications.

In a suid program that is designed to launch other programs (e.g. sudo), significant logic bugs are very likely to have security implications too.

This is supported by sudo's CVE list-- the vast majority appear to be logic bugs with no memory safety involvement. One argument made for rust is that with memory safety "in the bag" developer time can be better invested in other areas. But it isn't safe to assume that: Rust is a very different language and other properties of it such as its far greater complexity than C may make logic bugs more likely. As far as I know the defect rate in rust software has never been seriously studied.

It would be a huge relief if there were some serious analysis that could provide some confidence that rust wouldn't make the software quality situation worse. Especially since I'm not convinced that trading memory safety bugs for other bugs alone would be an improvement: At least memory safety flaws are always bugs, so when valgrind, memcheck, stack protector, etc tell us about them during testing or formal methods tell us they exist (which hardly can exist for rust given that the language isn't even formally specified) we always know we have an issue. With general logic bugs it's much harder to be confident that a behavior is a bug.

And, of course, memory safety issues can arise in rust, due to compiler/library bugs or because other restrictions or performance issues have caused users to use unsafe or depend on external library code... so it's unclear how much we can really say that memory safety is in-the-bag. I think to be confident that a critical piece of rust code lacks memory safety bugs we still must test comprehensively, including with fuzzing and we must review its dependencies which are almost always far far far far worse than in C (creating a whole issue for sneaking in bad code).

Informally, my experience with software written in Rust is that it is far more likely to crash (panic) on the spot when I attempt to use it than software written in C-- usually because the author just hasn't bothered with error handling due of some mixture of the language making it somewhat harder to do, out of a culture that doesn't regard code that panics unexpectedly as shoddy work (because unlike a crash in C, it's unlikely to be the sign of a potential vulnerability), or in some cases because the goal was just "rewrite in rust" and the programmer didn't take much care or pride in their work or lacked the subject matter expertise to do it competently.

It's heartening to see this effort has a test suite-- Of course (AFAIK) sudo doesn't have one itself but arguably sudo's test suite is the decades of use it's had in production. A newly written program has a lot more need for a test suite than an established one.

I think rust programs are more likely to have some amount of tests compared to really old free software, but usually not enough to compensate for their newness.

1 comments

> It's heartening to see this effort has a test suite

A test suite which sudo (here named "ogsudo" although I'm not sure how "gangsta" sudo really is) failed, and as a result sudo's authors had to fix sudo as described in the article we're discussing right ?

> Informally, my experience with software written in Rust is that it is far more likely to crash (panic) on the spot when I attempt to use it than software written in C

Sure, in the C when the author wrote no error handling, it just presses on. Is its internal state now incoherent? Who cares, error handling is for pussies, YOLO. In the Rust it panics. I'd argue that for many cases, including sudo, the panic is much better though still not the ideal outcome of course.

The canonical "Hello, world" program in C and in Rust when given a stdout that claims to be full behaves differently. In C it just exits successfully. Sure, it couldn't actually output the "Hello, world" message, but who checks errors anyway? In Rust it panics, nobody told it how to handle the condition where the output device is full.

> A test suite which sudo (here named "ogsudo" although I'm not sure how "gangsta" sudo really is) failed, and as a result sudo's authors had to fix sudo as described in the article we're discussing right ?

Yup which is table stakes, as the original software didn't have tests (but did have decades of use in production, which is why it has less need for tests than the rewrite).

> Sure, in the C when the author wrote no error handling, it just presses on. Is its internal state now incoherent? Who cares, error handling is for pussies, YOLO. I'd argue that for many cases, including sudo, the panic is much better though still not the ideal outcome of course.

My concern there is that because bad things happen the C program has the error handling, while in rust it may be "don't handle that case? who cares? rust is safe(tm)".

It's not necessarily the case that both are yolo. I'm sure you've heard of risk compensation. https://en.wikipedia.org/wiki/Risk_compensation

The kind of experience I've had with rust code isn't a case where the c-analog is yolo. You just don't expect widely used C code to crash on some command-line argument misuse or when a file is missing, it's not entirely unheard of but it's not common. In my experience it's extremely common in rustlandia. In that sense, rust culturally has really managed to give me a very strong yolo vibe.

"It can just panic" is no so good when the code is in a library that called from the motor controller for a forklift holding a pallet over your head. ... and in plenty of other less drastic situations.

I agree for sudo most of the time panicing is probably not directly unsafe (though it might produce an outage that causes harm). For software that deals with more complex external state, panicing can still be pretty bad-- like leaving the system in a vulnerable state, leaving confidential information laying around, etc. There are plenty of examples where a simple DOS attack can be used to compromise a system, e.g. DOS a master system to cause a fall over to a slave.

> no so good when the code is in a library that called from the motor controller for a forklift holding a pallet over your head

There should be a mechanical fail safe. The Therac-25's first important difference from prior hardware was that they removed the physical fail safes because hey, nobody will write a program that's incorrect. Yes they will, and it killed people - so stop designing hardware which assumes unreasonable things about software. With an appropriate fail safe if the code panics, the forklift locks up, maybe there's some sort of mechanical reset needed - this is annoying but nobody is dead.

When the firmware in your elevator freaks out, which isn't even a rare occurrence, nobody dies because the hardware people don't trust that firmware. If you let the firmware control it directly, you'd be lucky if anybody used them because they'd be too dangerous. I've watched Third Year undergraduates in electronics learning with (toy) elevators how to write real time software and they were not good at this. The toys were designed so that they weren't damaged when (not if, when) the students smashed the elevator into the top or bottom of the shaft and still kept the motors running.

> My concern there is that because bad things happen the C program has the error handling,

The example we just looked at is common, and in fact the C program doesn't have error handling, it's just ignoring the error because caring about errors is more trouble in C so why bother.

> The kind of experience I've had with rust code isn't a case where the c-analog is yolo

You're going to have to give a lot more details. It's so easy to YOLO in C that it's harder to think of cases you can't just YOLO than cases where you can. C loves functions where if your inputs are invalid you get invalid outputs, which you can then blindly supply to another function where likewise the invalid inputs result in invalid outputs. YOLO all the way.

On mechanical fail safes, they're sometimes impossible, wildly expensive, or simply less safe. In some devices the safe region is a complex polytope defined over a dozen degrees of freedom and may not even be static.

Perhaps for cases where someone will literally be squished when it fails you can draw a bright line rule, but you can turn the safety requirements down some-- instead of being crushed they might just lose a finger, or a million dollar float glass batch will be lost. At some point the risk isn't worth the elaborate hardware failsafe and software will be all you've got. There really isn't a safe threshold in any case: maybe it's just a word processor but its failure costs someone days of work and leads to their suicide. Software reliability matters.

Panicing on exceptional situations is often only slightly more acceptable than crashing or corrupting in other ways (and sometimes less, commonly the corruption is inconsequential).

> caring about errors is more trouble in C

That hasn't matched my experience. YMMV I guess. It's my experience that it's the exception rather than the rule that rust programs won't just panic instead of handling errors sensibly, in particularly because wrapping types to express failure and explicitly handling it along with all the required lifetime management adds a lot of complexity.

> here named "ogsudo" although I'm not sure how "gangsta" sudo really is

It's a joke.