> On 14 Aug 2026, at 20:21, [email protected] wrote:
> 
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) 
> to consider:
> - [High] Bypassing `T::close` when the DRM device is unregistered leaks 
> driver-specific resources and software state allocated in `T::open`.
> - [High] Wrapping the entire `open` and `close` callbacks in 
> `RegistrationGuard` introduces a severe AB-BA deadlock hazard with the device 
> unplug path.
> --
> 
> --- Patch [2]: [PATCH 2/7] rust: drm: gem: gate open/close callbacks with 
> RegistrationGuard ---
> commit 56b4431da0d3b7c0798814690d882352e01b7d71
> Author: Danilo Krummrich <[email protected]>
> 
> rust: drm: gem: gate open/close callbacks with RegistrationGuard
> 
> Wrap the GEM object open and close callbacks with a RegistrationGuard
> (drm_dev_enter / drm_dev_exit) to ensure the driver callbacks only run
> while the parent bus device is bound.
> 
> If the device has been unbound, open returns -ENODEV and close silently
> returns. This prevents driver code from accessing device resources after
> unbind and is a prerequisite for making drm::Driver::File
> lifetime-parameterized.
> 
>> diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
>> index 80d8f524f9d57..560403ca8e38f 100644
>> --- a/rust/kernel/drm/gem/mod.rs
>> +++ b/rust/kernel/drm/gem/mod.rs
>> @@ -128,6 +128,14 @@ extern "C" fn open_callback<T: DriverObject>(
>>     raw_obj: *mut bindings::drm_gem_object,
>>     raw_file: *mut bindings::drm_file,
>> ) -> core::ffi::c_int {
>> +    // SAFETY: `raw_obj` is a valid pointer to a `struct drm_gem_object` 
>> with a valid `dev`.
>> +    let dev: &drm::Device<T::Driver, drm::Userspace> =
>> +        unsafe { drm::Device::from_raw((*raw_obj).dev) };
>> +
>> +    let Some(_guard) = dev.registration_guard() else {
> 
> [Severity: High]
> Could this cause an AB-BA deadlock with the device unplug path?
> 
> If an unbind thread acquires a driver-specific lock and then calls
> drm_dev_unplug(), it will block in synchronize_srcu(&drm_unplug_srcu)
> waiting for SRCU read sections to finish.
> 
> Concurrently, if a userspace thread opens a GEM handle, this
> registration_guard() call takes the drm_unplug_srcu read lock.
> 
> When the callback proceeds to call T::open(), the driver might try to
> acquire the same driver-specific lock held by the unbind thread, deadlocking
> the system.
> 
>> +        return ENODEV.to_errno();
>> +    };
>> +
>>     // SAFETY: `open_callback` is only ever called with a valid pointer to a 
>> `struct drm_file`.
>>     let file = unsafe { DriverFile::<T>::from_raw(raw_file) };
> 
> [ ... ]
> 
>> @@ -148,6 +156,14 @@ extern "C" fn close_callback<T: DriverObject>(
>>     raw_obj: *mut bindings::drm_gem_object,
>>     raw_file: *mut bindings::drm_file,
>> ) {
>> +    // SAFETY: `raw_obj` is a valid pointer to a `struct drm_gem_object` 
>> with a valid `dev`.
>> +    let dev: &drm::Device<T::Driver, drm::Userspace> =
>> +        unsafe { drm::Device::from_raw((*raw_obj).dev) };
>> +
>> +    let Some(_guard) = dev.registration_guard() else {
>> +        return;
> 
> [Severity: High]
> Is it safe to return early here without calling T::close()?
> 
> If a GEM object is created while the device is bound, and the device is then
> hot-unplugged, the guard check will fail.
> 
> Returning early skips the software cleanup in T::close(), which could
> permanently leak driver-specific memory and state (like tracking lists or IDR
> entries) allocated during T::open().

I wonder if this is a problem in practice? And if so, would passing a e.g.:
Option<&File> be a solution?

From a purely logical perspective, I do agree that a balanced open()/close()
makes more sense than silently skipping close() though.

> 
>> +    };
>> +
>>     // SAFETY: `open_callback` is only ever called with a valid pointer to a 
>> `struct drm_file`.
>>     let file = unsafe { DriverFile::<T>::from_raw(raw_file) };
>> 
> 
> -- 
> Sashiko AI review ยท 
> https://sashiko.dev/#/patchset/[email protected]?part=2

Reply via email to