History

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.

Eric Paris committed 17 years ago

Commit 788084a1 parent 8cf948e11 files · +92 −30Browse files

Unified · Split

11 files
  1. include/linux/mm.h +0 −15
  2. include/linux/security.h +17 −0
  3. kernel/sysctl.c +4 −3
  4. mm/Kconfig +3 −3
  5. mm/mmap.c +0 −3
  6. mm/nommu.c +0 −3
  7. security/Kconfig +16 −0
  8. security/Makefile +1 −1
  9. security/commoncap.c +1 −1
  10. security/min_addr.c +49 −0
  11. security/selinux/hooks.c +1 −1
include/linux/mm.h+0−15
@@ -34,8 +34,6 @@ extern int sysctl_legacy_va_layout; · 33 unmodified lines
3434 #define sysctl_legacy_va_layout 0
3535 #endif
3636
37−extern unsigned long mmap_min_addr;
38−
3937 #include <asm/page.h>
4038 #include <asm/pgtable.h>
4139 #include <asm/processor.h>
@@ -574,19 +572,6 @@ static inline void set_page_links(struct page *page, enum zone_type zone, · 532 unmodified lines
574572 set_page_section(page, pfn_to_section_nr(pfn));
575573 }
576574
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−}
589−
590575 /*
591576 * Some inline functions in vmstat.h depend on page_zone()
592577 */
include/linux/security.h+17−0
@@ -28,6 +28,7 @@ · 27 unmodified lines
2828 #include <linux/resource.h>
2929 #include <linux/sem.h>
3030 #include <linux/shm.h>
31+#include <linux/mm.h> /* PAGE_ALIGN */
3132 #include <linux/msg.h>
3233 #include <linux/sched.h>
3334 #include <linux/key.h>
@@ -95,6 +96,7 @@ extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb); · 61 unmodified lines
9596 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
9697
9798 extern unsigned long mmap_min_addr;
99+extern unsigned long dac_mmap_min_addr;
98100 /*
99101 * Values used in the task_security_ops calls
100102 */
@@ -147,6 +149,21 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) · 46 unmodified lines
147149 opts->num_mnt_opts = 0;
148150 }
149151
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);
150167 /**
151168 * struct security_operations - main security structure
152169 *
kernel/sysctl.c+4−3
@@ -49,6 +49,7 @@ · 48 unmodified lines
4949 #include <linux/acpi.h>
5050 #include <linux/reboot.h>
5151 #include <linux/ftrace.h>
52+#include <linux/security.h>
5253 #include <linux/slow-work.h>
5354 #include <linux/perf_counter.h>
5455
@@ -1306,10 +1307,10 @@ static struct ctl_table vm_table[] = { · 1251 unmodified lines
13061307 {
13071308 .ctl_name = CTL_UNNUMBERED,
13081309 .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),
13111312 .mode = 0644,
1312− .proc_handler = &proc_doulongvec_minmax,
1313+ .proc_handler = &mmap_min_addr_handler,
13131314 },
13141315 #ifdef CONFIG_NUMA
13151316 {
mm/Kconfig+3−3
@@ -225,9 +225,9 @@ config DEFAULT_MMAP_MIN_ADDR · 224 unmodified lines
225225 For most ia64, ppc64 and x86 users with lots of address space
226226 a value of 65536 is reasonable and should cause no problems.
227227 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.
231231
232232 This value can be changed after boot using the
233233 /proc/sys/vm/mmap_min_addr tunable.
mm/mmap.c+0−3
@@ -88,9 +88,6 @@ int sysctl_overcommit_ratio = 50; /* default is 50% */ · 87 unmodified lines
8888 int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
8989 struct percpu_counter vm_committed_as;
9090
91−/* amount of vm to protect from userspace access */
92−unsigned long mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
93−
9491 /*
9592 * Check that a process has enough memory to allocate a new virtual
9693 * mapping. 0 means there is enough memory for the allocation to
mm/nommu.c+0−3
@@ -69,9 +69,6 @@ int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT; · 68 unmodified lines
6969 int sysctl_nr_trim_pages = CONFIG_NOMMU_INITIAL_TRIM_EXCESS;
7070 int heap_stack_gap = 0;
7171
72−/* amount of vm to protect from userspace access */
73−unsigned long mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
74−
7572 atomic_long_t mmap_pages_allocated;
7673
7774 EXPORT_SYMBOL(mem_map);
security/Kconfig+16−0
@@ -113,6 +113,22 @@ config SECURITY_ROOTPLUG · 112 unmodified lines
113113
114114 If you are unsure how to answer this question, answer N.
115115
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+
116132 source security/selinux/Kconfig
117133 source security/smack/Kconfig
118134 source security/tomoyo/Kconfig
security/Makefile+1−1
@@ -8,7 +8,7 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack · 7 unmodified lines
88 subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
99
1010 # always enable default capabilities
11−obj-y += commoncap.o
11+obj-y += commoncap.o min_addr.o
1212
1313 # Object file lists
1414 obj-$(CONFIG_SECURITY) += security.o capability.o
security/commoncap.c+1−1
@@ -1005,7 +1005,7 @@ int cap_file_mmap(struct file *file, unsigned long reqprot, · 1004 unmodified lines
10051005 {
10061006 int ret = 0;
10071007
1008− if (addr < mmap_min_addr) {
1008+ if (addr < dac_mmap_min_addr) {
10091009 ret = cap_capable(current, current_cred(), CAP_SYS_RAWIO,
10101010 SECURITY_CAP_AUDIT);
10111011 /* set PF_SUPERPRIV if it turns out we allow the low mmap */
security/min_addr.c+49−0
@@ -0,0 +1,49 @@
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+1−1
@@ -3036,7 +3036,7 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot, · 3035 unmodified lines
30363036 * at bad behaviour/exploit that we always want to get the AVC, even
30373037 * if DAC would have also denied the operation.
30383038 */
3039− if (addr < mmap_min_addr) {
3039+ if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
30403040 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
30413041 MEMPROTECT__MMAP_ZERO, NULL);
30423042 if (rc)