From 3e7b7a8e60b027c3bcb152886b4bcece8b06e1c6 Mon Sep 17 00:00:00 2001 From: Hesham Almatary Date: Tue, 25 Jul 2023 15:51:30 +0100 Subject: [PATCH] libsel4utils: Fix TLS page fault if PT_PHDR exists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PT_PHDR is emitted by ld.lld but not ld.bfd. This segment should only exist if the program header *is* part of the program memory image itself (which is not the case in seL4, as it copies the program header in the sack). This is important as muslc’s TLS init is relying on the existence of PT_PHDR to get the base address of the image in memory and from that, it calculates the TLS base for the source ELF. The calculation will be wrong in seL4 as the program header is copied in the stack; thus it may trigger a page fault if the new TLS base is not mapped, or affects the integrity of programs relying on TLS variables (e.g., those with __thread). By setting PT_PHDR's segment to PT_NULL, muslc will skip this search and won't do any relocations for the TLS segment which is part of the loaded ELF image itself, thus getting the correct mapped address. Sponsored by: DARPA. Signed-off-by: Hesham Almatary --- libsel4utils/src/process.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libsel4utils/src/process.c b/libsel4utils/src/process.c index aafafd649..a6be66f72 100644 --- a/libsel4utils/src/process.c +++ b/libsel4utils/src/process.c @@ -271,9 +271,22 @@ int sel4utils_spawn_process_v(sel4utils_process_t *process, vka_t *vka, vspace_t int error; int envc = 0; char *envp[] = {}; + Elf_Phdr *phdr = process->elf_phdrs; uintptr_t initial_stack_pointer = (uintptr_t) process->thread.stack_top - sizeof(seL4_Word); + /* If PT_PHDR exists in the program headers, assign PT_NULL to it. + * This is because muslc libc searches for PT_PHDR and if found, + * it assumes it's part of the ELF image and relocates the entire + * subsequent program header segments according to PT_PHDR's base. This is + * wrong and will trigger mapping errors. + */ + for (int i = 0; i < process->num_elf_phdrs; i++, phdr++) { + if (phdr->p_type == PT_PHDR) { + phdr->p_type = PT_NULL; + } + } + /* Copy the elf headers */ uintptr_t at_phdr; error = sel4utils_stack_write(vspace, &process->vspace, vka, process->elf_phdrs,