aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig16
-rw-r--r--security/Makefile2
-rw-r--r--security/capability.c9
-rw-r--r--security/commoncap.c30
-rw-r--r--security/integrity/ima/ima_crypto.c6
-rw-r--r--security/integrity/ima/ima_main.c4
-rw-r--r--security/min_addr.c49
-rw-r--r--security/selinux/hooks.c17
8 files changed, 119 insertions, 14 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 5721847a7a62..fb363cd81cf6 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -143,6 +143,22 @@ config INTEL_TXT
143 143
144 If you are unsure as to whether this is required, answer N. 144 If you are unsure as to whether this is required, answer N.
145 145
146config LSM_MMAP_MIN_ADDR
147 int "Low address space for LSM to protect from user allocation"
148 depends on SECURITY && SECURITY_SELINUX
149 default 65536
150 help
151 This is the portion of low virtual memory which should be protected
152 from userspace allocation. Keeping a user from writing to low pages
153 can help reduce the impact of kernel NULL pointer bugs.
154
155 For most ia64, ppc64 and x86 users with lots of address space
156 a value of 65536 is reasonable and should cause no problems.
157 On arm and other archs it should not be higher than 32768.
158 Programs which use vm86 functionality or have some need to map
159 this low address space will need the permission specific to the
160 systems running LSM.
161
146source security/selinux/Kconfig 162source security/selinux/Kconfig
147source security/smack/Kconfig 163source security/smack/Kconfig
148source security/tomoyo/Kconfig 164source security/tomoyo/Kconfig
diff --git a/security/Makefile b/security/Makefile
index c67557cdaa85..b56e7f9ecbc2 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -8,7 +8,7 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack
8subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo 8subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
9 9
10# always enable default capabilities 10# always enable default capabilities
11obj-y += commoncap.o 11obj-y += commoncap.o min_addr.o
12 12
13# Object file lists 13# Object file lists
14obj-$(CONFIG_SECURITY) += security.o capability.o 14obj-$(CONFIG_SECURITY) += security.o capability.o
diff --git a/security/capability.c b/security/capability.c
index 21b6cead6a8e..88f752e8152c 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -330,15 +330,6 @@ static int cap_file_ioctl(struct file *file, unsigned int command,
330 return 0; 330 return 0;
331} 331}
332 332
333static int cap_file_mmap(struct file *file, unsigned long reqprot,
334 unsigned long prot, unsigned long flags,
335 unsigned long addr, unsigned long addr_only)
336{
337 if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO))
338 return -EACCES;
339 return 0;
340}
341
342static int cap_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, 333static int cap_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
343 unsigned long prot) 334 unsigned long prot)
344{ 335{
diff --git a/security/commoncap.c b/security/commoncap.c
index 48b7e0228fa3..e3097c0a1311 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -984,3 +984,33 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
984 cap_sys_admin = 1; 984 cap_sys_admin = 1;
985 return __vm_enough_memory(mm, pages, cap_sys_admin); 985 return __vm_enough_memory(mm, pages, cap_sys_admin);
986} 986}
987
988/*
989 * cap_file_mmap - check if able to map given addr
990 * @file: unused
991 * @reqprot: unused
992 * @prot: unused
993 * @flags: unused
994 * @addr: address attempting to be mapped
995 * @addr_only: unused
996 *
997 * If the process is attempting to map memory below mmap_min_addr they need
998 * CAP_SYS_RAWIO. The other parameters to this function are unused by the
999 * capability security module. Returns 0 if this mapping should be allowed
1000 * -EPERM if not.
1001 */
1002int cap_file_mmap(struct file *file, unsigned long reqprot,
1003 unsigned long prot, unsigned long flags,
1004 unsigned long addr, unsigned long addr_only)
1005{
1006 int ret = 0;
1007
1008 if (addr < dac_mmap_min_addr) {
1009 ret = cap_capable(current, current_cred(), CAP_SYS_RAWIO,
1010 SECURITY_CAP_AUDIT);
1011 /* set PF_SUPERPRIV if it turns out we allow the low mmap */
1012 if (ret == 0)
1013 current->flags |= PF_SUPERPRIV;
1014 }
1015 return ret;
1016}
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 63003a63aaee..46642a19bc78 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -45,9 +45,9 @@ int ima_calc_hash(struct file *file, char *digest)
45{ 45{
46 struct hash_desc desc; 46 struct hash_desc desc;
47 struct scatterlist sg[1]; 47 struct scatterlist sg[1];
48 loff_t i_size; 48 loff_t i_size, offset = 0;
49 char *rbuf; 49 char *rbuf;
50 int rc, offset = 0; 50 int rc;
51 51
52 rc = init_desc(&desc); 52 rc = init_desc(&desc);
53 if (rc != 0) 53 if (rc != 0)
@@ -67,6 +67,8 @@ int ima_calc_hash(struct file *file, char *digest)
67 rc = rbuf_len; 67 rc = rbuf_len;
68 break; 68 break;
69 } 69 }
70 if (rbuf_len == 0)
71 break;
70 offset += rbuf_len; 72 offset += rbuf_len;
71 sg_init_one(sg, rbuf, rbuf_len); 73 sg_init_one(sg, rbuf, rbuf_len);
72 74
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 101c512564ec..4732f5e5d127 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -262,6 +262,8 @@ void ima_counts_put(struct path *path, int mask)
262 else if (mask & (MAY_READ | MAY_EXEC)) 262 else if (mask & (MAY_READ | MAY_EXEC))
263 iint->readcount--; 263 iint->readcount--;
264 mutex_unlock(&iint->mutex); 264 mutex_unlock(&iint->mutex);
265
266 kref_put(&iint->refcount, iint_free);
265} 267}
266 268
267/* 269/*
@@ -291,6 +293,8 @@ void ima_counts_get(struct file *file)
291 if (file->f_mode & FMODE_WRITE) 293 if (file->f_mode & FMODE_WRITE)
292 iint->writecount++; 294 iint->writecount++;
293 mutex_unlock(&iint->mutex); 295 mutex_unlock(&iint->mutex);
296
297 kref_put(&iint->refcount, iint_free);
294} 298}
295EXPORT_SYMBOL_GPL(ima_counts_get); 299EXPORT_SYMBOL_GPL(ima_counts_get);
296 300
diff --git a/security/min_addr.c b/security/min_addr.c
new file mode 100644
index 000000000000..14cc7b3b8d03
--- /dev/null
+++ b/security/min_addr.c
@@ -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*/
7unsigned long mmap_min_addr;
8/* amount of vm to protect from userspace using CAP_SYS_RAWIO (DAC) */
9unsigned 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 */
15static 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 */
31int 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
43int __init init_mmap_min_addr(void)
44{
45 update_mmap_min_addr();
46
47 return 0;
48}
49pure_initcall(init_mmap_min_addr);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 15c2a08a66f1..8d8b69c5664e 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1285,6 +1285,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1285 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, 1285 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1286 context, len); 1286 context, len);
1287 if (rc == -ERANGE) { 1287 if (rc == -ERANGE) {
1288 kfree(context);
1289
1288 /* Need a larger buffer. Query for the right size. */ 1290 /* Need a larger buffer. Query for the right size. */
1289 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, 1291 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1290 NULL, 0); 1292 NULL, 0);
@@ -1292,7 +1294,6 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1292 dput(dentry); 1294 dput(dentry);
1293 goto out_unlock; 1295 goto out_unlock;
1294 } 1296 }
1295 kfree(context);
1296 len = rc; 1297 len = rc;
1297 context = kmalloc(len+1, GFP_NOFS); 1298 context = kmalloc(len+1, GFP_NOFS);
1298 if (!context) { 1299 if (!context) {
@@ -3029,9 +3030,21 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot,
3029 int rc = 0; 3030 int rc = 0;
3030 u32 sid = current_sid(); 3031 u32 sid = current_sid();
3031 3032
3032 if (addr < mmap_min_addr) 3033 /*
3034 * notice that we are intentionally putting the SELinux check before
3035 * the secondary cap_file_mmap check. This is such a likely attempt
3036 * at bad behaviour/exploit that we always want to get the AVC, even
3037 * if DAC would have also denied the operation.
3038 */
3039 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3033 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, 3040 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3034 MEMPROTECT__MMAP_ZERO, NULL); 3041 MEMPROTECT__MMAP_ZERO, NULL);
3042 if (rc)
3043 return rc;
3044 }
3045
3046 /* do DAC check on address space usage */
3047 rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
3035 if (rc || addr_only) 3048 if (rc || addr_only)
3036 return rc; 3049 return rc;
3037 3050