summaryrefslogtreecommitdiff
path: root/rust/kernel/platform.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/platform.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/platform.rs')
-rw-r--r--rust/kernel/platform.rs27
1 files changed, 18 insertions, 9 deletions
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index ed889f079cab..35a5813ffb33 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -26,13 +26,22 @@ use core::{
/// An adapter for the registration of platform drivers.
pub struct Adapter<T: Driver>(T);
-// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
+// SAFETY:
+// - `bindings::platform_driver` is a C type declared as `repr(C)`.
+// - `T` is the type of the driver's device private data.
+// - `struct platform_driver` embeds a `struct device_driver`.
+// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.
+unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> {
+ type DriverType = bindings::platform_driver;
+ type DriverData = T;
+ const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);
+}
+
+// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
// a preceding call to `register` has been successful.
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
- type RegType = bindings::platform_driver;
-
unsafe fn register(
- pdrv: &Opaque<Self::RegType>,
+ pdrv: &Opaque<Self::DriverType>,
name: &'static CStr,
module: &'static ThisModule,
) -> Result {
@@ -55,12 +64,12 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
(*pdrv.get()).driver.acpi_match_table = acpi_table;
}
- // SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
+ // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) })
}
- unsafe fn unregister(pdrv: &Opaque<Self::RegType>) {
- // SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
+ unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) {
+ // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
unsafe { bindings::platform_driver_unregister(pdrv.get()) };
}
}
@@ -92,9 +101,9 @@ impl<T: Driver + 'static> Adapter<T> {
// SAFETY: `remove_callback` is only ever called after a successful call to
// `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called
// and stored a `Pin<KBox<T>>`.
- let data = unsafe { pdev.as_ref().drvdata_obtain::<T>() };
+ let data = unsafe { pdev.as_ref().drvdata_borrow::<T>() };
- T::unbind(pdev, data.as_ref());
+ T::unbind(pdev, data);
}
}