Skip to content

Commit

Permalink
Fix soundness issue with container_of! macro
Browse files Browse the repository at this point in the history
Previously it was possible to trigger UB from safe code using the
`container_of!` macro. For example:

```rust
struct Foo {
    a: (),
}

fn main() {
    container_of!(core::ptr::null(), Foo, a); // UB
}
```

Using `wrapping_offset` instead of `offset` makes the macro safe to call
for any input.

Signed-off-by: Léo Lanteri Thauvin <[email protected]>
  • Loading branch information
LeSeulArtichaut committed Jul 31, 2021
1 parent 38512f6 commit 2a90d87
Showing 1 changed file with 4 additions and 3 deletions.
7 changes: 4 additions & 3 deletions rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ macro_rules! offset_of {
/// # Safety
///
/// Callers must ensure that the pointer to the field is in fact a pointer to the specified field,
/// as opposed to a pointer to another object of the same type.
/// as opposed to a pointer to another object of the same type. If this condition is not met,
/// any dereference of the resulting pointer is UB.
///
/// # Example
///
Expand All @@ -212,7 +213,7 @@ macro_rules! offset_of {
/// fn test() {
/// let test = Test { a: 10, b: 20 };
/// let b_ptr = &test.b;
/// let test_alias = unsafe { container_of!(b_ptr, Test, b) };
/// let test_alias = container_of!(b_ptr, Test, b);
/// // This prints `true`.
/// pr_info!("{}\n", core::ptr::eq(&test, test_alias));
/// }
Expand All @@ -222,6 +223,6 @@ macro_rules! container_of {
($ptr:expr, $type:ty, $($f:tt)*) => {{
let ptr = $ptr as *const _ as *const u8;
let offset = $crate::offset_of!($type, $($f)*);
unsafe { ptr.offset(-offset) as *const $type }
ptr.wrapping_offset(-offset) as *const $type
}}
}

0 comments on commit 2a90d87

Please sign in to comment.