shared/options: fix crash by aligning struct to sizeof(void*)
On some architectures like m68k, alignof(void*) is 2, not sizeof(void*)
(which is 4). So the natural alignment of struct Option is 2 and
sizeof(Option) == 26.
However, each variable placed in the SYSTEMD_OPTIONS ELF section via
_OPTION() carries _alignptr_ (= __attribute__((aligned(sizeof(void*))))),
which forces each entry to start at a 4-byte boundary. The linker
therefore inserts 2 bytes of padding between adjacent entries, producing
an actual stride of 28 in the section.
option_parse() iterates over the section with pointer arithmetic
("opt++"), which advances by sizeof(Option) == 26 and lands inside the
padding. The fields read back as zero, and since commit cf88903637
("tree-wide: get rid of most uses of ALIGN_PTR") added the ordering
assertion below, the resulting "0 < 0" trips it when running --help:
Assertion 'opt->id < (opt + 1)->id' failed at src/shared/options.c:116, function option_parse(). Aborting.
#0 0xc0a7b248 in ?? () from /usr/lib/m68k-linux-gnu/libc.so.6
#1 0xc0a7b2ce in pthread_kill () from /usr/lib/m68k-linux-gnu/libc.so.6
#2 0xc0a2edc6 in raise () from /usr/lib/m68k-linux-gnu/libc.so.6
#3 0xc0a1c128 in abort () from /usr/lib/m68k-linux-gnu/libc.so.6
#4 0xc05c6f78 in option_parse (options=0x0, options_end=0x0, state=0xc09ca968) at ../src/shared/options.c:116
Fix this by applying _alignptr_ to the struct definition itself, so that
sizeof(Option) is padded up to a multiple of sizeof(void*) and matches
the actual on-disk stride. Add an assert_cc() so any future regression
is caught at compile time.
The same latent bug applies to Verb and TestFunc, which use the same
section-placement pattern. Their natural sizeof was already a multiple
of sizeof(void*) so no crash was observed, but apply the same fix
defensively.
Follow-up for cf88903637
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
committed by
Daan De Meyer
parent
112453b9a2
commit
a7ecad77cb
@@ -36,7 +36,8 @@ typedef struct SimpleCleanup {
|
||||
free_func_t destroy;
|
||||
} SimpleCleanup;
|
||||
|
||||
typedef struct StaticDestructor {
|
||||
/* Note: see the comment on struct Option in options.h for why _alignptr_ is required here. */
|
||||
typedef struct _alignptr_ StaticDestructor {
|
||||
StaticDestructorType type;
|
||||
union {
|
||||
SimpleCleanup simple;
|
||||
|
||||
Reference in New Issue
Block a user