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]

Reply via email to