Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

take security_mmap_file() outside of ->mmap_sem

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 8b3ec681 e5467859

+62 -28
+3 -4
include/linux/security.h
··· 1745 1745 int security_file_alloc(struct file *file); 1746 1746 void security_file_free(struct file *file); 1747 1747 int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 1748 - int security_mmap_file(struct file *file, unsigned long reqprot, 1749 - unsigned long prot, unsigned long flags); 1748 + int security_mmap_file(struct file *file, unsigned long prot, 1749 + unsigned long flags); 1750 1750 int security_mmap_addr(unsigned long addr); 1751 1751 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, 1752 1752 unsigned long prot); ··· 2183 2183 return 0; 2184 2184 } 2185 2185 2186 - static inline int security_mmap_file(struct file *file, unsigned long reqprot, 2187 - unsigned long prot, 2186 + static inline int security_mmap_file(struct file *file, unsigned long prot, 2188 2187 unsigned long flags) 2189 2188 { 2190 2189 return 0;
+5
ipc/shm.c
··· 1036 1036 sfd->file = shp->shm_file; 1037 1037 sfd->vm_ops = NULL; 1038 1038 1039 + err = security_mmap_file(file, prot, flags); 1040 + if (err) 1041 + goto out_fput; 1042 + 1039 1043 down_write(&current->mm->mmap_sem); 1040 1044 if (addr && !(shmflg & SHM_REMAP)) { 1041 1045 err = -EINVAL; ··· 1062 1058 invalid: 1063 1059 up_write(&current->mm->mmap_sem); 1064 1060 1061 + out_fput: 1065 1062 fput(file); 1066 1063 1067 1064 out_nattch:
+12 -11
mm/mmap.c
··· 979 979 struct inode *inode; 980 980 vm_flags_t vm_flags; 981 981 int error; 982 - unsigned long reqprot = prot; 983 982 984 983 /* 985 984 * Does the application expect PROT_READ to imply PROT_EXEC? ··· 1104 1105 if (error) 1105 1106 return error; 1106 1107 1107 - error = security_mmap_file(file, reqprot, prot, flags); 1108 - if (error) 1109 - return error; 1110 - 1111 1108 return mmap_region(file, addr, len, flags, vm_flags, pgoff); 1112 1109 } 1113 1110 ··· 1125 1130 unsigned long ret; 1126 1131 struct mm_struct *mm = current->mm; 1127 1132 1128 - down_write(&mm->mmap_sem); 1129 - ret = do_mmap(file, addr, len, prot, flag, offset); 1130 - up_write(&mm->mmap_sem); 1133 + ret = security_mmap_file(file, prot, flag); 1134 + if (!ret) { 1135 + down_write(&mm->mmap_sem); 1136 + ret = do_mmap(file, addr, len, prot, flag, offset); 1137 + up_write(&mm->mmap_sem); 1138 + } 1131 1139 return ret; 1132 1140 } 1133 1141 EXPORT_SYMBOL(vm_mmap); ··· 1166 1168 1167 1169 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 1168 1170 1169 - down_write(&current->mm->mmap_sem); 1170 - retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 1171 - up_write(&current->mm->mmap_sem); 1171 + retval = security_mmap_file(file, prot, flags); 1172 + if (!retval) { 1173 + down_write(&current->mm->mmap_sem); 1174 + retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 1175 + up_write(&current->mm->mmap_sem); 1176 + } 1172 1177 1173 1178 if (file) 1174 1179 fput(file);
+12 -10
mm/nommu.c
··· 889 889 unsigned long *_capabilities) 890 890 { 891 891 unsigned long capabilities, rlen; 892 - unsigned long reqprot = prot; 893 892 int ret; 894 893 895 894 /* do the simple checks first */ ··· 1047 1048 1048 1049 /* allow the security API to have its say */ 1049 1050 ret = security_mmap_addr(addr); 1050 - if (ret < 0) 1051 - return ret; 1052 - ret = security_mmap_file(file, reqprot, prot, flags); 1053 1051 if (ret < 0) 1054 1052 return ret; 1055 1053 ··· 1488 1492 unsigned long ret; 1489 1493 struct mm_struct *mm = current->mm; 1490 1494 1491 - down_write(&mm->mmap_sem); 1492 - ret = do_mmap(file, addr, len, prot, flag, offset); 1493 - up_write(&mm->mmap_sem); 1495 + ret = security_mmap_file(file, prot, flag); 1496 + if (!ret) { 1497 + down_write(&mm->mmap_sem); 1498 + ret = do_mmap(file, addr, len, prot, flag, offset); 1499 + up_write(&mm->mmap_sem); 1500 + } 1494 1501 return ret; 1495 1502 } 1496 1503 EXPORT_SYMBOL(vm_mmap); ··· 1514 1515 1515 1516 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 1516 1517 1517 - down_write(&current->mm->mmap_sem); 1518 - retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 1519 - up_write(&current->mm->mmap_sem); 1518 + ret = security_mmap_file(file, prot, flags); 1519 + if (!ret) { 1520 + down_write(&current->mm->mmap_sem); 1521 + retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 1522 + up_write(&current->mm->mmap_sem); 1523 + } 1520 1524 1521 1525 if (file) 1522 1526 fput(file);
+30 -3
security/security.c
··· 20 20 #include <linux/ima.h> 21 21 #include <linux/evm.h> 22 22 #include <linux/fsnotify.h> 23 + #include <linux/mman.h> 24 + #include <linux/mount.h> 25 + #include <linux/personality.h> 23 26 #include <net/flow.h> 24 27 25 28 #define MAX_LSM_EVM_XATTR 2 ··· 660 657 return security_ops->file_ioctl(file, cmd, arg); 661 658 } 662 659 663 - int security_mmap_file(struct file *file, unsigned long reqprot, 664 - unsigned long prot, unsigned long flags) 660 + int security_mmap_file(struct file *file, unsigned long prot, 661 + unsigned long flags) 665 662 { 663 + unsigned long reqprot = prot; 666 664 int ret; 667 - 665 + /* 666 + * Does the application expect PROT_READ to imply PROT_EXEC? 667 + * 668 + * (the exception is when the underlying filesystem is noexec 669 + * mounted, in which case we dont add PROT_EXEC.) 670 + */ 671 + if (!(reqprot & PROT_READ)) 672 + goto out; 673 + if (!(current->personality & READ_IMPLIES_EXEC)) 674 + goto out; 675 + if (!file) { 676 + prot |= PROT_EXEC; 677 + } else if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) { 678 + #ifndef CONFIG_MMU 679 + unsigned long caps = 0; 680 + struct address_space *mapping = file->f_mapping; 681 + if (mapping && mapping->backing_dev_info) 682 + caps = mapping->backing_dev_info->capabilities; 683 + if (!(caps & BDI_CAP_EXEC_MAP)) 684 + goto out; 685 + #endif 686 + prot |= PROT_EXEC; 687 + } 688 + out: 668 689 ret = security_ops->mmap_file(file, reqprot, prot, flags); 669 690 if (ret) 670 691 return ret;