All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alice Ryhl <aliceryhl@google.com>
To: Eliot Courtney <ecourtney@nvidia.com>
Cc: "David Airlie" <airlied@gmail.com>,
	"Simona Vetter" <simona@ffwll.ch>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Alexandre Courbot" <acourbot@nvidia.com>,
	dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH] rust: drm: fix unsound initialization in drm::Device::new
Date: Wed, 29 Apr 2026 08:03:02 +0000	[thread overview]
Message-ID: <afG7Np4Lmv9k7D1U@google.com> (raw)
In-Reply-To: <20260428-fix-drm-1-v1-1-755057178066@nvidia.com>

On Tue, Apr 28, 2026 at 09:20:21PM +0900, Eliot Courtney wrote:
> If pinned initialization of drm::Device::Data fails, it calls
> drm::Device::release via drm_dev_put. This materializes a reference to
> &drm::Device, but it's not fully constructed yet, because initializing
> `data` failed. It should not be dropped either. Instead, if pinned
> initialization fails, make sure drm::Device::release isn't called.
> 
> Fixes: 2e9fdbe5ec7a ("rust: drm: device: drop_in_place() the drm::Device in release()")
> Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>

For the concerns about duplicating vtables, could the temporary vtable
be a stack variable?

>  rust/kernel/drm/device.rs | 22 ++++++++++++++++------
>  1 file changed, 16 insertions(+), 6 deletions(-)
> 
> diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
> index adbafe8db54d..78ea0eb12535 100644
> --- a/rust/kernel/drm/device.rs
> +++ b/rust/kernel/drm/device.rs
> @@ -111,6 +111,13 @@ impl<T: drm::Driver> Device<T> {
>          fops: &Self::GEM_FOPS,
>      };
>  
> +    // Use a vtable without a `release` callback until `data` is initialized, so init failure
> +    // can release the DRM device without dropping uninitialized fields.
> +    const ALLOC_VTABLE: bindings::drm_driver = bindings::drm_driver {
> +        release: None,
> +        ..Self::VTABLE
> +    };
> +
>      const GEM_FOPS: bindings::file_operations = drm::gem::create_fops();
>  
>      /// Create a new `drm::Device` for a `drm::Driver`.
> @@ -120,12 +127,12 @@ pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<A
>          let layout = Kmalloc::aligned_layout(Layout::new::<Self>());
>  
>          // SAFETY:
> -        // - `VTABLE`, as a `const` is pinned to the read-only section of the compilation,
> +        // - `ALLOC_VTABLE`, as a `const` is pinned to the read-only section of the compilation,
>          // - `dev` is valid by its type invarants,
>          let raw_drm: *mut Self = unsafe {
>              bindings::__drm_dev_alloc(
>                  dev.as_raw(),
> -                &Self::VTABLE,
> +                &Self::ALLOC_VTABLE,
>                  layout.size(),
>                  mem::offset_of!(Self, dev),
>              )
> @@ -133,6 +140,10 @@ pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<A
>          .cast();
>          let raw_drm = NonNull::new(from_err_ptr(raw_drm)?).ok_or(ENOMEM)?;
>  
> +        // SAFETY: `raw_drm` is a valid pointer to `Self`, given that `__drm_dev_alloc` was
> +        // successful.
> +        let drm_dev = unsafe { Self::into_drm_device(raw_drm) };
> +
>          // SAFETY: `raw_drm` is a valid pointer to `Self`.
>          let raw_data = unsafe { ptr::addr_of_mut!((*raw_drm.as_ptr()).data) };
>  
> @@ -140,15 +151,14 @@ pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<A
>          // - `raw_data` is a valid pointer to uninitialized memory.
>          // - `raw_data` will not move until it is dropped.
>          unsafe { data.__pinned_init(raw_data) }.inspect_err(|_| {
> -            // SAFETY: `raw_drm` is a valid pointer to `Self`, given that `__drm_dev_alloc` was
> -            // successful.
> -            let drm_dev = unsafe { Self::into_drm_device(raw_drm) };
> -
>              // SAFETY: `__drm_dev_alloc()` was successful, hence `drm_dev` must be valid and the
>              // refcount must be non-zero.
>              unsafe { bindings::drm_dev_put(drm_dev) };
>          })?;
>  
> +        // SAFETY: `drm_dev` is still private to this function.
> +        unsafe { (*drm_dev).driver = &Self::VTABLE };

It would be bad if this ended up being a reference to a local variable.
Please use `&const { Self::VTABLE }` so that it doesn't compile if this
occurs.

Alice

  parent reply	other threads:[~2026-04-29  8:03 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-28 12:20 [PATCH] rust: drm: fix unsound initialization in drm::Device::new Eliot Courtney
2026-04-28 12:43 ` Danilo Krummrich
2026-04-28 12:50   ` Gary Guo
2026-04-28 13:13     ` Eliot Courtney
2026-04-29  8:03 ` Alice Ryhl [this message]
2026-04-29 11:34   ` Gary Guo
2026-05-01 10:50     ` Eliot Courtney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=afG7Np4Lmv9k7D1U@google.com \
    --to=aliceryhl@google.com \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=airlied@gmail.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=dakr@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=ecourtney@nvidia.com \
    --cc=gary@garyguo.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=simona@ffwll.ch \
    --cc=tmgross@umich.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.