Module Name: src Committed By: christos Date: Wed May 25 17:43:58 UTC 2016
Modified Files: src/sys/kern: kern_pax.c kern_proc.c subr_copy.c sys_process.c src/sys/rump/librump/rumpkern: rumpcopy.c src/sys/sys: pax.h src/sys/uvm: uvm_extern.h uvm_io.c uvm_map.c uvm_map.h Log Message: Introduce security.pax.mprotect.ptrace sysctl which can be used to bypass mprotect settings so that debuggers can write to the text segment of traced processes so that they can insert breakpoints. Turned off by default. Ok: chuq (for now) To generate a diff of this commit: cvs rdiff -u -r1.51 -r1.52 src/sys/kern/kern_pax.c cvs rdiff -u -r1.195 -r1.196 src/sys/kern/kern_proc.c cvs rdiff -u -r1.6 -r1.7 src/sys/kern/subr_copy.c cvs rdiff -u -r1.168 -r1.169 src/sys/kern/sys_process.c cvs rdiff -u -r1.21 -r1.22 src/sys/rump/librump/rumpkern/rumpcopy.c cvs rdiff -u -r1.22 -r1.23 src/sys/sys/pax.h cvs rdiff -u -r1.196 -r1.197 src/sys/uvm/uvm_extern.h cvs rdiff -u -r1.27 -r1.28 src/sys/uvm/uvm_io.c cvs rdiff -u -r1.336 -r1.337 src/sys/uvm/uvm_map.c cvs rdiff -u -r1.72 -r1.73 src/sys/uvm/uvm_map.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_pax.c diff -u src/sys/kern/kern_pax.c:1.51 src/sys/kern/kern_pax.c:1.52 --- src/sys/kern/kern_pax.c:1.51 Wed May 25 13:25:32 2016 +++ src/sys/kern/kern_pax.c Wed May 25 13:43:58 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_pax.c,v 1.51 2016/05/25 17:25:32 christos Exp $ */ +/* $NetBSD: kern_pax.c,v 1.52 2016/05/25 17:43:58 christos Exp $ */ /* * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_pax.c,v 1.51 2016/05/25 17:25:32 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_pax.c,v 1.52 2016/05/25 17:43:58 christos Exp $"); #include "opt_pax.h" @@ -117,6 +117,7 @@ static bool pax_aslr_elf_flags_active(ui #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 @@ -206,6 +207,14 @@ SYSCTL_SETUP(sysctl_security_pax_setup, "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 mprotect 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, @@ -433,6 +442,24 @@ pax_mprotect_adjust( *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: src/sys/kern/kern_proc.c diff -u src/sys/kern/kern_proc.c:1.195 src/sys/kern/kern_proc.c:1.196 --- src/sys/kern/kern_proc.c:1.195 Mon Apr 4 16:47:57 2016 +++ src/sys/kern/kern_proc.c Wed May 25 13:43:58 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_proc.c,v 1.195 2016/04/04 20:47:57 christos Exp $ */ +/* $NetBSD: kern_proc.c,v 1.196 2016/05/25 17:43:58 christos Exp $ */ /*- * Copyright (c) 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.195 2016/04/04 20:47:57 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.196 2016/05/25 17:43:58 christos Exp $"); #ifdef _KERNEL_OPT #include "opt_kstack.h" @@ -2114,7 +2114,7 @@ copy_procargs(struct proc *p, int oid, s 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: src/sys/kern/subr_copy.c diff -u src/sys/kern/subr_copy.c:1.6 src/sys/kern/subr_copy.c:1.7 --- src/sys/kern/subr_copy.c:1.6 Tue Apr 21 09:17:25 2015 +++ src/sys/kern/subr_copy.c Wed May 25 13:43:58 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_copy.c,v 1.6 2015/04/21 13:17:25 riastradh Exp $ */ +/* $NetBSD: subr_copy.c,v 1.7 2016/05/25 17:43:58 christos Exp $ */ /*- * Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc. @@ -79,7 +79,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: subr_copy.c,v 1.6 2015/04/21 13:17:25 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_copy.c,v 1.7 2016/05/25 17:43:58 christos Exp $"); #include <sys/param.h> #include <sys/fcntl.h> @@ -223,7 +223,7 @@ copyin_vmspace(struct vmspace *vm, const 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 @@ copyout_vmspace(struct vmspace *vm, cons 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: src/sys/kern/sys_process.c diff -u src/sys/kern/sys_process.c:1.168 src/sys/kern/sys_process.c:1.169 --- src/sys/kern/sys_process.c:1.168 Mon Apr 4 16:47:57 2016 +++ src/sys/kern/sys_process.c Wed May 25 13:43:58 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: sys_process.c,v 1.168 2016/04/04 20:47:57 christos Exp $ */ +/* $NetBSD: sys_process.c,v 1.169 2016/05/25 17:43:58 christos Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -118,16 +118,18 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.168 2016/04/04 20:47:57 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.169 2016/05/25 17:43:58 christos Exp $"); #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 @@ process_domem(struct lwp *curl /*tracer* 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: src/sys/rump/librump/rumpkern/rumpcopy.c diff -u src/sys/rump/librump/rumpkern/rumpcopy.c:1.21 src/sys/rump/librump/rumpkern/rumpcopy.c:1.22 --- src/sys/rump/librump/rumpkern/rumpcopy.c:1.21 Tue Jan 26 18:12:17 2016 +++ src/sys/rump/librump/rumpkern/rumpcopy.c Wed May 25 13:43:58 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpcopy.c,v 1.21 2016/01/26 23:12:17 pooka Exp $ */ +/* $NetBSD: rumpcopy.c,v 1.22 2016/05/25 17:43:58 christos Exp $ */ /* * Copyright (c) 2009 Antti Kantee. All Rights Reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rumpcopy.c,v 1.21 2016/01/26 23:12:17 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rumpcopy.c,v 1.22 2016/05/25 17:43:58 christos Exp $"); #include <sys/param.h> #include <sys/lwp.h> @@ -180,7 +180,7 @@ kcopy(const void *src, void *dst, size_t * i.e. the current thread does not have an appropriate vm context. */ int -uvm_io(struct vm_map *vm, struct uio *uio) +uvm_io(struct vm_map *vm, struct uio *uio, int flag) { int error = 0; Index: src/sys/sys/pax.h diff -u src/sys/sys/pax.h:1.22 src/sys/sys/pax.h:1.23 --- src/sys/sys/pax.h:1.22 Wed May 25 13:25:32 2016 +++ src/sys/sys/pax.h Wed May 25 13:43:58 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: pax.h,v 1.22 2016/05/25 17:25:32 christos Exp $ */ +/* $NetBSD: pax.h,v 1.23 2016/05/25 17:43:58 christos Exp $ */ /*- * Copyright (c) 2006 Elad Efrat <e...@netbsd.org> @@ -67,6 +67,7 @@ void pax_mprotect_adjust( 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 @@ void pax_mprotect_adjust( # 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: src/sys/uvm/uvm_extern.h diff -u src/sys/uvm/uvm_extern.h:1.196 src/sys/uvm/uvm_extern.h:1.197 --- src/sys/uvm/uvm_extern.h:1.196 Thu Feb 4 23:18:55 2016 +++ src/sys/uvm/uvm_extern.h Wed May 25 13:43:58 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_extern.h,v 1.196 2016/02/05 04:18:55 christos Exp $ */ +/* $NetBSD: uvm_extern.h,v 1.197 2016/05/25 17:43:58 christos Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -622,7 +622,7 @@ void uvm_cpu_attach(struct cpu_info *) 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: src/sys/uvm/uvm_io.c diff -u src/sys/uvm/uvm_io.c:1.27 src/sys/uvm/uvm_io.c:1.28 --- src/sys/uvm/uvm_io.c:1.27 Fri Jan 27 14:48:41 2012 +++ src/sys/uvm/uvm_io.c Wed May 25 13:43:58 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_io.c,v 1.27 2012/01/27 19:48:41 para Exp $ */ +/* $NetBSD: uvm_io.c,v 1.28 2016/05/25 17:43:58 christos Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_io.c,v 1.27 2012/01/27 19:48:41 para Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_io.c,v 1.28 2016/05/25 17:43:58 christos Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -53,7 +53,7 @@ __KERNEL_RCSID(0, "$NetBSD: uvm_io.c,v 1 */ 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 @@ uvm_io(struct vm_map *map, struct uio *u 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 @@ uvm_io(struct vm_map *map, struct uio *u */ 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: src/sys/uvm/uvm_map.c diff -u src/sys/uvm/uvm_map.c:1.336 src/sys/uvm/uvm_map.c:1.337 --- src/sys/uvm/uvm_map.c:1.336 Wed Nov 4 19:10:48 2015 +++ src/sys/uvm/uvm_map.c Wed May 25 13:43:58 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_map.c,v 1.336 2015/11/05 00:10:48 pgoyette Exp $ */ +/* $NetBSD: uvm_map.c,v 1.337 2016/05/25 17:43:58 christos Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.336 2015/11/05 00:10:48 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.337 2016/05/25 17:43:58 christos Exp $"); #include "opt_ddb.h" #include "opt_uvmhist.h" @@ -2546,6 +2546,7 @@ uvm_map_replace(struct vm_map *map, vadd * 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 @@ uvm_map_extract(struct vm_map *srcmap, v 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: src/sys/uvm/uvm_map.h diff -u src/sys/uvm/uvm_map.h:1.72 src/sys/uvm/uvm_map.h:1.73 --- src/sys/uvm/uvm_map.h:1.72 Mon Oct 29 12:00:05 2012 +++ src/sys/uvm/uvm_map.h Wed May 25 13:43:58 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_map.h,v 1.72 2012/10/29 16:00:05 para Exp $ */ +/* $NetBSD: uvm_map.h,v 1.73 2016/05/25 17:43:58 christos Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -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 */