Re: The Case for Rust (in the base system)

From: David Chisnall <theraven_at_FreeBSD.org>
Date: Wed, 31 Jan 2024 15:50:40 UTC
On 31 Jan 2024, at 15:07, Tomoaki AOKI <junchoon@dec.sakura.ne.jp> wrote:
> 
> First of all, NO MEMORY-SAFE language can write codes using volatile
> memory objects, most notably, memory-mapped I/O and/or DMA driver.

The first half of that is obvious nonsense.  Memory-mapped I/O is not intrinsically unsafe, from a memory-safety perspective.  Even Java has volatile objects and Sun Labs used Java for device drivers twenty years ago.  Having a memory-safe interface for MMIO is helpful.

With another hat, I am the maintainer of CHERIoT RTOS, which uses hardware-enforced memory safety for all code, including RTOS code.  All of our drivers do direct MMIO and are memory safe.

DMA is in the category of things that I class as real systems programming because it sits below the level of the language abstract machine and so *is* able to violate the guarantees.  Even in C; however, the busdma framework tries to make this safe: you are not *supposed to* DMA to and from arbitrary memory.  A strong type system can enforce this.

> I formerly thought "Rust should NOT be able to write one by itself
> only, as Rust guys states it's memory-safe". But I huppened to know
> "unsafe" keyword to allowing such a thing.

Correct, for things that are real systems programming tasks, you need to poke holes in Rust’s abstract machine via the unsafe keyword.  These come with an implicit contract that *you* are now responsible for enforcing those rules at the boundary.  For a DMA interface, for example, a Rust equivalent of the busdma framework would provide objects that encapsulate valid DMA mappings whose lifetime manages IOMMU entries.  These would be passed into unsafe blocks for DMA operations.  Within those blocks, you could still violate memory safety, but the code review required to ensure that you don’t is entirely local reasoning.

> So I come to consider Rust as non-memory-safe. Evil programmer CAN
> ABUSE THE MECHANISM. Recall what happened to Linux kernel by UMN. [1]
> [2]

A malicious programmer, whose code is not reviewed properly or who manages to sneak in bad code, can break out of the type system for Rust.  In contrast, a C programmer whose attention drifts for a few seconds while typing can do the same thing.

> Even using Rust, memory safety is ON HUMAN. Rust should have NOT
> introducing such a functionality and let them be kept on C and/or
> assembler codes to be called. This way, C/assembler could have been
> focused upon left C/assembler codes only about memory-safety.

I don’t understand the rationale here.  FFI in Rust, due to the tight coupling, needs to be unsafe.  Whether your unsafe language is a subset of Rust or is purely FFI code, it still exists.  If it’s a subset of Rust, then it’s easier to review because it’s in context and can operate over Rust types.

> Yes, there can be memory-mapped I/O devices which completely divide
> addresses it uses for input and output. In such devices, "unsafe"
> keyword should be needed at all IN THEORY, but hardware/firmware bugs
> and intentional backdoors could overrun the buffer on write.

This is specific to MMIO devices *that initiate DMAs*

> Keeping these in mind, Rust would be EASIER to write memory-safe codes
> than C/assembler.

Correct.

David