From: Maksym Sobolyev <[email protected]> When loading non-PIE binary (could be either static or dymanic), make sure to set MAP_EXCL while mapping the program text. Otherwise if qemu is also non-PIE it might be loaded at the very same address, effectively self-destructing after mapping target binary over its own text area.
It is not a problem for fully dynamic binaries loading, as in that case the initial mapping is non-fixed, so the kernel would pick some non-conflicting area for us. 32625 qemu-x86_64 CALL openat(AT_FDCWD,0x7fffffffe240,0<O_RDONLY>) 32625 qemu-x86_64 NAMI "/usr/bin/cc" 32625 qemu-x86_64 RET openat 3 [...] 32625 qemu-x86_64 CALL mmap(0x809222000,0x20001000,0x7<PROT_READ|PROT_WRITE|PROT_EXEC>,0x1012<MAP_PRIVATE|MAP_FIXED|MAP_ANON>,0xffffffff,0) 32625 qemu-x86_64 RET mmap 34512969728/0x809222000 32625 qemu-x86_64 CALL mprotect(0x809222000,0x1000,0<PROT_NONE>) 32625 qemu-x86_64 RET mprotect 0 32625 qemu-x86_64 CALL mmap(0,0x458,0x3<PROT_READ|PROT_WRITE>,0x1002<MAP_PRIVATE|MAP_ANON>,0xffffffff,0) 32625 qemu-x86_64 RET mmap 35049844736/0x829223000 32625 qemu-x86_64 CALL minherit(0x829223000,0x458,INHERIT_ZERO) 32625 qemu-x86_64 RET minherit 0 32625 qemu-x86_64 CALL getrandom(0x7fffffffde10,0x28,0) 32625 qemu-x86_64 RET getrandom 40/0x28 32625 qemu-x86_64 CALL mmap(0x200000,0x2053000,0x1<PROT_READ>,0x12<MAP_PRIVATE|MAP_FIXED>,0x3,0) 32625 qemu-x86_64 RET mmap 2097152/0x200000 32625 qemu-x86_64 PSIG SIGSEGV SIG_DFL code=SEGV_ACCERR 32625 qemu-x86_64 RET nanosleep -1 errno 4 Interrupted system call Signed-off-by: Maksym Sobolyev <[email protected]> Reviewed-by: Warner Losh <[email protected]> Signed-off-by: Warner Losh <[email protected]> --- bsd-user/elfload.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c index 295dad4643..eaa8676f5a 100644 --- a/bsd-user/elfload.c +++ b/bsd-user/elfload.c @@ -561,12 +561,14 @@ load_elf_sections(const struct elfhdr *hdr, struct elf_phdr *phdr, int fd, elf_prot |= PROT_EXEC; } + int flags = MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE; + if (rbase == 0) { + flags |= MAP_EXCL; + } error = target_mmap(TARGET_ELF_PAGESTART(rbase + elf_ppnt->p_vaddr), (elf_ppnt->p_filesz + TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), - elf_prot, - (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), - fd, + elf_prot, flags, fd, (elf_ppnt->p_offset - TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); if (error == -1) { -- 2.55.0
