aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2011-04-25 16:26:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-04-25 21:16:32 -0400
commit9ade0cf440a1e5800dc68eef2e77b8d9d83a6dff (patch)
tree17a06970af5a26cd340b785a894f20f262335575 /security/selinux/hooks.c
parent1879fd6a26571fd4e8e1f4bb3e7537bc936b1fe7 (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> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
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 a73f4e463774..f7cf0ea6faea 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1446,8 +1446,11 @@ static int task_has_capability(struct task_struct *tsk,
1446 } 1446 }
1447 1447
1448 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); 1448 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
1449 if (audit == SECURITY_CAP_AUDIT) 1449 if (audit == SECURITY_CAP_AUDIT) {
1450 avc_audit(sid, sid, sclass, av, &avd, rc, &ad); 1450 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
1451 if (rc2)
1452 return rc2;
1453 }
1451 return rc; 1454 return rc;
1452} 1455}
1453 1456
@@ -1467,7 +1470,8 @@ static int task_has_system(struct task_struct *tsk,
1467static int inode_has_perm(const struct cred *cred, 1470static int inode_has_perm(const struct cred *cred,
1468 struct inode *inode, 1471 struct inode *inode,
1469 u32 perms, 1472 u32 perms,
1470 struct common_audit_data *adp) 1473 struct common_audit_data *adp,
1474 unsigned flags)
1471{ 1475{
1472 struct inode_security_struct *isec; 1476 struct inode_security_struct *isec;
1473 struct common_audit_data ad; 1477 struct common_audit_data ad;
@@ -1487,7 +1491,7 @@ static int inode_has_perm(const struct cred *cred,
1487 ad.u.fs.inode = inode; 1491 ad.u.fs.inode = inode;
1488 } 1492 }
1489 1493
1490 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp); 1494 return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
1491} 1495}
1492 1496
1493/* Same as inode_has_perm, but pass explicit audit data containing 1497/* Same as inode_has_perm, but pass explicit audit data containing
@@ -1504,7 +1508,7 @@ static inline int dentry_has_perm(const struct cred *cred,
1504 COMMON_AUDIT_DATA_INIT(&ad, FS); 1508 COMMON_AUDIT_DATA_INIT(&ad, FS);
1505 ad.u.fs.path.mnt = mnt; 1509 ad.u.fs.path.mnt = mnt;
1506 ad.u.fs.path.dentry = dentry; 1510 ad.u.fs.path.dentry = dentry;
1507 return inode_has_perm(cred, inode, av, &ad); 1511 return inode_has_perm(cred, inode, av, &ad, 0);
1508} 1512}
1509 1513
1510/* Check whether a task can use an open file descriptor to 1514/* Check whether a task can use an open file descriptor to
@@ -1540,7 +1544,7 @@ static int file_has_perm(const struct cred *cred,
1540 /* av is zero if only checking access to the descriptor. */ 1544 /* av is zero if only checking access to the descriptor. */
1541 rc = 0; 1545 rc = 0;
1542 if (av) 1546 if (av)
1543 rc = inode_has_perm(cred, inode, av, &ad); 1547 rc = inode_has_perm(cred, inode, av, &ad, 0);
1544 1548
1545out: 1549out:
1546 return rc; 1550 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)
@@ -3209,7 +3209,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
3209 * new inode label or new policy. 3209 * new inode label or new policy.
3210 * This check is not redundant - do not remove. 3210 * This check is not redundant - do not remove.
3211 */ 3211 */
3212 return inode_has_perm(cred, inode, open_file_to_av(file), NULL); 3212 return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0);
3213} 3213}
3214 3214
3215/* task security operations */ 3215/* task security operations */