Live data from Hacker News

Rust in the kernel is no longer experimental

lwn.net

721–730 of 853 posts

Re: Rust in the kernel is no longer experimental

#721
post #152

Earlier quoted context omitted.

Why? You can interact with C libraries from Rust just fine.

But you now have more complexity and no extra safety.

That's not really the case. Not all C APIs are inherently unsafe by construction, and I've always appreciated when someone has wrapped a C library and produced two crates:

- a pure binding crate, which exposes the C lib libraries API, and

- a wrapper library that performs some basic improvements

Stuff in the second category typically includes adding Drop impls to resources that need to be released, translating "accepts pointer + len" into "accepts slices" (or vice versa on return), and "check return value of C call and turn it into a Result, possibly with a stringified error".

All of those are also good examples of local reasoning about unsafety. If a C API returns a buffer + size, it's unsafe to turn it into a reference/slice. But if you check the function succeeded, you unsafely make the slice/reference, and return it from a safe function. If it crashes, you've either not upheld the C calls preconditions (your fault, check how to call the C function), or the C code has a bug (not your fault, the bug is elsewhere).

Re: Rust in the kernel is no longer experimental

#722
post #45

Earlier quoted context omitted.

By most accounts the Rust4Linux project has made the kernel less complex by forcing some technical debt to be addressed and bad APIs to be improved.

This made me quite curious, is there a list somewhere of what bad APIs have been removed/improved and/or technical debt that's been addressed? Or if not a list, some notable examples?

I don't know that there's a list, but cases come to mind because they've been controversial.

(Not a Linux hacker, so apologies if I get this wrong)

The filesystem APIs were quite arcane, and in particular whether or not you were allowed to call a C function at a certain point wasn't documented, and relied on experience to know already.

In trying to write idiomatic Rust bindings, the Rust for Linux group asked the filesystems maintainer if they could document these requirements, so that the Rust bindings could enforce as much of them as they could.

The result was... drama.

Re: Rust in the kernel is no longer experimental

#724

Earlier quoted context omitted.

Complexity of Rust is just codifying existing complexity.

I've been working on Rust bindings for a C SDK recently, and the Rust wrapper code was far more complex than the C code it wrapped. I ended up ceding and getting reasonable wrappers by limiting how it can be used, instead of moddeling the C API's full capabilities. There are certainly sound, reasonable models of memory ownership that are difficult or impossible to express with Rust's ownership model. Sure, a differen…

This is ultimately a good example of how to use Rust. You express as much of the API as you can safely, and the rest is unsafe. APIs that can't be safely modelled can still be exposed to Rust & marked unsafe, if they're needed

Re: Rust in the kernel is no longer experimental

#725

Earlier quoted context omitted.

I'd say, that even more than pointer sizes, the idea that a pointer is just a number really needs to die, and is in no way a forward looking decision expected of a modern language. Pointers should at no point be converted into numbers and back as that trips up many assumptions (special runtimes, static/dynamic analysis tools, compiler optimizations). Additionally, I would make it a priority that writing FFIs should b…

C doesn't require convertibility to an integer and recognizes that pointers may have atypical representations. Casting to integer types has always been implementation defined. [u]intptr_t is optional specifically to allow such platforms to claim standard conformance.

I know, but from what you wrote, Rust kinda assumes pointers are ints (because they are the same type as array indices)

So as to not only hate on Rust, I want to remark, that baking in the idea that pointers can be used for arithmetic isn't a good one as well.

Re: Rust in the kernel is no longer experimental

#726

Earlier quoted context omitted.

Afaik despite Rust not having exceptions, panic still unwinds the stack and executes 'drop'-s the same way C++ does, which means the code retains much of the machinery necessary to support exceptions.

The panic_immediate_abort feature should prevent this. build-std is the name of the feature that recompiles the Rust standard libraries with your chosen profile, so the combination of these two features should result in no unwinding code bloat.

Are all crates compatible with this feature?

Re: Rust in the kernel is no longer experimental

#727

Earlier quoted context omitted.

The panic_immediate_abort feature should prevent this. build-std is the name of the feature that recompiles the Rust standard libraries with your chosen profile, so the combination of these two features should result in no unwinding code bloat.

Are all crates compatible with this feature?

