Hi,
The diff below works in my tests.
It allows OpenBSD to use the PROT_GROWSUP and PROT_GROWSDOWN flags
for mprotect under Linux emulation.
Cherrypicked from http://marc.info/?l=openbsd-misc&m=118277676431920
with minor modifications.
Please comment/help, as I'd like to have it in so I can update
print/acroread to the latest version...
Ciao,
David
Index: linux_misc.c
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_misc.c,v
retrieving revision 1.76
diff -u -p -r1.76 linux_misc.c
--- linux_misc.c 22 Apr 2012 05:43:14 -0000 1.76
+++ linux_misc.c 30 Apr 2012 08:43:50 -0000
@@ -1449,11 +1449,62 @@ linux_sys_sysinfo(p, v, retval)
int
linux_sys_mprotect(struct proc *p, void *v, register_t *retval)
{
- struct sys_mprotect_args *uap = v;
+ struct linux_sys_mprotect_args /* {
+ syscallarg(const void *) start;
+ syscallarg(unsigned long) len;
+ syscallarg(int) prot;
+ } */ *uap = v;
+ struct vm_map_entry *entry;
+ struct vm_map *map;
+ vaddr_t end, start, len, stacklim;
+ int prot, grows;
- if (SCARG(uap, prot) & (PROT_WRITE | PROT_EXEC))
- SCARG(uap, prot) |= PROT_READ;
- return (sys_mprotect(p, uap, retval));
+ 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;
+ if (end == start)
+ return 0;
+
+ if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
+ return EINVAL;
+ if (grows == (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP))
+ return EINVAL;
+
+ map = &p->p_vmspace->vm_map;
+ vm_map_lock(map);
+ if (!uvm_map_lookup_entry(map, start, &entry) || entry->start > start) {
+ vm_map_unlock(map);
+ return ENOMEM;
+ }
+
+ /*
+ * Approximate the behaviour of PROT_GROWS{DOWN,UP}.
+ */
+
+ stacklim = (vaddr_t)p->p_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);
}
int
Index: linux_mmap.h
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_mmap.h,v
retrieving revision 1.3
diff -u -p -r1.3 linux_mmap.h
--- linux_mmap.h 5 Apr 2011 22:54:30 -0000 1.3
+++ linux_mmap.h 30 Apr 2012 08:43:50 -0000
@@ -38,6 +38,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
Index: syscalls.master
===================================================================
RCS file: /cvs/src/sys/compat/linux/syscalls.master,v
retrieving revision 1.66
diff -u -p -r1.66 syscalls.master
--- syscalls.master 14 Dec 2011 08:33:18 -0000 1.66
+++ syscalls.master 30 Apr 2012 08:43:51 -0000
@@ -222,7 +222,8 @@
123 STD { int linux_sys_modify_ldt(void); }
#endif
124 STD { int linux_sys_adjtimex(void); }
-125 STD { int linux_sys_mprotect(caddr_t addr, int len, int
prot); }
+125 STD { int linux_sys_mprotect(const void *start, \
+ unsigned long len, int prot); }
126 STD { int linux_sys_sigprocmask(int how, \
linux_old_sigset_t *set, linux_old_sigset_t *oset);
}
127 STD { int linux_sys_create_module(void); }
[demime 1.01d removed an attachment of type application/octet-stream]