[PATCH 1/2] seccomp: Allow for auditing functionality specific to return actions

From: Tyler Hicks
Date: Mon Jan 02 2017 - 11:54:14 EST


This patch introduces the concept of auditing formats that are specific
to the action specified in a filter's return value. Initially, only
SECCOMP_RET_KILL has an auditing message that differs from other return
actions because it specifies the signal that is to be sent.

This patch causes a small functional change in that "sig=0" is not
printed when auditing seccomp actions other than SECCOMP_RET_KILL.

Signed-off-by: Tyler Hicks <tyhicks@xxxxxxxxxxxxx>
---
include/linux/audit.h | 39 +++++++++++++++++++++++++++++++++------
kernel/auditsc.c | 19 +++++++++++++++----
kernel/seccomp.c | 6 +++---
3 files changed, 51 insertions(+), 13 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index f51fca8d..8c588c3 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -85,6 +85,11 @@ struct audit_field {
u32 op;
};

+struct audit_seccomp_info {
+ int code;
+ long signr;
+};
+
extern int is_audit_feature_set(int which);

extern int __init audit_register_class(int class, unsigned *list);
@@ -243,7 +248,8 @@ extern void __audit_file(const struct file *);
extern void __audit_inode_child(struct inode *parent,
const struct dentry *dentry,
const unsigned char type);
-extern void __audit_seccomp(unsigned long syscall, long signr, int code);
+extern void __audit_seccomp(unsigned long syscall,
+ struct audit_seccomp_info *info);
extern void __audit_ptrace(struct task_struct *t);

static inline bool audit_dummy_context(void)
@@ -313,14 +319,31 @@ static inline void audit_inode_child(struct inode *parent,
}
void audit_core_dumps(long signr);

-static inline void audit_seccomp(unsigned long syscall, long signr, int code)
+static inline void audit_seccomp_signal(unsigned long syscall, long signr,
+ int code)
{
if (!audit_enabled)
return;

/* Force a record to be reported if a signal was delivered. */
- if (signr || unlikely(!audit_dummy_context()))
- __audit_seccomp(syscall, signr, code);
+ if (signr || unlikely(!audit_dummy_context())) {
+ struct audit_seccomp_info info = { .code = code,
+ .signr = signr };
+
+ __audit_seccomp(syscall, &info);
+ }
+}
+
+static inline void audit_seccomp_common(unsigned long syscall, int code)
+{
+ if (!audit_enabled)
+ return;
+
+ if (code || unlikely(!audit_dummy_context())) {
+ struct audit_seccomp_info info = { .code = code };
+
+ __audit_seccomp(syscall, &info);
+ }
}

static inline void audit_ptrace(struct task_struct *t)
@@ -485,9 +508,13 @@ static inline void audit_inode_child(struct inode *parent,
{ }
static inline void audit_core_dumps(long signr)
{ }
-static inline void __audit_seccomp(unsigned long syscall, long signr, int code)
+static inline void __audit_seccomp(unsigned long syscall,
+ struct audit_seccomp_info *info);
+{ }
+static inline void audit_seccomp_signal(unsigned long syscall, long signr,
+ int code)
{ }
-static inline void audit_seccomp(unsigned long syscall, long signr, int code)
+static inline void audit_seccomp_common(unsigned long syscall, int code)
{ }
static inline int auditsc_get_stamp(struct audit_context *ctx,
struct timespec *t, unsigned int *serial)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index cf1fa43..b3472f2 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -74,6 +74,7 @@
#include <linux/string.h>
#include <linux/uaccess.h>
#include <uapi/linux/limits.h>
+#include <uapi/linux/seccomp.h>

#include "audit.h"

@@ -2415,7 +2416,7 @@ void audit_core_dumps(long signr)
audit_log_end(ab);
}

-void __audit_seccomp(unsigned long syscall, long signr, int code)
+void __audit_seccomp(unsigned long syscall, struct audit_seccomp_info *info)
{
struct audit_buffer *ab;

@@ -2423,9 +2424,19 @@ void __audit_seccomp(unsigned long syscall, long signr, int code)
if (unlikely(!ab))
return;
audit_log_task(ab);
- audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x",
- signr, syscall_get_arch(), syscall,
- in_compat_syscall(), KSTK_EIP(current), code);
+
+ switch (info->code) {
+ case SECCOMP_RET_KILL:
+ audit_log_format(ab, " sig=%ld", info->signr);
+ break;
+ default:
+ break;
+ }
+
+ audit_log_format(ab,
+ " arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x",
+ syscall_get_arch(), syscall, in_compat_syscall(),
+ KSTK_EIP(current), info->code);
audit_log_end(ab);
}

diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index f7ce79a..54c01b6 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -532,7 +532,7 @@ static void __secure_computing_strict(int this_syscall)
#ifdef SECCOMP_DEBUG
dump_stack();
#endif
- audit_seccomp(this_syscall, SIGKILL, SECCOMP_RET_KILL);
+ audit_seccomp_signal(this_syscall, SIGKILL, SECCOMP_RET_KILL);
do_exit(SIGKILL);
}

@@ -635,14 +635,14 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,

case SECCOMP_RET_KILL:
default:
- audit_seccomp(this_syscall, SIGSYS, action);
+ audit_seccomp_signal(this_syscall, SIGSYS, action);
do_exit(SIGSYS);
}

unreachable();

skip:
- audit_seccomp(this_syscall, 0, action);
+ audit_seccomp_common(this_syscall, action);
return -1;
}
#else
--
2.7.4