It's possible for a crate to assume there will be unwinding, but given the Rust communities general attitude to exceptions it's not common.

By default, all it means is that unwinding the stack doesn't happen, so Drop implementations don't get called. Which _can_ result in bugs, but they're a fairly familiar kind: it's the same kind of fault if a process is aborted (crashes?), and it doesn't get a chance to finalise external resources.

EDIT: to clarify, the feature isn't really something crates have to opt in to support

Re: Rust in the kernel is no longer experimental

#728

Earlier quoted context omitted.

I've been working on Rust bindings for a C SDK recently, and the Rust wrapper code was far more complex than the C code it wrapped. I ended up ceding and getting reasonable wrappers by limiting how it can be used, instead of moddeling the C API's full capabilities. There are certainly sound, reasonable models of memory ownership that are difficult or impossible to express with Rust's ownership model. Sure, a differen…

This is ultimately a good example of how to use Rust. You express as much of the API as you can safely, and the rest is unsafe. APIs that can't be safely modelled can still be exposed to Rust & marked unsafe, if they're needed

That works for functions. For datatypes that are used throughout the API, it does not work so well.

Re: Rust in the kernel is no longer experimental

#729
post #649

Earlier quoted context omitted.

I'm curious why your perspective on Rust as a HW engineer. Hardware does a ton of things - DMA, interrupts, etc. that are not really compatible with Rust's memory model - after all Rust's immutable borrows should guarantee the values you are reading are not aliased by writers and should be staying constant as long as the borrow exists. This is obviously not true when the CPU can either yank away the execution to a di…

I’d like to take a swipe at this Rust has no_std to handle not having an allocator. Tons of things end up being marked “unsafe” in systems/embedded Rust. The idea is you sandbox the unsafeness. Libraries like zero copy are a good example of “containing” unsafe memory accesses in a way that still gets you as much memory safety as possible given the realities of embedded. Tl;dr you don’t get as much safety as higher le…

Dunno. I used to do embedded. A ton of (highly capable) systems have tiny amounts of RAM (like 32kb-128kb). Usually these controllers run a program in an infinite event loop (with perhaps a sleep in the end of the iteration), communication with peripherals is triggered via interrupts. There's no malloc, memory is pre-mapped.

This means:

- All lifetimes are either 'stack' or 'forever'

- Thread safety in the main loop is ensured by disabling interrupts in the critical section - Rust doesn't understand this paradigm (it can be taught to, I'm sure)

- Thread safety in ISRs should also be taught to Rust

- Peripherals read and write to memory via DMA, unbekownst to the CPU

etc.

So all in all, I don't see Rust being that much more beneficial (except for stuff like array bounds checking).

I'm sure you can describe all these behaviors to Rust so that it can check your program, but threading issues are limited, and there's no allocation, and no standard lib (or much else from cargo).

Rust may be a marginally better language than C due to some convenience features, but I feel like there's too much extra work very little benefit.

Re: Rust in the kernel is no longer experimental

#730

Earlier quoted context omitted.

> which is not fully correct. Undefined behavior in unsafe blocks can and will leak into the safe Rust code so there is nothing there about the "local reasoning" or "encapsulation" or "safety invariants". Strictly speaking, that encapsulation enables local reasoning about safety invariants does not necessarily imply that encapsulation guarantees local reasoning about safety invariants. It's always possible to write s…

Yes, but my point is when things blow up how exactly do you know which unsafe block you should look into? From their statement it appears as if there's such a simple correlation between "here's your segfault" and "here's your unsafe block that caused it", and which I believe there isn't, and which is why I said there's no encapsulation, local reasoning etc.

> Yes, but my point is when things blow up how exactly do you know which unsafe block you should look into?

In the most general case, you don't. But again, I think that that rather misses the point the statement was trying to get at.

Perhaps a more useful framing for you would be that in the most general case the encapsulation and local reasoning here is between modules that use unsafe and everything else. In some (many? most?) cases you can further bound how much code you need to look at if/when something goes wrong since not all code in unsafe modules/functions/blocks depend on each other, but in any case the point is that you only need to inspect a subset of code when reasoning about safety invariants and/or debugging a crash.

> From their statement it appears as if there's such a simple correlation between "here's your segfault" and "here's your unsafe block that caused it",

I don't get that sense from the statement at all.

Post reply on HN