Skip to content

Commit f0ab9f3

Browse files
committed
Merge tag 'rust-fixes-6.5-rc5' of https://github.com/Rust-for-Linux/linux
Pull rust fixes from Miguel Ojeda: - Allocator: prevent mis-aligned allocation - Types: delete 'ForeignOwnable::borrow_mut'. A sound replacement is planned for the merge window - Build: fix bindgen error with UBSAN_BOUNDS_STRICT * tag 'rust-fixes-6.5-rc5' of https://github.com/Rust-for-Linux/linux: rust: fix bindgen build error with UBSAN_BOUNDS_STRICT rust: delete `ForeignOwnable::borrow_mut` rust: allocator: Prevent mis-aligned allocation
2 parents fb0d919 + b055448 commit f0ab9f3

File tree

5 files changed

+64
-38
lines changed

5 files changed

+64
-38
lines changed

rust/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \
257257
-fno-partial-inlining -fplugin-arg-arm_ssp_per_task_plugin-% \
258258
-fno-reorder-blocks -fno-allow-store-data-races -fasan-shadow-offset=% \
259259
-fzero-call-used-regs=% -fno-stack-clash-protection \
260-
-fno-inline-functions-called-once \
260+
-fno-inline-functions-called-once -fsanitize=bounds-strict \
261261
--param=% --param asan-%
262262

263263
# Derived from `scripts/Makefile.clang`.

rust/bindings/bindings_helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
#include <linux/sched.h>
1414

1515
/* `bindgen` gets confused at certain things. */
16+
const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
1617
const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL;
1718
const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO;

rust/kernel/allocator.rs

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,36 @@ use crate::bindings;
99

1010
struct KernelAllocator;
1111

