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

Reply via email to