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


Reply via email to