12+
/// Calls `krealloc` with a proper size to alloc a new object aligned to `new_layout`'s alignment.
13+
///
14+
/// # Safety
15+
///
16+
/// - `ptr` can be either null or a pointer which has been allocated by this allocator.
17+
/// - `new_layout` must have a non-zero size.
18+
unsafe fn krealloc_aligned(ptr: *mut u8, new_layout: Layout, flags: bindings::gfp_t) -> *mut u8 {
19+
// Customized layouts from `Layout::from_size_align()` can have size < align, so pad first.
20+
let layout = new_layout.pad_to_align();
21+
22+
let mut size = layout.size();
23+
24+
if layout.align() > bindings::BINDINGS_ARCH_SLAB_MINALIGN {
25+
// The alignment requirement exceeds the slab guarantee, thus try to enlarge the size
26+
// to use the "power-of-two" size/alignment guarantee (see comments in `kmalloc()` for
27+
// more information).
28+
//
29+
// Note that `layout.size()` (after padding) is guaranteed to be a multiple of
30+
// `layout.align()`, so `next_power_of_two` gives enough alignment guarantee.
31+
size = size.next_power_of_two();
32+
}
33+
34+
// SAFETY:
35+
// - `ptr` is either null or a pointer returned from a previous `k{re}alloc()` by the
36+
// function safety requirement.
37+
// - `size` is greater than 0 since it's either a `layout.size()` (which cannot be zero
38+
// according to the function safety requirement) or a result from `next_power_of_two()`.
39+
unsafe { bindings::krealloc(ptr as *const core::ffi::c_void, size, flags) as *mut u8 }
40+
}
41+
1242
unsafe impl GlobalAlloc for KernelAllocator {
1343
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
1444
// `krealloc()` is used instead of `kmalloc()` because the latter is
@@ -30,10 +60,20 @@ static ALLOCATOR: KernelAllocator = KernelAllocator;
3060
// to extract the object file that has them from the archive. For the moment,
3161
// let's generate them ourselves instead.
3262
//
63+
// Note: Although these are *safe* functions, they are called by the compiler
64+
// with parameters that obey the same `GlobalAlloc` function safety
65+
// requirements: size and align should form a valid layout, and size is
66+
// greater than 0.
67+
//
3368
// Note that `#[no_mangle]` implies exported too, nowadays.
3469
#[no_mangle]
35-
fn __rust_alloc(size: usize, _align: usize) -> *mut u8 {
36-
unsafe { bindings::krealloc(core::ptr::null(), size, bindings::GFP_KERNEL) as *mut u8 }
70+
fn __rust_alloc(size: usize, align: usize) -> *mut u8 {
71+
// SAFETY: See assumption above.
72+
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
73+
74+
// SAFETY: `ptr::null_mut()` is null, per assumption above the size of `layout` is greater
75+
// than 0.
76+
unsafe { krealloc_aligned(ptr::null_mut(), layout, bindings::GFP_KERNEL) }
3777
}
3878

3979
#[no_mangle]
@@ -42,23 +82,27 @@ fn __rust_dealloc(ptr: *mut u8, _size: usize, _align: usize) {
4282
}
4383

4484
#[no_mangle]
45-
fn __rust_realloc(ptr: *mut u8, _old_size: usize, _align: usize, new_size: usize) -> *mut u8 {
46-
unsafe {
47-
bindings::krealloc(
48-
ptr as *const core::ffi::c_void,
49-
new_size,
50-
bindings::GFP_KERNEL,
51-
) as *mut u8
52-
}
85+
fn __rust_realloc(ptr: *mut u8, _old_size: usize, align: usize, new_size: usize) -> *mut u8 {
86+
// SAFETY: See assumption above.
87+
let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, align) };
88+
89+
// SAFETY: Per assumption above, `ptr` is allocated by `__rust_*` before, and the size of
90+
// `new_layout` is greater than 0.
91+
unsafe { krealloc_aligned(ptr, new_layout, bindings::GFP_KERNEL) }
5392
}
5493

5594
#[no_mangle]
56-
fn __rust_alloc_zeroed(size: usize, _align: usize) -> *mut u8 {
95+
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
96+
// SAFETY: See assumption above.
97+
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
98+
99+
// SAFETY: `ptr::null_mut()` is null, per assumption above the size of `layout` is greater
100+
// than 0.
57101
unsafe {
58-
bindings::krealloc(
59-
core::ptr::null(),
60-
size,
102+
krealloc_aligned(
103+
ptr::null_mut(),
104+
layout,
61105
bindings::GFP_KERNEL | bindings::__GFP_ZERO,
62-
) as *mut u8
106+
)
63107
}
64108
}

rust/kernel/sync/arc.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,7 @@ impl<T: 'static> ForeignOwnable for Arc<T> {
243243
let inner = NonNull::new(ptr as *mut ArcInner<T>).unwrap();
244244

245245
// SAFETY: The safety requirements of `from_foreign` ensure that the object remains alive
246-
// for the lifetime of the returned value. Additionally, the safety requirements of
247-
// `ForeignOwnable::borrow_mut` ensure that no new mutable references are created.
246+
// for the lifetime of the returned value.
248247
unsafe { ArcBorrow::new(inner) }
249248
}
250249

rust/kernel/types.rs

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,34 +35,16 @@ pub trait ForeignOwnable: Sized {
3535
///
3636
/// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
3737
/// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
38-
/// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow_mut`]
39-
/// for this object must have been dropped.
4038
unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Self::Borrowed<'a>;
4139

42-
/// Mutably borrows a foreign-owned object.
43-
///
44-
/// # Safety
45-
///
46-
/// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
47-
/// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
48-
/// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and
49-
/// [`ForeignOwnable::borrow_mut`] for this object must have been dropped.
50-
unsafe fn borrow_mut(ptr: *const core::ffi::c_void) -> ScopeGuard<Self, fn(Self)> {
51-
// SAFETY: The safety requirements ensure that `ptr` came from a previous call to
52-
// `into_foreign`.
53-
ScopeGuard::new_with_data(unsafe { Self::from_foreign(ptr) }, |d| {
54-
d.into_foreign();
55-
})
56-
}
57-
5840
/// Converts a foreign-owned object back to a Rust-owned one.
5941
///
6042
/// # Safety
6143
///
6244
/// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
6345
/// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
64-
/// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and
65-
/// [`ForeignOwnable::borrow_mut`] for this object must have been dropped.
46+
/// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] for
47+
/// this object must have been dropped.
6648
unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self;
6749
}
6850

0 commit comments

Comments
 (0)