diff options
| author | chs <chs@NetBSD.org> | 2005-10-30 16:25:50 +0000 |
|---|---|---|
| committer | chs <chs@NetBSD.org> | 2005-10-30 16:25:50 +0000 |
| commit | d17f6e14bc5d2684bbd72ee5b9b9b2e5e64a8b1d (patch) | |
| tree | 88785500b6ea78e7e6e6a33dc4d02c331f6bb676 /sys/compat/linux | |
| parent | df1287ee8b30d2e411c571fae20fcf202f31967b (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.c | 47 | ||||
| -rw-r--r-- | sys/compat/linux/common/linux_mmap.h | 4 |
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 |
