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 */