Commit 95f4efb2 authored by Linus Torvalds's avatar Linus Torvalds

selinux: simplify and clean up inode_has_perm()

This is a rather hot function that is called with a potentially NULL
"struct common_audit_data" pointer argument.  And in that case it has to
provide and initialize its own dummy common_audit_data structure.

However, all the _common_ cases already pass it a real audit-data
structure, so that uncommon NULL case not only creates a silly run-time
test, more importantly it causes that function to have a big stack frame
for the dummy variable that isn't even used in the common case!

So get rid of that stupid run-time behavior, and make the (few)
functions that currently call with a NULL pointer just call a new helper
function instead (naturally called inode_has_perm_noapd(), since it has
no adp argument).

This makes the run-time test be a static code generation issue instead,
and allows for a much denser stack since none of the common callers need
the dummy structure.  And a denser stack not only means less stack space
usage, it means better cache behavior.  So we have a win-win-win from
this simplification: less code executed, smaller stack footprint, and
better cache behavior.
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 4c1f683a
...@@ -1476,7 +1476,6 @@ static int inode_has_perm(const struct cred *cred, ...@@ -1476,7 +1476,6 @@ static int inode_has_perm(const struct cred *cred,
unsigned flags) unsigned flags)
{ {
struct inode_security_struct *isec; struct inode_security_struct *isec;
struct common_audit_data ad;
u32 sid; u32 sid;
validate_creds(cred); validate_creds(cred);
...@@ -1487,13 +1486,19 @@ static int inode_has_perm(const struct cred *cred, ...@@ -1487,13 +1486,19 @@ static int inode_has_perm(const struct cred *cred,
sid = cred_sid(cred); sid = cred_sid(cred);
isec = inode->i_security; isec = inode->i_security;
if (!adp) { return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
adp = &ad; }
static int inode_has_perm_noadp(const struct cred *cred,
struct inode *inode,
u32 perms,
unsigned flags)
{
struct common_audit_data ad;
COMMON_AUDIT_DATA_INIT(&ad, INODE); COMMON_AUDIT_DATA_INIT(&ad, INODE);
ad.u.inode = inode; ad.u.inode = inode;
} return inode_has_perm(cred, inode, perms, &ad, flags);
return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
} }
/* Same as inode_has_perm, but pass explicit audit data containing /* Same as inode_has_perm, but pass explicit audit data containing
...@@ -2122,8 +2127,8 @@ static inline void flush_unauthorized_files(const struct cred *cred, ...@@ -2122,8 +2127,8 @@ static inline void flush_unauthorized_files(const struct cred *cred,
struct tty_file_private, list); struct tty_file_private, list);
file = file_priv->file; file = file_priv->file;
inode = file->f_path.dentry->d_inode; inode = file->f_path.dentry->d_inode;
if (inode_has_perm(cred, inode, if (inode_has_perm_noadp(cred, inode,
FILE__READ | FILE__WRITE, NULL, 0)) { FILE__READ | FILE__WRITE, 0)) {
drop_tty = 1; drop_tty = 1;
} }
} }
...@@ -3228,7 +3233,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred) ...@@ -3228,7 +3233,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
* new inode label or new policy. * new inode label or new policy.
* This check is not redundant - do not remove. * This check is not redundant - do not remove.
*/ */
return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0); return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0);
} }
/* task security operations */ /* task security operations */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment