diff options
author | Andrew Waterman <andrew@sifive.com> | 2016-11-02 12:16:09 -0700 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2016-11-02 12:20:59 -0700 |
commit | c6b55ce3a8e45c8747945ab3bcd85580f0d344dd (patch) | |
tree | 17c09c1386183bdaca7f99f6e899a61bae1893cc | |
parent | 6c1d0604dcabf36a6a8d8d9a839b2d4634e202d2 (diff) | |
download | pk-c6b55ce3a8e45c8747945ab3bcd85580f0d344dd.zip pk-c6b55ce3a8e45c8747945ab3bcd85580f0d344dd.tar.gz pk-c6b55ce3a8e45c8747945ab3bcd85580f0d344dd.tar.bz2 |
Acquire write permissions before zeroing page in ELF loader
f81b722bf004177eadaf6f1b4b9e699e20257521 is a regression. If a
read-only segment does not begin on a page boundary, it would cause
the ELF loader to blow up.
-rw-r--r-- | pk/elf.c | 5 | ||||
-rw-r--r-- | pk/mmap.c | 3 |
2 files changed, 6 insertions, 2 deletions
@@ -74,9 +74,12 @@ void load_elf(const char* fn, elf_info* info) info->brk_min = vaddr + ph[i].p_memsz; int flags2 = flags | (prepad ? MAP_POPULATE : 0); int prot = get_prot(ph[i].p_flags); - if (__do_mmap(vaddr - prepad, ph[i].p_filesz + prepad, prot, flags2, file, ph[i].p_offset - prepad) != vaddr - prepad) + if (__do_mmap(vaddr - prepad, ph[i].p_filesz + prepad, prot | PROT_WRITE, flags2, file, ph[i].p_offset - prepad) != vaddr - prepad) goto fail; memset((void*)vaddr - prepad, 0, prepad); + if (!(prot & PROT_WRITE)) + if (do_mprotect(vaddr - prepad, ph[i].p_filesz + prepad, prot)) + goto fail; size_t mapped = ROUNDUP(ph[i].p_filesz + prepad, RISCV_PGSIZE) - prepad; if (ph[i].p_memsz > mapped) if (__do_mmap(vaddr + mapped, ph[i].p_memsz - mapped, prot, flags|MAP_ANONYMOUS, 0, 0) != vaddr + mapped) @@ -354,7 +354,8 @@ uintptr_t do_mprotect(uintptr_t addr, size_t length, int prot) } } spinlock_unlock(&vm_lock); - + + flush_tlb(); return res; } |