Re: [PATCH 2/2] rust: pin-init: internal: init: document load-bearing fact of field accessors

From: Gary Guo

Date: Sat Feb 28 2026 - 06:56:22 EST


On Sat Feb 28, 2026 at 11:37 AM GMT, Benno Lossin wrote:
> We cannot support packed structs without significant changes [1]. The
> field accessors ensure that the compiler emits an error if one tries to
> create an initializer for a packed struct.
>
> Link: https://github.com/Rust-for-Linux/pin-init/issues/112 [1]
> Fixes: 90e53c5e70a6 ("rust: add pin-init API core")
> Cc: stable@xxxxxxxxxxxxxxx # needed in 6.19, 6.18, 6.17, 6.16, 6.12, 6.6. see below the `---` for more info
> Signed-off-by: Benno Lossin <lossin@xxxxxxxxxx>
> ---
> As already explained in the previous email, we discovered an unsoundness
> in pin-init that exists since the beginning, but was unknowingly fixed
> in commit 42415d163e5d ("rust: pin-init: add references to previously
> initialized fields").
>
> We introduced pin-init in 90e53c5e70a6 ("rust: add pin-init API core"),
> which was included in 6.4. The affected stable trees that are still
> maintained are: 6.17, 6.16, 6.12, and 6.6. Note that 6.18 and 6.19
> already contain 42415d163e5d, so they are unaffected.
>
> We still should backport this piece of documentation explaining the need
> for the field accessors for soundness. For this reasons we also want to
> backport it to 6.18 and 6.19.
>
> Note that this patch depends on 42415d163e5d; so the only versions this
> patch can go in directly are 6.18 and 6.19. I will send separate patch
> series' for the older versions. The series' will include a backport of
> 42415d163e5d as well as this patch, since this patch depends on the
> `syn` rewrite, which is not present in older versions.
> ---
> rust/pin-init/internal/src/init.rs | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/rust/pin-init/internal/src/init.rs b/rust/pin-init/internal/src/init.rs
> index da53adc44ecf..533029d53d30 100644
> --- a/rust/pin-init/internal/src/init.rs
> +++ b/rust/pin-init/internal/src/init.rs
> @@ -251,6 +251,11 @@ fn init_fields(
> });
> // Again span for better diagnostics
> let write = quote_spanned!(ident.span()=> ::core::ptr::write);
> + // NOTE: the field accessor ensures that the initialized struct is not
> + // `repr(packed)`. If it were, the compiler would emit E0793. We do not support
> + // packed structs, since `Init::__init` requires an aligned pointer; the same
> + // requirement that the call to `ptr::write` below has.
> + // For more info see <https://github.com/Rust-for-Linux/pin-init/issues/112>

The emphasis should be unaligned fields instead of `repr(packed)`. Of course,
unaligned fields can only occur with `repr(packed)`, but packed structs can
contain well-aligned fields, too (e.g. 1-byte aligned members, or
`repr(packed(2))` with 2-byte aligned members, etc...). Rust permits creation of
references to these fields.

Something like:

NOTE: the field accessor ensures that the initialized field is properly
aligned. Unaligned fields will cause the compiler to emit E0793. We do not
support unaligned fields since `Init::__init` requires an aligned pointer;
the `ptr::write` below has the same requirement.

Also, it is not immediately clear to me which one, buyt one of the two occurance
should be `PinInit::__pin_init`?

Best,
Gary

> let accessor = if pinned {
> let project_ident = format_ident!("__project_{ident}");
> quote! {
> @@ -278,6 +283,11 @@ fn init_fields(
> InitializerKind::Init { ident, value, .. } => {
> // Again span for better diagnostics
> let init = format_ident!("init", span = value.span());
> + // NOTE: the field accessor ensures that the initialized struct is not
> + // `repr(packed)`. If it were, the compiler would emit E0793. We do not support
> + // packed structs, since `Init::__init` requires an aligned pointer; the same
> + // requirement that the call to `ptr::write` below has.
> + // For more info see <https://github.com/Rust-for-Linux/pin-init/issues/112>
> let (value_init, accessor) = if pinned {
> let project_ident = format_ident!("__project_{ident}");
> (