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
This commit is contained in:
christos 2018-12-05 18:16:51 +00:00
parent 122244022d
commit dea5460561
8 changed files with 127 additions and 83 deletions

View File

@ -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 .

View File

@ -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_mostly;
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.
*/

View File

@ -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(SYSCTLFN_PROTO);
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 kern subtree setup")
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")
@ -1353,37 +1339,6 @@ sysctl_security_setidcore(SYSCTLFN_ARGS)
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);
*(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)
{

View File

@ -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, kauth_action_t action, void *cookie,
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;
}
@ -374,6 +391,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",
@ -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, struct proc *p)
* 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 *ep, bool zombie)
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 *ep, bool zombie)
* 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_proc2 *ki, bool zombie)
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, size_t *len)
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;
}

View File

@ -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, struct lwp *l,
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, struct lwp *l,
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,

View File

@ -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__)

View File

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

View File

@ -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