As some of you may recall, there are Linux binaries (such as Mathematica) 
which will not run under OpenBSD's Linux emulation because the 
Linux mprotect system-call uses flags that are not supported by OpenBSD.  
To remedy this problem, I had posted a patch for OpenBSD 4.1

 http://marc.info/?l=openbsd-misc&m=118275040601937

I have included a new version of that patch, updated for OpenBSD 4.2, at 
the end of this message.

After applying the patch to the OpenBSD 4.2 source-code, be sure to run 
make in the directory

 /usr/src/sys/compat/linux/

If you forget to run that special makefile, then the patch will fail.

As before, I should mention that I am not the author of the majority of 
the code in this patch.  Instead, it has been ported from the 
corresponding NetBSD patches

 
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/compat/linux/common/linux_misc.c.diff?r1=1.140&r2=1.141
 
 
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/compat/linux/common/linux_mmap.h.diff?r1=1.16&r2=1.17
 
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/compat/linux/arch/i386/syscalls.master.diff?r1=1.61&r2=1.62

The OpenBSD 4.2 patch follows:


--- /usr/src/sys/compat/linux/linux_misc.c.orig Wed Feb 14 18:07:51 2007
+++ /usr/src/sys/compat/linux/linux_misc.c      Sun Nov 11 02:40:01 2007
@@ -718,6 +718,70 @@
 
 }
 
+int
+linux_sys_mprotect(p, v, retval)
+       struct proc *p;
+       void *v;
+       register_t *retval;
+{
+       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;
+
+       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_p->ps_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);
+}
+
 /*
  * This code is partly stolen from src/lib/libc/gen/times.c
  * XXX - CLK_TCK isn't declared in /sys, just in <time.h>, done here
--- /usr/src/sys/compat/linux/linux_mmap.h.orig Wed Apr 17 05:23:56 1996
+++ /usr/src/sys/compat/linux/linux_mmap.h      Sat Nov 10 23:21:24 2007
@@ -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
--- /usr/src/sys/compat/linux/syscalls.master.orig      Mon Jun 18 20:33:13 2007
+++ /usr/src/sys/compat/linux/syscalls.master   Sat Nov 10 23:21:24 2007
@@ -223,7 +223,8 @@
 123    STD             { int linux_sys_modify_ldt(void); }
 #endif
 124    STD             { int linux_sys_adjtimex(void); }
-125    NOARGS          { int 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); }

Reply via email to