aboutsummaryrefslogtreecommitdiff
path: root/pk
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2016-11-02 12:16:09 -0700
committerAndrew Waterman <andrew@sifive.com>2016-11-02 12:20:59 -0700
commitc6b55ce3a8e45c8747945ab3bcd85580f0d344dd (patch)
tree17c09c1386183bdaca7f99f6e899a61bae1893cc /pk
parent6c1d0604dcabf36a6a8d8d9a839b2d4634e202d2 (diff)
downloadpk-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.
Diffstat (limited to 'pk')
-rw-r--r--pk/elf.c5
-rw-r--r--pk/mmap.c3
2 files changed, 6 insertions, 2 deletions
diff --git a/pk/elf.c b/pk/elf.c
index d0cf8a7..1da29b2 100644
--- a/pk/elf.c
+++ b/pk/elf.c
@@ -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)
diff --git a/pk/mmap.c b/pk/mmap.c
index e00d18e..1fac4c8 100644
--- a/pk/mmap.c
+++ b/pk/mmap.c
@@ -354,7 +354,8 @@ uintptr_t do_mprotect(uintptr_t addr, size_t length, int prot)
}
}
spinlock_unlock(&vm_lock);
-
+
+ flush_tlb();
return res;
}