zlacker

[return to "“Rust is safe” is not some kind of absolute guarantee of code safety"]
1. jmilli+Fb[view] [source] 2022-10-02 15:34:06
>>rvz+(OP)
As usual HN comments react to the headline, without reading the content.

A lot of modern userspace code, including Rust code in the standard library, thinks that invariant failures (AKA "programmer errors") should cause some sort of assertion failure or crash (Rust or Go `panic`, C/C++ `assert`, etc). In the kernel, claims Linus, failing loudly is worse than trying to keep going because failing would also kill the failure reporting mechanisms.

He advocates for a sort of soft-failure, where the code tells you you're entering unknown territory and then goes ahead and does whatever. Maybe it crashes later, maybe it returns the wrong answer, who knows, the only thing it won't do is halt the kernel at the point the error was detected.

Think of the following Rust API for an array, which needs to be able to handle the case of a user reading an index outside its bounds:

  struct Array<T> { ... }
  impl<T> Array<T> {
    fn len(&self) -> usize;

    // if idx >= len, panic
    fn get_or_panic(&self, idx: usize) -> T;

    // if idx >= len, return None
    fn get_or_none(&self, idx: usize) -> Option<T>;

    // if idx >= len, print a stack trace and return
    // who knows what
    unsafe fn get_or_undefined(&self, idx: usize) -> T;
  }
The first two are safe by the Rust definition, because they can't cause memory-unsafe behavior. The second two are safe by the Linus/Linux definition, because they won't cause a kernel panic. If you have to choose between #1 and #3, Linus is putting his foot down and saying that the kernel's answer is #3.
◧◩
2. layer8+0d[view] [source] 2022-10-02 15:41:34
>>jmilli+Fb
Please correct me if I’m wrong, but Rust also has no built-in mechanism to statically determine “this code won’t ever panic”, and thus with regards to Linux kernel requirements isn’t safer in that aspect than C. To the contrary, Rust is arguably less safe in that aspect than C, due to the general Rust practice of panicking upon unexpected conditions.
◧◩◪
3. pornel+ze[view] [source] 2022-10-02 15:49:45
>>layer8+0d
Lack of a non-hacky no-panic guarantee is a pain. That would be like a no-segfault guarantee in C.

But Rust's situation is still safer, because Rust can typically prevent more errors from ever becoming a run-time issue, e.g. you may not even need to use array indexing at all if you use iterators. You have a guarantee that references are never NULL, so you don't risk nullptr crash, etc.

Rust panics are safer, because they reliably happen instead of an actually unsafe operation. Mitigations in C are usually best-effort and you may be lucky/unlucky to silently corrupt memory.

Panics are a problem for uptime, but not for safety (in the sense they're not exploitable for more than DoS).

In the long term crashing loud and clear may be better for reliability. You shake out all the bugs instead of having latent issues that corrupt your data.

◧◩◪◨
4. hegels+8l[view] [source] 2022-10-02 16:25:53
>>pornel+ze
I think you're missing the point Linus made. Panicking is safer from a memory safety perspective, but it's not from a kernel perspective. You'll lose all the file changes that are not saved, you'll risk having disk written in a bad state which can be catastrophic, etc.
◧◩◪◨⬒
5. zozbot+Xt[view] [source] 2022-10-02 17:12:08
>>hegels+8l
Panic in Rust need not equate to a literal kernel panic. It can call an oops handler, which might manage to keep the system operational depending on where the failure occurred.
◧◩◪◨⬒⬓
6. hegels+3E1[view] [source] 2022-10-03 01:32:36
>>zozbot+Xt
As far as I'm aware there's no way to reliably catch all panics. catch_unwind does not catch all panics. Handlers don't stop the program from terminating abruptly.
[go to top]