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

+209 -74
+2
drivers/base/dd.c
··· 548 548 static void device_unbind_cleanup(struct device *dev) 549 549 { 550 550 devres_release_all(dev); 551 + if (dev->driver->p_cb.post_unbind_rust) 552 + dev->driver->p_cb.post_unbind_rust(dev); 551 553 arch_teardown_dma_ops(dev); 552 554 kfree(dev->dma_range_map); 553 555 dev->dma_range_map = NULL;
+9
include/linux/device/driver.h
··· 85 85 * uevent. 86 86 * @p: Driver core's private data, no one other than the driver 87 87 * core can touch this. 88 + * @p_cb: Callbacks private to the driver core; no one other than the 89 + * driver core is allowed to touch this. 88 90 * 89 91 * The device driver-model tracks all of the drivers known to the system. 90 92 * The main reason for this tracking is to enable the driver core to match ··· 121 119 void (*coredump) (struct device *dev); 122 120 123 121 struct driver_private *p; 122 + struct { 123 + /* 124 + * Called after remove() and after all devres entries have been 125 + * processed. This is a Rust only callback. 126 + */ 127 + void (*post_unbind_rust)(struct device *dev); 128 + } p_cb; 124 129 }; 125 130 126 131
+33 -8
rust/kernel/auxiliary.rs
··· 23 23 /// An adapter for the registration of auxiliary drivers. 24 24 pub struct Adapter<T: Driver>(T); 25 25 26 - // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 26 + // SAFETY: 27 + // - `bindings::auxiliary_driver` is a C type declared as `repr(C)`. 28 + // - `T` is the type of the driver's device private data. 29 + // - `struct auxiliary_driver` embeds a `struct device_driver`. 30 + // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`. 31 + unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> { 32 + type DriverType = bindings::auxiliary_driver; 33 + type DriverData = T; 34 + const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver); 35 + } 36 + 37 + // SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if 27 38 // a preceding call to `register` has been successful. 28 39 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 29 - type RegType = bindings::auxiliary_driver; 30 - 31 40 unsafe fn register( 32 - adrv: &Opaque<Self::RegType>, 41 + adrv: &Opaque<Self::DriverType>, 33 42 name: &'static CStr, 34 43 module: &'static ThisModule, 35 44 ) -> Result { ··· 50 41 (*adrv.get()).id_table = T::ID_TABLE.as_ptr(); 51 42 } 52 43 53 - // SAFETY: `adrv` is guaranteed to be a valid `RegType`. 44 + // SAFETY: `adrv` is guaranteed to be a valid `DriverType`. 54 45 to_result(unsafe { 55 46 bindings::__auxiliary_driver_register(adrv.get(), module.0, name.as_char_ptr()) 56 47 }) 57 48 } 58 49 59 - unsafe fn unregister(adrv: &Opaque<Self::RegType>) { 60 - // SAFETY: `adrv` is guaranteed to be a valid `RegType`. 50 + unsafe fn unregister(adrv: &Opaque<Self::DriverType>) { 51 + // SAFETY: `adrv` is guaranteed to be a valid `DriverType`. 61 52 unsafe { bindings::auxiliary_driver_unregister(adrv.get()) } 62 53 } 63 54 } ··· 96 87 // SAFETY: `remove_callback` is only ever called after a successful call to 97 88 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 98 89 // and stored a `Pin<KBox<T>>`. 99 - drop(unsafe { adev.as_ref().drvdata_obtain::<T>() }); 90 + let data = unsafe { adev.as_ref().drvdata_borrow::<T>() }; 91 + 92 + T::unbind(adev, data); 100 93 } 101 94 } 102 95 ··· 198 187 /// 199 188 /// Called when an auxiliary device is matches a corresponding driver. 200 189 fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> impl PinInit<Self, Error>; 190 + 191 + /// Auxiliary driver unbind. 192 + /// 193 + /// Called when a [`Device`] is unbound from its bound [`Driver`]. Implementing this callback 194 + /// is optional. 195 + /// 196 + /// This callback serves as a place for drivers to perform teardown operations that require a 197 + /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O 198 + /// operations to gracefully tear down the device. 199 + /// 200 + /// Otherwise, release operations for driver resources should be performed in `Self::drop`. 201 + fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) { 202 + let _ = (dev, this); 203 + } 201 204 } 202 205 203 206 /// The auxiliary device representation.
+11 -9
rust/kernel/device.rs
··· 232 232 /// 233 233 /// # Safety 234 234 /// 235 - /// - Must only be called once after a preceding call to [`Device::set_drvdata`]. 236 235 /// - The type `T` must match the type of the `ForeignOwnable` previously stored by 237 236 /// [`Device::set_drvdata`]. 238 - pub unsafe fn drvdata_obtain<T: 'static>(&self) -> Pin<KBox<T>> { 237 + pub(crate) unsafe fn drvdata_obtain<T: 'static>(&self) -> Option<Pin<KBox<T>>> { 239 238 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 240 239 let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) }; 241 240 242 241 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 243 242 unsafe { bindings::dev_set_drvdata(self.as_raw(), core::ptr::null_mut()) }; 244 243 244 + if ptr.is_null() { 245 + return None; 246 + } 247 + 245 248 // SAFETY: 246 - // - By the safety requirements of this function, `ptr` comes from a previous call to 247 - // `into_foreign()`. 249 + // - If `ptr` is not NULL, it comes from a previous call to `into_foreign()`. 248 250 // - `dev_get_drvdata()` guarantees to return the same pointer given to `dev_set_drvdata()` 249 251 // in `into_foreign()`. 250 - unsafe { Pin::<KBox<T>>::from_foreign(ptr.cast()) } 252 + Some(unsafe { Pin::<KBox<T>>::from_foreign(ptr.cast()) }) 251 253 } 252 254 253 255 /// Borrow the driver's private data bound to this [`Device`]. 254 256 /// 255 257 /// # Safety 256 258 /// 257 - /// - Must only be called after a preceding call to [`Device::set_drvdata`] and before 258 - /// [`Device::drvdata_obtain`]. 259 + /// - Must only be called after a preceding call to [`Device::set_drvdata`] and before the 260 + /// device is fully unbound. 259 261 /// - The type `T` must match the type of the `ForeignOwnable` previously stored by 260 262 /// [`Device::set_drvdata`]. 261 263 pub unsafe fn drvdata_borrow<T: 'static>(&self) -> Pin<&T> { ··· 273 271 /// # Safety 274 272 /// 275 273 /// - Must only be called after a preceding call to [`Device::set_drvdata`] and before 276 - /// [`Device::drvdata_obtain`]. 274 + /// the device is fully unbound. 277 275 /// - The type `T` must match the type of the `ForeignOwnable` previously stored by 278 276 /// [`Device::set_drvdata`]. 279 277 unsafe fn drvdata_unchecked<T: 'static>(&self) -> Pin<&T> { ··· 322 320 323 321 // SAFETY: 324 322 // - The above check of `dev_get_drvdata()` guarantees that we are called after 325 - // `set_drvdata()` and before `drvdata_obtain()`. 323 + // `set_drvdata()`. 326 324 // - We've just checked that the type of the driver's private data is in fact `T`. 327 325 Ok(unsafe { self.drvdata_unchecked() }) 328 326 }
+70 -16
rust/kernel/driver.rs
··· 99 99 use core::pin::Pin; 100 100 use pin_init::{pin_data, pinned_drop, PinInit}; 101 101 102 + /// Trait describing the layout of a specific device driver. 103 + /// 104 + /// This trait describes the layout of a specific driver structure, such as `struct pci_driver` or 105 + /// `struct platform_driver`. 106 + /// 107 + /// # Safety 108 + /// 109 + /// Implementors must guarantee that: 110 + /// - `DriverType` is `repr(C)`, 111 + /// - `DriverData` is the type of the driver's device private data. 112 + /// - `DriverType` embeds a valid `struct device_driver` at byte offset `DEVICE_DRIVER_OFFSET`. 113 + pub unsafe trait DriverLayout { 114 + /// The specific driver type embedding a `struct device_driver`. 115 + type DriverType: Default; 116 + 117 + /// The type of the driver's device private data. 118 + type DriverData; 119 + 120 + /// Byte offset of the embedded `struct device_driver` within `DriverType`. 121 + /// 122 + /// This must correspond exactly to the location of the embedded `struct device_driver` field. 123 + const DEVICE_DRIVER_OFFSET: usize; 124 + } 125 + 102 126 /// The [`RegistrationOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform, 103 127 /// Amba, etc.) to provide the corresponding subsystem specific implementation to register / 104 - /// unregister a driver of the particular type (`RegType`). 128 + /// unregister a driver of the particular type (`DriverType`). 105 129 /// 106 - /// For instance, the PCI subsystem would set `RegType` to `bindings::pci_driver` and call 130 + /// For instance, the PCI subsystem would set `DriverType` to `bindings::pci_driver` and call 107 131 /// `bindings::__pci_register_driver` from `RegistrationOps::register` and 108 132 /// `bindings::pci_unregister_driver` from `RegistrationOps::unregister`. 109 133 /// 110 134 /// # Safety 111 135 /// 112 - /// A call to [`RegistrationOps::unregister`] for a given instance of `RegType` is only valid if a 113 - /// preceding call to [`RegistrationOps::register`] has been successful. 114 - pub unsafe trait RegistrationOps { 115 - /// The type that holds information about the registration. This is typically a struct defined 116 - /// by the C portion of the kernel. 117 - type RegType: Default; 118 - 136 + /// A call to [`RegistrationOps::unregister`] for a given instance of `DriverType` is only valid if 137 + /// a preceding call to [`RegistrationOps::register`] has been successful. 138 + pub unsafe trait RegistrationOps: DriverLayout { 119 139 /// Registers a driver. 120 140 /// 121 141 /// # Safety ··· 143 123 /// On success, `reg` must remain pinned and valid until the matching call to 144 124 /// [`RegistrationOps::unregister`]. 145 125 unsafe fn register( 146 - reg: &Opaque<Self::RegType>, 126 + reg: &Opaque<Self::DriverType>, 147 127 name: &'static CStr, 148 128 module: &'static ThisModule, 149 129 ) -> Result; ··· 154 134 /// 155 135 /// Must only be called after a preceding successful call to [`RegistrationOps::register`] for 156 136 /// the same `reg`. 157 - unsafe fn unregister(reg: &Opaque<Self::RegType>); 137 + unsafe fn unregister(reg: &Opaque<Self::DriverType>); 158 138 } 159 139 160 140 /// A [`Registration`] is a generic type that represents the registration of some driver type (e.g. ··· 166 146 #[pin_data(PinnedDrop)] 167 147 pub struct Registration<T: RegistrationOps> { 168 148 #[pin] 169 - reg: Opaque<T::RegType>, 149 + reg: Opaque<T::DriverType>, 170 150 } 171 151 172 152 // SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to ··· 177 157 // any thread, so `Registration` is `Send`. 178 158 unsafe impl<T: RegistrationOps> Send for Registration<T> {} 179 159 180 - impl<T: RegistrationOps> Registration<T> { 160 + impl<T: RegistrationOps + 'static> Registration<T> { 161 + extern "C" fn post_unbind_callback(dev: *mut bindings::device) { 162 + // SAFETY: The driver core only ever calls the post unbind callback with a valid pointer to 163 + // a `struct device`. 164 + // 165 + // INVARIANT: `dev` is valid for the duration of the `post_unbind_callback()`. 166 + let dev = unsafe { &*dev.cast::<device::Device<device::CoreInternal>>() }; 167 + 168 + // `remove()` and all devres callbacks have been completed at this point, hence drop the 169 + // driver's device private data. 170 + // 171 + // SAFETY: By the safety requirements of the `Driver` trait, `T::DriverData` is the 172 + // driver's device private data type. 173 + drop(unsafe { dev.drvdata_obtain::<T::DriverData>() }); 174 + } 175 + 176 + /// Attach generic `struct device_driver` callbacks. 177 + fn callbacks_attach(drv: &Opaque<T::DriverType>) { 178 + let ptr = drv.get().cast::<u8>(); 179 + 180 + // SAFETY: 181 + // - `drv.get()` yields a valid pointer to `Self::DriverType`. 182 + // - Adding `DEVICE_DRIVER_OFFSET` yields the address of the embedded `struct device_driver` 183 + // as guaranteed by the safety requirements of the `Driver` trait. 184 + let base = unsafe { ptr.add(T::DEVICE_DRIVER_OFFSET) }; 185 + 186 + // CAST: `base` points to the offset of the embedded `struct device_driver`. 187 + let base = base.cast::<bindings::device_driver>(); 188 + 189 + // SAFETY: It is safe to set the fields of `struct device_driver` on initialization. 190 + unsafe { (*base).p_cb.post_unbind_rust = Some(Self::post_unbind_callback) }; 191 + } 192 + 181 193 /// Creates a new instance of the registration object. 182 194 pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> { 183 195 try_pin_init!(Self { 184 - reg <- Opaque::try_ffi_init(|ptr: *mut T::RegType| { 196 + reg <- Opaque::try_ffi_init(|ptr: *mut T::DriverType| { 185 197 // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write. 186 - unsafe { ptr.write(T::RegType::default()) }; 198 + unsafe { ptr.write(T::DriverType::default()) }; 187 199 188 200 // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write, and it has 189 201 // just been initialised above, so it's also valid for read. 190 - let drv = unsafe { &*(ptr as *const Opaque<T::RegType>) }; 202 + let drv = unsafe { &*(ptr as *const Opaque<T::DriverType>) }; 203 + 204 + Self::callbacks_attach(drv); 191 205 192 206 // SAFETY: `drv` is guaranteed to be pinned until `T::unregister`. 193 207 unsafe { T::register(drv, name, module) }
+20 -11
rust/kernel/i2c.rs
··· 92 92 /// An adapter for the registration of I2C drivers. 93 93 pub struct Adapter<T: Driver>(T); 94 94 95 - // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 95 + // SAFETY: 96 + // - `bindings::i2c_driver` is a C type declared as `repr(C)`. 97 + // - `T` is the type of the driver's device private data. 98 + // - `struct i2c_driver` embeds a `struct device_driver`. 99 + // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`. 100 + unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> { 101 + type DriverType = bindings::i2c_driver; 102 + type DriverData = T; 103 + const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver); 104 + } 105 + 106 + // SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if 96 107 // a preceding call to `register` has been successful. 97 108 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 98 - type RegType = bindings::i2c_driver; 99 - 100 109 unsafe fn register( 101 - idrv: &Opaque<Self::RegType>, 110 + idrv: &Opaque<Self::DriverType>, 102 111 name: &'static CStr, 103 112 module: &'static ThisModule, 104 113 ) -> Result { ··· 142 133 (*idrv.get()).driver.acpi_match_table = acpi_table; 143 134 } 144 135 145 - // SAFETY: `idrv` is guaranteed to be a valid `RegType`. 136 + // SAFETY: `idrv` is guaranteed to be a valid `DriverType`. 146 137 to_result(unsafe { bindings::i2c_register_driver(module.0, idrv.get()) }) 147 138 } 148 139 149 - unsafe fn unregister(idrv: &Opaque<Self::RegType>) { 150 - // SAFETY: `idrv` is guaranteed to be a valid `RegType`. 140 + unsafe fn unregister(idrv: &Opaque<Self::DriverType>) { 141 + // SAFETY: `idrv` is guaranteed to be a valid `DriverType`. 151 142 unsafe { bindings::i2c_del_driver(idrv.get()) } 152 143 } 153 144 } ··· 178 169 // SAFETY: `remove_callback` is only ever called after a successful call to 179 170 // `probe_callback`, hence it's guaranteed that `I2cClient::set_drvdata()` has been called 180 171 // and stored a `Pin<KBox<T>>`. 181 - let data = unsafe { idev.as_ref().drvdata_obtain::<T>() }; 172 + let data = unsafe { idev.as_ref().drvdata_borrow::<T>() }; 182 173 183 - T::unbind(idev, data.as_ref()); 174 + T::unbind(idev, data); 184 175 } 185 176 186 177 extern "C" fn shutdown_callback(idev: *mut bindings::i2c_client) { ··· 190 181 // SAFETY: `shutdown_callback` is only ever called after a successful call to 191 182 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 192 183 // and stored a `Pin<KBox<T>>`. 193 - let data = unsafe { idev.as_ref().drvdata_obtain::<T>() }; 184 + let data = unsafe { idev.as_ref().drvdata_borrow::<T>() }; 194 185 195 - T::shutdown(idev, data.as_ref()); 186 + T::shutdown(idev, data); 196 187 } 197 188 198 189 /// The [`i2c::IdTable`] of the corresponding driver.
+6 -3
rust/kernel/io.rs
··· 142 142 /// Bound checks are performed on compile time, hence if the offset is not known at compile 143 143 /// time, the build will fail. 144 144 $(#[$attr])* 145 - #[inline] 145 + // Always inline to optimize out error path of `io_addr_assert`. 146 + #[inline(always)] 146 147 pub fn $name(&self, offset: usize) -> $type_name { 147 148 let addr = self.io_addr_assert::<$type_name>(offset); 148 149 ··· 172 171 /// Bound checks are performed on compile time, hence if the offset is not known at compile 173 172 /// time, the build will fail. 174 173 $(#[$attr])* 175 - #[inline] 174 + // Always inline to optimize out error path of `io_addr_assert`. 175 + #[inline(always)] 176 176 pub fn $name(&self, value: $type_name, offset: usize) { 177 177 let addr = self.io_addr_assert::<$type_name>(offset); 178 178 ··· 241 239 self.addr().checked_add(offset).ok_or(EINVAL) 242 240 } 243 241 244 - #[inline] 242 + // Always inline to optimize out error path of `build_assert`. 243 + #[inline(always)] 245 244 fn io_addr_assert<U>(&self, offset: usize) -> usize { 246 245 build_assert!(Self::offset_valid::<U>(offset, SIZE)); 247 246
+2
rust/kernel/io/resource.rs
··· 226 226 /// Resource represents a memory region that must be ioremaped using `ioremap_np`. 227 227 pub const IORESOURCE_MEM_NONPOSTED: Flags = Flags::new(bindings::IORESOURCE_MEM_NONPOSTED); 228 228 229 + // Always inline to optimize out error path of `build_assert`. 230 + #[inline(always)] 229 231 const fn new(value: u32) -> Self { 230 232 crate::build_assert!(value as u64 <= c_ulong::MAX as u64); 231 233 Flags(value as c_ulong)
+2
rust/kernel/irq/flags.rs
··· 96 96 self.0 97 97 } 98 98 99 + // Always inline to optimize out error path of `build_assert`. 100 + #[inline(always)] 99 101 const fn new(value: u32) -> Self { 100 102 build_assert!(value as u64 <= c_ulong::MAX as u64); 101 103 Self(value as c_ulong)
+18 -9
rust/kernel/pci.rs
··· 50 50 /// An adapter for the registration of PCI drivers. 51 51 pub struct Adapter<T: Driver>(T); 52 52 53 - // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 53 + // SAFETY: 54 + // - `bindings::pci_driver` is a C type declared as `repr(C)`. 55 + // - `T` is the type of the driver's device private data. 56 + // - `struct pci_driver` embeds a `struct device_driver`. 57 + // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`. 58 + unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> { 59 + type DriverType = bindings::pci_driver; 60 + type DriverData = T; 61 + const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver); 62 + } 63 + 64 + // SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if 54 65 // a preceding call to `register` has been successful. 55 66 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 56 - type RegType = bindings::pci_driver; 57 - 58 67 unsafe fn register( 59 - pdrv: &Opaque<Self::RegType>, 68 + pdrv: &Opaque<Self::DriverType>, 60 69 name: &'static CStr, 61 70 module: &'static ThisModule, 62 71 ) -> Result { ··· 77 68 (*pdrv.get()).id_table = T::ID_TABLE.as_ptr(); 78 69 } 79 70 80 - // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. 71 + // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`. 81 72 to_result(unsafe { 82 73 bindings::__pci_register_driver(pdrv.get(), module.0, name.as_char_ptr()) 83 74 }) 84 75 } 85 76 86 - unsafe fn unregister(pdrv: &Opaque<Self::RegType>) { 87 - // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. 77 + unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) { 78 + // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`. 88 79 unsafe { bindings::pci_unregister_driver(pdrv.get()) } 89 80 } 90 81 } ··· 123 114 // SAFETY: `remove_callback` is only ever called after a successful call to 124 115 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 125 116 // and stored a `Pin<KBox<T>>`. 126 - let data = unsafe { pdev.as_ref().drvdata_obtain::<T>() }; 117 + let data = unsafe { pdev.as_ref().drvdata_borrow::<T>() }; 127 118 128 - T::unbind(pdev, data.as_ref()); 119 + T::unbind(pdev, data); 129 120 } 130 121 } 131 122
+18 -9
rust/kernel/platform.rs
··· 26 26 /// An adapter for the registration of platform drivers. 27 27 pub struct Adapter<T: Driver>(T); 28 28 29 - // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 29 + // SAFETY: 30 + // - `bindings::platform_driver` is a C type declared as `repr(C)`. 31 + // - `T` is the type of the driver's device private data. 32 + // - `struct platform_driver` embeds a `struct device_driver`. 33 + // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`. 34 + unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> { 35 + type DriverType = bindings::platform_driver; 36 + type DriverData = T; 37 + const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver); 38 + } 39 + 40 + // SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if 30 41 // a preceding call to `register` has been successful. 31 42 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 32 - type RegType = bindings::platform_driver; 33 - 34 43 unsafe fn register( 35 - pdrv: &Opaque<Self::RegType>, 44 + pdrv: &Opaque<Self::DriverType>, 36 45 name: &'static CStr, 37 46 module: &'static ThisModule, 38 47 ) -> Result { ··· 64 55 (*pdrv.get()).driver.acpi_match_table = acpi_table; 65 56 } 66 57 67 - // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. 58 + // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`. 68 59 to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) }) 69 60 } 70 61 71 - unsafe fn unregister(pdrv: &Opaque<Self::RegType>) { 72 - // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. 62 + unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) { 63 + // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`. 73 64 unsafe { bindings::platform_driver_unregister(pdrv.get()) }; 74 65 } 75 66 } ··· 101 92 // SAFETY: `remove_callback` is only ever called after a successful call to 102 93 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 103 94 // and stored a `Pin<KBox<T>>`. 104 - let data = unsafe { pdev.as_ref().drvdata_obtain::<T>() }; 95 + let data = unsafe { pdev.as_ref().drvdata_borrow::<T>() }; 105 96 106 - T::unbind(pdev, data.as_ref()); 97 + T::unbind(pdev, data); 107 98 } 108 99 } 109 100
+18 -9
rust/kernel/usb.rs
··· 27 27 /// An adapter for the registration of USB drivers. 28 28 pub struct Adapter<T: Driver>(T); 29 29 30 - // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 30 + // SAFETY: 31 + // - `bindings::usb_driver` is a C type declared as `repr(C)`. 32 + // - `T` is the type of the driver's device private data. 33 + // - `struct usb_driver` embeds a `struct device_driver`. 34 + // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`. 35 + unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> { 36 + type DriverType = bindings::usb_driver; 37 + type DriverData = T; 38 + const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver); 39 + } 40 + 41 + // SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if 31 42 // a preceding call to `register` has been successful. 32 43 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 33 - type RegType = bindings::usb_driver; 34 - 35 44 unsafe fn register( 36 - udrv: &Opaque<Self::RegType>, 45 + udrv: &Opaque<Self::DriverType>, 37 46 name: &'static CStr, 38 47 module: &'static ThisModule, 39 48 ) -> Result { ··· 54 45 (*udrv.get()).id_table = T::ID_TABLE.as_ptr(); 55 46 } 56 47 57 - // SAFETY: `udrv` is guaranteed to be a valid `RegType`. 48 + // SAFETY: `udrv` is guaranteed to be a valid `DriverType`. 58 49 to_result(unsafe { 59 50 bindings::usb_register_driver(udrv.get(), module.0, name.as_char_ptr()) 60 51 }) 61 52 } 62 53 63 - unsafe fn unregister(udrv: &Opaque<Self::RegType>) { 64 - // SAFETY: `udrv` is guaranteed to be a valid `RegType`. 54 + unsafe fn unregister(udrv: &Opaque<Self::DriverType>) { 55 + // SAFETY: `udrv` is guaranteed to be a valid `DriverType`. 65 56 unsafe { bindings::usb_deregister(udrv.get()) }; 66 57 } 67 58 } ··· 103 94 // SAFETY: `disconnect_callback` is only ever called after a successful call to 104 95 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 105 96 // and stored a `Pin<KBox<T>>`. 106 - let data = unsafe { dev.drvdata_obtain::<T>() }; 97 + let data = unsafe { dev.drvdata_borrow::<T>() }; 107 98 108 - T::disconnect(intf, data.as_ref()); 99 + T::disconnect(intf, data); 109 100 } 110 101 } 111 102