> As it turns out, this bug in compat_linux was encountered in NetBSD in 
> 2005 and then fixed.  The NetBSD patches are

I have successfully ported the relevant material from the 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

to OpenBSD.  The OpenBSD patch is given at the end of this message.  Be 
sure to run the make file at

 /usr/src/sys/compat/linux/

after applying the patch.  The make file will update some important files.

This patch allows OpenBSD to use the PROT_GROWSUP and PROT_GROWSDOWN flags 
to mprotect under Linux emulation.  I have tested this new functionality 
with the Linux version of the Mathematica 6.0 Kernel, which now runs 
successfully.  Presumably, OpenBSD will also be able to run other Linux 
applications that use these flags, such as Adobe Acrobat Reader (for which 
the NetBSD patches were originally intended).

What steps need to be taken to ensure that this fix is merged into the 
official OpenBSD source code?


*** /usr/src/sys/compat/linux/linux_misc.c.orig Wed Feb 14 18:07:51 2007
--- /usr/src/sys/compat/linux/linux_misc.c      Mon Jun 25 00:13:42 2007
***************
*** 718,723 ****
--- 718,787 ----
  
  }
  
+ 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_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      Mon Jun 25 00:13:42 2007
***************
*** 38,43 ****
--- 38,45 ----
  #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      Wed Oct 27 13:23:38 2004
--- /usr/src/sys/compat/linux/syscalls.master   Mon Jun 25 00:13:42 2007
***************
*** 223,229 ****
  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); }
  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); }
--- 223,230 ----
  123   STD             { int linux_sys_modify_ldt(void); }
  #endif
  124   STD             { int linux_sys_adjtimex(void); }
! 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