On Fri, Jun 5, 2026 at 4:41 PM Boqun Feng <[email protected]> wrote:
>
> On Fri, Jun 05, 2026 at 01:49:35PM +0000, [email protected] wrote:
> > Thank you for your contribution! Sashiko AI review found 2 potential 
> > issue(s) to consider:
> > - [Critical] RcuBox::into_foreign drops `self` instead of forgetting it, 
> > causing a guaranteed Use-After-Free.
> > - [High] RcuBox::drop bypasses the custom Allocator A and hardcodes 
> > kvfree_call_rcu() for types that do not require dropping, causing undefined 
> > behavior for non-kvfree compatible allocators.
> > --
> >
> > commit f69c06884595bb68a76f4f1dd4014ee9e2c9e31c
> > Author: Alice Ryhl <[email protected]>
> >
> > rust: rcu: add RcuBox type
> >
> > This adds an RcuBox container, which is like Box except that the value
> > is freed after waiting for one grace period (via {kvfree_,}call_rcu()).
> > To allow containers to rely on the RCU properties of RcuBox, an
> > extension of ForeignOwnable is added.
> >
> > > diff --git a/rust/kernel/sync/rcu/rcu_box.rs 
> > > b/rust/kernel/sync/rcu/rcu_box.rs
> > > new file mode 100644
> > > index 0000000000000..943fe3e8974e0
> > > --- /dev/null
> > > +++ b/rust/kernel/sync/rcu/rcu_box.rs
> >
> > [ ... ]
> >
> > > +// SAFETY:
> > > +// * The `RcuBoxInner<T>` was allocated with `A`.
> > > +// * `NonNull::as_ptr` returns a non-null pointer.
> > > +unsafe impl<T: Send + 'static, A: Allocator> ForeignOwnable for 
> > > RcuBox<T, A> {
> > > +    const FOREIGN_ALIGN: usize = <Box<RcuBoxInner<T>, A> as 
> > > ForeignOwnable>::FOREIGN_ALIGN;
> > > +
> > > +    type Borrowed<'a> = &'a T;
> > > +    type BorrowedMut<'a> = &'a T;
> > > +
> > > +    fn into_foreign(self) -> *mut c_void {
> > > +        self.0.as_ptr().cast()
> > > +    }
> >
> > [Severity: Critical]
> > Since `self` is consumed by value here without being wrapped in 
> > `ManuallyDrop`
> > or passed to `core::mem::forget()`, won't it be dropped at the end of this
> > method?
> >
> > This seems like it would immediately schedule the memory for RCU free, 
> > causing
> > a use-after-free for the foreign code when it later accesses the pointer.
> >
>
> [Cc Alice]
>
> I fixed this locally by:
>
>     fn into_foreign(self) -> *mut c_void {
>         let ptr = self.0.as_ptr().cast();
>
>         // FORGET: Leaking it as a pointer, the caller is responsible to free 
> it or unleak it by
>         // from_foreign().
>         core::mem::forget(self);
>
>         ptr
>     }

I prefer to avoid use core::mem::forget.

    ManuallyDrop(self).0.as_ptr().cast()

Alice

Reply via email to