[PATCH v13 1/4] rust: types: Add Ownable/Owned types

Gary Guo gary at garyguo.net
Mon Feb 2 12:29:28 UTC 2026


On Mon Feb 2, 2026 at 9:37 AM GMT, Andreas Hindborg wrote:
> Gary Guo <gary at garyguo.net> writes:
>
>> On Mon, 17 Nov 2025 10:07:40 +0000
>> Oliver Mangold <oliver.mangold at pm.me> wrote:
>>
>>> From: Asahi Lina <lina+kernel at asahilina.net>
>>> 
>>> By analogy to `AlwaysRefCounted` and `ARef`, an `Ownable` type is a
>>> (typically C FFI) type that *may* be owned by Rust, but need not be. Unlike
>>> `AlwaysRefCounted`, this mechanism expects the reference to be unique
>>> within Rust, and does not allow cloning.
>>> 
>>> Conceptually, this is similar to a `KBox<T>`, except that it delegates
>>> resource management to the `T` instead of using a generic allocator.
>>> 
>>> [ om:
>>>   - Split code into separate file and `pub use` it from types.rs.
>>>   - Make from_raw() and into_raw() public.
>>>   - Remove OwnableMut, and make DerefMut dependent on Unpin instead.
>>>   - Usage example/doctest for Ownable/Owned.
>>>   - Fixes to documentation and commit message.
>>> ]
>>> 
>>> Link: https://lore.kernel.org/all/20250202-rust-page-v1-1-e3170d7fe55e@asahilina.net/
>>> Signed-off-by: Asahi Lina <lina+kernel at asahilina.net>
>>> Co-developed-by: Oliver Mangold <oliver.mangold at pm.me>
>>> Signed-off-by: Oliver Mangold <oliver.mangold at pm.me>
>>> Co-developed-by: Andreas Hindborg <a.hindborg at kernel.org>
>>> Signed-off-by: Andreas Hindborg <a.hindborg at kernel.org>
>>> Reviewed-by: Boqun Feng <boqun.feng at gmail.com>
>>> ---
>>>  rust/kernel/lib.rs       |   1 +
>>>  rust/kernel/owned.rs     | 195 +++++++++++++++++++++++++++++++++++++++++++++++
>>>  rust/kernel/sync/aref.rs |   5 ++
>>>  rust/kernel/types.rs     |   2 +
>>>  4 files changed, 203 insertions(+)
>>> 
>>> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
>>> index 3dd7bebe7888..e0ee04330dd0 100644
>>> --- a/rust/kernel/lib.rs
>>> +++ b/rust/kernel/lib.rs
>>> @@ -112,6 +112,7 @@
>>>  pub mod of;
>>>  #[cfg(CONFIG_PM_OPP)]
>>>  pub mod opp;
>>> +pub mod owned;
>>>  pub mod page;
>>>  #[cfg(CONFIG_PCI)]
>>>  pub mod pci;
>>> diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs
>>> new file mode 100644
>>> index 000000000000..a2cdd2cb8a10
>>> --- /dev/null
>>> +++ b/rust/kernel/owned.rs
>>> @@ -0,0 +1,195 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +
>>> +//! Unique owned pointer types for objects with custom drop logic.
>>> +//!
>>> +//! These pointer types are useful for C-allocated objects which by API-contract
>>> +//! are owned by Rust, but need to be freed through the C API.
>>> +
>>> +use core::{
>>> +    mem::ManuallyDrop,
>>> +    ops::{Deref, DerefMut},
>>> +    pin::Pin,
>>> +    ptr::NonNull,
>>> +};
>>> +
>>> +/// Type allocated and destroyed on the C side, but owned by Rust.
>>
>> The example given in the documentation below shows a valid way of
>> defining a type that's handled on the Rust side, so I think this
>> message is somewhat inaccurate.
>>
>> Perhaps something like
>>
>> 	Types that specify their own way of performing allocation and
>> 	destruction. Typically, this trait is implemented on types from
>> 	the C side.
>
> Thanks, I'll use this.
>
>>
>> ?
>>
>>> +///
>>> +/// Implementing this trait allows types to be referenced via the [`Owned<Self>`] pointer type. This
>>> +/// is useful when it is desirable to tie the lifetime of the reference to an owned object, rather
>>> +/// than pass around a bare reference. [`Ownable`] types can define custom drop logic that is
>>> +/// executed when the owned reference [`Owned<Self>`] pointing to the object is dropped.
>>> +///
>>> +/// Note: The underlying object is not required to provide internal reference counting, because it
>>> +/// represents a unique, owned reference. If reference counting (on the Rust side) is required,
>>> +/// [`AlwaysRefCounted`](crate::types::AlwaysRefCounted) should be implemented.
>>> +///
>>> +/// # Safety
>>> +///
>>> +/// Implementers must ensure that the [`release()`](Self::release) function frees the underlying
>>> +/// object in the correct way for a valid, owned object of this type.
>>> +///
>>> +/// # Examples
>>> +///
>>> +/// A minimal example implementation of [`Ownable`] and its usage with [`Owned`] looks like this:
>>> +///
>>> +/// ```
>>> +/// # #![expect(clippy::disallowed_names)]
>>> +/// # use core::cell::Cell;
>>> +/// # use core::ptr::NonNull;
>>> +/// # use kernel::sync::global_lock;
>>> +/// # use kernel::alloc::{flags, kbox::KBox, AllocError};
>>> +/// # use kernel::types::{Owned, Ownable};
>>> +///
>>> +/// // Let's count the allocations to see if freeing works.
>>> +/// kernel::sync::global_lock! {
>>> +///     // SAFETY: we call `init()` right below, before doing anything else.
>>> +///     unsafe(uninit) static FOO_ALLOC_COUNT: Mutex<usize> = 0;
>>> +/// }
>>> +/// // SAFETY: We call `init()` only once, here.
>>> +/// unsafe { FOO_ALLOC_COUNT.init() };
>>> +///
>>> +/// struct Foo {
>>> +/// }
>>> +///
>>> +/// impl Foo {
>>> +///     fn new() -> Result<Owned<Self>, AllocError> {
>>> +///         // We are just using a `KBox` here to handle the actual allocation, as our `Foo` is
>>> +///         // not actually a C-allocated object.
>>> +///         let result = KBox::new(
>>> +///             Foo {},
>>> +///             flags::GFP_KERNEL,
>>> +///         )?;
>>> +///         let result = NonNull::new(KBox::into_raw(result))
>>> +///             .expect("Raw pointer to newly allocation KBox is null, this should never happen.");
>>> +///         // Count new allocation
>>> +///         *FOO_ALLOC_COUNT.lock() += 1;
>>> +///         // SAFETY: We just allocated the `Self`, thus it is valid and there cannot be any other
>>> +///         // Rust references. Calling `into_raw()` makes us responsible for ownership and we won't
>>> +///         // use the raw pointer anymore. Thus we can transfer ownership to the `Owned`.
>>> +///         Ok(unsafe { Owned::from_raw(result) })
>>> +///     }
>>> +/// }
>>> +///
>>> +/// // SAFETY: What out `release()` function does is safe of any valid `Self`.
>>
>> I can't parse this sentence. Is "out" supposed to be a different word?
>
> I think it should be "our".
>
>>
>>> +/// unsafe impl Ownable for Foo {
>>> +///     unsafe fn release(this: NonNull<Self>) {
>>> +///         // The `Foo` will be dropped when `KBox` goes out of scope.
>>
>> I would just write `drop(unsafe { ... })` to make drop explicit instead
>> of commenting about the implicit drop.
>
> Agree, that is easier to read.
>
>>
>>> +///         // SAFETY: The [`KBox<Self>`] is still alive. We can pass ownership to the [`KBox`], as
>>> +///         // by requirement on calling this function, the `Self` will no longer be used by the
>>> +///         // caller.
>>> +///         unsafe { KBox::from_raw(this.as_ptr()) };
>>> +///         // Count released allocation
>>> +///         *FOO_ALLOC_COUNT.lock() -= 1;
>>> +///     }
>>> +/// }
>>> +///
>>> +/// {
>>> +///    let foo = Foo::new().expect("Failed to allocate a Foo. This shouldn't happen");
>>> +///    assert!(*FOO_ALLOC_COUNT.lock() == 1);
>>> +/// }
>>> +/// // `foo` is out of scope now, so we expect no live allocations.
>>> +/// assert!(*FOO_ALLOC_COUNT.lock() == 0);
>>> +/// ```
>>> +pub unsafe trait Ownable {
>>> +    /// Releases the object.
>>> +    ///
>>> +    /// # Safety
>>> +    ///
>>> +    /// Callers must ensure that:
>>> +    /// - `this` points to a valid `Self`.
>>> +    /// - `*this` is no longer used after this call.
>>> +    unsafe fn release(this: NonNull<Self>);
>>> +}
>>> +
>>> +/// An owned reference to an owned `T`.
>>> +///
>>> +/// The [`Ownable`] is automatically freed or released when an instance of [`Owned`] is
>>> +/// dropped.
>>> +///
>>> +/// # Invariants
>>> +///
>>> +/// - The [`Owned<T>`] has exclusive access to the instance of `T`.
>>> +/// - The instance of `T` will stay alive at least as long as the [`Owned<T>`] is alive.
>>> +pub struct Owned<T: Ownable> {
>>> +    ptr: NonNull<T>,
>>> +}
>>> +
>>> +// SAFETY: It is safe to send an [`Owned<T>`] to another thread when the underlying `T` is [`Send`],
>>> +// because of the ownership invariant. Sending an [`Owned<T>`] is equivalent to sending the `T`.
>>> +unsafe impl<T: Ownable + Send> Send for Owned<T> {}
>>> +
>>> +// SAFETY: It is safe to send [`&Owned<T>`] to another thread when the underlying `T` is [`Sync`],
>>> +// because of the ownership invariant. Sending an [`&Owned<T>`] is equivalent to sending the `&T`.
>>> +unsafe impl<T: Ownable + Sync> Sync for Owned<T> {}
>>> +
>>> +impl<T: Ownable> Owned<T> {
>>> +    /// Creates a new instance of [`Owned`].
>>> +    ///
>>> +    /// It takes over ownership of the underlying object.
>>> +    ///
>>> +    /// # Safety
>>> +    ///
>>> +    /// Callers must ensure that:
>>> +    /// - `ptr` points to a valid instance of `T`.
>>> +    /// - Ownership of the underlying `T` can be transferred to the `Self<T>` (i.e. operations
>>> +    ///   which require ownership will be safe).
>>> +    /// - No other Rust references to the underlying object exist. This implies that the underlying
>>> +    ///   object is not accessed through `ptr` anymore after the function call (at least until the
>>> +    ///   the `Self<T>` is dropped.
>>
>> Is this correct? If `Self<T>` is dropped then `T::release` is called so
>> the pointer should also not be accessed further?
>
> I can't follow you point here. Are you saying that the requirement is
> wrong because `T::release` will access the object by reference? If so,
> that is part of `Owned<_>::drop`, which is explicitly mentioned in the
> comment (until .. dropped).

I meant that the `Self<T>` is dropped, the object is destroyed so it should also
not be accessed further. Perhaps just remove the "(at least ...)" part from
comment.

>
>>
>>> +    /// - The C code follows the usual shared reference requirements. That is, the kernel will never
>>> +    ///   mutate or free the underlying object (excluding interior mutability that follows the usual
>>> +    ///   rules) while Rust owns it.
>>
>> The concept "interior mutability" doesn't really exist on the C side.
>> Also, use of interior mutability (by UnsafeCell) would be incorrect if
>> the type is implemented in the rust side (as this requires a
>> UnsafePinned).
>>
>> Interior mutability means things can be mutated behind a shared
>> reference -- however in this case, we have a mutable reference (either
>> `Pin<&mut Self>` or `&mut Self`)!
>>
>> Perhaps together with the next line, they could be just phrased like
>> this?
>>
>> - The underlying object must not be accessed (read or mutated) through
>>   any pointer other than the created `Owned<T>`.
>>   Opt-out is still possbile similar to a mutable reference (e.g. by
>>   using p`Opaque`]). 
>>
>> I think we should just tell the user "this is just a unique reference
>> similar to &mut". They should be able to deduce that all the `!Unpin`
>> that opts out from uniqueness of mutable reference applies here too.
>
> I agree. I would suggest updating the struct documentation:
>
>     @@ -108,7 +108,7 @@ pub unsafe trait Ownable {
>         unsafe fn release(this: NonNull<Self>);
>     }
>
>     -/// An owned reference to an owned `T`.
>     +/// An mutable reference to an owned `T`.
>     ///
>     /// The [`Ownable`] is automatically freed or released when an instance of [`Owned`] is
>     /// dropped.
>
> And then the safety requirement as
>
>  An `Owned<T>` is a mutable reference to the underlying object. As such,
>  the object must not be accessed (read or mutated) through any pointer
>  other than the created `Owned<T>`. Opt-out is still possbile similar to
>  a mutable reference (e.g. by using [`Opaque`]).

