Re: Can the Kernel Concurrency Sanitizer Own Rust Code?
flat view
From: Miguel Ojeda <hidden>
Date: 2021-10-08 21:32:48
On Fri, Oct 8, 2021 at 7:40 PM Paul E. McKenney [off-list ref] wrote:
Just in case there is lingering confusion, my purpose in providing an example from the field of safety-critical systems was nothing more or less than to derive an extreme lower bound for the expected bug rate in
Yes, safety-critical systems usually have lower rate of bugs, but they can actually be very buggy as long as they comply with requirements... :P
production software. Believe me, there is no way that I am advocating use of Rust as it currently exists for use in safety-critical systems! Not that this will necessarily prevent such use, mind you! ;-)
Well, people are already working on bringing Rust to safety-critical domains! :) In any case, for example, DO-178 describes the software development process, but does not require a particular language to be used even if a particular project following that standard may do so.
From what I have seen, people prevent unsafe Rust code from introducing UB by adding things, for example assertions and proofs of correctness. Each and every one of those added things have a non-zero probability of themselves containing bugs or mistakes. Therefore, a Rust program containing a sufficiently large quantity of unsafe code will with high probability invoke UB. Hopefully, a much lower UB-invocation probability than a similar quantity of C code, but nevertheless, a decidedly non-zero probability. So what am I missing here?
Rust does not guarantee UB-freedom in an absolute way -- after all, there is unsafe code in the standard library, we have unsafe code in the kernel abstractions, the compiler may have bugs, the hardware may misbehave, there may be a single-event upset, etc. However, the key is to understand Rust as a way to minimize unsafe code, and therefore minimize the chances of UB happening. Let's take an example: we need to dereference a pointer 10 times in a driver. And 10 more times in another driver. We may do it writing `unsafe` many times in every driver, and checking that every single usage does not trigger UB. This is fine, and we can write Rust code like that, but is not buying us much. And, as you say, if we keep accumulating those dereferences, the probability of a mistake grows and grows. Instead, we could write an abstraction that provides a safe way to do the same thing. Then we can focus our efforts in checking the abstraction, and reuse it everywhere, in all drivers. That abstraction does not guarantee there is no UB -- after all, it may have a bug, or someone else may corrupt our memory, or the hardware may have a bug, etc. However, that abstraction is promising that, as long as there is no other UB subverting it, then it will not allow safe code to create UB. Therefore, as a driver writer, as long as I keep writing only safe code, I do not have to care about introducing UB. As a reviewer, if the driver does not contain unsafe code, I don't need to worry about any UB either. If UB is actually introduced, then the bug is in the abstractions, not the safe driver. Thus we are reducing the amount of places where we risk using a potentially-UB operation. Cheers, Miguel