summaryrefslogtreecommitdiff
path: root/sys/compat/linux
diff options
context:
space:
mode:
authorchs <chs@NetBSD.org>2005-10-30 16:25:50 +0000
committerchs <chs@NetBSD.org>2005-10-30 16:25:50 +0000
commitd17f6e14bc5d2684bbd72ee5b9b9b2e5e64a8b1d (patch)
tree88785500b6ea78e7e6e6a33dc4d02c331f6bb676 /sys/compat/linux
parentdf1287ee8b30d2e411c571fae20fcf202f31967b (diff)
add support for the linux PROT_GROWS{DOWN,UP} mprotect() flags.
fixes PR 30008.
Diffstat (limited to 'sys/compat/linux')
-rw-r--r--sys/compat/linux/common/linux_misc.c47
-rw-r--r--sys/compat/linux/common/linux_mmap.h4
2 files changed, 40 insertions, 11 deletions
diff --git a/sys/compat/linux/common/linux_misc.c b/sys/compat/linux/common/linux_misc.c
index 9840ce78ec6..2cd7a4df1da 100644
--- a/sys/compat/linux/common/linux_misc.c
+++ b/sys/compat/linux/common/linux_misc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_misc.c,v 1.140 2005/09/10 19:20:50 jmmv Exp $ */
+/* $NetBSD: linux_misc.c,v 1.141 2005/10/30 16:25:50 chs Exp $ */
/*-
* Copyright (c) 1995, 1998, 1999 The NetBSD Foundation, Inc.
@@ -64,7 +64,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.140 2005/09/10 19:20:50 jmmv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.141 2005/10/30 16:25:50 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -674,25 +674,33 @@ linux_sys_mprotect(l, v, retval)
syscallarg(unsigned long) len;
syscallarg(int) prot;
} */ *uap = v;
- unsigned long end, start = (unsigned long)SCARG(uap, start), len;
- int prot = SCARG(uap, prot);
struct vm_map_entry *entry;
- struct vm_map *map = &l->l_proc->p_vmspace->vm_map;
-
- if (start & PAGE_MASK)
- return EINVAL;
+ struct vm_map *map;
+ struct proc *p;
+ vaddr_t end, start, len, stacklim;
+ int prot, grows;
+ start = (vaddr_t)SCARG(uap, start);
len = round_page(SCARG(uap, len));
+ prot = SCARG(uap, prot);
+ grows = prot & (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP);
+ prot &= ~grows;
end = start + len;
+ if (start & PAGE_MASK)
+ return EINVAL;
if (end < start)
return EINVAL;
- else if (end == start)
+ if (end == start)
return 0;
- if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
+ if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
+ return EINVAL;
+ if (grows == (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP))
return EINVAL;
+ p = l->l_proc;
+ map = &p->p_vmspace->vm_map;
vm_map_lock(map);
#ifdef notdef
VM_MAP_RANGE_CHECK(map, start, end);
@@ -701,6 +709,25 @@ linux_sys_mprotect(l, v, retval)
vm_map_unlock(map);
return ENOMEM;
}
+
+ /*
+ * Approximate the behaviour of PROT_GROWS{DOWN,UP}.
+ */
+
+ stacklim = (vaddr_t)p->p_limit->pl_rlimit[RLIMIT_STACK].rlim_cur;
+ if (grows & LINUX_PROT_GROWSDOWN) {
+ if (USRSTACK - stacklim <= start && start < USRSTACK) {
+ start = USRSTACK - stacklim;
+ } else {
+ start = entry->start;
+ }
+ } else if (grows & LINUX_PROT_GROWSUP) {
+ if (USRSTACK <= end && end < USRSTACK + stacklim) {
+ end = USRSTACK + stacklim;
+ } else {
+ end = entry->end;
+ }
+ }
vm_map_unlock(map);
return uvm_map_protect(map, start, end, prot, FALSE);
}
diff --git a/sys/compat/linux/common/linux_mmap.h b/sys/compat/linux/common/linux_mmap.h
index 3fa4133c8e1..f31b0d14cde 100644
--- a/sys/compat/linux/common/linux_mmap.h
+++ b/sys/compat/linux/common/linux_mmap.h
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_mmap.h,v 1.16 2005/05/03 16:26:29 manu Exp $ */
+/* $NetBSD: linux_mmap.h,v 1.17 2005/10/30 16:25:50 chs Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -43,6 +43,8 @@
#define LINUX_PROT_READ 0x01
#define LINUX_PROT_WRITE 0x02
#define LINUX_PROT_EXEC 0x04
+#define LINUX_PROT_GROWSDOWN 0x01000000
+#define LINUX_PROT_GROWSUP 0x02000000
#define LINUX_MAP_SHARED 0x0001
#define LINUX_MAP_PRIVATE 0x0002