diff options
| author | drochner <drochner@NetBSD.org> | 2010-02-18 14:57:01 +0000 |
|---|---|---|
| committer | drochner <drochner@NetBSD.org> | 2010-02-18 14:57:01 +0000 |
| commit | dda500d0d8a5edd00a1ba42f05bfcdc646dbfc88 (patch) | |
| tree | 0b7f4e774046e654dfdd9208b4e9af85f5769b8a /sys | |
| parent | fe9cd1c415ddbf294f5edf31013ff5602fc0cde6 (diff) | |
Disable mapping of virtual address 0 by user programs per default.
This blocks an easy exploit of kernel bugs leading to dereference
of a NULL pointer on some architectures (eg i386).
The check can be disabled in various ways:
-by CPP definitions in machine/types.h (portmaster's choice)
-by a kernel config option USER_VA0_DISABLED_DEFAULT=0
-at runtime by sysctl vm.user_va0_disabled (cannot be cleared
at securelevel>0)
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/uvm/files.uvm | 3 | ||||
| -rw-r--r-- | sys/uvm/uvm_map.c | 63 |
2 files changed, 63 insertions, 3 deletions
diff --git a/sys/uvm/files.uvm b/sys/uvm/files.uvm index 4d33c5b4a2c..4bfffb64ec6 100644 --- a/sys/uvm/files.uvm +++ b/sys/uvm/files.uvm @@ -1,4 +1,4 @@ -# $NetBSD: files.uvm,v 1.16 2009/10/21 21:12:07 rmind Exp $ +# $NetBSD: files.uvm,v 1.17 2010/02/18 14:57:01 drochner Exp $ # # UVM options @@ -10,6 +10,7 @@ defflag opt_readahead.h READAHEAD_STATS defflag opt_ubc.h UBC_STATS defparam opt_pagermap.h PAGER_MAP_SIZE defflag PDPOLICY_CLOCKPRO +defparam USER_VA0_DISABLED_DEFAULT file uvm/uvm_amap.c file uvm/uvm_anon.c diff --git a/sys/uvm/uvm_map.c b/sys/uvm/uvm_map.c index 797e2a17755..bf867eb5010 100644 --- a/sys/uvm/uvm_map.c +++ b/sys/uvm/uvm_map.c @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_map.c,v 1.287 2010/02/08 19:02:33 joerg Exp $ */ +/* $NetBSD: uvm_map.c,v 1.288 2010/02/18 14:57:01 drochner Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.287 2010/02/08 19:02:33 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.288 2010/02/18 14:57:01 drochner Exp $"); #include "opt_ddb.h" #include "opt_uvmhist.h" @@ -89,6 +89,11 @@ __KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.287 2010/02/08 19:02:33 joerg Exp $"); #include <sys/vnode.h> #include <sys/lockdebug.h> #include <sys/atomic.h> +#ifndef __USER_VA0_IS_SAFE +#include <sys/sysctl.h> +#include <sys/kauth.h> +#include "opt_user_va0_disabled_default.h" +#endif #ifdef SYSVSHM #include <sys/shm.h> @@ -168,6 +173,17 @@ MALLOC_DEFINE(M_VMPMAP, "VM pmap", "VM pmap"); vaddr_t uvm_maxkaddr; #endif +#ifndef __USER_VA0_IS_SAFE +#ifndef __USER_VA0_DISABLED_DEFAULT +#define __USER_VA0_DISABLED_DEFAULT 1 +#endif +#ifdef USER_VA0_DISABLED_DEFAULT /* kernel config option overrides */ +#undef __USER_VA0_DISABLED_DEFAULT +#define __USER_VA0_DISABLED_DEFAULT USER_VA0_DISABLED_DEFAULT +#endif +static int user_va0_disabled = __USER_VA0_DISABLED_DEFAULT; +#endif + /* * macros */ @@ -1174,6 +1190,12 @@ uvm_map(struct vm_map *map, vaddr_t *startp /* IN/OUT */, vsize_t size, KASSERT((flags & UVM_FLAG_QUANTUM) == 0 || VM_MAP_IS_KERNEL(map)); KASSERT((size & PAGE_MASK) == 0); +#ifndef __USER_VA0_IS_SAFE + if ((flags & UVM_FLAG_FIXED) && *startp == 0 && + !VM_MAP_IS_KERNEL(map) && user_va0_disabled) + return EACCES; +#endif + /* * for pager_map, allocate the new entry first to avoid sleeping * for memory while we have the map locked. @@ -5215,3 +5237,40 @@ uvm_whatis(uintptr_t addr, void (*pr)(const char *, ...)) } #endif /* DDB || DEBUGPRINT */ + +#ifndef __USER_VA0_IS_SAFE +static int +sysctl_user_va0_disabled(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + int t, error; + + node = *rnode; + node.sysctl_data = &t; + t = user_va0_disabled; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return (error); + + /* lower only at securelevel < 1 */ + if (!t && user_va0_disabled && + kauth_authorize_system(l->l_cred, + KAUTH_SYSTEM_CHSYSFLAGS /* XXX */, 0, + NULL, NULL, NULL)) + return EPERM; + + user_va0_disabled = !!t; + return 0; +} + +SYSCTL_SETUP(sysctl_uvmmap_setup, "sysctl uvmmap setup") +{ + + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "user_va0_disabled", + SYSCTL_DESCR("Disable VA 0"), + sysctl_user_va0_disabled, 0, &user_va0_disabled, 0, + CTL_VM, CTL_CREATE, CTL_EOL); +} +#endif |
