Re:Rustproofing Linux (Part 1/4 Leaking Addresses) (2023)
by carlmr on Wednesday August 28, 2024 @05:09AM
(#41377541)
I think these are just general pitfalls that happen when you port something.
Also thinking everything is safe from a security perspective because you don't use the keyword `unsafe` seems kind of naive to me. For one safety and security are two separate issues. Also this assumes you really did not understand why Rust has the keyword in the first place and what it's used for.
Obviously Rust can't prevent all logic errors, and doesn't promise to. If you adhere to idiomatic Rust (e.g. using sum types to make impossible states not representable) you'll probably prevent quite a few. But if you port line by line it won't be idiomatic.
Rust does offer a lot of error checking at compile time that you only get at runtime with a combination of ASan, LSan, UBSan, TSan, MSan in C. But it doesn't mean you can stop thinking entirely.
Re:Rustproofing Linux (Part 1/4 Leaking Addresses) (2023)
by smj-edison on Wednesday August 28, 2024 @07:53PM
(#41385688)
Oh for sure! It does take understanding the idioms of the language you're porting to, and rust only guarantees memory safety when (iirc) 1. Being in an interrupt free and linear memory environment, and 2. All unsafe code maintains invariants (XOR mutability, etc). There's some others but I can't think of them off the top of my head.
But, I wouldn't say this article is only about porting in general. It's very specific in using example drivers written for Linux (which is very different than application C) and showing pitfalls _specifically_ when going to rust. For example, in one of the later parts it talks about Rust mutexes, which are RAII. If you lock twice, you'll have a double fetch that can cause a race condition. That's not a general rule of thumb for code porting.
Re:Rustproofing Linux (Part 1/4 Leaking Addresses) (2023)
by tetromino_ on Tuesday August 27, 2024 @04:31PM
(#41372635)
Summary: a naive port of a kernel driver from C to Rust can easily introduce information leak vulnerabilities, which in kernel-style C were automatically prevented by preprocessor trickery.
Re:Rustproofing Linux (Part 1/4 Leaking Addresses) (2023)
by one_even_prime on Tuesday August 27, 2024 @05:33PM
(#41373325)
More like: the Linux kernel re-implementation of Rust "print" has a bug that causes it to not adhere to Linux kernel conventions.
I'd expect that now that the bug has been reported, it'd be fixed by just hashing pointer addresses before printing them.
I also expect that "reimplementing X in a different programming language" introduces logic bugs, like the one above, and that those involved have deemed what they get out of it worth the effort of hashing these sort of bugs long term.
From the kernel pov, all of these bugs are safety issues, so the article authors are surprised the unsafe keyword is not required to introduce them, but from Rust's pov, they are just logic bugs, which safe Rust does not protect against. One of the main challenges those working on Rust in the kernel will have is figuring out how to educate other kernel developers about Rust (what it does and does not protect against, setting the right expectations, etc.). I think these articles are a great step in that direction.
Re:Rustproofing Linux (Part 1/4 Leaking Addresses) (2023)
by Tuna-Fish on Tuesday August 27, 2024 @07:03PM
(#41374194)
> article authors are surprised the unsafe keyword is not required
The often surprising part of raw pointers to system programmers newly dabbling in Rust is that every operation on them is safe, except for deref. You can freely take addresses and do pointer arithmetic on them without having to deal with unsafe, and only have to tell the compiler that you know what you are doing when you either load or store something through them.
Re:Rustproofing Linux (Part 1/4 Leaking Addresses) (2023)
by akira2501 on Wednesday August 28, 2024 @05:21AM
(#41377628)
The El Camino was supposed to be an improvement. A combination between a car and a truck. It turns out it was not an improvement. It's better to just have a car or a truck. Cutting them in half and then weirdly stitching the two parts together creates a Frankenstein nightmare of bad engineering. Which even the best explanations on the planet can't fix.
Re:Rustproofing Linux (Part 1/4 Leaking Addresses) (2023)
by Wowfunhappy on Wednesday August 28, 2024 @06:57AM
(#41378169)
^ If I can try to steel man this, it may be that having two different languages is simply worse than having one, even if the one language is non-optimal. Sure, if you were starting Linux today you wouldn't choose C, and hopefully Linux won't be the last operating system to ever exist, and the next one can use Rust. But Linux uses C, and no one is contemplating a full rewrite, so it's best to stick with C.
I have no idea if this is true, I am very much not a kernel developer.
Re:Rustproofing Linux (Part 1/4 Leaking Addresses) (2023)
by sundarurfriend on Wednesday August 28, 2024 @01:23AM
(#41376221)
A higher level summary: A lot of institutional knowledge has been embedded into the C code over the years, sometimes in subtle ways, and a naive port to Rust can introduce security vulnerabilities if some of these subtleties get overlooked.
Re:Rustproofing Linux (Part 1/4 Leaking Addresses) (2023)
by iknowstuff on Tuesday August 27, 2024 @09:20PM
(#41375079)
This article is written ass backwards.
Should start with the last part which explains that they have the WritableToBytes trait - implementing it has to be marked unsafe because it has an explicit invariant: no padding.
When it’s not implemented on a type, you can’t pass it to the writer unless you do what they did and use two pointer casts within an unsafe block. So you don’t do that. Instead, you write the initialized parts of the struct individually. They’ll probably add a derive macro to make implementing something a safe equivalent of the trait trivial.
Re:Rustproofing Linux (Part 1/4 Leaking Addresses) (2023)
by fulafel on Wednesday August 28, 2024 @04:26AM
(#41377292)
The hidden unsafety in the pr_ macros (here under the heading Bonus Point for no unsafe) was interesting. I wonder if there's anything the compiler could do to detect this kind surprise-unsafety happening, for example a no-unsafe assertion in a source file.
Also, why doesn't the compiler know by default that the stack allocated struct is "MaybeUninit"?
Also thinking everything is safe from a security perspective because you don't use the keyword `unsafe` seems kind of naive to me. For one safety and security are two separate issues. Also this assumes you really did not understand why Rust has the keyword in the first place and what it's used for.
Obviously Rust can't prevent all logic errors, and doesn't promise to. If you adhere to idiomatic Rust (e.g. using sum types to make impossible states not representable) you'll probably prevent quite a few. But if you port line by line it won't be idiomatic.
Rust does offer a lot of error checking at compile time that you only get at runtime with a combination of ASan, LSan, UBSan, TSan, MSan in C. But it doesn't mean you can stop thinking entirely.
But, I wouldn't say this article is only about porting in general. It's very specific in using example drivers written for Linux (which is very different than application C) and showing pitfalls _specifically_ when going to rust. For example, in one of the later parts it talks about Rust mutexes, which are RAII. If you lock twice, you'll have a double fetch that can cause a race condition. That's not a general rule of thumb for code porting.
I'd expect that now that the bug has been reported, it'd be fixed by just hashing pointer addresses before printing them.
I also expect that "reimplementing X in a different programming language" introduces logic bugs, like the one above, and that those involved have deemed what they get out of it worth the effort of hashing these sort of bugs long term.
From the kernel pov, all of these bugs are safety issues, so the article authors are surprised the unsafe keyword is not required to introduce them, but from Rust's pov, they are just logic bugs, which safe Rust does not protect against. One of the main challenges those working on Rust in the kernel will have is figuring out how to educate other kernel developers about Rust (what it does and does not protect against, setting the right expectations, etc.). I think these articles are a great step in that direction.
The often surprising part of raw pointers to system programmers newly dabbling in Rust is that every operation on them is safe, except for deref. You can freely take addresses and do pointer arithmetic on them without having to deal with unsafe, and only have to tell the compiler that you know what you are doing when you either load or store something through them.
Why have one class of logic errors when you can have two?
Thinking about my uncle, running Windows 97 in his company.
I have no idea if this is true, I am very much not a kernel developer.
Should start with the last part which explains that they have the WritableToBytes trait - implementing it has to be marked unsafe because it has an explicit invariant: no padding.
When it’s not implemented on a type, you can’t pass it to the writer unless you do what they did and use two pointer casts within an unsafe block. So you don’t do that. Instead, you write the initialized parts of the struct individually. They’ll probably add a derive macro to make implementing something a safe equivalent of the trait trivial.
Also, why doesn't the compiler know by default that the stack allocated struct is "MaybeUninit"?
https://web.archive.org/web/20240828122042/https://research....
A search also provides
https://www.nccgroup.com/us/research-blog/rustproofing-linux...