summaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorEric Paris2012-04-04 21:01:42 +0200
committerEric Paris2012-04-09 18:22:59 +0200
commit2e33405785d3eaec303c54b4a10afdebf3729da7 (patch)
treef4c0d114503796e9f958341393e336f76a7eb6dd /security/selinux/hooks.c
parentSELinux: if sel_make_bools errors don't leave inconsistent state (diff)
downloadkernel-qcow2-linux-2e33405785d3eaec303c54b4a10afdebf3729da7.tar.gz
kernel-qcow2-linux-2e33405785d3eaec303c54b4a10afdebf3729da7.tar.xz
kernel-qcow2-linux-2e33405785d3eaec303c54b4a10afdebf3729da7.zip
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)
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)