Commit 788084aba2ab7348257597496befcbccabdc98a3

Authored by Eric Paris
Committed by James Morris
1 parent 8cf948e744

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>

Showing 11 changed files with 92 additions and 30 deletions Side-by-side Diff

... ... @@ -34,8 +34,6 @@
34 34 #define sysctl_legacy_va_layout 0
35 35 #endif
36 36  
37   -extern unsigned long mmap_min_addr;
38   -
39 37 #include <asm/page.h>
40 38 #include <asm/pgtable.h>
41 39 #include <asm/processor.h>
... ... @@ -572,19 +570,6 @@
572 570 set_page_zone(page, zone);
573 571 set_page_node(page, node);
574 572 set_page_section(page, pfn_to_section_nr(pfn));
575   -}
576   -
577   -/*
578   - * If a hint addr is less than mmap_min_addr change hint to be as
579   - * low as possible but still greater than mmap_min_addr
580   - */
581   -static inline unsigned long round_hint_to_min(unsigned long hint)
582   -{
583   - hint &= PAGE_MASK;
584   - if (((void *)hint != NULL) &&
585   - (hint < mmap_min_addr))
586   - return PAGE_ALIGN(mmap_min_addr);
587   - return hint;
588 573 }
589 574  
590 575 /*
include/linux/security.h
... ... @@ -28,6 +28,7 @@
28 28 #include <linux/resource.h>
29 29 #include <linux/sem.h>
30 30 #include <linux/shm.h>
  31 +#include <linux/mm.h> /* PAGE_ALIGN */
31 32 #include <linux/msg.h>
32 33 #include <linux/sched.h>
33 34 #include <linux/key.h>
... ... @@ -95,6 +96,7 @@
95 96 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
96 97  
97 98 extern unsigned long mmap_min_addr;
  99 +extern unsigned long dac_mmap_min_addr;
98 100 /*
99 101 * Values used in the task_security_ops calls
100 102 */
... ... @@ -147,6 +149,21 @@
147 149 opts->num_mnt_opts = 0;
148 150 }
149 151  
  152 +/*
  153 + * If a hint addr is less than mmap_min_addr change hint to be as
  154 + * low as possible but still greater than mmap_min_addr
  155 + */
  156 +static inline unsigned long round_hint_to_min(unsigned long hint)
  157 +{
  158 + hint &= PAGE_MASK;
  159 + if (((void *)hint != NULL) &&
  160 + (hint < mmap_min_addr))
  161 + return PAGE_ALIGN(mmap_min_addr);
  162 + return hint;
  163 +}
  164 +
  165 +extern int mmap_min_addr_handler(struct ctl_table *table, int write, struct file *filp,
  166 + void __user *buffer, size_t *lenp, loff_t *ppos);
150 167 /**
151 168 * struct security_operations - main security structure
152 169 *
... ... @@ -49,6 +49,7 @@
49 49 #include <linux/acpi.h>
50 50 #include <linux/reboot.h>
51 51 #include <linux/ftrace.h>
  52 +#include <linux/security.h>
52 53 #include <linux/slow-work.h>
53 54 #include <linux/perf_counter.h>
54 55  
55 56  
... ... @@ -1306,10 +1307,10 @@
1306 1307 {
1307 1308 .ctl_name = CTL_UNNUMBERED,
1308 1309 .procname = "mmap_min_addr",
1309   - .data = &mmap_min_addr,
1310   - .maxlen = sizeof(unsigned long),
  1310 + .data = &dac_mmap_min_addr,
  1311 + .maxlen = sizeof(unsigned long),
1311 1312 .mode = 0644,
1312   - .proc_handler = &proc_doulongvec_minmax,
  1313 + .proc_handler = &mmap_min_addr_handler,
1313 1314 },
1314 1315 #ifdef CONFIG_NUMA
1315 1316 {
... ... @@ -225,9 +225,9 @@
225 225 For most ia64, ppc64 and x86 users with lots of address space
226 226 a value of 65536 is reasonable and should cause no problems.
227 227 On arm and other archs it should not be higher than 32768.
228   - Programs which use vm86 functionality would either need additional
229   - permissions from either the LSM or the capabilities module or have
230   - this protection disabled.
  228 + Programs which use vm86 functionality or have some need to map
  229 + this low address space will need CAP_SYS_RAWIO or disable this
  230 + protection by setting the value to 0.
231 231  
232 232 This value can be changed after boot using the
233 233 /proc/sys/vm/mmap_min_addr tunable.
... ... @@ -88,9 +88,6 @@
88 88 int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
89 89 struct percpu_counter vm_committed_as;
90 90  
91   -/* amount of vm to protect from userspace access */
92   -unsigned long mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
93   -
94 91 /*
95 92 * Check that a process has enough memory to allocate a new virtual
96 93 * mapping. 0 means there is enough memory for the allocation to
... ... @@ -69,9 +69,6 @@
69 69 int sysctl_nr_trim_pages = CONFIG_NOMMU_INITIAL_TRIM_EXCESS;
70 70 int heap_stack_gap = 0;
71 71  
72   -/* amount of vm to protect from userspace access */
73   -unsigned long mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
74   -
75 72 atomic_long_t mmap_pages_allocated;
76 73  
77 74 EXPORT_SYMBOL(mem_map);
... ... @@ -113,6 +113,22 @@
113 113  
114 114 If you are unsure how to answer this question, answer N.
115 115  
  116 +config LSM_MMAP_MIN_ADDR
  117 + int "Low address space for LSM to from user allocation"
  118 + depends on SECURITY && SECURITY_SELINUX
  119 + default 65535
  120 + help
  121 + This is the portion of low virtual memory which should be protected
  122 + from userspace allocation. Keeping a user from writing to low pages
  123 + can help reduce the impact of kernel NULL pointer bugs.
  124 +
  125 + For most ia64, ppc64 and x86 users with lots of address space
  126 + a value of 65536 is reasonable and should cause no problems.
  127 + On arm and other archs it should not be higher than 32768.
  128 + Programs which use vm86 functionality or have some need to map
  129 + this low address space will need the permission specific to the
  130 + systems running LSM.
  131 +
