Skip to content

Commit 15afb4a

Browse files
asahilinaFabo
authored andcommitted
rust: sync: Replace static LockClassKey refs with a pointer wrapper
We want to be able to handle dynamic lock class creation and using pointers to things that aren't a real lock_class_key as lock classes. Doing this by casting around Rust references is difficult without accidentally invoking UB. Instead, switch LockClassKey to being a raw pointer wrapper around a lock_class_key, which means there is no UB possible on the Rust side just by creating and consuming these objects. The C code also should never actually dereference lock classes, only use their address (possibly with an offset). We still provide a dummy ZST version of this wrapper, to be used when lockdep is disabled. Signed-off-by: Asahi Lina <[email protected]> (cherry picked from commit 1f50256) Signed-off-by: Fabien Parent <[email protected]>
1 parent 31b295a commit 15afb4a

File tree

8 files changed

+44
-16
lines changed

8 files changed

+44
-16
lines changed

rust/kernel/sync.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@ pub use arc::{Arc, ArcBorrow, UniqueArc};
2222
pub use condvar::{new_condvar, CondVar, CondVarTimeoutResult};
2323
pub use lock::mutex::{new_mutex, Mutex};
2424
pub use lock::spinlock::{new_spinlock, SpinLock};
25-
pub use lockdep::LockClassKey;
25+
pub use lockdep::{LockClassKey, StaticLockClassKey};
2626
pub use locked_by::LockedBy;
2727

2828
/// Defines a new static lock class and returns a pointer to it.
2929
#[doc(hidden)]
3030
#[macro_export]
3131
macro_rules! static_lock_class {
3232
() => {{
33-
static CLASS: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
34-
&CLASS
33+
static CLASS: $crate::sync::StaticLockClassKey = $crate::sync::StaticLockClassKey::new();
34+
CLASS.key()
3535
}};
3636
}
3737

rust/kernel/sync/condvar.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ unsafe impl Sync for CondVar {}
103103

104104
impl CondVar {
105105
/// Constructs a new condvar initialiser.
106-
pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self> {
106+
pub fn new(name: &'static CStr, key: LockClassKey) -> impl PinInit<Self> {
107107
pin_init!(Self {
108108
_pin: PhantomPinned,
109109
// SAFETY: `slot` is valid while the closure is called and both `name` and `key` have

rust/kernel/sync/lock.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ unsafe impl<T: ?Sized + Send, B: Backend> Sync for Lock<T, B> {}
114114

115115
impl<T, B: Backend> Lock<T, B> {
116116
/// Constructs a new lock initialiser.
117-
pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self> {
117+
pub fn new(t: T, name: &'static CStr, key: LockClassKey) -> impl PinInit<Self> {
118118
pin_init!(Self {
119119
data: UnsafeCell::new(t),
120120
_pin: PhantomPinned,
@@ -130,7 +130,7 @@ impl<T, B: Backend> Lock<T, B> {
130130
pub fn pin_init<E>(
131131
t: impl PinInit<T, E>,
132132
name: &'static CStr,
133-
key: &'static LockClassKey,
133+
key: LockClassKey,
134134
) -> impl PinInit<Self, E>
135135
where
136136
E: core::convert::From<core::convert::Infallible>,

rust/kernel/sync/lockdep.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,36 @@ use crate::types::Opaque;
99

1010
/// Represents a lockdep class. It's a wrapper around C's `lock_class_key`.
1111
#[repr(transparent)]
12-
pub struct LockClassKey(Opaque<bindings::lock_class_key>);
12+
pub struct StaticLockClassKey(Opaque<bindings::lock_class_key>);
1313

14-
impl LockClassKey {
14+
impl StaticLockClassKey {
1515
/// Creates a new lock class key.
1616
pub const fn new() -> Self {
1717
Self(Opaque::uninit())
1818
}
1919

20+
/// Returns the lock class key reference for this static lock class.
21+
pub const fn key(&self) -> LockClassKey {
22+
LockClassKey(self.0.get())
23+
}
24+
}
25+
26+
// SAFETY: `bindings::lock_class_key` just represents an opaque memory location, and is never
27+
// actually dereferenced.
28+
unsafe impl Sync for StaticLockClassKey {}
29+
30+
/// A reference to a lock class key. This is a raw pointer to a lock_class_key,
31+
/// which is required to have a static lifetime.
32+
#[derive(Copy, Clone)]
33+
pub struct LockClassKey(*mut bindings::lock_class_key);
34+
35+
impl LockClassKey {
2036
pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key {
21-
self.0.get()
37+
self.0
2238
}
2339
}
2440

25-
// SAFETY: `bindings::lock_class_key` is designed to be used concurrently from multiple threads and
26-
// provides its own synchronization.
41+
// SAFETY: `bindings::lock_class_key` just represents an opaque memory location, and is never
42+
// actually dereferenced.
43+
unsafe impl Send for LockClassKey {}
2744
unsafe impl Sync for LockClassKey {}

rust/kernel/sync/no_lockdep.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,25 @@
55
//! Takes the place of the `lockdep` module when lockdep is disabled.
66
77
/// A dummy, zero-sized lock class.
8-
pub struct LockClassKey();
8+
pub struct StaticLockClassKey();
99

10-
impl LockClassKey {
10+
impl StaticLockClassKey {
1111
/// Creates a new dummy lock class key.
1212
pub const fn new() -> Self {
1313
Self()
1414
}
1515

16+
/// Returns the lock class key reference for this static lock class.
17+
pub const fn key(&self) -> LockClassKey {
18+
LockClassKey()
19+
}
20+
}
21+
22+
/// A dummy reference to a lock class key.
23+
#[derive(Copy, Clone)]
24+
pub struct LockClassKey();
25+
26+
impl LockClassKey {
1627
pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key {
1728
core::ptr::null_mut()
1829
}

rust/kernel/sync/poll.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub struct PollCondVar {
8585

8686
impl PollCondVar {
8787
/// Constructs a new condvar initialiser.
88-
pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self> {
88+
pub fn new(name: &'static CStr, key: LockClassKey) -> impl PinInit<Self> {
8989
pin_init!(Self {
9090
inner <- CondVar::new(name, key),
9191
})

rust/kernel/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ impl<T> Opaque<T> {
296296
}
297297

298298
/// Returns a raw pointer to the opaque data.
299-
pub fn get(&self) -> *mut T {
299+
pub const fn get(&self) -> *mut T {
300300
UnsafeCell::get(&self.value).cast::<T>()
301301
}
302302

rust/kernel/workqueue.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ impl<T: ?Sized, const ID: u64> Work<T, ID> {
363363
/// Creates a new instance of [`Work`].
364364
#[inline]
365365
#[allow(clippy::new_ret_no_self)]
366-
pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self>
366+
pub fn new(name: &'static CStr, key: LockClassKey) -> impl PinInit<Self>
367367
where
368368
T: WorkItem<ID>,
369369
{

0 commit comments

Comments
 (0)