All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Lyude Paul" <lyude@redhat.com>
Cc: ojeda@kernel.org, linux-media@vger.kernel.org
Subject: Re: [PATCH v17 6/6] rust: drm: gem: Introduce shmem::Object::sg_table()
Date: Wed, 03 Jun 2026 20:12:06 +0000	[thread overview]
Message-ID: <20260603201206.C95721F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260603195210.693856-7-lyude@redhat.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Critical] `SGTableMap::drop` unconditionally frees the scatter/gather table, which corrupts memory for imported dma-buf GEM objects.
- [Critical] Concurrent device unbind and GEM object destruction causes a Use-After-Free of the GEM object and its dma_resv lock in `SGTableMap::drop`.
- [High] `SGTableMap` fails to pin the shmem GEM object backing pages, exposing the SG table to being purged by the shrinker and causing a NULL pointer dereference. It also leaks the `pages_use_count` on drop.
--

commit 8870abbe2654a7715fcd51335a14b62f57e22680
Author: Lyude Paul <lyude@redhat.com>
rust: drm: gem: Introduce shmem::Object::sg_table()

This commit introduces a Devres-managed SGTableMap to ensure that
scatterlist mappings for GEM shmem objects are released upon driver
unbind. It adds the sg_table() method to shmem::Object which is intended
to pin the object and return its scatter/gather table.

> diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs
> index 1f05a5bc5fe66..dff90771eb34a 100644
> --- a/rust/kernel/drm/gem/shmem.rs
> +++ b/rust/kernel/drm/gem/shmem.rs
[ ... ]
> @@ -189,18 +210,25 @@ extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) {
>          // - DRM always passes a valid gem object here
>          // - We used drm_gem_shmem_create() in our create_gem_object callback, so we know that
>          //   `obj` is contained within a drm_gem_shmem_object
> -        let this = unsafe { container_of!(obj, bindings::drm_gem_shmem_object, base) };
> -
> -        // SAFETY:
> -        // - We're in free_callback - so this function is safe to call.
> -        // - We won't be using the gem resources on `this` after this call.
> -        unsafe { bindings::drm_gem_shmem_release(this) };
> +        let base = unsafe { container_of!(obj, bindings::drm_gem_shmem_object, base) };
>  
>          // SAFETY:
>          // - We verified above that `obj` is valid, which makes `this` valid
>          // - This function is set in AllocOps, so we know that `this` is contained within a
>          //   `Object<T, C>`
> -        let this = unsafe { container_of!(Opaque::cast_from(this), Self, obj) }.cast_mut();
> +        let this = unsafe { container_of!(Opaque::cast_from(base), Self, obj) }.cast_mut();
> +
> +        // We need to drop `sgt_res` first, since doing so requires that the GEM object is still
> +        // alive.
> +        // SAFETY:
> +        // - We verified above that `this` is valid.
> +        // - We are in free_callback, guaranteeing we have exclusive access to `this`.
> +        unsafe { &mut (*this).sgt_res }.reset();

[Severity: Critical]
Does this leave a window for a use-after-free if the device unbinds
concurrently?

If the devres subsystem is already running SGTableMap::drop() in another
thread during device unbind, sgt_res.reset() could silently fail to remove
the action. The callback would then proceed to free the GEM object while
SGTableMap::drop() is still dereferencing and locking it.

> +
> +        // SAFETY:
> +        // - We're in free_callback - so this function is safe to call.
> +        // - We won't be using the gem resources on `this` after this call.
> +        unsafe { bindings::drm_gem_shmem_release(base) };
[ ... ]
> +impl<T: DriverObject, C: DeviceContext> Drop for SGTableMap<T, C> {
> +    fn drop(&mut self) {
> +        // SAFETY: `obj` is always valid via our type invariants
> +        let obj = unsafe { self.obj.as_ref() };
> +        let _lock = DmaResvGuard::new(obj);
> +
> +        // SAFETY: We acquired the lock needed for calling this function above
> +        unsafe { bindings::__drm_gem_shmem_free_sgt_locked(obj.as_raw_shmem()) };

[Severity: Critical]
Is it safe to unconditionally free the scatter/gather table here?

If the GEM object was imported from a dma-buf, the scatter/gather table
belongs to the exporter. Calling __drm_gem_shmem_free_sgt_locked() directly
without checking drm_gem_is_imported() seems like it might illegally free
the exporter's memory.

[Severity: High]
Could this drop implementation also leak the pages_use_count?

Calling __drm_gem_shmem_free_sgt_locked() alone doesn't seem to drop the
page use count acquired during SGTableMap::new(). Should this also call
drm_gem_shmem_put_pages_locked() to balance the counts?

> +    }
> +}
> +
> +impl<T: DriverObject, C: DeviceContext> SGTableMap<T, C> {
> +    fn new(obj: &Object<T, C>) -> impl Init<Self, Error> {
> +        // INVARIANT:
> +        // - We call drm_gem_shmem_get_pages_sgt_locked below and check whether or not it
> +        //   succeeds, fulfilling the invariant of SGTableMap that the object's `sgt` field is
> +        //   initialized.
> +        // SAFETY:
> +        // - `obj` is fully initialized, making this function safe to call.
> +        from_err_ptr(unsafe { bindings::drm_gem_shmem_get_pages_sgt(obj.as_raw_shmem()) })?;

[Severity: High]
Does this expose the object to being purged by the DRM LRU shrinker?

The Object::sg_table() documentation mentions this will pin the object in
memory, but drm_gem_shmem_get_pages_sgt() only increments the
pages_use_count, not the pages_pin_count. If userspace marks the object as
MADV_DONTNEED, the shrinker could purge it and set shmem->sgt to NULL.

Could this lead to a NULL pointer dereference later in SGTableMap::drop()
when it passes the pointer to __drm_gem_shmem_free_sgt_locked()?

> +
> +        Ok(Self { obj: obj.into() })
> +    }
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260603195210.693856-1-lyude@redhat.com?part=6

      reply	other threads:[~2026-06-03 20:12 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-03 19:42 [PATCH v17 0/6] Rust bindings for gem shmem Lyude Paul
2026-06-03 19:42 ` Lyude Paul
2026-06-03 19:42 ` [PATCH v17 1/6] rust: drm: gem: shmem: Fix Default implementation for ObjectConfig Lyude Paul
2026-06-03 19:42   ` Lyude Paul
2026-06-03 20:02   ` sashiko-bot
2026-06-04 11:49   ` Alice Ryhl
2026-06-04 11:49     ` Alice Ryhl
2026-06-03 19:42 ` [PATCH v17 2/6] rust: drm: gem: shmem: Add DmaResvGuard helper Lyude Paul
2026-06-03 19:42   ` Lyude Paul
2026-06-03 20:09   ` sashiko-bot
2026-06-03 19:42 ` [PATCH v17 3/6] rust: drm: gem: shmem: Add vmap functions Lyude Paul
2026-06-03 19:42   ` Lyude Paul
2026-06-03 20:11   ` sashiko-bot
2026-06-03 19:42 ` [PATCH v17 4/6] rust: faux: Allow retrieving a bound Device Lyude Paul
2026-06-03 19:42   ` Lyude Paul
2026-06-03 20:08   ` sashiko-bot
2026-06-04 13:25   ` Danilo Krummrich
2026-06-04 13:25     ` Danilo Krummrich
2026-06-04 18:48     ` lyude
2026-06-04 18:48       ` lyude
2026-06-03 19:42 ` [PATCH v17 5/6] rust: sync: Add SetOnce::reset() Lyude Paul
2026-06-03 19:42   ` Lyude Paul
2026-06-03 20:07   ` sashiko-bot
2026-06-04 11:58   ` Alice Ryhl
2026-06-04 18:53     ` lyude
2026-06-03 19:42 ` [PATCH v17 6/6] rust: drm: gem: Introduce shmem::Object::sg_table() Lyude Paul
2026-06-03 19:42   ` Lyude Paul
2026-06-03 20:12   ` sashiko-bot [this message]

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=20260603201206.C95721F00893@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=lyude@redhat.com \
    --cc=ojeda@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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.