Re: [TECH TOPIC] Rust for Linux

Miguel Ojeda
2021-07-09T16:02:52Z

On Fri, Jul 9, 2021 at 12:02 PM Marco Elver <elver@google.com> wrote:
>
> I think the main point was about the combination of sanitizers paired
> with fuzzers like syzkaller.

Yes, and my reply was that compile-time detection of bugs is way, way
better than runtime detection + relying on being lucky enough to hit
the bug via testing and/or fuzzing.

> I sincerely hope that not too much trust will be put into Rust-only
> dynamic analysis via something like Miri (for the unsafe parts). For the
> (...)

I never claimed that we should blindly trust unsafe code written in
Rust, nor that we should only perform Rust-only dynamic analysis.
Quite the opposite: I mentioned there is already tooling around it
precisely because we need as much of it as possible.

Put another way: the topic is "what Rust buys us", not "what unsafe
Rust buys us". That is, the goal is writing abstractions in a way that
we maximize the amount of safe Rust code for modules etc. But,
obviously, the Rust abstractions that deal with unsafe code (e.g.
calling C) need to be as carefully reviewed and analyzed as C code is
-- nobody claimed otherwise.

> It is very likely that if the Rust portion is analyzed alone, be it
> statically or dynamically, that there will remain undiscovered bugs due
> to improper abstractions between C and Rust. While I fully see that

Definitely, but there are some things that are amenable to be analyzed
on their own. For instance, for data structures written in pure Rust,
Miri is a powerful tool we should be using right away.

> Rust's static guarantees are strong for safe code, I'm pragmatic and

Note that even within the unsafe subset there are some benefits over
C, such as the borrow checker (it is still enabled in unsafe code),
pattern matching and type system in general (e.g. like the
`Option`/`Result` example a few emails above about being unable to
mistakenly use its contents if there are none; that you can create
types that enforce invariants, that it is stronger overall than
C's...), etc.

It also has some downsides, though: the rules one needs to abide by in
unsafe code are different than C's (e.g. due to new concepts like
references), and thus one should be careful about conflating
assumptions.

Side-note: our coding guidelines enforce that every `unsafe` block
must be documented with a proof of why such block is sound. Same for
invariants that a type holds. Moreover, we require all public APIs to
be documented, etc. This is a way of saying that, even for unsafe
code, we are trying to be stricter than the C side.

> just do not believe those building the safe abstractions from unsafe
> code will not make mistakes nor will those abstractions shield from
> changed behaviour on the C side that directly affects safety of the Rust
> abstraction.

Again, please note we never claimed anything like that.

It is the opposite: we want to use Rust precisely because we want to
be able to statically enforce as much as we can -- that is, maximizing
the amount of safe code.

> Not only will Rust integration with K*SANs be required to catch early
> bugs in the abstractions, but also be necessary to catch e.g.
> use-after-frees in Rust code where C code freed the memory erroneously,
> or data races between Rust and C code.

It might be possible to eliminate some classes of bugs if we avoid
mixing C and Rust too much.

For instance, if we have a model where we allow the Rust side to
manage ownership of some objects (instead of being forced to always go
through the C APIs), then we may be able to statically guarantee more
things and further maximize the amount of safe code, in particular in
modules -- which is why I raised the question earlier.

Cheers,
Miguel