Commit 50979953 authored by Ankur Arora's avatar Ankur Arora Committed by Paul Moore

audit: unify audit_filter_{uring(), inode_name(), syscall()}

audit_filter_uring(), audit_filter_inode_name() are substantially
similar to audit_filter_syscall(). Move the core logic to
__audit_filter_op() which can be parametrized for all three.

On a Skylakex system, getpid() latency (all results aggregated
across 12 boot cycles):

         Min     Mean    Median   Max      pstdev
         (ns)    (ns)    (ns)     (ns)

 -    196.63   207.86  206.60  230.98      (+- 3.92%)
 +    183.73   196.95  192.31  232.49	   (+- 6.04%)

Performance counter stats for 'bin/getpid' (3 runs) go from:
    cycles               805.58  (  +-  4.11% )
    instructions        1654.11  (  +-   .05% )
    IPC                    2.06  (  +-  3.39% )
    branches             430.02  (  +-   .05% )
    branch-misses          1.55  (  +-  7.09% )
    L1-dcache-loads      440.01  (  +-   .09% )
    L1-dcache-load-misses  9.05  (  +- 74.03% )
to:
    cycles		 765.37  (  +-  6.66% )
    instructions        1677.07  (  +-  0.04% )
    IPC		           2.20  (  +-  5.90% )
    branches	         431.10  (  +-  0.04% )
    branch-misses	   1.60  (  +- 11.25% )
    L1-dcache-loads	 521.04  (  +-  0.05% )
    L1-dcache-load-misses  6.92  (  +- 77.60% )

(Both aggregated over 12 boot cycles.)

The increased L1-dcache-loads are due to some intermediate values now
coming from the stack.

The improvement in cycles is due to a slightly denser loop (the list
parameter in the list_for_each_entry_rcu() exit check now comes from
a register rather than a constant as before.)
Signed-off-by: default avatarAnkur Arora <ankur.a.arora@oracle.com>
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent 06954599
...@@ -806,30 +806,53 @@ static int audit_in_mask(const struct audit_krule *rule, unsigned long val) ...@@ -806,30 +806,53 @@ static int audit_in_mask(const struct audit_krule *rule, unsigned long val)
} }
/** /**
* audit_filter_uring - apply filters to an io_uring operation * __audit_filter_op - common filter helper for operations (syscall/uring/etc)
* @tsk: associated task * @tsk: associated task
* @ctx: audit context * @ctx: audit context
* @list: audit filter list
* @name: audit_name (can be NULL)
* @op: current syscall/uring_op
*
* Run the udit filters specified in @list against @tsk using @ctx,
* @name, and @op, as necessary; the caller is responsible for ensuring
* that the call is made while the RCU read lock is held. The @name
* parameter can be NULL, but all others must be specified.
* Returns 1/true if the filter finds a match, 0/false if none are found.
*/ */
static void audit_filter_uring(struct task_struct *tsk, static int __audit_filter_op(struct task_struct *tsk,
struct audit_context *ctx) struct audit_context *ctx,
struct list_head *list,
struct audit_names *name,
unsigned long op)
{ {
struct audit_entry *e; struct audit_entry *e;
enum audit_state state; enum audit_state state;
list_for_each_entry_rcu(e, list, list) {
if (audit_in_mask(&e->rule, op) &&
audit_filter_rules(tsk, &e->rule, ctx, name,
&state, false)) {
ctx->current_state = state;
return 1;
}
}
return 0;
}
/**
* audit_filter_uring - apply filters to an io_uring operation
* @tsk: associated task
* @ctx: audit context
*/
static void audit_filter_uring(struct task_struct *tsk,
struct audit_context *ctx)
{
if (auditd_test_task(tsk)) if (auditd_test_task(tsk))
return; return;
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_URING_EXIT], __audit_filter_op(tsk, ctx, &audit_filter_list[AUDIT_FILTER_URING_EXIT],
list) { NULL, ctx->uring_op);
if (audit_in_mask(&e->rule, ctx->uring_op) &&
audit_filter_rules(tsk, &e->rule, ctx, NULL, &state,
false)) {
rcu_read_unlock();
ctx->current_state = state;
return;
}
}
rcu_read_unlock(); rcu_read_unlock();
} }
...@@ -841,25 +864,13 @@ static void audit_filter_uring(struct task_struct *tsk, ...@@ -841,25 +864,13 @@ static void audit_filter_uring(struct task_struct *tsk,
static void audit_filter_syscall(struct task_struct *tsk, static void audit_filter_syscall(struct task_struct *tsk,
struct audit_context *ctx) struct audit_context *ctx)
{ {
struct audit_entry *e;
enum audit_state state;
unsigned long major = ctx->major;
if (auditd_test_task(tsk)) if (auditd_test_task(tsk))
return; return;
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_EXIT], list) { __audit_filter_op(tsk, ctx, &audit_filter_list[AUDIT_FILTER_EXIT],
if (audit_in_mask(&e->rule, major) && NULL, ctx->major);
audit_filter_rules(tsk, &e->rule, ctx, NULL,
&state, false)) {
rcu_read_unlock();
ctx->current_state = state;
return;
}
}
rcu_read_unlock(); rcu_read_unlock();
return;
} }
/* /*
...@@ -871,17 +882,8 @@ static int audit_filter_inode_name(struct task_struct *tsk, ...@@ -871,17 +882,8 @@ static int audit_filter_inode_name(struct task_struct *tsk,
struct audit_context *ctx) { struct audit_context *ctx) {
int h = audit_hash_ino((u32)n->ino); int h = audit_hash_ino((u32)n->ino);
struct list_head *list = &audit_inode_hash[h]; struct list_head *list = &audit_inode_hash[h];
struct audit_entry *e;
enum audit_state state;
list_for_each_entry_rcu(e, list, list) { return __audit_filter_op(tsk, ctx, list, n, ctx->major);
if (audit_in_mask(&e->rule, ctx->major) &&
audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) {
ctx->current_state = state;
return 1;
}
}
return 0;
} }
/* At syscall exit time, this filter is called if any audit_names have been /* At syscall exit time, this filter is called if any audit_names have been
......
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