Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rust: device: introduce Device::drvdata()

In C dev_get_drvdata() has specific requirements under which it is valid
to access the returned pointer. That is, drivers have to ensure that

(1) for the duration the returned pointer is accessed the driver is
bound and remains to be bound to the corresponding device,

(2) the returned void * is treated according to the driver's private
data type, i.e. according to what has been passed to
dev_set_drvdata().

In Rust, (1) can be ensured by simply requiring the Bound device
context, i.e. provide the drvdata() method for Device<Bound> only.

For (2) we would usually make the device type generic over the driver
type, e.g. Device<T: Driver>, where <T as Driver>::Data is the type of
the driver's private data.

However, a device does not have a driver type known at compile time and
may be bound to multiple drivers throughout its lifetime.

Hence, in order to be able to provide a safe accessor for the driver's
device private data, we have to do the type check on runtime.

This is achieved by letting a driver assert the expected type, which is
then compared to a type hash stored in struct device_private when
dev_set_drvdata() is called.

Example:

// `dev` is a `&Device<Bound>`.
let data = dev.drvdata::<SampleDriver>()?;

There are two aspects to note:

(1) Technically, the same check could be achieved by comparing the
struct device_driver pointer of struct device with the struct
device_driver pointer of the driver struct (e.g. struct
pci_driver).

However, this would - in addition the pointer comparison - require
to tie back the private driver data type to the struct
device_driver pointer of the driver struct to prove correctness.

Besides that, accessing the driver struct (stored in the module
structure) isn't trivial and would result into horrible code and
API ergonomics.

(2) Having a direct accessor to the driver's private data is not
commonly required (at least in Rust): Bus callback methods already
provide access to the driver's device private data through a &self
argument, while other driver entry points such as IRQs,
workqueues, timers, IOCTLs, etc. have their own private data with
separate ownership and lifetime.

In other words, a driver's device private data is only relevant
for driver model contexts (such a file private is only relevant
for file contexts).

