]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
rust: devres: initialize Devres::inner::data last
authorDanilo Krummrich <dakr@kernel.org>
Mon, 14 Jul 2025 11:32:35 +0000 (13:32 +0200)
committerDanilo Krummrich <dakr@kernel.org>
Tue, 15 Jul 2025 12:46:09 +0000 (14:46 +0200)
Users may want to access the Devres object from callbacks registered
through the initialization of Devres::inner::data.

For those accesses to be valid, Devres::inner::data must be initialized
last [1].

Credit to Boqun for spotting this [2].

Link: https://lore.kernel.org/lkml/DBBPHO26CPBS.2OVI1OERCB2J5@kernel.org/
Link: https://lore.kernel.org/lkml/aHSmxWeIy3L-AKIV@Mac.home/
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20250714113712.22158-1-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
rust/kernel/devres.rs

index f43de3d77d6159e807871b1b728fbef788dbb163..ac5e5d94ee9637c14ec58d0478f099c7f2777f28 100644 (file)
@@ -137,14 +137,10 @@ impl<T: Send> Devres<T> {
         let callback = Self::devres_callback;
 
         try_pin_init!(&this in Self {
-            // INVARIANT: `inner` is properly initialized.
-            inner <- Opaque::pin_init(try_pin_init!(Inner {
-                data <- Revocable::new(data),
-                devm <- Completion::new(),
-                revoke <- Completion::new(),
-            })),
+            dev: dev.into(),
             callback,
-            dev: {
+            // INVARIANT: `inner` is properly initialized.
+            inner <- {
                 // SAFETY: `this` is a valid pointer to uninitialized memory.
                 let inner = unsafe { &raw mut (*this.as_ptr()).inner };
 
@@ -158,7 +154,11 @@ impl<T: Send> Devres<T> {
                     bindings::devm_add_action(dev.as_raw(), Some(callback), inner.cast())
                 })?;
 
-                dev.into()
+                Opaque::pin_init(try_pin_init!(Inner {
+                    devm <- Completion::new(),
+                    revoke <- Completion::new(),
+                    data <- Revocable::new(data),
+                }))
             },
         })
     }