Index: sys/dev/mm.c =================================================================== RCS file: /cvsroot/src/sys/dev/mm.c,v retrieving revision 1.22 diff -u -p -u -r1.22 mm.c --- dev/mm.c 13 Oct 2016 08:56:31 -0000 1.22 +++ dev/mm.c 5 Dec 2018 16:09:12 -0000 @@ -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,17 @@ const struct cdevsw mem_ultrix_cdevsw = }; #endif +static int +mm_open(dev_t dev, int flag, int mode, struct lwp *l) +{ + l->l_proc->p_flag |= PK_KMEM; +#ifdef __HAVE_MM_MD_OPEN + return mm_md_open(dev, flag, mode, l); +#else + return 0; +#endif +} + /* * mm_init: initialize memory device driver. */ Index: sys/kern/init_sysctl.c =================================================================== RCS file: /cvsroot/src/sys/kern/init_sysctl.c,v retrieving revision 1.220 diff -u -p -u -r1.220 init_sysctl.c --- kern/init_sysctl.c 3 Dec 2018 00:11:02 -0000 1.220 +++ kern/init_sysctl.c 5 Dec 2018 16:09:13 -0000 @@ -36,7 +36,6 @@ __KERNEL_RCSID(0, "$NetBSD: init_sysctl. #include "opt_compat_netbsd.h" #include "opt_modular.h" #include "opt_gprof.h" -#include "opt_kaslr.h" #include "pty.h" #include @@ -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: sys/kern/kern_proc.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_proc.c,v retrieving revision 1.221 diff -u -p -u -r1.221 kern_proc.c --- kern/kern_proc.c 24 Nov 2018 19:22:17 -0000 1.221 +++ kern/kern_proc.c 5 Dec 2018 16:09:13 -0000 @@ -219,7 +219,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 +247,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 +286,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 +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", SYSCTL_DESCR("System-wide process information"), @@ -1639,6 +1661,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 +1822,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 +2197,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 +2290,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 +2298,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 +2346,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 +2358,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 +2622,34 @@ 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); + + *(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: sys/sys/proc.h =================================================================== RCS file: /cvsroot/src/sys/sys/proc.h,v retrieving revision 1.349 diff -u -p -u -r1.349 proc.h --- sys/proc.h 10 Aug 2018 21:44:59 -0000 1.349 +++ sys/proc.h 5 Dec 2018 16:09:13 -0000 @@ -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: sys/sys/sysctl.h =================================================================== RCS file: /cvsroot/src/sys/sys/sysctl.h,v retrieving revision 1.228 diff -u -p -u -r1.228 sysctl.h --- sys/sysctl.h 22 Aug 2018 01:05:24 -0000 1.228 +++ sys/sysctl.h 5 Dec 2018 16:09:13 -0000 @@ -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 Index: sys/miscfs/procfs/procfs_linux.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/procfs/procfs_linux.c,v retrieving revision 1.73 diff -u -p -u -r1.73 procfs_linux.c --- sys/miscfs/procfs/procfs_linux.c 13 Apr 2017 09:54:18 -0000 1.73 +++ sys/miscfs/procfs/procfs_linux.c 5 Dec 2018 16:17:27 -0000 @@ -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: share/man/man7/sysctl.7 =================================================================== RCS file: /cvsroot/src/share/man/man7/sysctl.7,v retrieving revision 1.135 diff -u -p -u -r1.135 sysctl.7 --- share/man/man7/sysctl.7 4 Nov 2018 16:30:28 -0000 1.135 +++ share/man/man7/sysctl.7 5 Dec 2018 16:17:50 -0000 @@ -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 .