From 72f3ecde58edb03d76cb359607fef98c1663d481 Mon Sep 17 00:00:00 2001 From: Yang Yang Date: Thu, 21 Jan 2021 21:05:04 +0800 Subject: [PATCH] [RFC,v2,1/1] speed up syscall rule match while exiting syscall audit_filter_syscall() traverses struct list_head audit_filter_list to find out whether current syscall match one rule. This takes o(n), which is not necessary, specially for user who add a very few syscall rules. On the other hand, user may not much care about rule add/delete speed. So do o(n) calculate at rule changing, and ease the burden of audit_filter_syscall(). Define audit_syscall[NR_syscalls], every element stands for one syscall. audit_filter_syscall() checks audit_syscall[NR_syscalls]. audit_syscall[n] == 0 indicates no rule audit syscall n, do a quick exit. audit_syscall[n] > 0 indicates at least one rule audit syscall n. audit_syscall[n] update when syscall rule changes. Signed-off-by: Yang Yang --- include/linux/audit.h | 2 ++ kernel/audit.c | 4 ++++ kernel/auditfilter.c | 30 ++++++++++++++++++++++++++++++ kernel/auditsc.c | 5 ++++- 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 82b7c11..7885531 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -549,6 +549,8 @@ static inline void audit_log_nfcfg(const char *name, u8 af, extern int audit_n_rules; extern int audit_signals; +extern u32 auditing_syscall[NR_syscalls]; +extern int audit_in_mask(const struct audit_krule *rule, unsigned long val); #else /* CONFIG_AUDITSYSCALL */ static inline int audit_alloc(struct task_struct *task) { diff --git a/kernel/audit.c b/kernel/audit.c index 1ffc2e0..07f4590 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -208,6 +208,10 @@ struct audit_reply { struct sk_buff *skb; }; +#ifdef CONFIG_AUDITSYSCALL +u32 auditing_syscall[NR_syscalls] = {0}; +#endif + /** * auditd_test_task - Check to see if a given task is an audit daemon * @task: the task to check diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 333b3bc..9d3e703 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -926,6 +926,28 @@ static struct audit_entry *audit_find_rule(struct audit_entry *entry, static u64 prio_low = ~0ULL/2; static u64 prio_high = ~0ULL/2 - 1; +#ifdef CONFIG_AUDITSYSCALL +static inline void update_auditing_syscall(struct audit_krule rule, bool add) +{ + int i; + + /* syscall rule with type AUDIT_FILTER_EXIT */ + if (rule.listnr == AUDIT_FILTER_EXIT && !rule.watch && !rule.tree) { + for (i = 0; i < NR_syscalls; i++) { + /* whether this rule include one syscall */ + if (unlikely(audit_in_mask(&rule, i))) { + if (add == true) + auditing_syscall[i]++; + else + auditing_syscall[i]--; + } + } + } + + return; +} +#endif + /* Add rule to given filterlist if not a duplicate. */ static inline int audit_add_rule(struct audit_entry *entry) { @@ -957,6 +979,10 @@ static inline int audit_add_rule(struct audit_entry *entry) return err; } +#ifdef CONFIG_AUDITSYSCALL + update_auditing_syscall(entry->rule, true); +#endif + if (watch) { /* audit_filter_mutex is dropped and re-taken during this call */ err = audit_add_watch(&entry->rule, &list); @@ -1035,6 +1061,10 @@ int audit_del_rule(struct audit_entry *entry) goto out; } +#ifdef CONFIG_AUDITSYSCALL + update_auditing_syscall(e->rule, false); +#endif + if (e->rule.watch) audit_remove_watch_rule(&e->rule); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index ce8c9e2..90490aa 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -783,7 +783,7 @@ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key) return AUDIT_BUILD_CONTEXT; } -static int audit_in_mask(const struct audit_krule *rule, unsigned long val) +int audit_in_mask(const struct audit_krule *rule, unsigned long val) { int word, bit; @@ -814,6 +814,9 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk, if (auditd_test_task(tsk)) return AUDIT_DISABLED; + if (!auditing_syscall[ctx->major]) + return AUDIT_BUILD_CONTEXT; + rcu_read_lock(); list_for_each_entry_rcu(e, list, list) { if (audit_in_mask(&e->rule, ctx->major) && -- 2.15.2