aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/security.h7
-rw-r--r--ipc/shm.c5
-rw-r--r--mm/mmap.c23
-rw-r--r--mm/nommu.c22
-rw-r--r--security/security.c33
5 files changed, 62 insertions, 28 deletions
diff --git a/include/linux/security.h b/include/linux/security.h
index f1bae0963ddc..4e5a73cdbbef 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1745,8 +1745,8 @@ int security_file_permission(struct file *file, int mask);
1745int security_file_alloc(struct file *file); 1745int security_file_alloc(struct file *file);
1746void security_file_free(struct file *file); 1746void security_file_free(struct file *file);
1747int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 1747int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
1748int security_mmap_file(struct file *file, unsigned long reqprot, 1748int security_mmap_file(struct file *file, unsigned long prot,
1749 unsigned long prot, unsigned long flags); 1749 unsigned long flags);
1750int security_mmap_addr(unsigned long addr); 1750int security_mmap_addr(unsigned long addr);
1751int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, 1751int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
1752 unsigned long prot); 1752 unsigned long prot);
@@ -2183,8 +2183,7 @@ static inline int security_file_ioctl(struct file *file, unsigned int cmd,
2183 return 0; 2183 return 0;
2184} 2184}
2185 2185
2186static inline int security_mmap_file(struct file *file, unsigned long reqprot, 2186static inline int security_mmap_file(struct file *file, unsigned long prot,
2187 unsigned long prot,
2188 unsigned long flags) 2187 unsigned long flags)
2189{ 2188{
2190 return 0; 2189 return 0;
diff --git a/ipc/shm.c b/ipc/shm.c
index 406c5b208193..e3a8063b1768 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1036,6 +1036,10 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
1036 sfd->file = shp->shm_file; 1036 sfd->file = shp->shm_file;
1037 sfd->vm_ops = NULL; 1037 sfd->vm_ops = NULL;
1038 1038
1039 err = security_mmap_file(file, prot, flags);
1040 if (err)
1041 goto out_fput;
1042
1039 down_write(&current->mm->mmap_sem); 1043 down_write(&current->mm->mmap_sem);
1040 if (addr && !(shmflg & SHM_REMAP)) { 1044 if (addr && !(shmflg & SHM_REMAP)) {
1041 err = -EINVAL; 1045 err = -EINVAL;
@@ -1058,6 +1062,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
1058invalid: 1062invalid:
1059 up_write(&current->mm->mmap_sem); 1063 up_write(&current->mm->mmap_sem);
1060 1064
1065out_fput:
1061 fput(file); 1066 fput(file);
1062 1067
1063out_nattch: 1068out_nattch:
diff --git a/mm/mmap.c b/mm/mmap.c
index 49283da9a2ae..34b280f4238d 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -979,7 +979,6 @@ static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
979 struct inode *inode; 979 struct inode *inode;
980 vm_flags_t vm_flags; 980 vm_flags_t vm_flags;
981 int error; 981 int error;
982 unsigned long reqprot = prot;
983 982
984 /* 983 /*
985 * Does the application expect PROT_READ to imply PROT_EXEC? 984 * Does the application expect PROT_READ to imply PROT_EXEC?
@@ -1105,10 +1104,6 @@ static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
1105 if (error) 1104 if (error)
1106 return error; 1105 return error;
1107 1106
1108 error = security_mmap_file(file, reqprot, prot, flags);
1109 if (error)
1110 return error;
1111
1112 return mmap_region(file, addr, len, flags, vm_flags, pgoff); 1107 return mmap_region(file, addr, len, flags, vm_flags, pgoff);
1113} 1108}
1114 1109
@@ -1130,9 +1125,12 @@ unsigned long vm_mmap(struct file *file, unsigned long addr,
1130 unsigned long ret; 1125 unsigned long ret;
1131 struct mm_struct *mm = current->mm; 1126 struct mm_struct *mm = current->mm;
1132 1127
1133 down_write(&mm->mmap_sem); 1128 ret = security_mmap_file(file, prot, flag);
1134 ret = do_mmap(file, addr, len, prot, flag, offset); 1129 if (!ret) {
1135 up_write(&mm->mmap_sem); 1130 down_write(&mm->mmap_sem);
1131 ret = do_mmap(file, addr, len, prot, flag, offset);
1132 up_write(&mm->mmap_sem);
1133 }
1136 return ret; 1134 return ret;
1137} 1135}
1138EXPORT_SYMBOL(vm_mmap); 1136EXPORT_SYMBOL(vm_mmap);
@@ -1168,9 +1166,12 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
1168 1166
1169 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 1167 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
1170 1168
1171 down_write(&current->mm->mmap_sem); 1169 retval = security_mmap_file(file, prot, flags);
1172 retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 1170 if (!retval) {
1173 up_write(&current->mm->mmap_sem); 1171 down_write(&current->mm->mmap_sem);
1172 retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
1173 up_write(&current->mm->mmap_sem);
1174 }
1174 1175
1175 if (file) 1176 if (file)
1176 fput(file); 1177 fput(file);
diff --git a/mm/nommu.c b/mm/nommu.c
index acfe419785db..8cbfd623b04a 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -889,7 +889,6 @@ static int validate_mmap_request(struct file *file,
889 unsigned long *_capabilities) 889 unsigned long *_capabilities)
890{ 890{
891 unsigned long capabilities, rlen; 891 unsigned long capabilities, rlen;
892 unsigned long reqprot = prot;
893 int ret; 892 int ret;
894 893
895 /* do the simple checks first */ 894 /* do the simple checks first */
@@ -1050,9 +1049,6 @@ static int validate_mmap_request(struct file *file,
1050 ret = security_mmap_addr(addr); 1049 ret = security_mmap_addr(addr);
1051 if (ret < 0) 1050 if (ret < 0)
1052 return ret; 1051 return ret;
1053 ret = security_mmap_file(file, reqprot, prot, flags);
1054 if (ret < 0)
1055 return ret;
1056 1052
1057 /* looks okay */ 1053 /* looks okay */
1058 *_capabilities = capabilities; 1054 *_capabilities = capabilities;
@@ -1492,9 +1488,12 @@ unsigned long vm_mmap(struct file *file, unsigned long addr,
1492 unsigned long ret; 1488 unsigned long ret;
1493 struct mm_struct *mm = current->mm; 1489 struct mm_struct *mm = current->mm;
1494 1490
1495 down_write(&mm->mmap_sem); 1491 ret = security_mmap_file(file, prot, flag);
1496 ret = do_mmap(file, addr, len, prot, flag, offset); 1492 if (!ret) {
1497 up_write(&mm->mmap_sem); 1493 down_write(&mm->mmap_sem);
1494 ret = do_mmap(file, addr, len, prot, flag, offset);
1495 up_write(&mm->mmap_sem);
1496 }
1498 return ret; 1497 return ret;
1499} 1498}
1500EXPORT_SYMBOL(vm_mmap); 1499EXPORT_SYMBOL(vm_mmap);
@@ -1515,9 +1514,12 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
1515 1514
1516 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 1515 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
1517 1516
1518 down_write(&current->mm->mmap_sem); 1517 ret = security_mmap_file(file, prot, flags);
1519 retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 1518 if (!ret) {
1520 up_write(&current->mm->mmap_sem); 1519 down_write(&current->mm->mmap_sem);
1520 retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
1521 up_write(&current->mm->mmap_sem);
1522 }
1521 1523
1522 if (file) 1524 if (file)
1523 fput(file); 1525 fput(file);
diff --git a/security/security.c b/security/security.c
index d91c66d3956b..3b11b3b72fe2 100644
--- a/security/security.c
+++ b/security/security.c
@@ -20,6 +20,9 @@
20#include <linux/ima.h> 20#include <linux/ima.h>
21#include <linux/evm.h> 21#include <linux/evm.h>
22#include <linux/fsnotify.h> 22#include <linux/fsnotify.h>
23#include <linux/mman.h>
24#include <linux/mount.h>
25#include <linux/personality.h>
23#include <net/flow.h> 26#include <net/flow.h>
24 27
25#define MAX_LSM_EVM_XATTR 2 28#define MAX_LSM_EVM_XATTR 2
@@ -657,11 +660,35 @@ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
657 return security_ops->file_ioctl(file, cmd, arg); 660 return security_ops->file_ioctl(file, cmd, arg);
658} 661}
659 662
660int security_mmap_file(struct file *file, unsigned long reqprot, 663int security_mmap_file(struct file *file, unsigned long prot,
661 unsigned long prot, unsigned long flags) 664 unsigned long flags)
662{ 665{
666 unsigned long reqprot = prot;
663 int ret; 667 int ret;
664 668 /*
669 * Does the application expect PROT_READ to imply PROT_EXEC?
670 *
671 * (the exception is when the underlying filesystem is noexec
672 * mounted, in which case we dont add PROT_EXEC.)
673 */
674 if (!(reqprot & PROT_READ))
675 goto out;
676 if (!(current->personality & READ_IMPLIES_EXEC))
677 goto out;
678 if (!file) {
679 prot |= PROT_EXEC;
680 } else if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) {
681#ifndef CONFIG_MMU
682 unsigned long caps = 0;
683 struct address_space *mapping = file->f_mapping;
684 if (mapping && mapping->backing_dev_info)
685 caps = mapping->backing_dev_info->capabilities;
686 if (!(caps & BDI_CAP_EXEC_MAP))
687 goto out;
688#endif
689 prot |= PROT_EXEC;
690 }
691out:
665 ret = security_ops->mmap_file(file, reqprot, prot, flags); 692 ret = security_ops->mmap_file(file, reqprot, prot, flags);
666 if (ret) 693 if (ret)
667 return ret; 694 return ret;