Sounds good to me.

>
>
>>> +    /// - In case `T` implements [`Unpin`] the previous requirement is extended from shared to
>>> +    ///   mutable reference requirements. That is, the kernel will not mutate or free the underlying
>>> +    ///   object and is okay with it being modified by Rust code.
>>
>> - If `T` implements [`Unpin`], the structure must not be mutated for
>>   the entire lifetime of `Owned<T>`.
>
> Would it be OK to just write "If `T: Unpin`, the ..."?
>
> Again, opt out is possible, right?
>

When the "mutable reference" framing above I think you can just drop this part.

>>
>>> +    pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
>>
>> This needs a (rather trivial) INVARIANT comment.
>
> OK.
>
>>
>>> +        Self {
>>> +            ptr,
>>> +        }
>>> +    }
>>> +
>>> +    /// Consumes the [`Owned`], returning a raw pointer.
>>> +    ///
>>> +    /// This function does not actually relinquish ownership of the object. After calling this
>>
>> Perhaps "relinquish" isn't the best word here? In my mental model
>> this function is pretty much relinquishing ownership as `Owned<T>` no
>> longer exists. It just doesn't release the object.
>
> How about this:
>
>
>     /// Consumes the [`Owned`], returning a raw pointer.
>     ///
>     /// This function does not drop the underlying `T`. When this function returns, ownership of the
>     /// underlying `T` is with the caller.

SGTM.

>
>
> Thanks for the comments!

Best,
Gary

>
>
> Best regards,
> Andreas Hindborg




More information about the Linux-security-module-archive mailing list