Create the 'nova_core' root debugfs entry when the driver loads.
The Dir entry is part of the NovaCoreModule, so when the module
unloads, the NovaCoreModule object is dropped, and that drops the
_debugfs_root, which automatically deletes the debugfs file.

Field order in Rust structs determines drop order - fields are dropped
in declaration order. By placing _driver before _debugfs_root:

1. The driver registration is dropped first, which removes all PCI
   devices and their associated debugfs subdirectories
2. Then _debugfs_root is dropped, removing the now-empty nova_core
   directory

This ordering is critical because debugfs_remove() performs recursive
removal. If the parent directory were removed first, it would free the
child dentries, and then the child's drop would attempt to remove an
already-freed dentry, causing a use-after-free crash.

Signed-off-by: Timur Tabi <[email protected]>
---
 drivers/gpu/nova-core/nova_core.rs | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/nova-core/nova_core.rs 
b/drivers/gpu/nova-core/nova_core.rs
index 01353be103ca..f17505e5e2b3 100644
--- a/drivers/gpu/nova-core/nova_core.rs
+++ b/drivers/gpu/nova-core/nova_core.rs
@@ -2,8 +2,7 @@
 
 //! Nova Core GPU Driver
 
-use kernel::{error::Error, pci, prelude::*, InPlaceModule};
-use pin_init::{PinInit, pinned_drop};
+use kernel::{debugfs::Dir, error::Error, pci, prelude::*, InPlaceModule};
 
 #[macro_use]
 mod bitfield;
@@ -24,17 +23,24 @@
 
 pub(crate) const MODULE_NAME: &kernel::str::CStr = <LocalModule as 
kernel::ModuleMetadata>::NAME;
 
-#[pin_data(PinnedDrop)]
+#[pin_data]
 struct NovaCoreModule {
+    // Note: field order matters for drop order. The driver must be dropped 
before
+    // the debugfs directory so that device subdirectories are removed first.
     #[pin]
     _driver: kernel::driver::Registration<pci::Adapter<driver::NovaCore>>,
+    _debugfs_root: Dir,
 }
 
 impl InPlaceModule for NovaCoreModule {
     fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> {
         pr_info!("NovaCore GPU driver loaded\n");
+
+        let debugfs_root = Dir::new(kernel::c_str!("nova_core"));
+
         try_pin_init!(Self {
             _driver <- kernel::driver::Registration::new(MODULE_NAME, module),
+            _debugfs_root: debugfs_root,
         })
     }
 }
-- 
2.52.0

Reply via email to