aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2011-04-21 20:23:20 -0400
committerEric Paris <eparis@redhat.com>2011-04-25 16:24:41 -0400
commit0dc1ba24f7fff659725eecbba2c9ad679a0954cd (patch)
treead5831b52b38ca8157dd3ba4e5dfb75768bd372f /security/selinux/hooks.c
parent1c9904297451f558191e211a48d8838b4bf792b0 (diff)
SELINUX: Make selinux cache VFS RCU walks safe
Now that the security modules can decide whether they support the dcache RCU walk or not it's possible to make selinux a bit more RCU friendly. The SELinux AVC and security server access decision code is RCU safe. A specific piece of the LSM audit code may not be RCU safe. This patch makes the VFS RCU walk retry if it would hit the non RCU safe chunk of code. It will normally just work under RCU. This is done simply by passing the VFS RCU state as a flag down into the avc_audit() code and returning ECHILD there if it would have an issue. Based-on-patch-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9a220be17a3f..ed5f29aa0a38 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1447,8 +1447,11 @@ static int task_has_capability(struct task_struct *tsk,
1447 } 1447 }
1448 1448
1449 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); 1449 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
1450 if (audit == SECURITY_CAP_AUDIT) 1450 if (audit == SECURITY_CAP_AUDIT) {
1451 avc_audit(sid, sid, sclass, av, &avd, rc, &ad); 1451 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
1452 if (rc2)
1453 return rc2;
1454 }
1452 return rc; 1455 return rc;
1453} 1456}
1454 1457
@@ -1468,7 +1471,8 @@ static int task_has_system(struct task_struct *tsk,
1468static int inode_has_perm(const struct cred *cred, 1471static int inode_has_perm(const struct cred *cred,
1469 struct inode *inode, 1472 struct inode *inode,
1470 u32 perms, 1473 u32 perms,
1471 struct common_audit_data *adp) 1474 struct common_audit_data *adp,
1475 unsigned flags)
1472{ 1476{
1473 struct inode_security_struct *isec; 1477 struct inode_security_struct *isec;
1474 struct common_audit_data ad; 1478 struct common_audit_data ad;
@@ -1488,7 +1492,7 @@ static int inode_has_perm(const struct cred *cred,
1488 ad.u.fs.inode = inode; 1492 ad.u.fs.inode = inode;
1489 } 1493 }
1490 1494
1491 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp); 1495 return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
1492} 1496}
1493 1497
1494/* Same as inode_has_perm, but pass explicit audit data containing 1498/* Same as inode_has_perm, but pass explicit audit data containing
@@ -1505,7 +1509,7 @@ static inline int dentry_has_perm(const struct cred *cred,
1505 COMMON_AUDIT_DATA_INIT(&ad, FS); 1509 COMMON_AUDIT_DATA_INIT(&ad, FS);
1506 ad.u.fs.path.mnt = mnt; 1510 ad.u.fs.path.mnt = mnt;
1507 ad.u.fs.path.dentry = dentry; 1511 ad.u.fs.path.dentry = dentry;
1508 return inode_has_perm(cred, inode, av, &ad); 1512 return inode_has_perm(cred, inode, av, &ad, 0);
1509} 1513}
1510 1514
1511/* Check whether a task can use an open file descriptor to 1515/* Check whether a task can use an open file descriptor to
@@ -1541,7 +1545,7 @@ static int file_has_perm(const struct cred *cred,
1541 /* av is zero if only checking access to the descriptor. */ 1545 /* av is zero if only checking access to the descriptor. */
1542 rc = 0; 1546 rc = 0;
1543 if (av) 1547 if (av)
1544 rc = inode_has_perm(cred, inode, av, &ad); 1548 rc = inode_has_perm(cred, inode, av, &ad, 0);
1545 1549
1546out: 1550out:
1547 return rc; 1551 return rc;
@@ -2103,7 +2107,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
2103 file = file_priv->file; 2107 file = file_priv->file;
2104 inode = file->f_path.dentry->d_inode; 2108 inode = file->f_path.dentry->d_inode;
2105 if (inode_has_perm(cred, inode, 2109 if (inode_has_perm(cred, inode,
2106 FILE__READ | FILE__WRITE, NULL)) { 2110 FILE__READ | FILE__WRITE, NULL, 0)) {
2107 drop_tty = 1; 2111 drop_tty = 1;
2108 } 2112 }
2109 } 2113 }
@@ -2649,10 +2653,6 @@ static int selinux_inode_permission(struct inode *inode, int mask, unsigned flag
2649 if (!mask) 2653 if (!mask)
2650 return 0; 2654 return 0;
2651 2655
2652 /* May be droppable after audit */
2653 if (flags & IPERM_FLAG_RCU)
2654 return -ECHILD;
2655
2656 COMMON_AUDIT_DATA_INIT(&ad, FS); 2656 COMMON_AUDIT_DATA_INIT(&ad, FS);
2657 ad.u.fs.inode = inode; 2657 ad.u.fs.inode = inode;
2658 2658
@@ -2661,7 +2661,7 @@ static int selinux_inode_permission(struct inode *inode, int mask, unsigned flag
2661 2661
2662 perms = file_mask_to_av(inode->i_mode, mask); 2662 perms = file_mask_to_av(inode->i_mode, mask);
2663 2663
2664 return inode_has_perm(cred, inode, perms, &ad); 2664 return inode_has_perm(cred, inode, perms, &ad, flags);
2665} 2665}
2666 2666
2667static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) 2667static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
@@ -3208,7 +3208,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
3208 * new inode label or new policy. 3208 * new inode label or new policy.
3209 * This check is not redundant - do not remove. 3209 * This check is not redundant - do not remove.
3210 */ 3210 */
3211 return inode_has_perm(cred, inode, open_file_to_av(file), NULL); 3211 return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0);
3212} 3212}
3213 3213
3214/* task security operations */ 3214/* task security operations */