Commit 5dbeeb26 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'driver-core-6.19-rc7' of...

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
parents 12a00948 a995fe1a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -548,6 +548,8 @@ static DEVICE_ATTR_RW(state_synced);
static void device_unbind_cleanup(struct device *dev)
{
	devres_release_all(dev);
	if (dev->driver->p_cb.post_unbind_rust)
		dev->driver->p_cb.post_unbind_rust(dev);
	arch_teardown_dma_ops(dev);
	kfree(dev->dma_range_map);
	dev->dma_range_map = NULL;
+9 −0
Original line number Diff line number Diff line
@@ -85,6 +85,8 @@ enum probe_type {
 *		uevent.
 * @p:		Driver core's private data, no one other than the driver
 *		core can touch this.
 * @p_cb:	Callbacks private to the driver core; no one other than the
 *		driver core is allowed to touch this.
 *
 * The device driver-model tracks all of the drivers known to the system.
 * The main reason for this tracking is to enable the driver core to match
@@ -119,6 +121,13 @@ struct device_driver {
	void (*coredump) (struct device *dev);

	struct driver_private *p;
	struct {
		/*
		 * Called after remove() and after all devres entries have been
		 * processed. This is a Rust only callback.
		 */
		void (*post_unbind_rust)(struct device *dev);
	} p_cb;
};


+33 −8
Original line number Diff line number Diff line
@@ -23,13 +23,22 @@
/// An adapter for the registration of auxiliary 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::auxiliary_driver` is a C type declared as `repr(C)`.
// - `T` is the type of the driver's device private data.
// - `struct auxiliary_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::auxiliary_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::auxiliary_driver;

    unsafe fn register(
        adrv: &Opaque<Self::RegType>,
        adrv: &Opaque<Self::DriverType>,
        name: &'static CStr,
        module: &'static ThisModule,
    ) -> Result {
@@ -41,14 +50,14 @@ unsafe fn register(
            (*adrv.get()).id_table = T::ID_TABLE.as_ptr();
        }

        // SAFETY: `adrv` is guaranteed to be a valid `RegType`.
        // SAFETY: `adrv` is guaranteed to be a valid `DriverType`.
        to_result(unsafe {
            bindings::__auxiliary_driver_register(adrv.get(), module.0, name.as_char_ptr())
        })
    }

    unsafe fn unregister(adrv: &Opaque<Self::RegType>) {
        // SAFETY: `adrv` is guaranteed to be a valid `RegType`.
    unsafe fn unregister(adrv: &Opaque<Self::DriverType>) {
        // SAFETY: `adrv` is guaranteed to be a valid `DriverType`.
        unsafe { bindings::auxiliary_driver_unregister(adrv.get()) }
    }
}
@@ -87,7 +96,9 @@ extern "C" fn remove_callback(adev: *mut bindings::auxiliary_device) {
        // 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>>`.
        drop(unsafe { adev.as_ref().drvdata_obtain::<T>() });
        let data = unsafe { adev.as_ref().drvdata_borrow::<T>() };

        T::unbind(adev, data);
    }
}

@@ -187,6 +198,20 @@ pub trait Driver {
    ///
    /// Called when an auxiliary device is matches a corresponding driver.
    fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> impl PinInit<Self, Error>;

    /// Auxiliary driver unbind.
    ///
    /// Called when a [`Device`] is unbound from its bound [`Driver`]. Implementing this callback
    /// is optional.
    ///
    /// This callback serves as a place for drivers to perform teardown operations that require a
    /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O
    /// operations to gracefully tear down the device.
    ///
    /// Otherwise, release operations for driver resources should be performed in `Self::drop`.
    fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) {
        let _ = (dev, this);
    }
}

/// The auxiliary device representation.
+11 −9
Original line number Diff line number Diff line
@@ -232,30 +232,32 @@ pub fn set_drvdata<T: 'static>(&self, data: impl PinInit<T, Error>) -> Result {
    ///
    /// # 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 @@ pub fn drvdata<T: 'static>(&self) -> Result<Pin<&T>> {

        // 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() })
    }
+70 −16
Original line number Diff line number Diff line
@@ -99,23 +99,43 @@
use core::pin::Pin;
use pin_init::{pin_data, pinned_drop, PinInit};

/// Trait describing the layout of a specific device driver.
///
/// This trait describes the layout of a specific driver structure, such as `struct pci_driver` or
/// `struct platform_driver`.
///
/// # Safety
///
/// Implementors must guarantee that:
/// - `DriverType` is `repr(C)`,
/// - `DriverData` is the type of the driver's device private data.
/// - `DriverType` embeds a valid `struct device_driver` at byte offset `DEVICE_DRIVER_OFFSET`.
pub unsafe trait DriverLayout {
    /// The specific driver type embedding a `struct device_driver`.
    type DriverType: Default;

    /// The type of the driver's device private data.
    type DriverData;

    /// Byte offset of the embedded `struct device_driver` within `DriverType`.
    ///
    /// This must correspond exactly to the location of the embedded `struct device_driver` field.
    const DEVICE_DRIVER_OFFSET: usize;
}

