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