Re: [PATCH v2 1/2] vdso: Add VDSO_UNALIGNED_PACKED config option
From: Arnd Bergmann
Date: Fri Oct 23 2026 - 17:50:40 EST
On Tue, Oct 20, 2026, at 20:07, David Laight wrote:
> On Tue, 20 Oct 2026 09:32:09 -0700 Ian Rogers <irogers@xxxxxxxxxx> wrote:
>>
>> #include <linux/compiler_types.h>
>>
>> +#ifdef CONFIG_VDSO_UNALIGNED_PACKED
>> +
>> +#define __get_unaligned_t(type, ptr) ({ \
>> + const struct { type x; } __packed * __get_pptr = (typeof(__get_pptr))(ptr); \
>> + __get_pptr->x; \
>> +})
>> +
>> +#define __put_unaligned_t(type, val, ptr) do { \
>> + struct { type x; } __packed * __put_pptr = (typeof(__put_pptr))(ptr); \
>> + __put_pptr->x = (val); \
>> +} while (0)
>
> I'm confused (easily done).
> That code relies on strict alignment being disabled regardless of whether
> misaligned accesses fault or not.
>
> So it is either always valid or always wrong.
>
> Additionally I think the compiler can sometimes track the alignment through
> casts (although it didn't for a quick check I did earlier).
This is the traditional way we have been doing the unaligned access
in the kernel before the change. By annotating the structure as
__packed, we tell the compiler that it cannot rely on alignment here,
so it uses whatever method it knows to access unaligned data depending
on the architecture and flags.
The reason we need the struct here is that you cannot use __packed
as a qualifier on a variable, only on a type or struct member.
> Since having misaligned non-packed structures really doesn't work, the only
> places these functions should be used is on u8[] buffers.
> Pointers into those can (probably) be cast to packed structure types
> without causing issues if strict aliasing is enabled.
strict aliasing is thankfully never enabled in the kernel.
The cast is from a higher alignment to byte alignment, and that
is always allowed unlike the reverse. Technically the only
reason we ever need the get_unaligned() helpers is to work
around pointers to objects that should exist because the
ABI requires them to be aligned but the pointer instead
came out of some byte stream or from taking a (non-__packed)
pointer of a __packed struct member.
Arnd