lkml.org 
[lkml]   [2018]   [Mar]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] audit: set TIF_AUDIT_SYSCALL only if audit filter has been populated
From: Jiri Kosina <jkosina@suse.cz>

There is no point going through all the audit slow path syscall entry/exit
in case the audit daemon is running, but hasn't populated the audit filter
with any rules whatsoever.

Only set TIF_AUDIT_SYSCALL in case the number of populated audit rules is
non-zero.

Originally-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---

This is basically resurrection / rebase of patch Andi Lutomirski sent some
time back in 2014 or so.

Andi, is there any reason this hasn't been pursued further? I think we
still want to get some of the slow path performance back.

Thanks.

include/linux/audit.h | 15 +++++++++++++--
kernel/auditfilter.c | 4 ++--
kernel/auditsc.c | 45 ++++++++++++++++++++++++++++++++++++++++-----
kernel/fork.c | 2 +-
4 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index af410d9fbf2d..3d5e96f96be5 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -451,8 +451,10 @@ static inline void audit_fanotify(unsigned int response)
__audit_fanotify(response);
}

-extern int audit_n_rules;
extern int audit_signals;
+extern void audit_populate(struct task_struct *tsk);
+extern void audit_inc_n_rules(void);
+extern void audit_dec_n_rules(void);
#else /* CONFIG_AUDITSYSCALL */
static inline int audit_alloc(struct task_struct *task)
{
@@ -572,7 +574,16 @@ static inline void audit_fanotify(unsigned int response)

static inline void audit_ptrace(struct task_struct *t)
{ }
-#define audit_n_rules 0
+
+static inline void audit_populate(struct task_struct *tsk)
+{ }
+
+static inline void audit_inc_n_rules(void)
+{ }
+
+static inline void audit_dec_n_rules(void)
+{ }
+
#define audit_signals 0
#endif /* CONFIG_AUDITSYSCALL */

diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 4a1758adb222..46ad138d8ba2 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -991,7 +991,7 @@ static inline int audit_add_rule(struct audit_entry *entry)
}
#ifdef CONFIG_AUDITSYSCALL
if (!dont_count)
- audit_n_rules++;
+ audit_inc_n_rules();

if (!audit_match_signal(entry))
audit_signals++;
@@ -1038,7 +1038,7 @@ int audit_del_rule(struct audit_entry *entry)

#ifdef CONFIG_AUDITSYSCALL
if (!dont_count)
- audit_n_rules--;
+ audit_dec_n_rules();

if (!audit_match_signal(entry))
audit_signals--;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e80459f7e132..642dd856e716 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -91,7 +91,7 @@
#define MAX_PROCTITLE_AUDIT_LEN 128

/* number of audit rules */
-int audit_n_rules;
+static int audit_n_rules;

/* determines whether we collect data for signals sent */
int audit_signals;
@@ -919,6 +919,36 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
return context;
}

+void audit_inc_n_rules()
+{
+ struct task_struct *p, *g;
+ unsigned long flags;
+
+ read_lock_irqsave(&tasklist_lock, flags);
+ if (!audit_n_rules++) {
+ do_each_thread(g, p) {
+ if (p->audit_context)
+ set_tsk_thread_flag(p, TIF_SYSCALL_AUDIT);
+ } while_each_thread(g, p);
+ }
+ read_unlock_irqrestore(&tasklist_lock, flags);
+}
+
+void audit_dec_n_rules()
+{
+ struct task_struct *p, *g;
+ unsigned long flags;
+
+ read_lock_irqsave(&tasklist_lock, flags);
+ audit_n_rules--;
+ if (!audit_n_rules) {
+ do_each_thread(g, p) {
+ clear_tsk_thread_flag(p, TIF_SYSCALL_AUDIT);
+ } while_each_thread(g, p);
+ }
+ read_unlock_irqrestore(&tasklist_lock, flags);
+}
+
/**
* audit_alloc - allocate an audit context block for a task
* @tsk: task
@@ -938,10 +968,8 @@ int audit_alloc(struct task_struct *tsk)
return 0; /* Return if not auditing. */

state = audit_filter_task(tsk, &key);
- if (state == AUDIT_DISABLED) {
- clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
+ if (state == AUDIT_DISABLED)
return 0;
- }

if (!(context = audit_alloc_context(state))) {
kfree(key);
@@ -951,7 +979,6 @@ int audit_alloc(struct task_struct *tsk)
context->filterkey = key;

tsk->audit_context = context;
- set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
return 0;
}

@@ -967,6 +994,14 @@ static inline void audit_free_context(struct audit_context *context)
kfree(context);
}

+void audit_populate(struct task_struct *tsk)
+{
+ if (tsk->audit_context && audit_n_rules)
+ set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
+ else
+ clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
+}
+
static int audit_log_pid_context(struct audit_context *context, pid_t pid,
kuid_t auid, kuid_t uid, unsigned int sessionid,
u32 sid, char *comm)
diff --git a/kernel/fork.c b/kernel/fork.c
index e5d9d405ae4e..79c828746d24 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1955,7 +1955,7 @@ static __latent_entropy struct task_struct *copy_process(
attach_pid(p, PIDTYPE_PID);
nr_threads++;
}
-
+ audit_populate(p);
total_forks++;
spin_unlock(&current->sighand->siglock);
syscall_tracepoint_update(p);
--
Jiri Kosina
SUSE Labs
\
 
 \ /
  Last update: 2018-03-07 11:33    [W:0.069 / U:0.780 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site