4 ms·
I need to check the rust parts of the kernel, I presume there is significant amounts of unsafe. Is unsafe Rust a bit better nowadays? I remember a couple of y
by ykonstant 10mo ago
I need to check the rust parts of the kernel, I presume there is significant amounts of unsafe. Is unsafe Rust a bit better nowadays? I remember a couple of years ago people complained that unsafe is really hard to write and very "un-ergonomic".
- jenadine 10mo agoThe idea is that most of the unsafe code to interact with the C API of the kernel is abstracted in the kernel crate, and the drivers themselves should use very little amount of unsafe code, if any.
- IshKebab 10mo agoI don't think unsafe Rust has gotten any easier to write, but I'd also be surprised if there was much unsafe except in the low-level stuff (hard to write Vec without unsafe), and to interface with C which is actually not hard to write. Mostly Rust has been used for drivers so far. Here's the first Rust driver I found: https://github.com/torvalds/linux/blob/2137cb863b8018710315138f40eefcceb8584d1b/drivers/pwm/pwm_th1520.rs https://github.com/torvalds/linux/blob/2137cb863b80187103151... It has one trivial use of `unsafe` - to support Send & Sync for a type - and that is apparently temporary. Everything else uses safe APIs.
- johncolanduoni 10mo agoDrivers are interesting from a safety perspective, because on systems without an IOMMU sending the wrong command to devices can potentially overwrite most of RAM. For example, if the safe wrappers let you write arbitrary data to a PCIe network card’s registers you could retarget a receive queue to the middle of a kernel memory page.
- josephg 10mo ago> if the safe wrappers let you write arbitrary data to a PCIe network card’s registers Functions like that can and should be marked unsafe in rust. The unsafe keyword in rust is used both to say “I want this block to have access to unsafe rust’s power” and to mark a function as being only callable from an unsafe context. This sounds like a perfect use for the latter.
- weebull 10mo agoSo if you're writing a device driver in rust... - Hardware access is unsafe - Kernel interface is unsafe How much remains in the layer in-between that's actually safe?
- viraptor 10mo agoAll logic, all state management, all per-device state machines, all command parsing and translation, all data queues, etc. Look at the examples people posted in other comments.
- josephg 10mo agoYep. Its kind of remarkable just how little unsafe code you often need in cases like this. I ported a C skip list implementation to rust a few years ago. Skip lists are like linked lists, but where instead of a single "next" pointer, each node contains an array of them. As you can imagine, the C code is packed full of fiddly pointer manipulation. The rust port certainly makes use of a fair bit of unsafe code. But the unsafe blocks still make up a surprisingly small minority of the code. Porting this package was one of my first experiences working with rust, and it was a big "aha!" moment for me. Debugging the C implementation was a nightmare, because a lot of bugs caused obscure memory corruption problems. They're always a headache to track down. When I first ported the C code to rust, one of my tests segfaulted. At first I was confused - rust doesn't segfault! Then I realised it could only segfault from a bug in an unsafe block. There were only two unsafe functions it could be, and one obvious candidate. I had a read of the code, and spotted the error nearly immediately. The same bug would probably have taken me hours to fix in C because it could have been anywhere. But in rust I found and fixed the problem in a few minutes.
- viraptor 10mo ago> Functions like that can and should be marked unsafe in rust. That's not how it works. You don't mark them unsafe unless it's actually required for some reason. And even then, you can limit that scope to a line or two in majority of cases. You mark blocks unsafe if you have to access raw memory and there's no way around it.
- School-Cotton 10mo agoIn normal user-mode rust, not running inside the kernel at all, you can open /dev/mem and write whatever you want to any process's memory (assuming you are root). This does not require "unsafe" at all. Another thing you can do from rust without "unsafe": output some buggy source code that invokes UB in a language like C to a file, then shell out to the compiler to compile that file and run it.
- johncolanduoni 10mo agoSure, but those are non-central to what the program is doing. Writing to the wrong register offset and hosing main memory is a thing that happens when developing drivers (though usually it breaks obviously during testing).
- School-Cotton 10mo agoRight, you're not wrong that this is a possible failure mode which Rust's guarantees don't prevent. I'm just pointing out that "your program manipulates the external system in such a way that UB is caused" is outside the scope of Rust's guarantees, and kernel development doesn't fundamentally change that (even though it might make it easier to trigger). Rust's guarantees are only about what the Rust code does; anything else would be hard or impossible to guarantee and Rust doesn't try to do so.
- Cthulhu_ 10mo agoWouldn't that be by design? If it isn't pleasant, people will avoid using it if they can. (but as others pointed out, unsafe should only be used at the 'edges', the vast majority should never need to use unsafe)
- jdub 10mo agounsafe { // this is normal Rust code, you can write as much of it as you like! // (and you can bend some crucial safety rules) // but try to limit and document what you put inside an unsafe block. // then wrap it in a safe interface so no one has to look at it again }