On May 22,  3:42pm, rhia...@falu.nl (Rhialto) wrote:
-- Subject: Re: PaX MPROTECT gdb and software breakpoints

Here's the sysctl way.

christos

Index: kern/kern_pax.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_pax.c,v
retrieving revision 1.49
diff -u -u -r1.49 kern_pax.c
--- kern/kern_pax.c     22 May 2016 14:26:09 -0000      1.49
+++ kern/kern_pax.c     22 May 2016 15:08:55 -0000
@@ -117,6 +117,7 @@
 #ifdef PAX_MPROTECT
 static int pax_mprotect_enabled = 1;
 static int pax_mprotect_global = PAX_MPROTECT;
+static int pax_mprotect_ptrace = 0;
 static bool pax_mprotect_elf_flags_active(uint32_t);
 #endif /* PAX_MPROTECT */
 #ifdef PAX_MPROTECT_DEBUG
@@ -205,6 +206,14 @@
                                    "all processes."),
                       NULL, 0, &pax_mprotect_global, 0,
                       CTL_CREATE, CTL_EOL);
+       sysctl_createv(clog, 0, &rnode, NULL,
+                      CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+                      CTLTYPE_INT, "ptrace",
+                      SYSCTL_DESCR("When enabled, allow ptrace(2) to "
+                           "override protect permissions on traced "
+                           "processes"),
+                      NULL, 0, &pax_mprotect_ptrace, 0,
+                      CTL_CREATE, CTL_EOL);
 #ifdef PAX_MPROTECT_DEBUG
        sysctl_createv(clog, 0, &rnode, NULL,
                       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
@@ -432,6 +441,24 @@
                *maxprot &= ~VM_PROT_WRITE;
        }
 }
+
+/*
+ * Bypass MPROTECT for traced processes
+ */
+int
+pax_mprotect_prot(struct lwp *l)
+{
+       uint32_t flags;
+
+       flags = l->l_proc->p_pax;
+       if (!pax_flags_active(flags, P_PAX_MPROTECT))
+               return 0;
+       if (!pax_mprotect_ptrace)
+               return 0;
+       return UVM_EXTRACT_PROT_ALL;
+}
+
+
 #endif /* PAX_MPROTECT */
 
 #ifdef PAX_ASLR
Index: kern/kern_proc.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_proc.c,v
retrieving revision 1.195
diff -u -u -r1.195 kern_proc.c
--- kern/kern_proc.c    4 Apr 2016 20:47:57 -0000       1.195
+++ kern/kern_proc.c    22 May 2016 15:08:55 -0000
@@ -2114,7 +2114,7 @@
                        auio.uio_resid = xlen;
                        auio.uio_rw = UIO_READ;
                        UIO_SETUP_SYSSPACE(&auio);
-                       error = uvm_io(&vmspace->vm_map, &auio);
+                       error = uvm_io(&vmspace->vm_map, &auio, 0);
                        if (error)
                                goto done;
 
Index: kern/subr_copy.c
===================================================================
RCS file: /cvsroot/src/sys/kern/subr_copy.c,v
retrieving revision 1.6
diff -u -u -r1.6 subr_copy.c
--- kern/subr_copy.c    21 Apr 2015 13:17:25 -0000      1.6
+++ kern/subr_copy.c    22 May 2016 15:08:55 -0000
@@ -223,7 +223,7 @@
        uio.uio_resid = len;
        uio.uio_rw = UIO_READ;
        UIO_SETUP_SYSSPACE(&uio);
-       error = uvm_io(&vm->vm_map, &uio);
+       error = uvm_io(&vm->vm_map, &uio, 0);
 
        return (error);
 }
@@ -256,7 +256,7 @@
        uio.uio_resid = len;
        uio.uio_rw = UIO_WRITE;
        UIO_SETUP_SYSSPACE(&uio);
-       error = uvm_io(&vm->vm_map, &uio);
+       error = uvm_io(&vm->vm_map, &uio, 0);
 
        return (error);
 }
Index: kern/sys_process.c
===================================================================
RCS file: /cvsroot/src/sys/kern/sys_process.c,v
retrieving revision 1.168
diff -u -u -r1.168 sys_process.c
--- kern/sys_process.c  4 Apr 2016 20:47:57 -0000       1.168
+++ kern/sys_process.c  22 May 2016 15:08:55 -0000
@@ -122,12 +122,14 @@
 
 #include "opt_ptrace.h"
 #include "opt_ktrace.h"
+#include "opt_pax.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
 #include <sys/errno.h>
 #include <sys/exec.h>
+#include <sys/pax.h>
 #include <sys/ptrace.h>
 #include <sys/uio.h>
 #include <sys/ras.h>
@@ -1118,7 +1120,7 @@
        mutex_exit(&vm->vm_map.misc_lock);
        if (error != 0)
                return (error);
-       error = uvm_io(&vm->vm_map, uio);
+       error = uvm_io(&vm->vm_map, uio, pax_mprotect_prot(l));
        uvmspace_free(vm);
 
 #ifdef PMAP_NEED_PROCWR
Index: sys/pax.h
===================================================================
RCS file: /cvsroot/src/sys/sys/pax.h,v
retrieving revision 1.21
diff -u -u -r1.21 pax.h
--- sys/pax.h   22 May 2016 14:26:10 -0000      1.21
+++ sys/pax.h   22 May 2016 15:08:55 -0000
@@ -67,6 +67,7 @@
     struct lwp *, vm_prot_t *, vm_prot_t *);
 #ifndef PAX_MPROTECT
 # define PAX_MPROTECT_ADJUST(a, b, c)
