Skip to content

Commit 951b2de

Browse files
stephensmalleypcmoore
authored andcommitted
selinux: optimize selinux_inode_getattr/permission() based on neveraudit|permissive
Extend the task avdcache to also cache whether the task SID is both permissive and neveraudit, and return immediately if so in both selinux_inode_getattr() and selinux_inode_permission(). The same approach could be applied to many of the hook functions although the avdcache would need to be updated for more than directory search checks in order for this optimization to be beneficial for checks on objects other than directories. To test, apply SELinuxProject/selinux#473 to your selinux userspace, build and install libsepol, and use the following CIL policy module: $ cat neverauditpermissive.cil (typeneveraudit unconfined_t) (typepermissive unconfined_t) Without this module inserted, running the following commands: perf record make -jN # on an already built allmodconfig tree perf report --sort=symbol,dso yields the following percentages (only showing __d_lookup_rcu for reference and only showing relevant SELinux functions): 1.65% [k] __d_lookup_rcu 0.53% [k] selinux_inode_permission 0.40% [k] selinux_inode_getattr 0.15% [k] avc_lookup 0.05% [k] avc_has_perm 0.05% [k] avc_has_perm_noaudit 0.02% [k] avc_policy_seqno 0.02% [k] selinux_file_permission 0.01% [k] selinux_inode_alloc_security 0.01% [k] selinux_file_alloc_security for a total of 1.24% for SELinux compared to 1.65% for __d_lookup_rcu(). After running the following command to insert this module: semodule -i neverauditpermissive.cil and then re-running the same perf commands from above yields the following non-zero percentages: 1.74% [k] __d_lookup_rcu 0.31% [k] selinux_inode_permission 0.03% [k] selinux_inode_getattr 0.03% [k] avc_policy_seqno 0.01% [k] avc_lookup 0.01% [k] selinux_file_permission 0.01% [k] selinux_file_open for a total of 0.40% for SELinux compared to 1.74% for __d_lookup_rcu(). Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
1 parent 1106896 commit 951b2de

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

security/selinux/hooks.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3181,6 +3181,8 @@ static inline void task_avdcache_update(struct task_security_struct *tsec,
31813181
tsec->avdcache.dir[spot].audited = audited;
31823182
tsec->avdcache.dir[spot].allowed = avd->allowed;
31833183
tsec->avdcache.dir[spot].permissive = avd->flags & AVD_FLAGS_PERMISSIVE;
3184+
tsec->avdcache.permissive_neveraudit =
3185+
(avd->flags == (AVD_FLAGS_PERMISSIVE|AVD_FLAGS_NEVERAUDIT));
31843186
}
31853187

31863188
/**
@@ -3207,10 +3209,13 @@ static int selinux_inode_permission(struct inode *inode, int requested)
32073209
if (!mask)
32083210
return 0;
32093211

3212+
tsec = selinux_cred(current_cred());
3213+
if (task_avdcache_permnoaudit(tsec))
3214+
return 0;
3215+
32103216
isec = inode_security_rcu(inode, requested & MAY_NOT_BLOCK);
32113217
if (IS_ERR(isec))
32123218
return PTR_ERR(isec);
3213-
tsec = selinux_cred(current_cred());
32143219
perms = file_mask_to_av(inode->i_mode, mask);
32153220

32163221
rc = task_avdcache_search(tsec, isec, &avdc);
@@ -3274,6 +3279,13 @@ static int selinux_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
32743279

32753280
static int selinux_inode_getattr(const struct path *path)
32763281
{
3282+
struct task_security_struct *tsec;
3283+
3284+
tsec = selinux_cred(current_cred());
3285+
3286+
if (task_avdcache_permnoaudit(tsec))
3287+
return 0;
3288+
32773289
return path_has_perm(current_cred(), path, FILE__GETATTR);
32783290
}
32793291

security/selinux/include/objsec.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,17 @@ struct task_security_struct {
4949
u32 seqno; /* AVC sequence number */
5050
unsigned int dir_spot; /* dir cache index to check first */
5151
struct avdc_entry dir[TSEC_AVDC_DIR_SIZE]; /* dir entries */
52+
bool permissive_neveraudit; /* permissive and neveraudit */
5253
} avdcache;
5354
} __randomize_layout;
5455

56+
static inline bool task_avdcache_permnoaudit(struct task_security_struct *tsec)
57+
{
58+
return (tsec->avdcache.permissive_neveraudit &&
59+
tsec->sid == tsec->avdcache.sid &&
60+
tsec->avdcache.seqno == avc_policy_seqno());
61+
}
62+
5563
enum label_initialized {
5664
LABEL_INVALID, /* invalid or not initialized */
5765
LABEL_INITIALIZED, /* initialized */

0 commit comments

Comments
 (0)