diff options
author | Eric Paris <eparis@redhat.com> | 2012-04-04 23:01:42 +0400 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2012-04-09 20:22:59 +0400 |
commit | 2e33405785d3eaec303c54b4a10afdebf3729da7 (patch) | |
tree | f4c0d114503796e9f958341393e336f76a7eb6dd /security/selinux/hooks.c | |
parent | 154c50ca4eb9ae472f50b6a481213e21ead4457d (diff) | |
download | linux-2e33405785d3eaec303c54b4a10afdebf3729da7.tar.xz |
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.c | 30 |
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) u32 perms; bool from_access; unsigned flags = mask & MAY_NOT_BLOCK; + struct inode_security_struct *isec; + u32 sid; + struct av_decision avd; + int rc, rc2; + u32 audited, denied; from_access = mask & MAY_ACCESS; mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); @@ -2692,6 +2697,23 @@ static int selinux_inode_permission(struct inode *inode, int mask) if (!mask) return 0; + validate_creds(cred); + + if (unlikely(IS_PRIVATE(inode))) + return 0; + + perms = file_mask_to_av(inode->i_mode, mask); + + sid = cred_sid(cred); + isec = inode->i_security; + + rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd); + audited = avc_audit_required(perms, &avd, rc, + from_access ? FILE__AUDIT_ACCESS : 0, + &denied); + if (likely(!audited)) + return rc; + COMMON_AUDIT_DATA_INIT(&ad, INODE); ad.selinux_audit_data = &sad; ad.u.inode = inode; @@ -2699,9 +2721,11 @@ static int selinux_inode_permission(struct inode *inode, int mask) if (from_access) ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS; - perms = file_mask_to_av(inode->i_mode, mask); - - return inode_has_perm(cred, inode, perms, &ad, flags); + rc2 = slow_avc_audit(sid, isec->sid, isec->sclass, perms, + audited, denied, &ad, flags); + if (rc2) + return rc2; + return rc; } static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |