aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-05-30 13:30:51 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-05-31 13:11:54 -0400
commite5467859f7f79b69fc49004403009dfdba3bec53 (patch)
tree73b011daf79eeddd61bbcaf65cd197b5e5f6f149
parentd007794a182bc072a7b7479909dbd0d67ba341be (diff)
split ->file_mmap() into ->mmap_addr()/->mmap_file()
... i.e. file-dependent and address-dependent checks. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/exec.c4
-rw-r--r--include/linux/security.h36
-rw-r--r--mm/mmap.c12
-rw-r--r--mm/mremap.c4
-rw-r--r--mm/nommu.c5
-rw-r--r--security/apparmor/lsm.c15
-rw-r--r--security/capability.c3
-rw-r--r--security/commoncap.c21
-rw-r--r--security/security.c12
-rw-r--r--security/selinux/hooks.c15
-rw-r--r--security/smack/smack_lsm.c15
11 files changed, 64 insertions, 78 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 52c9e2ff6e6b..a79786a8d2c8 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -280,10 +280,6 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
280 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); 280 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
281 INIT_LIST_HEAD(&vma->anon_vma_chain); 281 INIT_LIST_HEAD(&vma->anon_vma_chain);
282 282
283 err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
284 if (err)
285 goto err;
286
287 err = insert_vm_struct(mm, vma); 283 err = insert_vm_struct(mm, vma);
288 if (err) 284 if (err)
289 goto err; 285 goto err;
diff --git a/include/linux/security.h b/include/linux/security.h
index 4ad59c9fa731..f1bae0963ddc 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -87,9 +87,8 @@ extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
87extern int cap_inode_need_killpriv(struct dentry *dentry); 87extern int cap_inode_need_killpriv(struct dentry *dentry);
88extern int cap_inode_killpriv(struct dentry *dentry); 88extern int cap_inode_killpriv(struct dentry *dentry);
89extern int cap_mmap_addr(unsigned long addr); 89extern int cap_mmap_addr(unsigned long addr);
90extern int cap_file_mmap(struct file *file, unsigned long reqprot, 90extern int cap_mmap_file(struct file *file, unsigned long reqprot,
91 unsigned long prot, unsigned long flags, 91 unsigned long prot, unsigned long flags);
92 unsigned long addr, unsigned long addr_only);
93extern int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags); 92extern int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags);
94extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, 93extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
95 unsigned long arg4, unsigned long arg5); 94 unsigned long arg4, unsigned long arg5);
@@ -587,15 +586,17 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
587 * simple integer value. When @arg represents a user space pointer, it 586 * simple integer value. When @arg represents a user space pointer, it
588 * should never be used by the security module. 587 * should never be used by the security module.
589 * Return 0 if permission is granted. 588 * Return 0 if permission is granted.
590 * @file_mmap : 589 * @mmap_addr :
590 * Check permissions for a mmap operation at @addr.
591 * @addr contains virtual address that will be used for the operation.
592 * Return 0 if permission is granted.
593 * @mmap_file :
591 * Check permissions for a mmap operation. The @file may be NULL, e.g. 594 * Check permissions for a mmap operation. The @file may be NULL, e.g.
592 * if mapping anonymous memory. 595 * if mapping anonymous memory.
593 * @file contains the file structure for file to map (may be NULL). 596 * @file contains the file structure for file to map (may be NULL).
594 * @reqprot contains the protection requested by the application. 597 * @reqprot contains the protection requested by the application.
595 * @prot contains the protection that will be applied by the kernel. 598 * @prot contains the protection that will be applied by the kernel.
596 * @flags contains the operational flags. 599 * @flags contains the operational flags.
597 * @addr contains virtual address that will be used for the operation.
598 * @addr_only contains a boolean: 0 if file-backed VMA, otherwise 1.
599 * Return 0 if permission is granted. 600 * Return 0 if permission is granted.
600 * @file_mprotect: 601 * @file_mprotect:
601 * Check permissions before changing memory access permissions. 602 * Check permissions before changing memory access permissions.
@@ -1482,10 +1483,10 @@ struct security_operations {
1482 void (*file_free_security) (struct file *file); 1483 void (*file_free_security) (struct file *file);
1483 int (*file_ioctl) (struct file *file, unsigned int cmd, 1484 int (*file_ioctl) (struct file *file, unsigned int cmd,
1484 unsigned long arg); 1485 unsigned long arg);
1485 int (*file_mmap) (struct file *file, 1486 int (*mmap_addr) (unsigned long addr);
1487 int (*mmap_file) (struct file *file,
1486 unsigned long reqprot, unsigned long prot, 1488 unsigned long reqprot, unsigned long prot,
1487 unsigned long flags, unsigned long addr, 1489 unsigned long flags);
1488 unsigned long addr_only);
1489 int (*file_mprotect) (struct vm_area_struct *vma, 1490 int (*file_mprotect) (struct vm_area_struct *vma,
1490 unsigned long reqprot, 1491 unsigned long reqprot,
1491 unsigned long prot); 1492 unsigned long prot);
@@ -1744,9 +1745,9 @@ int security_file_permission(struct file *file, int mask);
1744int security_file_alloc(struct file *file); 1745int security_file_alloc(struct file *file);
1745void security_file_free(struct file *file); 1746void security_file_free(struct file *file);
1746int 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);
1747int security_file_mmap(struct file *file, unsigned long reqprot, 1748int security_mmap_file(struct file *file, unsigned long reqprot,
1748 unsigned long prot, unsigned long flags, 1749 unsigned long prot, unsigned long flags);
1749 unsigned long addr, unsigned long addr_only); 1750int security_mmap_addr(unsigned long addr);
1750int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, 1751int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
1751 unsigned long prot); 1752 unsigned long prot);
1752int security_file_lock(struct file *file, unsigned int cmd); 1753int security_file_lock(struct file *file, unsigned int cmd);
@@ -2182,11 +2183,14 @@ static inline int security_file_ioctl(struct file *file, unsigned int cmd,
2182 return 0; 2183 return 0;
2183} 2184}
2184 2185
2185static inline int security_file_mmap(struct file *file, unsigned long reqprot, 2186static inline int security_mmap_file(struct file *file, unsigned long reqprot,
2186 unsigned long prot, 2187 unsigned long prot,
2187 unsigned long flags, 2188 unsigned long flags)
2188 unsigned long addr, 2189{
2189 unsigned long addr_only) 2190 return 0;
2191}
2192
2193static inline int security_mmap_addr(unsigned long addr)
2190{ 2194{
2191 return cap_mmap_addr(addr); 2195 return cap_mmap_addr(addr);
2192} 2196}
diff --git a/mm/mmap.c b/mm/mmap.c
index 83c56624f1f6..49283da9a2ae 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1101,7 +1101,11 @@ static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
1101 } 1101 }
1102 } 1102 }
1103 1103
1104 error = security_file_mmap(file, reqprot, prot, flags, addr, 0); 1104 error = security_mmap_addr(addr);
1105 if (error)
1106 return error;
1107
1108 error = security_mmap_file(file, reqprot, prot, flags);
1105 if (error) 1109 if (error)
1106 return error; 1110 return error;
1107 1111
@@ -1817,7 +1821,7 @@ int expand_downwards(struct vm_area_struct *vma,
1817 return -ENOMEM; 1821 return -ENOMEM;
1818 1822
1819 address &= PAGE_MASK; 1823 address &= PAGE_MASK;
1820 error = security_file_mmap(NULL, 0, 0, 0, address, 1); 1824 error = security_mmap_addr(address);
1821 if (error) 1825 if (error)
1822 return error; 1826 return error;
1823 1827
@@ -2205,7 +2209,7 @@ static unsigned long do_brk(unsigned long addr, unsigned long len)
2205 if (!len) 2209 if (!len)
2206 return addr; 2210 return addr;
2207 2211
2208 error = security_file_mmap(NULL, 0, 0, 0, addr, 1); 2212 error = security_mmap_addr(addr);
2209 if (error) 2213 if (error)
2210 return error; 2214 return error;
2211 2215
@@ -2561,7 +2565,7 @@ int install_special_mapping(struct mm_struct *mm,
2561 vma->vm_ops = &special_mapping_vmops; 2565 vma->vm_ops = &special_mapping_vmops;
2562 vma->vm_private_data = pages; 2566 vma->vm_private_data = pages;
2563 2567
2564 ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); 2568 ret = security_mmap_addr(vma->vm_start);
2565 if (ret) 2569 if (ret)
2566 goto out; 2570 goto out;
2567 2571
diff --git a/mm/mremap.c b/mm/mremap.c
index 169c53b87749..ebf10892b63d 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -371,7 +371,7 @@ static unsigned long mremap_to(unsigned long addr,
371 if ((addr <= new_addr) && (addr+old_len) > new_addr) 371 if ((addr <= new_addr) && (addr+old_len) > new_addr)
372 goto out; 372 goto out;
373 373
374 ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); 374 ret = security_mmap_addr(new_addr);
375 if (ret) 375 if (ret)
376 goto out; 376 goto out;
377 377
@@ -532,7 +532,7 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
532 goto out; 532 goto out;
533 } 533 }
534 534
535 ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); 535 ret = security_mmap_addr(new_addr);
536 if (ret) 536 if (ret)
537 goto out; 537 goto out;
538 ret = move_vma(vma, addr, old_len, new_len, new_addr); 538 ret = move_vma(vma, addr, old_len, new_len, new_addr);
diff --git a/mm/nommu.c b/mm/nommu.c
index de6084e3a046..acfe419785db 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1047,7 +1047,10 @@ static int validate_mmap_request(struct file *file,
1047 } 1047 }
1048 1048
1049 /* allow the security API to have its say */ 1049 /* allow the security API to have its say */
1050 ret = security_file_mmap(file, reqprot, prot, flags, addr, 0); 1050 ret = security_mmap_addr(addr);
1051 if (ret < 0)
1052 return ret;
1053 ret = security_mmap_file(file, reqprot, prot, flags);
1051 if (ret < 0) 1054 if (ret < 0)
1052 return ret; 1055 return ret;
1053 1056
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 8430d8937afb..8ea39aabe948 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -490,17 +490,9 @@ static int common_mmap(int op, struct file *file, unsigned long prot,
490 return common_file_perm(op, file, mask); 490 return common_file_perm(op, file, mask);
491} 491}
492 492
493static int apparmor_file_mmap(struct file *file, unsigned long reqprot, 493static int apparmor_mmap_file(struct file *file, unsigned long reqprot,
494 unsigned long prot, unsigned long flags, 494 unsigned long prot, unsigned long flags)
495 unsigned long addr, unsigned long addr_only)
496{ 495{
497 int rc = 0;
498
499 /* do DAC check */
500 rc = cap_mmap_addr(addr);
501 if (rc || addr_only)
502 return rc;
503
504 return common_mmap(OP_FMMAP, file, prot, flags); 496 return common_mmap(OP_FMMAP, file, prot, flags);
505} 497}
506 498
@@ -646,7 +638,8 @@ static struct security_operations apparmor_ops = {
646 .file_permission = apparmor_file_permission, 638 .file_permission = apparmor_file_permission,
647 .file_alloc_security = apparmor_file_alloc_security, 639 .file_alloc_security = apparmor_file_alloc_security,
648 .file_free_security = apparmor_file_free_security, 640 .file_free_security = apparmor_file_free_security,
649 .file_mmap = apparmor_file_mmap, 641 .mmap_file = apparmor_mmap_file,
642 .mmap_addr = cap_mmap_addr,
650 .file_mprotect = apparmor_file_mprotect, 643 .file_mprotect = apparmor_file_mprotect,
651 .file_lock = apparmor_file_lock, 644 .file_lock = apparmor_file_lock,
652 645
diff --git a/security/capability.c b/security/capability.c
index fca889676c5e..61095df8b89a 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -949,7 +949,8 @@ void __init security_fixup_ops(struct security_operations *ops)
949 set_to_cap_if_null(ops, file_alloc_security); 949 set_to_cap_if_null(ops, file_alloc_security);
950 set_to_cap_if_null(ops, file_free_security); 950 set_to_cap_if_null(ops, file_free_security);
951 set_to_cap_if_null(ops, file_ioctl); 951 set_to_cap_if_null(ops, file_ioctl);
952 set_to_cap_if_null(ops, file_mmap); 952 set_to_cap_if_null(ops, mmap_addr);
953 set_to_cap_if_null(ops, mmap_file);
953 set_to_cap_if_null(ops, file_mprotect); 954 set_to_cap_if_null(ops, file_mprotect);
954 set_to_cap_if_null(ops, file_lock); 955 set_to_cap_if_null(ops, file_lock);
955 set_to_cap_if_null(ops, file_fcntl); 956 set_to_cap_if_null(ops, file_fcntl);
diff --git a/security/commoncap.c b/security/commoncap.c
index ebac3618896e..6dbae4650abe 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -980,23 +980,8 @@ int cap_mmap_addr(unsigned long addr)
980 return ret; 980 return ret;
981} 981}
982 982
983/* 983int cap_mmap_file(struct file *file, unsigned long reqprot,
984 * cap_file_mmap - check if able to map given addr 984 unsigned long prot, unsigned long flags)
985 * @file: unused
986 * @reqprot: unused
987 * @prot: unused
988 * @flags: unused
989 * @addr: address attempting to be mapped
990 * @addr_only: unused
991 *
992 * If the process is attempting to map memory below dac_mmap_min_addr they need
993 * CAP_SYS_RAWIO. The other parameters to this function are unused by the
994 * capability security module. Returns 0 if this mapping should be allowed
995 * -EPERM if not.
996 */
997int cap_file_mmap(struct file *file, unsigned long reqprot,
998 unsigned long prot, unsigned long flags,
999 unsigned long addr, unsigned long addr_only)
1000{ 985{
1001 return cap_mmap_addr(addr); 986 return 0;
1002} 987}
diff --git a/security/security.c b/security/security.c
index 5497a57fba01..d91c66d3956b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -657,18 +657,22 @@ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
657 return security_ops->file_ioctl(file, cmd, arg); 657 return security_ops->file_ioctl(file, cmd, arg);
658} 658}
659 659
660int security_file_mmap(struct file *file, unsigned long reqprot, 660int security_mmap_file(struct file *file, unsigned long reqprot,
661 unsigned long prot, unsigned long flags, 661 unsigned long prot, unsigned long flags)
662 unsigned long addr, unsigned long addr_only)
663{ 662{
664 int ret; 663 int ret;
665 664
666 ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only); 665 ret = security_ops->mmap_file(file, reqprot, prot, flags);
667 if (ret) 666 if (ret)
668 return ret; 667 return ret;
669 return ima_file_mmap(file, prot); 668 return ima_file_mmap(file, prot);
670} 669}
671 670
671int security_mmap_addr(unsigned long addr)
672{
673 return security_ops->mmap_addr(addr);
674}
675
672int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, 676int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
673 unsigned long prot) 677 unsigned long prot)
674{ 678{
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 25c125eaa3d8..372ec6502aa8 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3083,9 +3083,7 @@ error:
3083 return rc; 3083 return rc;
3084} 3084}
3085 3085
3086static int selinux_file_mmap(struct file *file, unsigned long reqprot, 3086static int selinux_mmap_addr(unsigned long addr)
3087 unsigned long prot, unsigned long flags,
3088 unsigned long addr, unsigned long addr_only)
3089{ 3087{
3090 int rc = 0; 3088 int rc = 0;
3091 u32 sid = current_sid(); 3089 u32 sid = current_sid();
@@ -3104,10 +3102,12 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot,
3104 } 3102 }
3105 3103
3106 /* do DAC check on address space usage */ 3104 /* do DAC check on address space usage */
3107 rc = cap_mmap_addr(addr); 3105 return cap_mmap_addr(addr);
3108 if (rc || addr_only) 3106}
3109 return rc;
3110 3107
3108static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3109 unsigned long prot, unsigned long flags)
3110{
3111 if (selinux_checkreqprot) 3111 if (selinux_checkreqprot)
3112 prot = reqprot; 3112 prot = reqprot;
3113 3113
@@ -5570,7 +5570,8 @@ static struct security_operations selinux_ops = {
5570 .file_alloc_security = selinux_file_alloc_security, 5570 .file_alloc_security = selinux_file_alloc_security,
5571 .file_free_security = selinux_file_free_security, 5571 .file_free_security = selinux_file_free_security,
5572 .file_ioctl = selinux_file_ioctl, 5572 .file_ioctl = selinux_file_ioctl,
5573 .file_mmap = selinux_file_mmap, 5573 .mmap_file = selinux_mmap_file,
5574 .mmap_addr = selinux_mmap_addr,
5574 .file_mprotect = selinux_file_mprotect, 5575 .file_mprotect = selinux_file_mprotect,
5575 .file_lock = selinux_file_lock, 5576 .file_lock = selinux_file_lock,
5576 .file_fcntl = selinux_file_fcntl, 5577 .file_fcntl = selinux_file_fcntl,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index a62197718768..ee0bb5735f35 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1171,7 +1171,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
1171} 1171}
1172 1172
1173/** 1173/**
1174 * smack_file_mmap : 1174 * smack_mmap_file :
1175 * Check permissions for a mmap operation. The @file may be NULL, e.g. 1175 * Check permissions for a mmap operation. The @file may be NULL, e.g.
1176 * if mapping anonymous memory. 1176 * if mapping anonymous memory.
1177 * @file contains the file structure for file to map (may be NULL). 1177 * @file contains the file structure for file to map (may be NULL).
@@ -1180,10 +1180,9 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
1180 * @flags contains the operational flags. 1180 * @flags contains the operational flags.
1181 * Return 0 if permission is granted. 1181 * Return 0 if permission is granted.
1182 */ 1182 */
1183static int smack_file_mmap(struct file *file, 1183static int smack_mmap_file(struct file *file,
1184 unsigned long reqprot, unsigned long prot, 1184 unsigned long reqprot, unsigned long prot,
1185 unsigned long flags, unsigned long addr, 1185 unsigned long flags)
1186 unsigned long addr_only)
1187{ 1186{
1188 struct smack_known *skp; 1187 struct smack_known *skp;
1189 struct smack_rule *srp; 1188 struct smack_rule *srp;
@@ -1198,11 +1197,6 @@ static int smack_file_mmap(struct file *file,
1198 int tmay; 1197 int tmay;
1199 int rc; 1198 int rc;
1200 1199
1201 /* do DAC check on address space usage */
1202 rc = cap_mmap_addr(addr);
1203 if (rc || addr_only)
1204 return rc;
1205
1206 if (file == NULL || file->f_dentry == NULL) 1200 if (file == NULL || file->f_dentry == NULL)
1207 return 0; 1201 return 0;
1208 1202
@@ -3482,7 +3476,8 @@ struct security_operations smack_ops = {
3482 .file_ioctl = smack_file_ioctl, 3476 .file_ioctl = smack_file_ioctl,
3483 .file_lock = smack_file_lock, 3477 .file_lock = smack_file_lock,
3484 .file_fcntl = smack_file_fcntl, 3478 .file_fcntl = smack_file_fcntl,
3485 .file_mmap = smack_file_mmap, 3479 .mmap_file = smack_mmap_file,
3480 .mmap_addr = cap_mmap_addr,
3486 .file_set_fowner = smack_file_set_fowner, 3481 .file_set_fowner = smack_file_set_fowner,
3487 .file_send_sigiotask = smack_file_send_sigiotask, 3482 .file_send_sigiotask = smack_file_send_sigiotask,
3488 .file_receive = smack_file_receive, 3483 .file_receive = smack_file_receive,