116 132 source security/selinux/Kconfig
117 133 source security/smack/Kconfig
118 134 source security/tomoyo/Kconfig
... ... @@ -8,7 +8,7 @@
8 8 subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
9 9  
10 10 # always enable default capabilities
11   -obj-y += commoncap.o
  11 +obj-y += commoncap.o min_addr.o
12 12  
13 13 # Object file lists
14 14 obj-$(CONFIG_SECURITY) += security.o capability.o
security/commoncap.c
... ... @@ -1005,7 +1005,7 @@
1005 1005 {
1006 1006 int ret = 0;
1007 1007  
1008   - if (addr < mmap_min_addr) {
  1008 + if (addr < dac_mmap_min_addr) {
1009 1009 ret = cap_capable(current, current_cred(), CAP_SYS_RAWIO,
1010 1010 SECURITY_CAP_AUDIT);
1011 1011 /* set PF_SUPERPRIV if it turns out we allow the low mmap */
  1 +#include <linux/init.h>
  2 +#include <linux/mm.h>
  3 +#include <linux/security.h>
  4 +#include <linux/sysctl.h>
  5 +
  6 +/* amount of vm to protect from userspace access by both DAC and the LSM*/
  7 +unsigned long mmap_min_addr;
  8 +/* amount of vm to protect from userspace using CAP_SYS_RAWIO (DAC) */
  9 +unsigned long dac_mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
  10 +/* amount of vm to protect from userspace using the LSM = CONFIG_LSM_MMAP_MIN_ADDR */
  11 +
  12 +/*
  13 + * Update mmap_min_addr = max(dac_mmap_min_addr, CONFIG_LSM_MMAP_MIN_ADDR)
  14 + */
  15 +static void update_mmap_min_addr(void)
  16 +{
  17 +#ifdef CONFIG_LSM_MMAP_MIN_ADDR
  18 + if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
  19 + mmap_min_addr = dac_mmap_min_addr;
  20 + else
  21 + mmap_min_addr = CONFIG_LSM_MMAP_MIN_ADDR;
  22 +#else
  23 + mmap_min_addr = dac_mmap_min_addr;
  24 +#endif
  25 +}
  26 +
  27 +/*
  28 + * sysctl handler which just sets dac_mmap_min_addr = the new value and then
  29 + * calls update_mmap_min_addr() so non MAP_FIXED hints get rounded properly
  30 + */
  31 +int mmap_min_addr_handler(struct ctl_table *table, int write, struct file *filp,
  32 + void __user *buffer, size_t *lenp, loff_t *ppos)
  33 +{
  34 + int ret;
  35 +
  36 + ret = proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos);
  37 +
  38 + update_mmap_min_addr();
  39 +
  40 + return ret;
  41 +}
  42 +
  43 +int __init init_mmap_min_addr(void)
  44 +{
  45 + update_mmap_min_addr();
  46 +
  47 + return 0;
  48 +}
  49 +pure_initcall(init_mmap_min_addr);
security/selinux/hooks.c
... ... @@ -3036,7 +3036,7 @@
3036 3036 * at bad behaviour/exploit that we always want to get the AVC, even
3037 3037 * if DAC would have also denied the operation.
3038 3038 */
3039   - if (addr < mmap_min_addr) {
  3039 + if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3040 3040 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3041 3041 MEMPROTECT__MMAP_ZERO, NULL);
3042 3042 if (rc)