about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2011-06-29 00:42:42 -0400
committerRich Felker <dalias@aerifal.cx>2011-06-29 00:42:42 -0400
commitaf3d5405b8d7b00c121643d7a0c0b9bb31cc7139 (patch)
tree3c98857f0b36a8f5f5b717170238bdb80e7bae8e
parent9f17413c753030811761d576fdb95f200bd818d7 (diff)
downloadmusl-af3d5405b8d7b00c121643d7a0c0b9bb31cc7139.tar.gz
musl-af3d5405b8d7b00c121643d7a0c0b9bb31cc7139.tar.xz
musl-af3d5405b8d7b00c121643d7a0c0b9bb31cc7139.zip
work around linux bug in mprotect
per POSIX: The mprotect() function shall change the access protections
to be that specified by prot for those whole pages containing any part
of the address space of the process starting at address addr and
continuing for len bytes.

on the other hand, linux mprotect fails with EINVAL if the base
address and/or length is not page-aligned, so we have to align them
before making the syscall.
-rw-r--r--src/mman/mprotect.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/src/mman/mprotect.c b/src/mman/mprotect.c
index 1db2aea2..5ab2d8b0 100644
--- a/src/mman/mprotect.c
+++ b/src/mman/mprotect.c
@@ -1,7 +1,11 @@
 #include <sys/mman.h>
+#include <limits.h>
 #include "syscall.h"
 
 int mprotect(void *addr, size_t len, int prot)
 {
-	return syscall(SYS_mprotect, addr, len, prot);
+	size_t start, end;
+	start = (size_t)addr & -PAGE_SIZE;
+	end = (size_t)((char *)addr + len + PAGE_SIZE-1) & -PAGE_SIZE;
+	return syscall(SYS_mprotect, start, end-start, prot);
 }