rust/kernel/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
When trying to use LinkedList in the kernel crate, build fails with an
error message demanding unsafe blocks in the container_of macro:
error[E0133]: call to unsafe function `core::ptr::mut_ptr::<impl *mut T>::byte_sub`
is unsafe and requires unsafe block
--> rust/kernel/lib.rs:252:29
|
252 | let container_ptr = field_ptr.byte_sub(offset).cast::<$Container>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
|
::: rust/kernel/drm/jq.rs:98:1
|
98 | / impl_list_item! {
99 | | impl ListItem<0> for BasicItem { using ListLinks { self.links }; }
100 | | }
| |_- in this macro invocation
|
note: an unsafe function restricts its caller, but its body is safe by default
--> rust/kernel/list/impl_list_item_mod.rs:216:13
|
216 | unsafe fn view_value(me: *mut $crate::list::ListLinks<$num>) -> *const Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
::: rust/kernel/drm/jq.rs:98:1
|
98 | / impl_list_item! {
99 | | impl ListItem<0> for BasicItem { using ListLinks { self.links }; }
100 | | }
| |_- in this macro invocation
= note: requested on the command line with `-D unsafe-op-in-unsafe-fn`
= note: this error originates in the macro `$crate::container_of` which comes
from the expansion of the macro `impl_list_item`
Add unsafe blocks to container_of to fix the issue.
Fixes: b20fbbc08a36 ("rust: check type of `$ptr` in `container_of!`")
Suggested-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Philipp Stanner <phasta@kernel.org>
---
I'm currently writing DrmJobqueue, a new piece of infrastructure. It
uses LinkedList and resides in the kernel crate. When using LinkedList
from within there, for reasons I don't fully understand the error above
shows up.
The other testing infrastructure doesn't seem to run into the error,
though.
P.
---
rust/kernel/lib.rs | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index fef97f2a5098..a26b87015e7d 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -249,8 +249,11 @@ macro_rules! container_of {
($field_ptr:expr, $Container:ty, $($fields:tt)*) => {{
let offset: usize = ::core::mem::offset_of!($Container, $($fields)*);
let field_ptr = $field_ptr;
- let container_ptr = field_ptr.byte_sub(offset).cast::<$Container>();
- $crate::assert_same_type(field_ptr, (&raw const (*container_ptr).$($fields)*).cast_mut());
+ // SAFETY: Offsetting the pointer to the container is correct because the offset was
+ // calculated validly above.
+ let container_ptr = unsafe { field_ptr.byte_sub(offset).cast::<$Container>() };
+ // SAFETY: Safe because the container_ptr was validly created above.
+ $crate::assert_same_type(field_ptr, unsafe { (&raw const (*container_ptr).$($fields)*) }.cast_mut());
container_ptr
}}
}
--
2.49.0
On Fri, Nov 14, 2025 at 3:00 PM Philipp Stanner <phasta@kernel.org> wrote:
>
> Add unsafe blocks to container_of to fix the issue.
The root issue is that we missed unsafe blocks on the list macros
because imported declarative macros from another crate do not respect
`unsafe_op_in_unsafe_fn` (or Edition 2024):
https://github.com/rust-lang/rust/issues/112504
I have added it to our list at:
https://github.com/Rust-for-Linux/linux/issues/355
And tagged it with the Rust for Linux label there.
Cheers,
Miguel
On Fri, 2025-11-14 at 21:21 +0100, Miguel Ojeda wrote: > On Fri, Nov 14, 2025 at 3:00 PM Philipp Stanner <phasta@kernel.org> wrote: > > > > Add unsafe blocks to container_of to fix the issue. > > The root issue is that we missed unsafe blocks on the list macros > because imported declarative macros from another crate do not respect > `unsafe_op_in_unsafe_fn` (or Edition 2024): > > https://github.com/rust-lang/rust/issues/112504 > > I have added it to our list at: > > https://github.com/Rust-for-Linux/linux/issues/355 > > And tagged it with the Rust for Linux label there. So shall we in the mean time merge a fix as suggested by Alice, IOW a version 2 of this patch here? P.
On Mon, Nov 17, 2025 at 7:36 AM Philipp Stanner <phasta@mailbox.org> wrote: > > So shall we in the mean time merge a fix as suggested by Alice, IOW a > version 2 of this patch here? Yes, of course, the missing blocks need to be added regardless (and otherwise will break the build when the compiler issue is fixed). Thanks! Cheers, Miguel
On Fri, Nov 14, 2025 at 03:00:21PM +0100, Philipp Stanner wrote:
> When trying to use LinkedList in the kernel crate, build fails with an
> error message demanding unsafe blocks in the container_of macro:
>
> error[E0133]: call to unsafe function `core::ptr::mut_ptr::<impl *mut T>::byte_sub`
> is unsafe and requires unsafe block
> --> rust/kernel/lib.rs:252:29
> |
> 252 | let container_ptr = field_ptr.byte_sub(offset).cast::<$Container>();
> | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
> |
> ::: rust/kernel/drm/jq.rs:98:1
> |
> 98 | / impl_list_item! {
> 99 | | impl ListItem<0> for BasicItem { using ListLinks { self.links }; }
> 100 | | }
> | |_- in this macro invocation
> |
> note: an unsafe function restricts its caller, but its body is safe by default
> --> rust/kernel/list/impl_list_item_mod.rs:216:13
> |
> 216 | unsafe fn view_value(me: *mut $crate::list::ListLinks<$num>) -> *const Self {
> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> |
> ::: rust/kernel/drm/jq.rs:98:1
> |
> 98 | / impl_list_item! {
> 99 | | impl ListItem<0> for BasicItem { using ListLinks { self.links }; }
> 100 | | }
> | |_- in this macro invocation
> = note: requested on the command line with `-D unsafe-op-in-unsafe-fn`
> = note: this error originates in the macro `$crate::container_of` which comes
> from the expansion of the macro `impl_list_item`
>
> Add unsafe blocks to container_of to fix the issue.
>
> Fixes: b20fbbc08a36 ("rust: check type of `$ptr` in `container_of!`")
> Suggested-by: Alice Ryhl <aliceryhl@google.com>
> Signed-off-by: Philipp Stanner <phasta@kernel.org>
> ---
> I'm currently writing DrmJobqueue, a new piece of infrastructure. It
> uses LinkedList and resides in the kernel crate. When using LinkedList
> from within there, for reasons I don't fully understand the error above
> shows up.
> The other testing infrastructure doesn't seem to run into the error,
> though.
>
> P.
> ---
> rust/kernel/lib.rs | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index fef97f2a5098..a26b87015e7d 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -249,8 +249,11 @@ macro_rules! container_of {
> ($field_ptr:expr, $Container:ty, $($fields:tt)*) => {{
> let offset: usize = ::core::mem::offset_of!($Container, $($fields)*);
> let field_ptr = $field_ptr;
> - let container_ptr = field_ptr.byte_sub(offset).cast::<$Container>();
> - $crate::assert_same_type(field_ptr, (&raw const (*container_ptr).$($fields)*).cast_mut());
> + // SAFETY: Offsetting the pointer to the container is correct because the offset was
> + // calculated validly above.
> + let container_ptr = unsafe { field_ptr.byte_sub(offset).cast::<$Container>() };
> + // SAFETY: Safe because the container_ptr was validly created above.
> + $crate::assert_same_type(field_ptr, unsafe { (&raw const (*container_ptr).$($fields)*) }.cast_mut());
The unsafe block goes in the impl_list_item! macro. This change makes
container_of! a safe operation, but is should not be a safe operation
because it uses byte_sub which promises the compiler that this pointer
offset operation stays within a single allocation.
Alice
On Fri, 2025-11-14 at 14:14 +0000, Alice Ryhl wrote:
> On Fri, Nov 14, 2025 at 03:00:21PM +0100, Philipp Stanner wrote:
> > When trying to use LinkedList in the kernel crate, build fails with an
> > error message demanding unsafe blocks in the container_of macro:
> >
[…]
> > rust/kernel/lib.rs | 7 +++++--
> > 1 file changed, 5 insertions(+), 2 deletions(-)
> >
> > diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> > index fef97f2a5098..a26b87015e7d 100644
> > --- a/rust/kernel/lib.rs
> > +++ b/rust/kernel/lib.rs
> > @@ -249,8 +249,11 @@ macro_rules! container_of {
> > ($field_ptr:expr, $Container:ty, $($fields:tt)*) => {{
> > let offset: usize = ::core::mem::offset_of!($Container, $($fields)*);
> > let field_ptr = $field_ptr;
> > - let container_ptr = field_ptr.byte_sub(offset).cast::<$Container>();
> > - $crate::assert_same_type(field_ptr, (&raw const (*container_ptr).$($fields)*).cast_mut());
> > + // SAFETY: Offsetting the pointer to the container is correct because the offset was
> > + // calculated validly above.
> > + let container_ptr = unsafe { field_ptr.byte_sub(offset).cast::<$Container>() };
> > + // SAFETY: Safe because the container_ptr was validly created above.
> > + $crate::assert_same_type(field_ptr, unsafe { (&raw const (*container_ptr).$($fields)*) }.cast_mut());
>
> The unsafe block goes in the impl_list_item! macro. This change makes
> container_of! a safe operation, but is should not be a safe operation
> because it uses byte_sub which promises the compiler that this pointer
> offset operation stays within a single allocation.
OK, so container_of is an unsafe function and all uses of it must be
guarded by an unsafe block.
If I do this, however
diff --git a/rust/kernel/list/impl_list_item_mod.rs b/rust/kernel/list/impl_list_item_mod.rs
index 202bc6f97c13..2f05b73c9eed 100644
--- a/rust/kernel/list/impl_list_item_mod.rs
+++ b/rust/kernel/list/impl_list_item_mod.rs
@@ -217,7 +217,7 @@ unsafe fn view_value(me: *mut $crate::list::ListLinks<$num>) -> *const Self {
// SAFETY: `me` originates from the most recent call to `prepare_to_insert`, so it
// points at the field `$field` in a value of type `Self`. Thus, reversing that
// operation is still in-bounds of the allocation.
- $crate::container_of!(me, Self, $($field).*)
+ unsafe { $crate::container_of!(me, Self, $($field).*) }
}
// GUARANTEES:
@@ -242,7 +242,7 @@ unsafe fn post_remove(me: *mut $crate::list::ListLinks<$num>) -> *const Self {
// SAFETY: `me` originates from the most recent call to `prepare_to_insert`, so it
// points at the field `$field` in a value of type `Self`. Thus, reversing that
// operation is still in-bounds of the allocation.
- $crate::container_of!(me, Self, $($field).*)
+ unsafe { $crate::container_of!(me, Self, $($field).*) }
}
}
)*};
then the compiler gets sad again, complaining precisely about the
internals of container_of:
error[E0133]: call to unsafe function `core::ptr::mut_ptr::<impl *mut T>::byte_sub` is unsafe and requires unsafe block
--> rust/kernel/lib.rs:252:29
|
252 | let container_ptr = field_ptr.byte_sub(offset).cast::<$Container>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
|
::: rust/kernel/drm/jq.rs:124:1
|
124 | / impl_list_item! {
125 | | impl ListItem<0> for EnqueuedJob<dyn JobData> { using ListLinksSelfPtr { self.links }; }
126 | | }
| |_- in this macro invocation
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/unsafe-op-in-unsafe-fn.html>
= note: consult the function's documentation for information on how to avoid undefined behavior
note: an unsafe function restricts its caller, but its body is safe by default
--> rust/kernel/list/impl_list_item_mod.rs:269:13
|
269 | unsafe fn prepare_to_insert(me: *const Self) -> *mut $crate::list::ListLinks<$num> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
::: rust/kernel/drm/jq.rs:124:1
|
124 | / impl_list_item! {
125 | | impl ListItem<0> for EnqueuedJob<dyn JobData> { using ListLinksSelfPtr { self.links }; }
126 | | }
| |_- in this macro invocation
= note: requested on the command line with `-D unsafe-op-in-unsafe-fn`
= note: this error originates in the macro `$crate::container_of` which comes from the expansion of the macro `impl_list_item` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0133]: dereference of raw pointer is unsafe and requires unsafe block
--> rust/kernel/lib.rs:254:57
|
254 | $crate::assert_same_type(field_ptr, (&raw const (*container_ptr).$($fields)*).cast_mut());
| ^^^^^^^^^^^^^^^^ dereference of raw pointer
|
::: rust/kernel/drm/jq.rs:124:1
|
124 | / impl_list_item! {
125 | | impl ListItem<0> for EnqueuedJob<dyn JobData> { using ListLinksSelfPtr { self.links }; }
126 | | }
| |_- in this macro invocation
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/unsafe-op-in-unsafe-fn.html>
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
= note: this error originates in the macro `$crate::container_of` which comes from the expansion of the macro `impl_list_item` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0133]: call to unsafe function `core::ptr::mut_ptr::<impl *mut T>::byte_sub` is unsafe and requires unsafe block
--> rust/kernel/lib.rs:252:29
|
252 | let container_ptr = field_ptr.byte_sub(offset).cast::<$Container>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
|
::: rust/kernel/drm/jq.rs:124:1
|
124 | / impl_list_item! {
125 | | impl ListItem<0> for EnqueuedJob<dyn JobData> { using ListLinksSelfPtr { self.links }; }
126 | | }
| |_- in this macro invocation
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/unsafe-op-in-unsafe-fn.html>
= note: consult the function's documentation for information on how to avoid undefined behavior
note: an unsafe function restricts its caller, but its body is safe by default
--> rust/kernel/list/impl_list_item_mod.rs:321:13
|
321 | unsafe fn view_value(links_field: *mut $crate::list::ListLinks<$num>) -> *const Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
::: rust/kernel/drm/jq.rs:124:1
|
124 | / impl_list_item! {
125 | | impl ListItem<0> for EnqueuedJob<dyn JobData> { using ListLinksSelfPtr { self.links }; }
126 | | }
| |_- in this macro invocation
= note: this error originates in the macro `$crate::container_of` which comes from the expansion of the macro `impl_list_item` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0133]: dereference of raw pointer is unsafe and requires unsafe block
--> rust/kernel/lib.rs:254:57
|
254 | $crate::assert_same_type(field_ptr, (&raw const (*container_ptr).$($fields)*).cast_mut());
| ^^^^^^^^^^^^^^^^ dereference of raw pointer
|
::: rust/kernel/drm/jq.rs:124:1
|
124 | / impl_list_item! {
125 | | impl ListItem<0> for EnqueuedJob<dyn JobData> { using ListLinksSelfPtr { self.links }; }
126 | | }
| |_- in this macro invocation
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/unsafe-op-in-unsafe-fn.html>
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
= note: this error originates in the macro `$crate::container_of` which comes from the expansion of the macro `impl_list_item` (in Nightly builds, run with -Z macro-backtrace for more info)
On Mon, Nov 17, 2025 at 9:24 AM Philipp Stanner <phasta@mailbox.org> wrote:
>
> OK, so container_of is an unsafe function and all uses of it must be
> guarded by an unsafe block.
>
> If I do this, however
>
> @@ -217,7 +217,7 @@ unsafe fn view_value(me: *mut $crate::list::ListLinks<$num>) -> *const Self {
> @@ -242,7 +242,7 @@ unsafe fn post_remove(me: *mut $crate::list::ListLinks<$num>) -> *const Self {
>
> then the compiler gets sad again, complaining precisely about the
> internals of container_of:
>
> 269 | unsafe fn prepare_to_insert(me: *const Self) -> *mut $crate::list::ListLinks<$num> {
> 321 | unsafe fn view_value(links_field: *mut $crate::list::ListLinks<$num>) -> *const Self {
Given the signatures above, it seems to me you have done it for 2 out
of 4 of the calls, thus the compiler complains as expected.
Cheers,
Miguel
© 2016 - 2026 Red Hat, Inc.