+# define pax_mprotect_prot(l)  0
 #else
 # ifdef PAX_MPROTECT_DEBUG
 #  define PAX_MPROTECT_ADJUST(a, b, c) \
@@ -75,6 +76,7 @@
 #  define PAX_MPROTECT_ADJUST(a, b, c) \
     pax_mprotect_adjust((a), (b), (c))
 # endif
+extern int pax_mprotect_prot(struct lwp *);
 #endif
 int pax_segvguard(struct lwp *, struct vnode *, const char *, bool);
 
Index: uvm/uvm_extern.h
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_extern.h,v
retrieving revision 1.196
diff -u -u -r1.196 uvm_extern.h
--- uvm/uvm_extern.h    5 Feb 2016 04:18:55 -0000       1.196
+++ uvm/uvm_extern.h    22 May 2016 15:08:55 -0000
@@ -622,7 +622,7 @@
 void                   uvm_init(void);
 
 /* uvm_io.c */
-int                    uvm_io(struct vm_map *, struct uio *);
+int                    uvm_io(struct vm_map *, struct uio *, int);
 
 /* uvm_km.c */
 vaddr_t                        uvm_km_alloc(struct vm_map *, vsize_t, vsize_t,
Index: uvm/uvm_io.c
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_io.c,v
retrieving revision 1.27
diff -u -u -r1.27 uvm_io.c
--- uvm/uvm_io.c        27 Jan 2012 19:48:41 -0000      1.27
+++ uvm/uvm_io.c        22 May 2016 15:08:55 -0000
@@ -53,7 +53,7 @@
  */
 
 int
-uvm_io(struct vm_map *map, struct uio *uio)
+uvm_io(struct vm_map *map, struct uio *uio, int flags)
 {
        vaddr_t baseva, endva, pageoffset, kva;
        vsize_t chunksz, togo, sz;
@@ -86,6 +86,7 @@
        chunksz = MIN(round_page(togo + pageoffset), trunc_page(MAXPHYS));
        error = 0;
 
+       flags |= UVM_EXTRACT_QREF | UVM_EXTRACT_CONTIG | UVM_EXTRACT_FIXPROT;
        /*
         * step 1: main loop...  while we've got data to move
         */
@@ -97,8 +98,7 @@
                 */
 
                error = uvm_map_extract(map, baseva, chunksz, kernel_map, &kva,
-                           UVM_EXTRACT_QREF | UVM_EXTRACT_CONTIG |
-                           UVM_EXTRACT_FIXPROT);
+                   flags);
                if (error) {
 
                        /* retry with a smaller chunk... */
Index: uvm/uvm_map.c
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_map.c,v
retrieving revision 1.336
diff -u -u -r1.336 uvm_map.c
--- uvm/uvm_map.c       5 Nov 2015 00:10:48 -0000       1.336
+++ uvm/uvm_map.c       22 May 2016 15:08:55 -0000
@@ -2546,6 +2546,7 @@
  *      UVM_EXTRACT_CONTIG: abort if unmapped area (advisory only)
  *      UVM_EXTRACT_QREF: for a temporary extraction do quick obj refs
  *      UVM_EXTRACT_FIXPROT: set prot to maxprot as we go
+ *      UVM_EXTRACT_PROT_ALL: set prot to UVM_PROT_ALL as we go
  *    >>>NOTE: if you set REMOVE, you are not allowed to use CONTIG or QREF!<<<
  *    >>>NOTE: QREF's must be unmapped via the QREF path, thus should only
  *             be used from within the kernel in a kernel level map <<<
@@ -2704,9 +2705,14 @@
                        newentry->offset = 0;
                }
                newentry->etype = entry->etype;
-               newentry->protection = (flags & UVM_EXTRACT_FIXPROT) ?
-                       entry->max_protection : entry->protection;
-               newentry->max_protection = entry->max_protection;
+               if (flags & UVM_EXTRACT_PROT_ALL) {
+                       newentry->protection = newentry->max_protection =
+                           UVM_PROT_ALL;
+               } else {
+                       newentry->protection = (flags & UVM_EXTRACT_FIXPROT) ?
+                           entry->max_protection : entry->protection;
+                       newentry->max_protection = entry->max_protection;
+               }
                newentry->inheritance = entry->inheritance;
                newentry->wired_count = 0;
                newentry->aref.ar_amap = entry->aref.ar_amap;
Index: uvm/uvm_map.h
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_map.h,v
retrieving revision 1.72
diff -u -u -r1.72 uvm_map.h
--- uvm/uvm_map.h       29 Oct 2012 16:00:05 -0000      1.72
+++ uvm/uvm_map.h       22 May 2016 15:08:55 -0000
@@ -108,6 +108,7 @@
 #define UVM_EXTRACT_QREF       0x04    /* use quick refs */
 #define UVM_EXTRACT_FIXPROT    0x08    /* set prot to maxprot as we go */
 #define UVM_EXTRACT_RESERVED   0x10    /* caller did uvm_map_reserve() */
+#define UVM_EXTRACT_PROT_ALL   0x20    /* set prot to UVM_PROT_ALL */
 
 #endif /* _KERNEL */
 

Reply via email to