Skip to content

Commit 1a4736c

Browse files
tamirdAndreas Hindborg
authored andcommitted
rust: types: add ForeignOwnable::PointedTo
Allow implementors to specify the foreign pointer type; this exposes information about the pointed-to type such as its alignment. This requires the trait to be `unsafe` since it is now possible for implementors to break soundness by returning a misaligned pointer. Encoding the pointer type in the trait (and avoiding pointer casts) allows the compiler to check that implementors return the correct pointer type. This is preferable to directly encoding the alignment in the trait using a constant as the compiler would be unable to check it. Acked-by: Danilo Krummrich <dakr@kernel.org> Signed-off-by: Tamir Duberstein <tamird@gmail.com> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Link: https://lore.kernel.org/r/20250423-rust-xarray-bindings-v19-1-83cdcf11c114@gmail.com Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
1 parent 9c32cda commit 1a4736c

File tree

6 files changed

+70
-49
lines changed

6 files changed

+70
-49
lines changed

rust/kernel/alloc/kbox.rs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -360,68 +360,70 @@ where
360360
}
361361
}
362362

363-
impl<T: 'static, A> ForeignOwnable for Box<T, A>
363+
// SAFETY: The `into_foreign` function returns a pointer that is well-aligned.
364+
unsafe impl<T: 'static, A> ForeignOwnable for Box<T, A>
364365
where
365366
A: Allocator,
366367
{
368+
type PointedTo = T;
367369
type Borrowed<'a> = &'a T;
368370
type BorrowedMut<'a> = &'a mut T;
369371

370-
fn into_foreign(self) -> *mut crate::ffi::c_void {
371-
Box::into_raw(self).cast()
372+
fn into_foreign(self) -> *mut Self::PointedTo {
373+
Box::into_raw(self)
372374
}
373375

374-
unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self {
376+
unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self {
375377
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
376378
// call to `Self::into_foreign`.
377-
unsafe { Box::from_raw(ptr.cast()) }
379+
unsafe { Box::from_raw(ptr) }
378380
}
379381

380-
unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> &'a T {
382+
unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> &'a T {
381383
// SAFETY: The safety requirements of this method ensure that the object remains alive and
382384
// immutable for the duration of 'a.
383-
unsafe { &*ptr.cast() }
385+
unsafe { &*ptr }
384386
}
385387

386-
unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> &'a mut T {
387-
let ptr = ptr.cast();
388+
unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> &'a mut T {
388389
// SAFETY: The safety requirements of this method ensure that the pointer is valid and that
389390
// nothing else will access the value for the duration of 'a.
390391
unsafe { &mut *ptr }
391392
}
392393
}
393394

394-
impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>
395+
// SAFETY: The `into_foreign` function returns a pointer that is well-aligned.
396+
unsafe impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>
395397
where
396398
A: Allocator,
397399
{
400+
type PointedTo = T;
398401
type Borrowed<'a> = Pin<&'a T>;
399402
type BorrowedMut<'a> = Pin<&'a mut T>;
400403

401-
fn into_foreign(self) -> *mut crate::ffi::c_void {
404+
fn into_foreign(self) -> *mut Self::PointedTo {
402405
// SAFETY: We are still treating the box as pinned.
403-
Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }).cast()
406+
Box::into_raw(unsafe { Pin::into_inner_unchecked(self) })
404407
}
405408

406-
unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self {
409+
unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self {
407410
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
408411
// call to `Self::into_foreign`.
409-
unsafe { Pin::new_unchecked(Box::from_raw(ptr.cast())) }
412+
unsafe { Pin::new_unchecked(Box::from_raw(ptr)) }
410413
}
411414

412-
unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> Pin<&'a T> {
415+
unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> Pin<&'a T> {
413416
// SAFETY: The safety requirements for this function ensure that the object is still alive,
414417
// so it is safe to dereference the raw pointer.
415418
// The safety requirements of `from_foreign` also ensure that the object remains alive for
416419
// the lifetime of the returned value.
417-
let r = unsafe { &*ptr.cast() };
420+
let r = unsafe { &*ptr };
418421

419422
// SAFETY: This pointer originates from a `Pin<Box<T>>`.
420423
unsafe { Pin::new_unchecked(r) }
421424
}
422425

