summaryrefslogtreecommitdiff
path: root/rust/kernel/device.rs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-01-24 10:13:22 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2026-01-24 10:13:22 -0800
commit5dbeeb268b63ea2d9795b3e5e8ffb48c236f5bb0 (patch)
tree56ec07e5dc3759334915e80ed2234a5e18f448b1 /rust/kernel/device.rs
parent12a0094839d095e6cfd23dc5f5336d260a363331 (diff)
parenta995fe1a3aa78b7d06cc1cc7b6b8436c5e93b07f (diff)
Merge tag 'driver-core-6.19-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core
Pull driver core fixes from Danilo Krummrich: - Always inline I/O and IRQ methods using build_assert!() to avoid false positive build errors - Do not free the driver's device private data in I2C shutdown() avoiding race conditions that can lead to UAF bugs - Drop the driver's device private data after the driver has been fully unbound from its device to avoid UAF bugs from &Device<Bound> scopes, such as IRQ callbacks * tag 'driver-core-6.19-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: rust: driver: drop device private data post unbind rust: driver: add DriverData type to the DriverLayout trait rust: driver: add DEVICE_DRIVER_OFFSET to the DriverLayout trait rust: driver: introduce a DriverLayout trait rust: auxiliary: add Driver::unbind() callback rust: i2c: do not drop device private data on shutdown() rust: irq: always inline functions using build_assert with arguments rust: io: always inline functions using build_assert with arguments
Diffstat (limited to 'rust/kernel/device.rs')
-rw-r--r--rust/kernel/device.rs20
1 files changed, 11 insertions, 9 deletions
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index 71b200df0f40..031720bf5d8c 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -232,30 +232,32 @@ impl Device<CoreInternal> {
///
/// # Safety
///
- /// - Must only be called once after a preceding call to [`Device::set_drvdata`].
/// - The type `T` must match the type of the `ForeignOwnable` previously stored by
/// [`Device::set_drvdata`].
- pub unsafe fn drvdata_obtain<T: 'static>(&self) -> Pin<KBox<T>> {
+ pub(crate) unsafe fn drvdata_obtain<T: 'static>(&self) -> Option<Pin<KBox<T>>> {
// SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) };
// SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
unsafe { bindings::dev_set_drvdata(self.as_raw(), core::ptr::null_mut()) };
+ if ptr.is_null() {
+ return None;
+ }
+
// SAFETY:
- // - By the safety requirements of this function, `ptr` comes from a previous call to
- // `into_foreign()`.
+ // - If `ptr` is not NULL, it comes from a previous call to `into_foreign()`.
// - `dev_get_drvdata()` guarantees to return the same pointer given to `dev_set_drvdata()`
// in `into_foreign()`.
- unsafe { Pin::<KBox<T>>::from_foreign(ptr.cast()) }
+ Some(unsafe { Pin::<KBox<T>>::from_foreign(ptr.cast()) })
}
/// Borrow the driver's private data bound to this [`Device`].
///
/// # Safety
///
- /// - Must only be called after a preceding call to [`Device::set_drvdata`] and before
- /// [`Device::drvdata_obtain`].
+ /// - Must only be called after a preceding call to [`Device::set_drvdata`] and before the
+ /// device is fully unbound.
/// - The type `T` must match the type of the `ForeignOwnable` previously stored by
/// [`Device::set_drvdata`].
pub unsafe fn drvdata_borrow<T: 'static>(&self) -> Pin<&T> {
@@ -271,7 +273,7 @@ impl Device<Bound> {
/// # Safety
///
/// - Must only be called after a preceding call to [`Device::set_drvdata`] and before
- /// [`Device::drvdata_obtain`].
+ /// the device is fully unbound.
/// - The type `T` must match the type of the `ForeignOwnable` previously stored by
/// [`Device::set_drvdata`].
unsafe fn drvdata_unchecked<T: 'static>(&self) -> Pin<&T> {
@@ -320,7 +322,7 @@ impl Device<Bound> {
// SAFETY:
// - The above check of `dev_get_drvdata()` guarantees that we are called after
- // `set_drvdata()` and before `drvdata_obtain()`.
+ // `set_drvdata()`.
// - We've just checked that the type of the driver's private data is in fact `T`.
Ok(unsafe { self.drvdata_unchecked() })
}