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:
parent
122244022d
commit
dea5460561
|
@ -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 .
|
||||
|
|
23
sys/dev/mm.c
23
sys/dev/mm.c
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue