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>

authored by Eric Paris and committed by Linus Torvalds 9ade0cf4 1879fd6a

+55 -25
+29 -7
security/selinux/avc.c
··· 471 * @avd: access vector decisions 472 * @result: result from avc_has_perm_noaudit 473 * @a: auxiliary audit data 474 * 475 * Audit the granting or denial of permissions in accordance 476 * with the policy. This function is typically called by ··· 482 * be performed under a lock, to allow the lock to be released 483 * before calling the auditing code. 484 */ 485 - void avc_audit(u32 ssid, u32 tsid, 486 u16 tclass, u32 requested, 487 - struct av_decision *avd, int result, struct common_audit_data *a) 488 { 489 struct common_audit_data stack_data; 490 u32 denied, audited; ··· 517 else 518 audited = requested & avd->auditallow; 519 if (!audited) 520 - return; 521 if (!a) { 522 a = &stack_data; 523 COMMON_AUDIT_DATA_INIT(a, NONE); 524 } 525 a->selinux_audit_data.tclass = tclass; 526 a->selinux_audit_data.requested = requested; 527 a->selinux_audit_data.ssid = ssid; ··· 544 a->lsm_pre_audit = avc_audit_pre_callback; 545 a->lsm_post_audit = avc_audit_post_callback; 546 common_lsm_audit(a); 547 } 548 549 /** ··· 809 * @tclass: target security class 810 * @requested: requested permissions, interpreted based on @tclass 811 * @auditdata: auxiliary audit data 812 * 813 * Check the AVC to determine whether the @requested permissions are granted 814 * for the SID pair (@ssid, @tsid), interpreting the permissions ··· 819 * permissions are granted, -%EACCES if any permissions are denied, or 820 * another -errno upon other errors. 821 */ 822 - int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, 823 - u32 requested, struct common_audit_data *auditdata) 824 { 825 struct av_decision avd; 826 - int rc; 827 828 rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd); 829 - avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); 830 return rc; 831 } 832
··· 471 * @avd: access vector decisions 472 * @result: result from avc_has_perm_noaudit 473 * @a: auxiliary audit data 474 + * @flags: VFS walk flags 475 * 476 * Audit the granting or denial of permissions in accordance 477 * with the policy. This function is typically called by ··· 481 * be performed under a lock, to allow the lock to be released 482 * before calling the auditing code. 483 */ 484 + int avc_audit(u32 ssid, u32 tsid, 485 u16 tclass, u32 requested, 486 + struct av_decision *avd, int result, struct common_audit_data *a, 487 + unsigned flags) 488 { 489 struct common_audit_data stack_data; 490 u32 denied, audited; ··· 515 else 516 audited = requested & avd->auditallow; 517 if (!audited) 518 + return 0; 519 + 520 if (!a) { 521 a = &stack_data; 522 COMMON_AUDIT_DATA_INIT(a, NONE); 523 } 524 + 525 + /* 526 + * When in a RCU walk do the audit on the RCU retry. This is because 527 + * the collection of the dname in an inode audit message is not RCU 528 + * safe. Note this may drop some audits when the situation changes 529 + * during retry. However this is logically just as if the operation 530 + * happened a little later. 531 + */ 532 + if ((a->type == LSM_AUDIT_DATA_FS) && 533 + (flags & IPERM_FLAG_RCU)) 534 + return -ECHILD; 535 + 536 a->selinux_audit_data.tclass = tclass; 537 a->selinux_audit_data.requested = requested; 538 a->selinux_audit_data.ssid = ssid; ··· 529 a->lsm_pre_audit = avc_audit_pre_callback; 530 a->lsm_post_audit = avc_audit_post_callback; 531 common_lsm_audit(a); 532 + return 0; 533 } 534 535 /** ··· 793 * @tclass: target security class 794 * @requested: requested permissions, interpreted based on @tclass 795 * @auditdata: auxiliary audit data 796 + * @flags: VFS walk flags 797 * 798 * Check the AVC to determine whether the @requested permissions are granted 799 * for the SID pair (@ssid, @tsid), interpreting the permissions ··· 802 * permissions are granted, -%EACCES if any permissions are denied, or 803 * another -errno upon other errors. 804 */ 805 + int avc_has_perm_flags(u32 ssid, u32 tsid, u16 tclass, 806 + u32 requested, struct common_audit_data *auditdata, 807 + unsigned flags) 808 { 809 struct av_decision avd; 810 + int rc, rc2; 811 812 rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd); 813 + 814 + rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata, 815 + flags); 816 + if (rc2) 817 + return rc2; 818 return rc; 819 } 820
+13 -13
security/selinux/hooks.c
··· 1446 } 1447 1448 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); 1449 - if (audit == SECURITY_CAP_AUDIT) 1450 - avc_audit(sid, sid, sclass, av, &avd, rc, &ad); 1451 return rc; 1452 } 1453 ··· 1470 static int inode_has_perm(const struct cred *cred, 1471 struct inode *inode, 1472 u32 perms, 1473 - struct common_audit_data *adp) 1474 { 1475 struct inode_security_struct *isec; 1476 struct common_audit_data ad; ··· 1491 ad.u.fs.inode = inode; 1492 } 1493 1494 - return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp); 1495 } 1496 1497 /* Same as inode_has_perm, but pass explicit audit data containing ··· 1508 COMMON_AUDIT_DATA_INIT(&ad, FS); 1509 ad.u.fs.path.mnt = mnt; 1510 ad.u.fs.path.dentry = dentry; 1511 - return inode_has_perm(cred, inode, av, &ad); 1512 } 1513 1514 /* Check whether a task can use an open file descriptor to ··· 1544 /* av is zero if only checking access to the descriptor. */ 1545 rc = 0; 1546 if (av) 1547 - rc = inode_has_perm(cred, inode, av, &ad); 1548 1549 out: 1550 return rc; ··· 2107 file = file_priv->file; 2108 inode = file->f_path.dentry->d_inode; 2109 if (inode_has_perm(cred, inode, 2110 - FILE__READ | FILE__WRITE, NULL)) { 2111 drop_tty = 1; 2112 } 2113 } ··· 2653 if (!mask) 2654 return 0; 2655 2656 - /* May be droppable after audit */ 2657 - if (flags & IPERM_FLAG_RCU) 2658 - return -ECHILD; 2659 - 2660 COMMON_AUDIT_DATA_INIT(&ad, FS); 2661 ad.u.fs.inode = inode; 2662 ··· 2661 2662 perms = file_mask_to_av(inode->i_mode, mask); 2663 2664 - return inode_has_perm(cred, inode, perms, &ad); 2665 } 2666 2667 static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) ··· 3209 * new inode label or new policy. 3210 * This check is not redundant - do not remove. 3211 */ 3212 - return inode_has_perm(cred, inode, open_file_to_av(file), NULL); 3213 } 3214 3215 /* task security operations */
··· 1446 } 1447 1448 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); 1449 + if (audit == SECURITY_CAP_AUDIT) { 1450 + int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0); 1451 + if (rc2) 1452 + return rc2; 1453 + } 1454 return rc; 1455 } 1456 ··· 1467 static int inode_has_perm(const struct cred *cred, 1468 struct inode *inode, 1469 u32 perms, 1470 + struct common_audit_data *adp, 1471 + unsigned flags) 1472 { 1473 struct inode_security_struct *isec; 1474 struct common_audit_data ad; ··· 1487 ad.u.fs.inode = inode; 1488 } 1489 1490 + return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); 1491 } 1492 1493 /* Same as inode_has_perm, but pass explicit audit data containing ··· 1504 COMMON_AUDIT_DATA_INIT(&ad, FS); 1505 ad.u.fs.path.mnt = mnt; 1506 ad.u.fs.path.dentry = dentry; 1507 + return inode_has_perm(cred, inode, av, &ad, 0); 1508 } 1509 1510 /* Check whether a task can use an open file descriptor to ··· 1540 /* av is zero if only checking access to the descriptor. */ 1541 rc = 0; 1542 if (av) 1543 + rc = inode_has_perm(cred, inode, av, &ad, 0); 1544 1545 out: 1546 return rc; ··· 2103 file = file_priv->file; 2104 inode = file->f_path.dentry->d_inode; 2105 if (inode_has_perm(cred, inode, 2106 + FILE__READ | FILE__WRITE, NULL, 0)) { 2107 drop_tty = 1; 2108 } 2109 } ··· 2649 if (!mask) 2650 return 0; 2651 2652 COMMON_AUDIT_DATA_INIT(&ad, FS); 2653 ad.u.fs.inode = inode; 2654 ··· 2661 2662 perms = file_mask_to_av(inode->i_mode, mask); 2663 2664 + return inode_has_perm(cred, inode, perms, &ad, flags); 2665 } 2666 2667 static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) ··· 3209 * new inode label or new policy. 3210 * This check is not redundant - do not remove. 3211 */ 3212 + return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0); 3213 } 3214 3215 /* task security operations */
+13 -5
security/selinux/include/avc.h
··· 54 55 void __init avc_init(void); 56 57 - void avc_audit(u32 ssid, u32 tsid, 58 u16 tclass, u32 requested, 59 struct av_decision *avd, 60 int result, 61 - struct common_audit_data *a); 62 63 #define AVC_STRICT 1 /* Ignore permissive mode. */ 64 int avc_has_perm_noaudit(u32 ssid, u32 tsid, ··· 66 unsigned flags, 67 struct av_decision *avd); 68 69 - int avc_has_perm(u32 ssid, u32 tsid, 70 - u16 tclass, u32 requested, 71 - struct common_audit_data *auditdata); 72 73 u32 avc_policy_seqno(void); 74
··· 54 55 void __init avc_init(void); 56 57 + int avc_audit(u32 ssid, u32 tsid, 58 u16 tclass, u32 requested, 59 struct av_decision *avd, 60 int result, 61 + struct common_audit_data *a, unsigned flags); 62 63 #define AVC_STRICT 1 /* Ignore permissive mode. */ 64 int avc_has_perm_noaudit(u32 ssid, u32 tsid, ··· 66 unsigned flags, 67 struct av_decision *avd); 68 69 + int avc_has_perm_flags(u32 ssid, u32 tsid, 70 + u16 tclass, u32 requested, 71 + struct common_audit_data *auditdata, 72 + unsigned); 73 + 74 + static inline int avc_has_perm(u32 ssid, u32 tsid, 75 + u16 tclass, u32 requested, 76 + struct common_audit_data *auditdata) 77 + { 78 + return avc_has_perm_flags(ssid, tsid, tclass, requested, auditdata, 0); 79 + } 80 81 u32 avc_policy_seqno(void); 82