/// The [`RegistrationOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform,
/// Amba, etc.) to provide the corresponding subsystem specific implementation to register /
/// unregister a driver of the particular type (`RegType`).
/// unregister a driver of the particular type (`DriverType`).
///
/// For instance, the PCI subsystem would set `RegType` to `bindings::pci_driver` and call
/// For instance, the PCI subsystem would set `DriverType` to `bindings::pci_driver` and call
/// `bindings::__pci_register_driver` from `RegistrationOps::register` and
/// `bindings::pci_unregister_driver` from `RegistrationOps::unregister`.
///
/// # Safety
///
/// A call to [`RegistrationOps::unregister`] for a given instance of `RegType` is only valid if a
/// preceding call to [`RegistrationOps::register`] has been successful.
pub unsafe trait RegistrationOps {
    /// The type that holds information about the registration. This is typically a struct defined
    /// by the C portion of the kernel.
    type RegType: Default;

/// A call to [`RegistrationOps::unregister`] for a given instance of `DriverType` is only valid if
/// a preceding call to [`RegistrationOps::register`] has been successful.
pub unsafe trait RegistrationOps: DriverLayout {
    /// Registers a driver.
    ///
    /// # Safety
@@ -123,7 +143,7 @@ pub unsafe trait RegistrationOps {
    /// On success, `reg` must remain pinned and valid until the matching call to
    /// [`RegistrationOps::unregister`].
    unsafe fn register(
        reg: &Opaque<Self::RegType>,
        reg: &Opaque<Self::DriverType>,
        name: &'static CStr,
        module: &'static ThisModule,
    ) -> Result;
@@ -134,7 +154,7 @@ unsafe fn register(
    ///
    /// Must only be called after a preceding successful call to [`RegistrationOps::register`] for
    /// the same `reg`.
    unsafe fn unregister(reg: &Opaque<Self::RegType>);
    unsafe fn unregister(reg: &Opaque<Self::DriverType>);
}

/// A [`Registration`] is a generic type that represents the registration of some driver type (e.g.
@@ -146,7 +166,7 @@ unsafe fn register(
#[pin_data(PinnedDrop)]
pub struct Registration<T: RegistrationOps> {
    #[pin]
    reg: Opaque<T::RegType>,
    reg: Opaque<T::DriverType>,
}

// SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to
@@ -157,17 +177,51 @@ unsafe impl<T: RegistrationOps> Sync for Registration<T> {}
// any thread, so `Registration` is `Send`.
unsafe impl<T: RegistrationOps> Send for Registration<T> {}

impl<T: RegistrationOps> Registration<T> {
impl<T: RegistrationOps + 'static> Registration<T> {
    extern "C" fn post_unbind_callback(dev: *mut bindings::device) {
        // SAFETY: The driver core only ever calls the post unbind callback with a valid pointer to
        // a `struct device`.
        //
        // INVARIANT: `dev` is valid for the duration of the `post_unbind_callback()`.
        let dev = unsafe { &*dev.cast::<device::Device<device::CoreInternal>>() };

        // `remove()` and all devres callbacks have been completed at this point, hence drop the
        // driver's device private data.
        //
        // SAFETY: By the safety requirements of the `Driver` trait, `T::DriverData` is the
        // driver's device private data type.
        drop(unsafe { dev.drvdata_obtain::<T::DriverData>() });
    }

    /// Attach generic `struct device_driver` callbacks.
    fn callbacks_attach(drv: &Opaque<T::DriverType>) {
        let ptr = drv.get().cast::<u8>();

        // SAFETY:
        // - `drv.get()` yields a valid pointer to `Self::DriverType`.
        // - Adding `DEVICE_DRIVER_OFFSET` yields the address of the embedded `struct device_driver`
        //   as guaranteed by the safety requirements of the `Driver` trait.
        let base = unsafe { ptr.add(T::DEVICE_DRIVER_OFFSET) };

        // CAST: `base` points to the offset of the embedded `struct device_driver`.
        let base = base.cast::<bindings::device_driver>();

        // SAFETY: It is safe to set the fields of `struct device_driver` on initialization.
        unsafe { (*base).p_cb.post_unbind_rust = Some(Self::post_unbind_callback) };
    }

    /// Creates a new instance of the registration object.
    pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> {
        try_pin_init!(Self {
            reg <- Opaque::try_ffi_init(|ptr: *mut T::RegType| {
            reg <- Opaque::try_ffi_init(|ptr: *mut T::DriverType| {
                // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write.
                unsafe { ptr.write(T::RegType::default()) };
                unsafe { ptr.write(T::DriverType::default()) };

                // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write, and it has
                // just been initialised above, so it's also valid for read.
                let drv = unsafe { &*(ptr as *const Opaque<T::RegType>) };
                let drv = unsafe { &*(ptr as *const Opaque<T::DriverType>) };

                Self::callbacks_attach(drv);

                // SAFETY: `drv` is guaranteed to be pinned until `T::unregister`.
                unsafe { T::register(drv, name, module) }
Loading