summaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2012-04-04 15:01:42 -0400
committerEric Paris <eparis@redhat.com>2012-04-09 12:22:59 -0400
commit2e33405785d3eaec303c54b4a10afdebf3729da7 (patch)
treef4c0d114503796e9f958341393e336f76a7eb6dd /security/selinux/hooks.c
parent154c50ca4eb9ae472f50b6a481213e21ead4457d (diff)
SELinux: delay initialization of audit data in selinux_inode_permission
We pay a rather large overhead initializing the common_audit_data. Since we only need this information if we actually emit an audit message there is little need to set it up in the hot path. This patch splits the functionality of avc_has_perm() into avc_has_perm_noaudit(), avc_audit_required() and slow_avc_audit(). But we take care of setting up to audit between required() and the actual audit call. Thus saving measurable time in a hot path. Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c3ee902306d8..c99027dc0b36 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2684,6 +2684,11 @@ static int selinux_inode_permission(struct inode *inode, int mask)
2684 u32 perms; 2684 u32 perms;
2685 bool from_access; 2685 bool from_access;
2686 unsigned flags = mask & MAY_NOT_BLOCK; 2686 unsigned flags = mask & MAY_NOT_BLOCK;
2687 struct inode_security_struct *isec;
2688 u32 sid;
2689 struct av_decision avd;
2690 int rc, rc2;
2691 u32 audited, denied;
2687 2692
2688 from_access = mask & MAY_ACCESS; 2693 from_access = mask & MAY_ACCESS;
2689 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); 2694 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
@@ -2692,6 +2697,23 @@ static int selinux_inode_permission(struct inode *inode, int mask)
2692 if (!mask) 2697 if (!mask)
2693 return 0; 2698 return 0;
2694 2699
2700 validate_creds(cred);
2701
2702 if (unlikely(IS_PRIVATE(inode)))
2703 return 0;
2704
2705 perms = file_mask_to_av(inode->i_mode, mask);
2706
2707 sid = cred_sid(cred);
2708 isec = inode->i_security;
2709
2710 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2711 audited = avc_audit_required(perms, &avd, rc,
2712 from_access ? FILE__AUDIT_ACCESS : 0,
2713 &denied);
2714 if (likely(!audited))
2715 return rc;
2716
2695 COMMON_AUDIT_DATA_INIT(&ad, INODE); 2717 COMMON_AUDIT_DATA_INIT(&ad, INODE);
2696 ad.selinux_audit_data = &sad; 2718 ad.selinux_audit_data = &sad;
2697 ad.u.inode = inode; 2719 ad.u.inode = inode;
@@ -2699,9 +2721,11 @@ static int selinux_inode_permission(struct inode *inode, int mask)
2699 if (from_access) 2721 if (from_access)
2700 ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS; 2722 ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS;
2701 2723
2702 perms = file_mask_to_av(inode->i_mode, mask); 2724 rc2 = slow_avc_audit(sid, isec->sid, isec->sclass, perms,
2703 2725 audited, denied, &ad, flags);
2704 return inode_has_perm(cred, inode, perms, &ad, flags); 2726 if (rc2)
2727 return rc2;
2728 return rc;
2705} 2729}
2706 2730
2707static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) 2731static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)