[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aBS0ZP9tFnujvodq@google.com>
Date: Fri, 2 May 2025 12:02:44 +0000
From: Alice Ryhl <aliceryhl@...gle.com>
To: Andreas Hindborg <a.hindborg@...nel.org>
Cc: Miguel Ojeda <ojeda@...nel.org>, Alex Gaynor <alex.gaynor@...il.com>,
Boqun Feng <boqun.feng@...il.com>, Gary Guo <gary@...yguo.net>,
"Björn Roy Baron" <bjorn3_gh@...tonmail.com>, Benno Lossin <benno.lossin@...ton.me>,
Trevor Gross <tmgross@...ch.edu>, Danilo Krummrich <dakr@...nel.org>,
Oliver Mangold <oliver.mangold@...me>, rust-for-linux@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH] rust: elaborate safety requirements for `AlwaysReferenceCounted`
On Fri, May 02, 2025 at 01:53:57PM +0200, Andreas Hindborg wrote:
> Clarify that implementers of `AlwaysReferenceCounted` must prevent the
> implementer from being directly initialized by users.
>
> It is a violation of the safety requirements of `AlwaysReferenceCounted` if
> its implementers can be initialized on the stack by users. Although this
> follows from the safety requirements, it is not immediately obvious.
>
> The following example demonstrates the issue. Note that the safety
> requirements for implementing `AlwaysRefCounted` and for calling
> `ARef::from_raw` are satisfied.
>
> struct Empty {}
>
> unsafe impl AlwaysRefCounted for Empty {
> fn inc_ref(&self) {}
> unsafe fn dec_ref(_obj: NonNull<Self>) {}
> }
>
> fn unsound() -> ARef<Empty> {
> use core::ptr::NonNull;
> use kernel::types::{ARef, RefCounted};
>
> let mut data = Empty {};
> let ptr = NonNull::<Empty>::new(&mut data).unwrap();
> let aref: ARef<Empty> = unsafe { ARef::from_raw(ptr) };
>
> aref
> }
I don't think it's entirely impossible to write an AlwaysRefCounted
value that can be on the stack. The type just needs a lifetime
parameter. For example, this API is not unsound:
struct MyDataStorage {
// ...
}
impl MyDataStorage {
fn as_aref(&self) -> ARef<MyData<'_>> {
unsafe { ARef::from_raw(ptr::from_ref(self).cast()) }
}
}
#[repr(transparent)]
struct MyData<'s> {
storage: MyDataStorage,
_lifetime: PhantomData<&'s MyDataStorage>,
}
unsafe impl AlwaysRefCounted for MyData<'_> {
fn inc_ref(&self) {}
unsafe fn dec_ref(_obj: NonNull<Self>) {}
}
impl Deref for MyData<'_> {
type Target = MyDataStorage;
fn deref(&self) -> &MyDataStorage {
&self.storage
}
}
Alice
Powered by blists - more mailing lists