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 <tyhi...@canonical.com>
---
 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

Reply via email to