From: sashiko-bot@kernel.org
To: "Lyude Paul" <lyude@redhat.com>
Cc: linux-media@vger.kernel.org, ojeda@kernel.org
Subject: Re: [PATCH v15 6/6] rust: drm: gem: Introduce shmem::Object::sg_table()
Date: Sat, 30 May 2026 05:50:27 +0000 [thread overview]
Message-ID: <20260530055027.6B09A1F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260529183702.677677-7-lyude@redhat.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Eager evaluation of `Devres::new` and `SGTableMap::new` inside `sg_table()` causes a use-after-free of the scatterlist and leaking of page references.
- [High] Concurrent device unbind and GEM object free causes Use-After-Free of the GEM object in `SGTableMap::drop`.
- [Low] The patch imports and uses `LazyInit`, `new_lazy_init`, and `LazyInitError` from `crate::sync`, but these are neither defined nor exported anywhere in the tree.
--
commit 2d2d3346ec26b2ca8eba7a05f0577c63628921d0
Author: Lyude Paul <lyude@redhat.com>
rust: drm: gem: Introduce shmem::Object::sg_table()
In order to do this, we need to be careful to ensure that any interface we
expose for scatterlists ensures that any mappings created from one are
destroyed on driver-unbind. To do this, we introduce a Devres resource into
shmem::Object that we use in order to ensure that we release any SGTable
mappings on driver-unbind.
> diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs
> index 494e0d0d8d0d6..5655c2a1ae8fb 100644
> --- a/rust/kernel/drm/gem/shmem.rs
> +++ b/rust/kernel/drm/gem/shmem.rs
[ ... ]
> sync::{
> aref::ARef,
> new_lazy_init,
> LazyInit,
> LazyInitError, //
> },
[Severity: Low]
Are these primitives defined somewhere else? The patch imports and uses
LazyInit, new_lazy_init, and LazyInitError from crate::sync, but these don't
seem to be present in the tree or introduced anywhere in this patch series.
Will this lead to a module resolution failure and compilation error?
[ ... ]
> extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) {
> // SAFETY:
> // - 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 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>`
> let this = unsafe { container_of!(Opaque::cast_from(base), Self, obj) }.cast_mut();
>
> // We need to reset `sgt_res` first, since doing so requires that the GEM object is still
> // alive.
> // SAFETY:
> // - We verified above that `this` is valid.
> // - `&mut (*this)` does not implement Unpin.
> unsafe { Pin::new_unchecked(&mut (*this).sgt_res) }.reset();
[Severity: High]
Does this code introduce a race condition causing a use-after-free?
If drm_gem_object_put() triggers free_callback() concurrently with a device
unbind, the device unbind thread's devres release callback calls
Revocable::revoke(). This swaps is_available to false and blocks on
synchronize_rcu() before dropping SGTableMap.
Concurrently, free_callback() calls sgt_res.reset(), which drops Devres.
Devres::drop() calls revoke_nosync(), which sees is_available is already false
and returns immediately without waiting for the unbind thread.
Then free_callback() proceeds to call drm_gem_shmem_release() and frees the GEM
object memory.
When the unbind thread finishes synchronize_rcu() and executes
SGTableMap::drop(), could it dereference the freed GEM object memory
to lock its dma_resv?
>
> // 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) };
[ ... ]
> pub fn sg_table<'a>(
> &'a self,
> dev: &'a device::Device<Bound>,
> ) -> Result<&'a scatterlist::SGTable> {
> if dev.as_raw() != self.dev().as_ref().as_raw() {
> return Err(EINVAL);
> }
>
> match self.sgt_res.init(Devres::new(dev, SGTableMap::new(self))) {
[Severity: High]
Can eager evaluation cause a use-after-free and leaked page references here?
In Rust, function arguments are evaluated eagerly. Devres::new allocates and
executes its initializer eagerly. SGTableMap::new(self) evaluates its
initializer, causing drm_gem_shmem_get_pages_sgt() to be called synchronously
every time sg_table() is executed, incrementing the page use count.
If sgt_res is already initialized, init() returns LazyInitError::AlreadyInit
and drops the newly created Devres argument.
When Devres is dropped, it drops the inner SGTableMap, calling
SGTableMap::drop(). This calls __drm_gem_shmem_free_sgt_locked(), which
unconditionally unmaps and frees the shared shmem->sgt memory and sets it to
NULL without decrementing the page use count.
Does this leave the originally cached SGTableMap holding a reference to a NULL
or freed shmem->sgt, which would cause a NULL pointer dereference or
use-after-free the next time it's accessed?
> Ok(ret) | Err(LazyInitError::AlreadyInit(ret)) => Ok(ret.access(dev)?),
> Err(LazyInitError::DuringInit(e)) => Err(e),
> }
> }
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260529183702.677677-1-lyude@redhat.com?part=6
prev parent reply other threads:[~2026-05-30 5:50 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-29 18:33 [PATCH v15 0/6] Rust bindings for gem shmem Lyude Paul
2026-05-29 18:33 ` [PATCH v15 1/6] rust: gem: shmem: Fix Default implementation for ObjectConfig Lyude Paul
2026-05-29 18:46 ` sashiko-bot
2026-05-29 18:34 ` [PATCH v15 2/6] rust: drm: gem/shmem: Add DmaResvGuard helper Lyude Paul
2026-05-29 18:57 ` sashiko-bot
2026-05-29 18:34 ` [PATCH v15 3/6] rust: drm: gem: Add vmap functions to shmem bindings Lyude Paul
2026-05-30 5:06 ` sashiko-bot
2026-05-29 18:34 ` [PATCH v15 4/6] rust: faux: Allow retrieving a bound Device Lyude Paul
2026-05-30 5:14 ` sashiko-bot
2026-05-29 18:34 ` [PATCH v15 5/6] drm/gem/shmem: Introduce __drm_gem_shmem_free_sgt_locked() Lyude Paul
2026-05-30 5:28 ` sashiko-bot
2026-05-29 18:34 ` [PATCH v15 6/6] rust: drm: gem: Introduce shmem::Object::sg_table() Lyude Paul
2026-05-30 5:50 ` 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=20260530055027.6B09A1F00893@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox