All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Lyude Paul" <lyude@redhat.com>
Cc: dri-devel@lists.freedesktop.org, ojeda@kernel.org
Subject: Re: [PATCH v21 4/4] rust: drm: gem: Introduce shmem::Object::sg_table()
Date: Fri, 12 Jun 2026 20:28:40 +0000	[thread overview]
Message-ID: <20260612202841.2577C1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260612194436.585385-5-lyude@redhat.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] `SGTableMap::drop()` unconditionally calls `__drm_gem_shmem_free_sgt_locked()`, which improperly frees the `sg_table` of imported DMA-BUF objects using `kfree()` instead of returning it to the exporter.
- [High] `Object::sg_table()` does not pin the GEM object, allowing the shrinker to purge it and free the scatter-gather table while Rust still holds references to it.
- [High] Concurrent execution of device unbind and GEM object free causes a Use-After-Free of the GEM object inside `SGTableMap::drop`.
--

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

This commit introduces a devres-managed SGTable mapping for GEM shmem
objects in Rust, ensuring mappings are released on driver unbind.

> diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs
> --- a/rust/kernel/drm/gem/shmem.rs
> +++ b/rust/kernel/drm/gem/shmem.rs

[ ... ]

> @@ -183,18 +207,26 @@ extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) {
>          // - 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` and that
> +        //   `sgt_res` will not be used after dropping it here.
> +        unsafe { ManuallyDrop::drop(&mut (*this).sgt_res) };
> +
>          // 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) };
> +        unsafe { bindings::drm_gem_shmem_release(base) };

[Severity: High]
Can this sequence cause a use-after-free if device unbind runs
concurrently with the last reference drop?

If the device unbind thread changes the Devres state to revoked and waits
in rcu::synchronize_rcu(), and free_callback() runs concurrently:

free_callback()
    ManuallyDrop::drop(&mut (*this).sgt_res)

Because the state is already revoked, will Devres::drop() return immediately
without waiting for the unbind thread? free_callback() would then proceed
to call drm_gem_shmem_release() and free the GEM object memory.

When the unbind thread finishes synchronize_rcu(), it will call
SGTableMap::drop() which dereferences the now-freed GEM object:

SGTableMap::drop()
    let obj = unsafe { self.obj.as_ref() };

[ ... ]

> +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: High]
Does this unconditionally free the scatter-gather table, even for imported
DMA-BUF objects?

The Rust GEM shmem abstraction supports imported DMA-BUF objects. For these
objects, the scatter-gather table is allocated and mapped by the exporter.

Calling __drm_gem_shmem_free_sgt_locked() here will unmap and call kfree()
on a pointer not allocated by this driver. Could this corrupt the exporter's
heap?

> +    }
> +}

[ ... ]

> +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 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]
Is the GEM object properly pinned here?

The documentation for Object::sg_table() states "This will pin the object
in memory." However, drm_gem_shmem_get_pages_sgt() increments
pages_use_count but does not increment pages_pin_count.

If the user marks the object with MADV_DONTNEED, could the shrinker purge
the object, freeing the scatter-gather table while Rust still hands out
references to it? This might also lead to a NULL pointer dereference later
in SGTableMap::drop() when it passes the freed table to
__drm_gem_shmem_free_sgt_locked().

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

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

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

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-12 19:43 [PATCH v21 0/4] Rust bindings for gem shmem Lyude Paul
2026-06-12 19:43 ` Lyude Paul
2026-06-12 19:43 ` [PATCH v21 1/4] rust: drm: gem: shmem: Add DmaResvGuard helper Lyude Paul
2026-06-12 19:43   ` Lyude Paul
2026-06-12 19:43 ` [PATCH v21 2/4] rust: drm: gem: shmem: Add vmap functions Lyude Paul
2026-06-12 19:43   ` Lyude Paul
2026-06-12 19:43 ` [PATCH v21 3/4] rust: faux: Allow retrieving a bound Device Lyude Paul
2026-06-12 19:43   ` Lyude Paul
2026-06-12 20:14   ` sashiko-bot
2026-06-12 19:43 ` [PATCH v21 4/4] rust: drm: gem: Introduce shmem::Object::sg_table() Lyude Paul
2026-06-12 19:43   ` Lyude Paul
2026-06-12 20:28   ` sashiko-bot [this message]
2026-06-25 21:24   ` Danilo Krummrich
2026-06-25 21:24     ` Danilo Krummrich
2026-06-25 21:24 ` (subset) [PATCH v21 0/4] Rust bindings for gem shmem Danilo Krummrich
2026-06-25 21:24   ` Danilo Krummrich

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=20260612202841.2577C1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=dri-devel@lists.freedesktop.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.