423-
unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> Pin<&'a mut T> {
424-
let ptr = ptr.cast();
426+
unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> Pin<&'a mut T> {
425427
// SAFETY: The safety requirements for this function ensure that the object is still alive,
426428
// so it is safe to dereference the raw pointer.
427429
// The safety requirements of `from_foreign` also ensure that the object remains alive for

rust/kernel/miscdevice.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
200200
// type.
201201
//
202202
// SAFETY: The open call of a file can access the private data.
203-
unsafe { (*raw_file).private_data = ptr.into_foreign() };
203+
unsafe { (*raw_file).private_data = ptr.into_foreign().cast() };
204204

205205
0
206206
}
@@ -211,7 +211,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
211211
/// must be associated with a `MiscDeviceRegistration<T>`.
212212
unsafe extern "C" fn release(_inode: *mut bindings::inode, file: *mut bindings::file) -> c_int {
213213
// SAFETY: The release call of a file owns the private data.
214-
let private = unsafe { (*file).private_data };
214+
let private = unsafe { (*file).private_data }.cast();
215215
// SAFETY: The release call of a file owns the private data.
216216
let ptr = unsafe { <T::Ptr as ForeignOwnable>::from_foreign(private) };
217217

@@ -228,7 +228,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
228228
/// `file` must be a valid file that is associated with a `MiscDeviceRegistration<T>`.
229229
unsafe extern "C" fn ioctl(file: *mut bindings::file, cmd: c_uint, arg: c_ulong) -> c_long {
230230
// SAFETY: The ioctl call of a file can access the private data.
231-
let private = unsafe { (*file).private_data };
231+
let private = unsafe { (*file).private_data }.cast();
232232
// SAFETY: Ioctl calls can borrow the private data of the file.
233233
let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
234234

@@ -253,7 +253,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
253253
arg: c_ulong,
254254
) -> c_long {
255255
// SAFETY: The compat ioctl call of a file can access the private data.
256-
let private = unsafe { (*file).private_data };
256+
let private = unsafe { (*file).private_data }.cast();
257257
// SAFETY: Ioctl calls can borrow the private data of the file.
258258
let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
259259

@@ -274,7 +274,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
274274
/// - `seq_file` must be a valid `struct seq_file` that we can write to.
275275
unsafe extern "C" fn show_fdinfo(seq_file: *mut bindings::seq_file, file: *mut bindings::file) {
276276
// SAFETY: The release call of a file owns the private data.
277-
let private = unsafe { (*file).private_data };
277+
let private = unsafe { (*file).private_data }.cast();
278278
// SAFETY: Ioctl calls can borrow the private data of the file.
279279
let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
280280
// SAFETY:

rust/kernel/pci.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl<T: Driver + 'static> Adapter<T> {
8989
extern "C" fn remove_callback(pdev: *mut bindings::pci_dev) {
9090
// SAFETY: The PCI bus only ever calls the remove callback with a valid pointer to a
9191
// `struct pci_dev`.
92-
let ptr = unsafe { bindings::pci_get_drvdata(pdev) };
92+
let ptr = unsafe { bindings::pci_get_drvdata(pdev) }.cast();
9393

9494
// SAFETY: `remove_callback` is only ever called after a successful call to
9595
// `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized

rust/kernel/platform.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl<T: Driver + 'static> Adapter<T> {
8080

8181
extern "C" fn remove_callback(pdev: *mut bindings::platform_device) {
8282
// SAFETY: `pdev` is a valid pointer to a `struct platform_device`.
83-
let ptr = unsafe { bindings::platform_get_drvdata(pdev) };
83+
let ptr = unsafe { bindings::platform_get_drvdata(pdev) }.cast();
8484

8585
// SAFETY: `remove_callback` is only ever called after a successful call to
8686
// `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized

rust/kernel/sync/arc.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,10 @@ pub struct Arc<T: ?Sized> {
140140
_p: PhantomData<ArcInner<T>>,
141141
}
142142

143+
#[doc(hidden)]
143144
#[pin_data]
144145
#[repr(C)]
145-
struct ArcInner<T: ?Sized> {
146+
pub struct ArcInner<T: ?Sized> {
146147
refcount: Opaque<bindings::refcount_t>,
147148
data: T,
148149
}
@@ -371,36 +372,38 @@ impl<T: ?Sized> Arc<T> {
371372
}
372373
}
373374

374-
impl<T: 'static> ForeignOwnable for Arc<T> {
375+
// SAFETY: The `into_foreign` function returns a pointer that is well-aligned.
376+
unsafe impl<T: 'static> ForeignOwnable for Arc<T> {
377+
type PointedTo = ArcInner<T>;
375378
type Borrowed<'a> = ArcBorrow<'a, T>;
376379
type BorrowedMut<'a> = Self::Borrowed<'a>;
377380

378-
fn into_foreign(self) -> *mut crate::ffi::c_void {
379-
ManuallyDrop::new(self).ptr.as_ptr().cast()
381+
fn into_foreign(self) -> *mut Self::PointedTo {
382+
ManuallyDrop::new(self).ptr.as_ptr()
380383
}
381384

382-
unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self {
385+
unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self {
383386
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
384387
// call to `Self::into_foreign`.
385-
let inner = unsafe { NonNull::new_unchecked(ptr.cast::<ArcInner<T>>()) };
388+
let inner = unsafe { NonNull::new_unchecked(ptr) };
386389

387390
// SAFETY: By the safety requirement of this function, we know that `ptr` came from
388391
// a previous call to `Arc::into_foreign`, which guarantees that `ptr` is valid and
389392
// holds a reference count increment that is transferrable to us.
390393
unsafe { Self::from_inner(inner) }
391394
}
392395

393-
unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> ArcBorrow<'a, T> {
396+
unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> ArcBorrow<'a, T> {
394397
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
395398
// call to `Self::into_foreign`.
396-
let inner = unsafe { NonNull::new_unchecked(ptr.cast::<ArcInner<T>>()) };
399+
let inner = unsafe { NonNull::new_unchecked(ptr) };
397400

398401
// SAFETY: The safety requirements of `from_foreign` ensure that the object remains alive
399402
// for the lifetime of the returned value.
400403
unsafe { ArcBorrow::new(inner) }
401404
}
402405

403-
unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> ArcBorrow<'a, T> {
406+
unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> ArcBorrow<'a, T> {
404407
// SAFETY: The safety requirements for `borrow_mut` are a superset of the safety
405408
// requirements for `borrow`.
406409
unsafe { Self::borrow(ptr) }

rust/kernel/types.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,19 @@ use pin_init::{PinInit, Zeroable};
1818
///
1919
/// This trait is meant to be used in cases when Rust objects are stored in C objects and
2020
/// eventually "freed" back to Rust.
21-
pub trait ForeignOwnable: Sized {
21+
///
22+
/// # Safety
23+
///
24+
/// Implementers must ensure that [`into_foreign`] returns a pointer which meets the alignment
25+
/// requirements of [`PointedTo`].
26+
///
27+
/// [`into_foreign`]: Self::into_foreign
28+
/// [`PointedTo`]: Self::PointedTo
29+
pub unsafe trait ForeignOwnable: Sized {
30+
/// Type used when the value is foreign-owned. In practical terms only defines the alignment of
31+
/// the pointer.
32+
type PointedTo;
33+
2234
/// Type used to immutably borrow a value that is currently foreign-owned.
2335
type Borrowed<'a>;
2436

@@ -27,16 +39,18 @@ pub trait ForeignOwnable: Sized {
2739

2840
/// Converts a Rust-owned object to a foreign-owned one.
2941
///
30-
/// The foreign representation is a pointer to void. There are no guarantees for this pointer.
31-
/// For example, it might be invalid, dangling or pointing to uninitialized memory. Using it in
32-
/// any way except for [`from_foreign`], [`try_from_foreign`], [`borrow`], or [`borrow_mut`] can
33-
/// result in undefined behavior.
42+
/// # Guarantees
43+
///
44+
/// The return value is guaranteed to be well-aligned, but there are no other guarantees for
45+
/// this pointer. For example, it might be null, dangling, or point to uninitialized memory.
46+
/// Using it in any way except for [`ForeignOwnable::from_foreign`], [`ForeignOwnable::borrow`],
47+
/// [`ForeignOwnable::try_from_foreign`] can result in undefined behavior.
3448
///
3549
/// [`from_foreign`]: Self::from_foreign
3650
/// [`try_from_foreign`]: Self::try_from_foreign
3751
/// [`borrow`]: Self::borrow
3852
/// [`borrow_mut`]: Self::borrow_mut
39-
fn into_foreign(self) -> *mut crate::ffi::c_void;
53+
fn into_foreign(self) -> *mut Self::PointedTo;
4054

4155
/// Converts a foreign-owned object back to a Rust-owned one.
4256
///
@@ -46,7 +60,7 @@ pub trait ForeignOwnable: Sized {
4660
/// must not be passed to `from_foreign` more than once.
4761
///
4862
/// [`into_foreign`]: Self::into_foreign
49-
unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self;
63+
unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self;
5064

5165
/// Tries to convert a foreign-owned object back to a Rust-owned one.
5266
///
@@ -58,7 +72,7 @@ pub trait ForeignOwnable: Sized {
5872
/// `ptr` must either be null or satisfy the safety requirements for [`from_foreign`].
5973
///
6074
/// [`from_foreign`]: Self::from_foreign
61-
unsafe fn try_from_foreign(ptr: *mut crate::ffi::c_void) -> Option<Self> {
75+
unsafe fn try_from_foreign(ptr: *mut Self::PointedTo) -> Option<Self> {
6276
if ptr.is_null() {
6377
None
6478
} else {
@@ -81,7 +95,7 @@ pub trait ForeignOwnable: Sized {
8195
///
8296
/// [`into_foreign`]: Self::into_foreign
8397
/// [`from_foreign`]: Self::from_foreign
84-
unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> Self::Borrowed<'a>;
98+
unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> Self::Borrowed<'a>;
8599

86100
/// Borrows a foreign-owned object mutably.
87101
///
@@ -109,21 +123,23 @@ pub trait ForeignOwnable: Sized {
109123
/// [`from_foreign`]: Self::from_foreign
110124
/// [`borrow`]: Self::borrow
111125
/// [`Arc`]: crate::sync::Arc
112-
unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> Self::BorrowedMut<'a>;
126+
unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> Self::BorrowedMut<'a>;
113127
}
114128

115-
impl ForeignOwnable for () {
129+
// SAFETY: The `into_foreign` function returns a pointer that is dangling, but well-aligned.
130+
unsafe impl ForeignOwnable for () {
131+
type PointedTo = ();
116132
type Borrowed<'a> = ();
117133
type BorrowedMut<'a> = ();
118134

119-
fn into_foreign(self) -> *mut crate::ffi::c_void {
135+
fn into_foreign(self) -> *mut Self::PointedTo {
120136
core::ptr::NonNull::dangling().as_ptr()
121137
}
122138

123-
unsafe fn from_foreign(_: *mut crate::ffi::c_void) -> Self {}
139+
unsafe fn from_foreign(_: *mut Self::PointedTo) -> Self {}
124140

125-
unsafe fn borrow<'a>(_: *mut crate::ffi::c_void) -> Self::Borrowed<'a> {}
126-
unsafe fn borrow_mut<'a>(_: *mut crate::ffi::c_void) -> Self::BorrowedMut<'a> {}
141+
unsafe fn borrow<'a>(_: *mut Self::PointedTo) -> Self::Borrowed<'a> {}
142+
unsafe fn borrow_mut<'a>(_: *mut Self::PointedTo) -> Self::BorrowedMut<'a> {}
127143
}
128144

129145
/// Runs a cleanup function/closure when dropped.

0 commit comments

Comments
 (0)