On Fri, Apr 16, 2021 at 02:07:49PM +0100, Wedson Almeida Filho wrote: > On Fri, Apr 16, 2021 at 01:24:23PM +0200, Peter Zijlstra wrote: > > int perf_event_task_enable(void) > > { > > + DEFINE_MUTEX_GUARD(event_mutex, ¤t->perf_event_mutex); > > There is nothing in C forcing developers to actually use DEFINE_MUTEX_GUARD. So > someone may simply forget (or not know that they need) to lock > current->perf_event_mutex and directly access some field protected by it. This > is unlikely to happen when one first writes the code, but over time as different > people modify the code and invariants change, it is possible for this to happen. > > In Rust, this isn't possible: the data protected by a lock is only accessible > when the lock is locked. So developers cannot accidentally make mistakes of this > kind. And since the enforcement happens at compile time, there is no runtime > cost. > > This, we believe, is fundamental to the discussion: we agree that many of these > idioms can be implemented in C (albeit in this case with a compiler extension), > but their use is optional, people can (and do) still make mistakes that lead to > vulnerabilities; Rust disallows classes of mistakes by construction. Does this also not prohibit constructs where modification must be done while holding two locks, but reading can be done while holding either lock? That's a semi common scheme in the kernel, but not something that's expressible by, for example, the Java sync keyword. It also very much doesn't work for RCU, where modification must be done under a lock, but access is done essentially lockless. I would much rather have a language extention where we can associate custom assertions with variable access, sorta like a sanitizer: static inline void assert_foo_bar(struct foo *f) { lockdep_assert_held(&f->lock); } struct foo { spinlock_t lock; int bar __assert__(assert_foo_bar); }; Such things can be optional and only enabled for debug builds on new compilers. > Another scenario: suppose within perf_event_task_enable you need to call a > function that requires the mutex to be locked and that will unlock it for you on > error (or unconditionally, doesn't matter). How would you do that in C? In Rust, > there is a clean idiomatic way of transferring ownership of a guard (or any > other object) such that the previous owner cannot continue to use it after > ownership is transferred. Again, this is enforced at compile time. I'm happy to > provide a small example if that would help. C does indeed not have the concept of ownership, unlike modern C++ I think. But I would much rather see a C language extention for that than go Rust. This would mean a far more agressive push for newer C compilers than we've ever done before, but at least it would all still be a single language. Convertion to the new stuff can be done gradually and where it makes sense and new extentions can be evaluated on performance impact etc.