Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] `DevresGuard` implements `Deref` tying the returned reference's inner lifetime to the `DevresLt` borrow rather than the guard itself, allowing references to escape the RCU read-side lock and causing a use-after-free. --
commit 62b48d10ff277ed9a20edb541dfb07cf0af74ca2 Author: Danilo Krummrich <[email protected]> rust: devres: add DevresLt for ForLt-aware device resource access This commit introduces DevresLt, a wrapper around Devres that safely shortens the synthetic 'static lifetime of stored resources to the caller's borrow lifetime. It provides both direct-reference accessors for CovariantForLt types and closure-based accessors for plain ForLt types. > diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs > index 11ce500e9b76f..b7c075a39ba47 100644 > --- a/rust/kernel/devres.rs > +++ b/rust/kernel/devres.rs [ ... ] > @@ -365,6 +367,110 @@ fn drop(&mut self) { > } > } > > +/// Guard returned by [`DevresLt::try_access`]. > +/// > +/// Dereferences to `F::Of<'a>`, shortening the lifetime of the stored data > to the guard's borrow > +/// lifetime. > +pub struct DevresGuard<'a, F: CovariantForLt>(RevocableGuard<'a, > F::Of<'static>>); > + > +impl<'a, F: CovariantForLt> core::ops::Deref for DevresGuard<'a, F> { > + type Target = F::Of<'a>; > + > + #[inline] > + fn deref(&self) -> &Self::Target { > + F::cast_ref(&*self.0) > + } > +} [Severity: High] Does this allow references to escape the RCU read-side lock and cause a use-after-free? Because Target is F::Of<'a>, the inner lifetime of the returned type is tied to the DevresLt borrow ('a) rather than the guard itself. If a caller extracts a reference from the returned type, it will have the lifetime 'a. The caller can then drop the guard, releasing the RCU read lock, and the device could unbind. This would free the devres allocation while the extracted reference remains alive in safe Rust for the duration of 'a. [ ... ] > +impl<F: CovariantForLt> DevresLt<F> > +where > + for<'a> F::Of<'a>: Send, > +{ [ ... ] > + /// [`DevresLt`] accessor for [`Revocable::try_access`]. > + #[inline] > + pub fn try_access(&self) -> Option<DevresGuard<'_, F>> { > + self.0.data().try_access().map(DevresGuard) > + } > +} [Severity: High] Does this accessor create a guard that enables the lifetime escape mentioned above? By parameterizing DevresGuard with the DevresLt borrow lifetime ('_), this sets up the condition where inner references can outlive the guard itself. -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=5
