[RFC PATCH 1/2] selinux: merge selinux_inode_permission and inode_has_perm
From: Eric Paris
Date: Mon Jun 03 2013 - 14:59:19 EST
selinux_inode_permission had some heavy lifting done to make it more
performance polite. But it still does largely the same thing as
inode_has_perm. So move that work into inode_has_perm and call
inode_has_perm from selinux_inode_permission.
Signed-off-by: Eric Paris <eparis@xxxxxxxxxx>
---
security/selinux/hooks.c | 92 ++++++++++++++++++++++--------------------------
1 file changed, 42 insertions(+), 50 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5c6f2cd..cfecb52 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1494,17 +1494,41 @@ static int task_has_system(struct task_struct *tsk,
SECCLASS_SYSTEM, perms, NULL);
}
+static noinline int audit_inode_permission(struct inode *inode,
+ struct common_audit_data *adp,
+ u32 perms, u32 audited, u32 denied,
+ unsigned flags)
+{
+ struct common_audit_data ad;
+ struct inode_security_struct *isec = inode->i_security;
+ int rc;
+
+ if (!adp) {
+ ad.type = LSM_AUDIT_DATA_INODE;
+ ad.u.inode = inode;
+ adp = &ad;
+ }
+
+ rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
+ audited, denied, adp, flags);
+ if (rc)
+ return rc;
+ return 0;
+}
+
/* Check whether a task has a particular permission to an inode.
The 'adp' parameter is optional and allows other audit
data to be passed (e.g. the dentry). */
static int inode_has_perm(const struct cred *cred,
struct inode *inode,
- u32 perms,
+ u32 perms, u32 dontaudit,
struct common_audit_data *adp,
unsigned flags)
{
struct inode_security_struct *isec;
- u32 sid;
+ struct av_decision avd;
+ u32 sid, denied, audited;
+ int rc, rc2;
validate_creds(cred);
@@ -1514,6 +1538,14 @@ static int inode_has_perm(const struct cred *cred,
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, dontaudit, &denied);
+ if (likely(!audited))
+ return rc;
+
+ rc2 = audit_inode_permission(inode, adp, perms, audited, denied, flags);
+ if (rc2)
+ return rc2;
return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
}
@@ -1529,7 +1561,7 @@ static inline int dentry_has_perm(const struct cred *cred,
ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry;
- return inode_has_perm(cred, inode, av, &ad, 0);
+ return inode_has_perm(cred, inode, av, 0, &ad, 0);
}
/* Same as inode_has_perm, but pass explicit audit data containing
@@ -1544,7 +1576,7 @@ static inline int path_has_perm(const struct cred *cred,
ad.type = LSM_AUDIT_DATA_PATH;
ad.u.path = *path;
- return inode_has_perm(cred, inode, av, &ad, 0);
+ return inode_has_perm(cred, inode, av, 0, &ad, 0);
}
/* Check whether a task can use an open file descriptor to
@@ -1580,7 +1612,7 @@ static int file_has_perm(const struct cred *cred,
/* av is zero if only checking access to the descriptor. */
rc = 0;
if (av)
- rc = inode_has_perm(cred, inode, av, &ad, 0);
+ rc = inode_has_perm(cred, inode, av, 0, &ad, 0);
out:
return rc;
@@ -2635,64 +2667,24 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
return dentry_has_perm(cred, dentry, FILE__READ);
}
-static noinline int audit_inode_permission(struct inode *inode,
- u32 perms, u32 audited, u32 denied,
- unsigned flags)
-{
- struct common_audit_data ad;
- struct inode_security_struct *isec = inode->i_security;
- int rc;
-
- ad.type = LSM_AUDIT_DATA_INODE;
- ad.u.inode = inode;
-
- rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
- audited, denied, &ad, flags);
- if (rc)
- return rc;
- return 0;
-}
-
static int selinux_inode_permission(struct inode *inode, int mask)
{
const struct cred *cred = current_cred();
- u32 perms;
- bool from_access;
+ u32 perms, dontaudit = 0;
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;
+ if (mask & MAY_ACCESS)
+ dontaudit = FILE__AUDIT_ACCESS;
+
mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
/* No permission to check. Existence test. */
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;
-
- rc2 = audit_inode_permission(inode, perms, audited, denied, flags);
- if (rc2)
- return rc2;
- return rc;
+ return inode_has_perm(cred, inode, perms, dontaudit, NULL, flags);
}
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
--
1.8.2.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/