Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Linus Torvalds <torvalds@linux-foundation.org>

+15 -10
+15 -10
security/selinux/hooks.c
··· 1476 1476 unsigned flags) 1477 1477 { 1478 1478 struct inode_security_struct *isec; 1479 - struct common_audit_data ad; 1480 1479 u32 sid; 1481 1480 1482 1481 validate_creds(cred); ··· 1486 1487 sid = cred_sid(cred); 1487 1488 isec = inode->i_security; 1488 1489 1489 - if (!adp) { 1490 - adp = &ad; 1491 - COMMON_AUDIT_DATA_INIT(&ad, INODE); 1492 - ad.u.inode = inode; 1493 - } 1494 - 1495 1490 return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); 1491 + } 1492 + 1493 + static int inode_has_perm_noadp(const struct cred *cred, 1494 + struct inode *inode, 1495 + u32 perms, 1496 + unsigned flags) 1497 + { 1498 + struct common_audit_data ad; 1499 + 1500 + COMMON_AUDIT_DATA_INIT(&ad, INODE); 1501 + ad.u.inode = inode; 1502 + return inode_has_perm(cred, inode, perms, &ad, flags); 1496 1503 } 1497 1504 1498 1505 /* Same as inode_has_perm, but pass explicit audit data containing ··· 2127 2122 struct tty_file_private, list); 2128 2123 file = file_priv->file; 2129 2124 inode = file->f_path.dentry->d_inode; 2130 - if (inode_has_perm(cred, inode, 2131 - FILE__READ | FILE__WRITE, NULL, 0)) { 2125 + if (inode_has_perm_noadp(cred, inode, 2126 + FILE__READ | FILE__WRITE, 0)) { 2132 2127 drop_tty = 1; 2133 2128 } 2134 2129 } ··· 3233 3228 * new inode label or new policy. 3234 3229 * This check is not redundant - do not remove. 3235 3230 */ 3236 - return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0); 3231 + return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0); 3237 3232 } 3238 3233 3239 3234 /* task security operations */