Hacker News new | ask | show | jobs
by bunderbunder 959 days ago
This gets said a lot, but I am coming to believe that the case is overstated. For two reasons:

1. Valgrind exists. It's not perfect, but it does arguably do a pretty good job as long as you're writing modern C. The biggest gap I'm aware of is that it can't really help you with global pre-allocated buffers. But I don't think that any language or tool can effectively protect you from information leakage if you're doing that sort of thing, not even Rust.

2. Memory-safe is not the same thing as secure. Programs written in memory-safe languages are rotten with security vulnerabilities, too. Rust's happening to be a memory-safe language that doesn't use garbage collection does not render it immune to this situation. It has some protections around concurrent usage of data that do add additional safety under certain circumstances (assuming you don't switch them off), but I doubt it's a panacea. I worry, though, that the Rust community's tendency to pitch this stuff as a security panacea could breed a culture of complacency that negates the advantages that Rust does bring to the table for systems programming languages. People tend to take unnecessary risks when they believe they're invincible.

5 comments

> Valgrind exists

You may be right on an infinite frictionless plane, but unfortunately that does not work in real life, cf. e.g. https://msrc.microsoft.com/blog/2019/07/why-rust-for-safe-sy...

> Memory-safe is not the same thing as secure.

And safety belts do not help you if your car is on fire, still it's better to wear it.

The fundamental problem with valgrind is it only looks at what happened, not what could happen. Valgrind is great at making sure you don't have memory safety issues for "normal" inputs, but is basically useless at making sure your code doesn't have memory safety vulnerabilities when fed atypical inputs.
It's true that it doesn't eliminate all bugs in general, but it can completely eliminate buffer overflows for example.

There is no excuse to not at least have bounds checking. This is one of the most basic memory safety problems and it's trivial to prevent.

Just preventing this small issue will prevent a non-trivial fraction of bugs. I don't have sudo's bug list on hand but I wouldn't be surprised if 25% or more are caused by buffer overflows.

So even if it doesn't prevent all logic bugs, it cuts out a pretty big chunk of the bug list.

>assuming you don't switch them off

You can't switch them off.

>Rust community's tendency to pitch this stuff as a security panacea

I've not seen anyone claim this so far.

I’d rather have safety default on with an opt-out, rather than the inverse that C gives you with -Werror -Wall -Weverything -Wyesireallymeanteverything. Compile it again one two different architectures, compile yet another time with clang-tidy and then static analysis with Coverity just to be sure. Run it with valgrind, asan and thread sanitizer. Sprinkle some fuzz testing on top.

Yet you still don’t the same level of confidence as a rust program that may have a small unsafe block in one corner of the code.

From this link:

>It’s important to understand that unsafe doesn’t turn off the borrow checker or disable any other of Rust’s safety checks: if you use a reference in unsafe code, it will still be checked.

Unsafe rust basically just lets you use raw pointers, mutate static variables, use C-style unions, and do FFI calls, but otherwise it's exactly the same, and the safety checks are not in any way disabled.

The main thing is that pointers let you access whatever memory you want, and borrow checking the pointer value itself doesn't prevent this.

I don't think I would describe this as "switching them off", I would describe it as, "using raw pointers" or something along those lines.

I feel pretty good about the fire safety measures at my apartment despite the fact that I own several lighters.
Even unsafe Rust comes with significantly more checks and safety built-in than C.
Many vulnerabilities rely on crafting very particular inputs that trigger memory corruption in programs. Unless you happen to have fed that same input to your program when running it under Valgrind then Valgrind is useless for this case.
> It's not perfect, but it does arguably do a pretty good job as long as you're writing modern C.

There's no such thing as modern C. C code that's written neatly and meticulously looks the same today as it did 30 or 40 years ago, except for language changes such as the move from K&R declarations to function prototypes. C the language hasn't changed since 1989 except for minor things like mixed functions and declarations, the introduction of the long long type, restrict pointers, designated initializers, compound literals, and threads being in the standard library.