Security/SELinux: seperate lsm specific mmap_min_addr
Currently SELinux enforcement of controls on the ability to map low memory is determined by the mmap_min_addr tunable. This patch causes SELinux to ignore the tunable and instead use a seperate Kconfig option specific to how much space the LSM should protect. The tunable will now only control the need for CAP_SYS_RAWIO and SELinux permissions will always protect the amount of low memory designated by CONFIG_LSM_MMAP_MIN_ADDR. This allows users who need to disable the mmap_min_addr controls (usual reason being they run WINE as a non-root user) to do so and still have SELinux controls preventing confined domains (like a web server) from being able to map some area of low memory. Signed-off-by: Eric Paris <eparis@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
@@ -113,6 +113,22 @@ config SECURITY_ROOTPLUG
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
config LSM_MMAP_MIN_ADDR
|
||||
int "Low address space for LSM to from user allocation"
|
||||
depends on SECURITY && SECURITY_SELINUX
|
||||
default 65535
|
||||
help
|
||||
This is the portion of low virtual memory which should be protected
|
||||
from userspace allocation. Keeping a user from writing to low pages
|
||||
can help reduce the impact of kernel NULL pointer bugs.
|
||||
|
||||
For most ia64, ppc64 and x86 users with lots of address space
|
||||
a value of 65536 is reasonable and should cause no problems.
|
||||
On arm and other archs it should not be higher than 32768.
|
||||
Programs which use vm86 functionality or have some need to map
|
||||
this low address space will need the permission specific to the
|
||||
systems running LSM.
|
||||
|
||||
source security/selinux/Kconfig
|
||||
source security/smack/Kconfig
|
||||
source security/tomoyo/Kconfig
|
||||
|
||||
@@ -8,7 +8,7 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack
|
||||
subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
|
||||
|
||||
# always enable default capabilities
|
||||
obj-y += commoncap.o
|
||||
obj-y += commoncap.o min_addr.o
|
||||
|
||||
# Object file lists
|
||||
obj-$(CONFIG_SECURITY) += security.o capability.o
|
||||
|
||||
@@ -1005,7 +1005,7 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (addr < mmap_min_addr) {
|
||||
if (addr < dac_mmap_min_addr) {
|
||||
ret = cap_capable(current, current_cred(), CAP_SYS_RAWIO,
|
||||
SECURITY_CAP_AUDIT);
|
||||
/* set PF_SUPERPRIV if it turns out we allow the low mmap */
|
||||
|
||||
49
security/min_addr.c
Normal file
49
security/min_addr.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/sysctl.h>
|
||||
|
||||
/* amount of vm to protect from userspace access by both DAC and the LSM*/
|
||||
unsigned long mmap_min_addr;
|
||||
/* amount of vm to protect from userspace using CAP_SYS_RAWIO (DAC) */
|
||||
unsigned long dac_mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
|
||||
/* amount of vm to protect from userspace using the LSM = CONFIG_LSM_MMAP_MIN_ADDR */
|
||||
|
||||
/*
|
||||
* Update mmap_min_addr = max(dac_mmap_min_addr, CONFIG_LSM_MMAP_MIN_ADDR)
|
||||
*/
|
||||
static void update_mmap_min_addr(void)
|
||||
{
|
||||
#ifdef CONFIG_LSM_MMAP_MIN_ADDR
|
||||
if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
|
||||
mmap_min_addr = dac_mmap_min_addr;
|
||||
else
|
||||
mmap_min_addr = CONFIG_LSM_MMAP_MIN_ADDR;
|
||||
#else
|
||||
mmap_min_addr = dac_mmap_min_addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* sysctl handler which just sets dac_mmap_min_addr = the new value and then
|
||||
* calls update_mmap_min_addr() so non MAP_FIXED hints get rounded properly
|
||||
*/
|
||||
int mmap_min_addr_handler(struct ctl_table *table, int write, struct file *filp,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos);
|
||||
|
||||
update_mmap_min_addr();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __init init_mmap_min_addr(void)
|
||||
{
|
||||
update_mmap_min_addr();
|
||||
|
||||
return 0;
|
||||
}
|
||||
pure_initcall(init_mmap_min_addr);
|
||||
@@ -3036,7 +3036,7 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot,
|
||||
* at bad behaviour/exploit that we always want to get the AVC, even
|
||||
* if DAC would have also denied the operation.
|
||||
*/
|
||||
if (addr < mmap_min_addr) {
|
||||
if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
|
||||
rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
|
||||
MEMPROTECT__MMAP_ZERO, NULL);
|
||||
if (rc)
|
||||
|
||||
Reference in New Issue
Block a user