mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[ld.so] Properly handle stack alignment in ld.so args
Now when loading a process, init will push all the loader args, align the stack so that the next pointer will have correct alignment, then push a pointer to the loader args. Also: * _ldso_start will pop all loader args off of the stack before jumping to the loaded program's entrypoint, as if it had never run. * The sentinel arg structures have a size instead of being all zeros, so that they can be popped off properly when done.
This commit is contained in:
@@ -43,7 +43,6 @@ struct j6_arg_loader
|
|||||||
uintptr_t *got;
|
uintptr_t *got;
|
||||||
uintptr_t entrypoint;
|
uintptr_t entrypoint;
|
||||||
uintptr_t start_addr;
|
uintptr_t start_addr;
|
||||||
uintptr_t other;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct j6_arg_driver
|
struct j6_arg_driver
|
||||||
|
|||||||
@@ -17,10 +17,12 @@ _ldso_start:
|
|||||||
; Call ldso_init with the loader-provided stack data and
|
; Call ldso_init with the loader-provided stack data and
|
||||||
; also the address of the GOT, since clang refuses to take
|
; also the address of the GOT, since clang refuses to take
|
||||||
; the address of it, only dereference it.
|
; the address of it, only dereference it.
|
||||||
mov rdi, rbp
|
mov rdi, [rbp]
|
||||||
lea rsi, [rel _GLOBAL_OFFSET_TABLE_]
|
lea rsi, [rel _GLOBAL_OFFSET_TABLE_]
|
||||||
call ldso_init
|
call ldso_init
|
||||||
; The real program's entrypoint is now in rax
|
|
||||||
|
; The real program's entrypoint is now in rax, save it to r11
|
||||||
|
mov r11, rax
|
||||||
|
|
||||||
; Put the function call params back
|
; Put the function call params back
|
||||||
pop r9
|
pop r9
|
||||||
@@ -30,7 +32,19 @@ _ldso_start:
|
|||||||
pop rsi
|
pop rsi
|
||||||
pop rdi
|
pop rdi
|
||||||
|
|
||||||
jmp rax
|
; Pop all the loader args
|
||||||
|
pop rsp ; Point the stack at the first arg
|
||||||
|
mov rax, 0
|
||||||
|
mov rbx, 0
|
||||||
|
.poploop:
|
||||||
|
mov eax, [dword rsp] ; size
|
||||||
|
mov ebx, [dword rsp+4] ; type
|
||||||
|
add rsp, rax
|
||||||
|
cmp ebx, 0
|
||||||
|
jne .poploop
|
||||||
|
|
||||||
|
mov rbp, rsp
|
||||||
|
jmp r11
|
||||||
.end:
|
.end:
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ stack_push_sentinel(uint8_t *&stack)
|
|||||||
memset(stack, 0, size);
|
memset(stack, 0, size);
|
||||||
j6_arg_header *header = reinterpret_cast<j6_arg_header*>(stack);
|
j6_arg_header *header = reinterpret_cast<j6_arg_header*>(stack);
|
||||||
header->type = j6_arg_type_none;
|
header->type = j6_arg_type_none;
|
||||||
header->size = 0;
|
header->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> T *
|
template <typename T> T *
|
||||||
@@ -222,6 +222,7 @@ load_program(
|
|||||||
uintptr_t entrypoint = program_elf.entrypoint() + program_image_base;
|
uintptr_t entrypoint = program_elf.entrypoint() + program_image_base;
|
||||||
|
|
||||||
if (dyn) {
|
if (dyn) {
|
||||||
|
stack_push_sentinel(stack);
|
||||||
j6_arg_loader *loader_arg = stack_push<j6_arg_loader>(stack, 0);
|
j6_arg_loader *loader_arg = stack_push<j6_arg_loader>(stack, 0);
|
||||||
const elf::file_header *h = program_elf.header();
|
const elf::file_header *h = program_elf.header();
|
||||||
loader_arg->image_base = program_image_base;
|
loader_arg->image_base = program_image_base;
|
||||||
@@ -240,6 +241,15 @@ load_program(
|
|||||||
handles_arg->handles[1].handle = vfs;
|
handles_arg->handles[1].handle = vfs;
|
||||||
handles_arg->handles[1].proto = j6::proto::vfs::id;
|
handles_arg->handles[1].proto = j6::proto::vfs::id;
|
||||||
|
|
||||||
|
// Align the stack to be one word short of 16-byte aligned, so
|
||||||
|
// that the arg address will be aligned when pushed
|
||||||
|
while ((reinterpret_cast<uintptr_t>(stack) & 0xf) != 0x8) --stack;
|
||||||
|
|
||||||
|
// Push the args list address itself
|
||||||
|
stack -= sizeof(uintptr_t);
|
||||||
|
uintptr_t *args_addr = reinterpret_cast<uintptr_t*>(stack);
|
||||||
|
*args_addr = stack_top - (stack_orig - reinterpret_cast<uint8_t*>(handles_arg));
|
||||||
|
|
||||||
uintptr_t ldso_image_base = (eop & ~(MiB-1)) + MiB;
|
uintptr_t ldso_image_base = (eop & ~(MiB-1)) + MiB;
|
||||||
|
|
||||||
for (auto seg : program_elf.segments()) {
|
for (auto seg : program_elf.segments()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user