Module Name: src Committed By: christos Date: Wed Dec 5 18:16:51 UTC 2018
Modified Files: src/share/man/man7: sysctl.7 src/sys/dev: mm.c src/sys/kern: init_sysctl.c kern_proc.c src/sys/miscfs/procfs: procfs_linux.c src/sys/sys: param.h proc.h sysctl.h Log Message: As discussed in tech-kern: - make sysctl kern.expose_address tri-state: 0: no access 1: access to processes with open /dev/kmem 2: access to everyone defaults: 0: KASLR kernels 1: non-KASLR kernels - improve efficiency by calling get_expose_address() per sysctl, not per process. - don't expose addresses for linux procfs - welcome to 8.99.27, changes to fill_*proc ABI To generate a diff of this commit: cvs rdiff -u -r1.135 -r1.136 src/share/man/man7/sysctl.7 cvs rdiff -u -r1.22 -r1.23 src/sys/dev/mm.c cvs rdiff -u -r1.220 -r1.221 src/sys/kern/init_sysctl.c cvs rdiff -u -r1.221 -r1.222 src/sys/kern/kern_proc.c cvs rdiff -u -r1.73 -r1.74 src/sys/miscfs/procfs/procfs_linux.c cvs rdiff -u -r1.571 -r1.572 src/sys/sys/param.h cvs rdiff -u -r1.349 -r1.350 src/sys/sys/proc.h cvs rdiff -u -r1.228 -r1.229 src/sys/sys/sysctl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/share/man/man7/sysctl.7 diff -u src/share/man/man7/sysctl.7:1.135 src/share/man/man7/sysctl.7:1.136 --- src/share/man/man7/sysctl.7:1.135 Sun Nov 4 11:30:28 2018 +++ src/share/man/man7/sysctl.7 Wed Dec 5 13:16:51 2018 @@ -1,4 +1,4 @@ -.\" $NetBSD: sysctl.7,v 1.135 2018/11/04 16:30:28 christos Exp $ +.\" $NetBSD: sysctl.7,v 1.136 2018/12/05 18:16:51 christos Exp $ .\" .\" Copyright (c) 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" @(#)sysctl.3 8.4 (Berkeley) 5/9/95 .\" -.Dd November 3, 2018 +.Dd December 5, 2018 .Dt SYSCTL 7 .Os .Sh NAME @@ -524,9 +524,28 @@ calls used by .Xr fstat 1 and .Xr sockstat 1 . +If it is set to +.Dv 0 +access is not allowed. +If it is set to +.Dv 1 +then only processes that have opened +.Pa /dev/kmem +can have access. +If it is set to +.Dv 2 +every process is allowed. Defaults to -.Dv 0 . -Turning it on renders KASLR ineffective. +.Dv 0 +for +.Dv KASLR +kernels +and +.Dv 1 +otherwise. +Allowing general access renders KASLR ineffective; allowing only kmem +accessing programs, weakens KASLR if those programs can be subverted +to leak the addresses. .It Li kern.dump_on_panic ( Dv KERN_DUMP_ON_PANIC ) Perform a crash dump on system .Xr panic 9 . Index: src/sys/dev/mm.c diff -u src/sys/dev/mm.c:1.22 src/sys/dev/mm.c:1.23 --- src/sys/dev/mm.c:1.22 Thu Oct 13 04:56:31 2016 +++ src/sys/dev/mm.c Wed Dec 5 13:16:51 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: mm.c,v 1.22 2016/10/13 08:56:31 ryo Exp $ */ +/* $NetBSD: mm.c,v 1.23 2018/12/05 18:16:51 christos Exp $ */ /*- * Copyright (c) 2002, 2008, 2010 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mm.c,v 1.22 2016/10/13 08:56:31 ryo Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mm.c,v 1.23 2018/12/05 18:16:51 christos Exp $"); #include "opt_compat_netbsd.h" @@ -53,17 +53,14 @@ static void * dev_zero_page __read_most static kmutex_t dev_mem_lock __cacheline_aligned; static vaddr_t dev_mem_addr __read_mostly; +static dev_type_open(mm_open); static dev_type_read(mm_readwrite); static dev_type_ioctl(mm_ioctl); static dev_type_mmap(mm_mmap); static dev_type_ioctl(mm_ioctl); const struct cdevsw mem_cdevsw = { -#ifdef __HAVE_MM_MD_OPEN - .d_open = mm_md_open, -#else - .d_open = nullopen, -#endif + .d_open = mm_open, .d_close = nullclose, .d_read = mm_readwrite, .d_write = mm_readwrite, @@ -94,6 +91,18 @@ const struct cdevsw mem_ultrix_cdevsw = }; #endif +static int +mm_open(dev_t dev, int flag, int mode, struct lwp *l) +{ +#ifdef __HAVE_MM_MD_OPEN + int error; + if ((error = mm_md_open(dev, flag, mode, l)) != 0) + return error; +#endif + l->l_proc->p_flag |= PK_KMEM; + return 0; +} + /* * mm_init: initialize memory device driver. */ Index: src/sys/kern/init_sysctl.c diff -u src/sys/kern/init_sysctl.c:1.220 src/sys/kern/init_sysctl.c:1.221 --- src/sys/kern/init_sysctl.c:1.220 Sun Dec 2 19:11:02 2018 +++ src/sys/kern/init_sysctl.c Wed Dec 5 13:16:51 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: init_sysctl.c,v 1.220 2018/12/03 00:11:02 christos Exp $ */ +/* $NetBSD: init_sysctl.c,v 1.221 2018/12/05 18:16:51 christos Exp $ */ /*- * Copyright (c) 2003, 2007, 2008, 2009 The NetBSD Foundation, Inc. @@ -30,13 +30,12 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.220 2018/12/03 00:11:02 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.221 2018/12/05 18:16:51 christos Exp $"); #include "opt_sysv.h" #include "opt_compat_netbsd.h" #include "opt_modular.h" #include "opt_gprof.h" -#include "opt_kaslr.h" #include "pty.h" #include <sys/types.h> @@ -86,12 +85,6 @@ int kern_has_sysvmsg = 0; int kern_has_sysvshm = 0; int kern_has_sysvsem = 0; -#ifdef KASLR -int kern_expose_address = 0; -#else -int kern_expose_address = 1; -#endif - static const u_int sysctl_lwpprflagmap[] = { LPR_DETACHED, L_DETACHED, 0 @@ -134,7 +127,6 @@ static int sysctl_kern_root_partition(SY static int sysctl_kern_drivers(SYSCTLFN_PROTO); static int sysctl_security_setidcore(SYSCTLFN_PROTO); static int sysctl_security_setidcorename(SYSCTLFN_PROTO); -static int sysctl_security_expose_address(SYSCTLFN_PROTO); static int sysctl_kern_cpid(SYSCTLFN_PROTO); static int sysctl_hw_usermem(SYSCTLFN_PROTO); static int sysctl_hw_cnmagic(SYSCTLFN_PROTO); @@ -607,12 +599,6 @@ SYSCTL_SETUP(sysctl_kern_setup, "sysctl SYSCTL_DESCR("Kernel message verbosity"), sysctl_kern_messages, 0, NULL, 0, CTL_KERN, CTL_CREATE, CTL_EOL); - sysctl_createv(clog, 0, NULL, NULL, - CTLFLAG_PERMANENT|CTLFLAG_READWRITE, - CTLTYPE_INT, "expose_address", - SYSCTL_DESCR("Expose kernel addresses to userland"), - sysctl_security_expose_address, 0, &kern_expose_address, - 0, CTL_KERN, CTL_CREATE, CTL_EOL); } SYSCTL_SETUP(sysctl_hw_misc_setup, "sysctl hw subtree misc setup") @@ -1354,37 +1340,6 @@ sysctl_security_setidcore(SYSCTLFN_ARGS) } static int -sysctl_security_expose_address(SYSCTLFN_ARGS) -{ - int expose_address, error; - struct sysctlnode node; - - node = *rnode; - node.sysctl_data = &expose_address; - expose_address = *(int *)rnode->sysctl_data; - error = sysctl_lookup(SYSCTLFN_CALL(&node)); - if (error || newp == NULL) - return error; - - if (kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_KERNADDR, - 0, NULL, NULL, NULL)) - return (EPERM); - - *(int *)rnode->sysctl_data = expose_address; - - return 0; -} - -bool -get_expose_address(struct proc *p) -{ - /* allow only if sysctl variable is set or privileged */ - return kern_expose_address || kauth_authorize_process(kauth_cred_get(), - KAUTH_PROCESS_CANSEE, p, - KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_KPTR), NULL, NULL) == 0; -} - -static int sysctl_security_setidcorename(SYSCTLFN_ARGS) { int error; Index: src/sys/kern/kern_proc.c diff -u src/sys/kern/kern_proc.c:1.221 src/sys/kern/kern_proc.c:1.222 --- src/sys/kern/kern_proc.c:1.221 Sat Nov 24 14:22:17 2018 +++ src/sys/kern/kern_proc.c Wed Dec 5 13:16:51 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_proc.c,v 1.221 2018/11/24 19:22:17 christos Exp $ */ +/* $NetBSD: kern_proc.c,v 1.222 2018/12/05 18:16:51 christos Exp $ */ /*- * Copyright (c) 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -62,13 +62,14 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.221 2018/11/24 19:22:17 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.222 2018/12/05 18:16:51 christos Exp $"); #ifdef _KERNEL_OPT #include "opt_kstack.h" #include "opt_maxuprc.h" #include "opt_dtrace.h" #include "opt_compat_netbsd32.h" +#include "opt_kaslr.h" #endif #if defined(__HAVE_COMPAT_NETBSD32) && !defined(COMPAT_NETBSD32) \ @@ -219,7 +220,13 @@ static const int maxuprc = MAXUPRC; static int sysctl_doeproc(SYSCTLFN_PROTO); static int sysctl_kern_proc_args(SYSCTLFN_PROTO); +static int sysctl_security_expose_address(SYSCTLFN_PROTO); +#ifdef KASLR +static int kern_expose_address_= 0; +#else +static int kern_expose_address = 1; +#endif /* * The process list descriptors, used during pid allocation and * by sysctl. No locking on this data structure is needed since @@ -241,7 +248,7 @@ static pool_cache_t proc_cache; static kauth_listener_t proc_listener; -static void fill_proc(const struct proc *, struct proc *); +static void fill_proc(const struct proc *, struct proc *, bool); static int fill_pathname(struct lwp *, pid_t, void *, size_t *); static int @@ -280,6 +287,16 @@ proc_listener_cb(kauth_cred_t cred, kaut break; case KAUTH_REQ_PROCESS_CANSEE_KPTR: + if (!kern_expose_address) + break; + + if (kern_expose_address == 1 && !(p->p_flag & PK_KMEM)) + break; + + result = KAUTH_RESULT_ALLOW; + + break; + default: break; } @@ -375,6 +392,12 @@ procinit_sysctl(void) static struct sysctllog *clog; sysctl_createv(&clog, 0, NULL, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "expose_address", + SYSCTL_DESCR("Enable exposing kernel addresses"), + sysctl_security_expose_address, 0, + &kern_expose_address, 0, CTL_KERN, CTL_CREATE, CTL_EOL); + sysctl_createv(&clog, 0, NULL, NULL, CTLFLAG_PERMANENT, CTLTYPE_NODE, "proc", SYSCTL_DESCR("System-wide process information"), @@ -1639,6 +1662,7 @@ sysctl_doeproc(SYSCTLFN_ARGS) u_int elem_size, kelem_size, elem_count; size_t buflen, needed; bool match, zombie, mmmbrains; + const bool allowaddr = get_expose_address(curproc); if (namelen == 1 && name[0] == CTL_QUERY) return (sysctl_query(SYSCTLFN_CALL(rnode))); @@ -1799,10 +1823,12 @@ sysctl_doeproc(SYSCTLFN_ARGS) if (buflen >= elem_size && (type == KERN_PROC || elem_count > 0)) { if (type == KERN_PROC) { - fill_proc(p, &kbuf->kproc.kp_proc); - fill_eproc(p, &kbuf->kproc.kp_eproc, zombie); + fill_proc(p, &kbuf->kproc.kp_proc, allowaddr); + fill_eproc(p, &kbuf->kproc.kp_eproc, zombie, + allowaddr); } else { - fill_kproc2(p, &kbuf->kproc2, zombie); + fill_kproc2(p, &kbuf->kproc2, zombie, + allowaddr); elem_count--; } mutex_exit(p->p_lock); @@ -2172,10 +2198,8 @@ done: * Fill in a proc structure for the specified process. */ static void -fill_proc(const struct proc *psrc, struct proc *p) +fill_proc(const struct proc *psrc, struct proc *p, bool allowaddr) { - const bool allowaddr = get_expose_address(curproc); - COND_SET_VALUE(p->p_list, psrc->p_list, allowaddr); COND_SET_VALUE(p->p_auxlock, psrc->p_auxlock, allowaddr); COND_SET_VALUE(p->p_lock, psrc->p_lock, allowaddr); @@ -2267,7 +2291,7 @@ fill_proc(const struct proc *psrc, struc * Fill in an eproc structure for the specified process. */ void -fill_eproc(struct proc *p, struct eproc *ep, bool zombie) +fill_eproc(struct proc *p, struct eproc *ep, bool zombie, bool allowaddr) { struct tty *tp; struct lwp *l; @@ -2275,8 +2299,6 @@ fill_eproc(struct proc *p, struct eproc KASSERT(mutex_owned(proc_lock)); KASSERT(mutex_owned(p->p_lock)); - const bool allowaddr = get_expose_address(curproc); - COND_SET_VALUE(ep->e_paddr, p, allowaddr); COND_SET_VALUE(ep->e_sess, p->p_session, allowaddr); if (p->p_cred) { @@ -2325,7 +2347,7 @@ fill_eproc(struct proc *p, struct eproc * Fill in a kinfo_proc2 structure for the specified process. */ void -fill_kproc2(struct proc *p, struct kinfo_proc2 *ki, bool zombie) +fill_kproc2(struct proc *p, struct kinfo_proc2 *ki, bool zombie, bool allowaddr) { struct tty *tp; struct lwp *l, *l2; @@ -2337,8 +2359,6 @@ fill_kproc2(struct proc *p, struct kinfo KASSERT(mutex_owned(proc_lock)); KASSERT(mutex_owned(p->p_lock)); - const bool allowaddr = get_expose_address(curproc); - sigemptyset(&ss1); sigemptyset(&ss2); @@ -2603,3 +2623,43 @@ proc_getauxv(struct proc *p, void **buf, return 0; } + + +static int +sysctl_security_expose_address(SYSCTLFN_ARGS) +{ + int expose_address, error; + struct sysctlnode node; + + node = *rnode; + node.sysctl_data = &expose_address; + expose_address = *(int *)rnode->sysctl_data; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return error; + + if (kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_KERNADDR, + 0, NULL, NULL, NULL)) + return EPERM; + + switch (expose_address) { + case 0: + case 1: + case 2: + break; + default: + return EINVAL; + } + + *(int *)rnode->sysctl_data = expose_address; + + return 0; +} + +bool +get_expose_address(struct proc *p) +{ + /* allow only if sysctl variable is set or privileged */ + return kauth_authorize_process(kauth_cred_get(), KAUTH_PROCESS_CANSEE, + p, KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_KPTR), NULL, NULL) == 0; +} Index: src/sys/miscfs/procfs/procfs_linux.c diff -u src/sys/miscfs/procfs/procfs_linux.c:1.73 src/sys/miscfs/procfs/procfs_linux.c:1.74 --- src/sys/miscfs/procfs/procfs_linux.c:1.73 Thu Apr 13 05:54:18 2017 +++ src/sys/miscfs/procfs/procfs_linux.c Wed Dec 5 13:16:51 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_linux.c,v 1.73 2017/04/13 09:54:18 hannken Exp $ */ +/* $NetBSD: procfs_linux.c,v 1.74 2018/12/05 18:16:51 christos Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.73 2017/04/13 09:54:18 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.74 2018/12/05 18:16:51 christos Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -383,7 +383,7 @@ procfs_do_pid_statm(struct lwp *curl, st mutex_enter(p->p_lock); /* retrieve RSS size */ - fill_kproc2(p, &ki, false); + fill_kproc2(p, &ki, false, false); mutex_exit(p->p_lock); mutex_exit(proc_lock); @@ -440,7 +440,7 @@ procfs_do_pid_stat(struct lwp *curl, str mutex_enter(proc_lock); mutex_enter(p->p_lock); - fill_kproc2(p, &ki, false); + fill_kproc2(p, &ki, false, false); calcru(p, NULL, NULL, NULL, &rt); len = snprintf(bf, LBFSZ, Index: src/sys/sys/param.h diff -u src/sys/sys/param.h:1.571 src/sys/sys/param.h:1.572 --- src/sys/sys/param.h:1.571 Fri Nov 16 12:18:29 2018 +++ src/sys/sys/param.h Wed Dec 5 13:16:51 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: param.h,v 1.571 2018/11/16 17:18:29 kre Exp $ */ +/* $NetBSD: param.h,v 1.572 2018/12/05 18:16:51 christos Exp $ */ /*- * Copyright (c) 1982, 1986, 1989, 1993 @@ -67,7 +67,7 @@ * 2.99.9 (299000900) */ -#define __NetBSD_Version__ 899002600 /* NetBSD 8.99.26 */ +#define __NetBSD_Version__ 899002700 /* NetBSD 8.99.27 */ #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \ (m) * 1000000) + (p) * 100) <= __NetBSD_Version__) Index: src/sys/sys/proc.h diff -u src/sys/sys/proc.h:1.349 src/sys/sys/proc.h:1.350 --- src/sys/sys/proc.h:1.349 Fri Aug 10 17:44:59 2018 +++ src/sys/sys/proc.h Wed Dec 5 13:16:51 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: proc.h,v 1.349 2018/08/10 21:44:59 pgoyette Exp $ */ +/* $NetBSD: proc.h,v 1.350 2018/12/05 18:16:51 christos Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -378,6 +378,7 @@ struct proc { #define PK_SYSTEM 0x00000002 /* System process (kthread) */ #define PK_SYSVSEM 0x00000004 /* Used SysV semaphores */ #define PK_SUGID 0x00000100 /* Had set id privileges since last exec */ +#define PK_KMEM 0x00000200 /* Has kmem access */ #define PK_EXEC 0x00004000 /* Process called exec */ #define PK_NOCLDWAIT 0x00020000 /* No zombies if child dies */ #define PK_32 0x00040000 /* 32-bit process (used on 64-bit kernels) */ Index: src/sys/sys/sysctl.h diff -u src/sys/sys/sysctl.h:1.228 src/sys/sys/sysctl.h:1.229 --- src/sys/sys/sysctl.h:1.228 Tue Aug 21 21:05:24 2018 +++ src/sys/sys/sysctl.h Wed Dec 5 13:16:51 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: sysctl.h,v 1.228 2018/08/22 01:05:24 msaitoh Exp $ */ +/* $NetBSD: sysctl.h,v 1.229 2018/12/05 18:16:51 christos Exp $ */ /* * Copyright (c) 1989, 1993 @@ -1055,8 +1055,8 @@ typedef int (*sysctlfn)(SYSCTLFN_PROTO); /* * used in more than just sysctl */ -void fill_eproc(struct proc *, struct eproc *, bool); -void fill_kproc2(struct proc *, struct kinfo_proc2 *, bool); +void fill_eproc(struct proc *, struct eproc *, bool, bool); +void fill_kproc2(struct proc *, struct kinfo_proc2 *, bool, bool); /* * subsystem setup