lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <0f3bc0e8-5111-4e2f-83b5-36b3aec0cbbd@ralfj.de>
Date: Thu, 27 Feb 2025 19:33:03 +0100
From: Ralf Jung <post@...fj.de>
To: Linus Torvalds <torvalds@...ux-foundation.org>,
 Kent Overstreet <kent.overstreet@...ux.dev>
Cc: Martin Uecker <uecker@...raz.at>, "Paul E. McKenney"
 <paulmck@...nel.org>, Alice Ryhl <aliceryhl@...gle.com>,
 Ventura Jack <venturajack85@...il.com>, Gary Guo <gary@...yguo.net>,
 airlied@...il.com, boqun.feng@...il.com, david.laight.linux@...il.com,
 ej@...i.de, gregkh@...uxfoundation.org, hch@...radead.org, hpa@...or.com,
 ksummit@...ts.linux.dev, linux-kernel@...r.kernel.org,
 miguel.ojeda.sandonis@...il.com, rust-for-linux@...r.kernel.org
Subject: Re: C aggregate passing (Rust kernel policy)

Hi Linus,

On 27.02.25 00:16, Linus Torvalds wrote:
> On Wed, 26 Feb 2025 at 14:27, Kent Overstreet <kent.overstreet@...ux.dev> wrote:
>>
>> This is another one that's entirely eliminated due to W^X references.
> 
> Are you saying rust cannot have global flags?

The way you do global flags in Rust is like this:

static FLAG: AtomicBool = AtomicBool::new(false);

// Thread A
FLAG.store(true, Ordering::SeqCst); // or release/acquire/relaxed

// Thread B
let val = FLAG.load(Ordering::SeqCst);
if val { // or release/acquire/relaxed
   // ...
}
println!("{}", val);

If you do this, the TOCTOU issues you mention all disappear. The compiler is 
indeed *not* allowed to re-load `FLAG` a second time for the `println`.

If you try do to do this without atomics, the program has a data race, and that 
is considered UB in Rust just like in C and C++. So, you cannot do concurrency 
with "*ptr = val;" or "ptr2.copy_from(ptr1)" or anything like that. You can only 
do concurrency with atomics. That's how compilers reconcile "optimize sequential 
code where there's no concurrency concerns" with "give programmers the ability 
to reliably program concurrent systems": the programmer has to tell the compiler 
whenever concurrency concerns are in play. This may sound terribly hard, but the 
Rust type system is pretty good at tracking this, so in practice it is generally 
not a big problem to keep track of which data can be accessed concurrently and 
which cannot.

Just to be clear, since I know you don't like "atomic objects": Rust does not 
have atomic objects. The AtomicBool type is primarily a convenience so that you 
don't accidentally cause a data race by doing concurrent non-atomic accesses. 
But ultimately, the underlying model is based on the properties of individual 
memory accesses (non-atomic, atomic-seqcst, atomic-relaxed, ...).

By using the C++ memory model (in an access-based way, which is possible -- the 
"object-based" view is not fundamental to the model), we can have reliable 
concurrent programming (no TOCTOU introduced by the compiler) while also still 
considering (non-volatile) memory accesses to be entirely "not observable" as 
far as compiler guarantees go. The load and store in the example above are not 
"observable" in that sense. After all, it's not the loads and stores that 
matter, it's what the program does with the values it loads. However, the 
abstract description of the possible behaviors of the source program above 
*does* guarantee that `val` has the same value everywhere it is used, and 
therefore everything you do with `val` that you can actually see (like printing, 
or using it to cause MMIO accesses, or whatever) has to behave in a consistent 
way. That may sound round-about, but it does square the circle successfully, if 
one is willing to accept "the programmer has to tell the compiler whenever 
concurrency concerns are in play". As far as I understand, the kernel already 
effectively does this with a suite of macros, so this should not be a 
fundamentally new constraint.

Kind regards,
Ralf


> 
> That seems unlikely. And broken if so.
> 
>> IOW: if you're writing code where rematerializing reads is even a
>> _concern_ in Rust, then you had to drop to unsafe {} to do it - and your
>> code is broken, and yes it will have UB.
> 
> If you need to drop to unsafe mode just to read a global flag that may
> be set concurrently, you're doing something wrong as a language
> designer.
> 
> And if your language then rematerializes reads, the language is shit.
> 
> Really.
> 
>               Linus


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