Having that said, the motivation for accessing the driver's device
private data with Device<Bound>::drvdata() are interactions between
drivers. For instance, when an auxiliary driver calls back into its
parent, the parent has to be capable to derive its private data from the
corresponding device (i.e. the parent of the auxiliary device).

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[ * Remove unnecessary `const _: ()` block,
* rename type_id_{store,match}() to {set,match}_type_id(),
* assert size_of::<bindings::driver_type>() >= size_of::<TypeId>(),
* add missing check in case Device::drvdata() is called from probe().

- Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

+103 -3
+16
drivers/base/base.h
··· 85 85 }; 86 86 #define to_driver(obj) container_of(obj, struct driver_private, kobj) 87 87 88 + #ifdef CONFIG_RUST 89 + /** 90 + * struct driver_type - Representation of a Rust driver type. 91 + */ 92 + struct driver_type { 93 + /** 94 + * @id: Representation of core::any::TypeId. 95 + */ 96 + u8 id[16]; 97 + } __packed; 98 + #endif 99 + 88 100 /** 89 101 * struct device_private - structure to hold the private to the driver core portions of the device structure. 90 102 * ··· 112 100 * @async_driver - pointer to device driver awaiting probe via async_probe 113 101 * @device - pointer back to the struct device that this structure is 114 102 * associated with. 103 + * @driver_type - The type of the bound Rust driver. 115 104 * @dead - This device is currently either in the process of or has been 116 105 * removed from the system. Any asynchronous events scheduled for this 117 106 * device should exit without taking any action. ··· 129 116 const struct device_driver *async_driver; 130 117 char *deferred_probe_reason; 131 118 struct device *device; 119 + #ifdef CONFIG_RUST 120 + struct driver_type driver_type; 121 + #endif 132 122 u8 dead:1; 133 123 }; 134 124 #define to_device_private_parent(obj) \
+6
rust/bindings/bindings_helper.h
··· 85 85 #include <linux/xarray.h> 86 86 #include <trace/events/rust_sample.h> 87 87 88 + /* 89 + * The driver-core Rust code needs to know about some C driver-core private 90 + * structures. 91 + */ 92 + #include <../../drivers/base/base.h> 93 + 88 94 #if defined(CONFIG_DRM_PANIC_SCREEN_QR_CODE) 89 95 // Used by `#[export]` in `drivers/gpu/drm/drm_panic_qr.rs`. 90 96 #include <drm/drm_panic.h>
+81 -3
rust/kernel/device.rs
··· 10 10 sync::aref::ARef, 11 11 types::{ForeignOwnable, Opaque}, 12 12 }; 13 - use core::{marker::PhantomData, ptr}; 13 + use core::{any::TypeId, marker::PhantomData, ptr}; 14 14 15 15 #[cfg(CONFIG_PRINTK)] 16 16 use crate::c_str; 17 17 18 18 pub mod property; 19 + 20 + // Assert that we can `read()` / `write()` a `TypeId` instance from / into `struct driver_type`. 21 + static_assert!(core::mem::size_of::<bindings::driver_type>() >= core::mem::size_of::<TypeId>()); 19 22 20 23 /// The core representation of a device in the kernel's driver model. 21 24 /// ··· 201 198 } 202 199 203 200 impl Device<CoreInternal> { 201 + fn set_type_id<T: 'static>(&self) { 202 + // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 203 + let private = unsafe { (*self.as_raw()).p }; 204 + 205 + // SAFETY: For a bound device (implied by the `CoreInternal` device context), `private` is 206 + // guaranteed to be a valid pointer to a `struct device_private`. 207 + let driver_type = unsafe { &raw mut (*private).driver_type }; 208 + 209 + // SAFETY: `driver_type` is valid for (unaligned) writes of a `TypeId`. 210 + unsafe { 211 + driver_type 212 + .cast::<TypeId>() 213 + .write_unaligned(TypeId::of::<T>()) 214 + }; 215 + } 216 + 204 217 /// Store a pointer to the bound driver's private data. 205 218 pub fn set_drvdata<T: 'static>(&self, data: impl PinInit<T, Error>) -> Result { 206 219 let data = KBox::pin_init(data, GFP_KERNEL)?; 207 220 208 221 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 209 222 unsafe { bindings::dev_set_drvdata(self.as_raw(), data.into_foreign().cast()) }; 223 + self.set_type_id::<T>(); 210 224 211 225 Ok(()) 212 226 } ··· 238 218 pub unsafe fn drvdata_obtain<T: 'static>(&self) -> Pin<KBox<T>> { 239 219 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 240 220 let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) }; 221 + 222 + // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 223 + unsafe { bindings::dev_set_drvdata(self.as_raw(), core::ptr::null_mut()) }; 241 224 242 225 // SAFETY: 243 226 // - By the safety requirements of this function, `ptr` comes from a previous call to ··· 258 235 /// [`Device::drvdata_obtain`]. 259 236 /// - The type `T` must match the type of the `ForeignOwnable` previously stored by 260 237 /// [`Device::set_drvdata`]. 261 - pub unsafe fn drvdata_borrow<T: ForeignOwnable>(&self) -> T::Borrowed<'_> { 238 + pub unsafe fn drvdata_borrow<T: 'static>(&self) -> Pin<&T> { 239 + // SAFETY: `drvdata_unchecked()` has the exact same safety requirements as the ones 240 + // required by this method. 241 + unsafe { self.drvdata_unchecked() } 242 + } 243 + } 244 + 245 + impl Device<Bound> { 246 + /// Borrow the driver's private data bound to this [`Device`]. 247 + /// 248 + /// # Safety 249 + /// 250 + /// - Must only be called after a preceding call to [`Device::set_drvdata`] and before 251 + /// [`Device::drvdata_obtain`]. 252 + /// - The type `T` must match the type of the `ForeignOwnable` previously stored by 253 + /// [`Device::set_drvdata`]. 254 + unsafe fn drvdata_unchecked<T: 'static>(&self) -> Pin<&T> { 262 255 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 263 256 let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) }; 264 257 ··· 283 244 // `into_foreign()`. 284 245 // - `dev_get_drvdata()` guarantees to return the same pointer given to `dev_set_drvdata()` 285 246 // in `into_foreign()`. 286 - unsafe { T::borrow(ptr.cast()) } 247 + unsafe { Pin::<KBox<T>>::borrow(ptr.cast()) } 248 + } 249 + 250 + fn match_type_id<T: 'static>(&self) -> Result { 251 + // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 252 + let private = unsafe { (*self.as_raw()).p }; 253 + 254 + // SAFETY: For a bound device, `private` is guaranteed to be a valid pointer to a 255 + // `struct device_private`. 256 + let driver_type = unsafe { &raw mut (*private).driver_type }; 257 + 258 + // SAFETY: 259 + // - `driver_type` is valid for (unaligned) reads of a `TypeId`. 260 + // - A bound device guarantees that `driver_type` contains a valid `TypeId` value. 261 + let type_id = unsafe { driver_type.cast::<TypeId>().read_unaligned() }; 262 + 263 + if type_id != TypeId::of::<T>() { 264 + return Err(EINVAL); 265 + } 266 + 267 + Ok(()) 268 + } 269 + 270 + /// Access a driver's private data. 271 + /// 272 + /// Returns a pinned reference to the driver's private data or [`EINVAL`] if it doesn't match 273 + /// the asserted type `T`. 274 + pub fn drvdata<T: 'static>(&self) -> Result<Pin<&T>> { 275 + // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 276 + if unsafe { bindings::dev_get_drvdata(self.as_raw()) }.is_null() { 277 + return Err(ENOENT); 278 + } 279 + 280 + self.match_type_id::<T>()?; 281 + 282 + // SAFETY: 283 + // - The above check of `dev_get_drvdata()` guarantees that we are called after 284 + // `set_drvdata()` and before `drvdata_obtain()`. 285 + // - We've just checked that the type of the driver's private data is in fact `T`. 286 + Ok(unsafe { self.drvdata_unchecked() }) 287 287 } 288 288 } 289 289