Skip to content

Commit 0f21818

Browse files
cataphractclaude
andcommitted
solib_bootstrap: fix x86-64 ld.so jump clobbering entry address
The x86-64 inline asm restoring the kernel stack and jumping to ld.so: "mov %[sp], %%rsp\n" "xor %%edx, %%edx\n" // required: rdx = 0 for ld.so startup ABI "jmp *%[entry]\n" GCC at -O0 allocated %[entry] (ldso_entry) to rdx, causing the xor to zero the jump target before the jmpq executed → SIGSEGV at address 0x0 on every x86-64 ExecSolib launch. Fix: use "m" constraint for ldso_entry so GCC keeps it in a stack slot (memory) instead of a register, making the xor harmless. The jmpq now emits "jmpq *-N(%rbp)" — an indirect memory jump — which reads ldso_entry from the old frame after rsp has been restored. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent e3c4da7 commit 0f21818

1 file changed

Lines changed: 8 additions & 4 deletions

File tree

ext/solib_bootstrap.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,17 @@ noreturn void _dd_solib_bootstrap(void *stack_top) {
337337
// function is noreturn - we transfer control via inline asm.
338338

339339
#ifdef __x86_64__
340+
// Restore the original kernel stack and jump to ld.so's entry point.
341+
// rdx must be 0 at ld.so startup (x86-64 ABI: rdx = rtld finalizer, 0 = none).
342+
// Use "m" for ldso_entry to keep it in memory, avoiding any register
343+
// allocation conflict with rdx (the xor would clobber a register input).
340344
uintptr_t ldso_entry = bs_ldso.entry;
341345
__asm__ volatile(
342-
"mov %0, %%rsp\n"
346+
"mov %[sp], %%rsp\n"
343347
"xor %%edx, %%edx\n"
344-
"jmp *%1\n"
345-
:: "r"(stack_top), "r"(ldso_entry)
346-
: "memory"
348+
"jmpq *%[entry]\n"
349+
:: [sp] "r"(stack_top), [entry] "m"(ldso_entry)
350+
: "rdx", "memory"
347351
);
348352
#elif defined(__aarch64__)
349353
uintptr_t ldso_entry = bs_ldso.entry;

0 commit comments

Comments
 (0)