]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - kernel/seccomp.c
extable: Consolidate *kernel_text_address() functions
[mirror_ubuntu-artful-kernel.git] / kernel / seccomp.c
index 54357e361aea5cbe90597208372f26ef94ead915..59cde2ed3b929166a82396e61b79176abef2ce8c 100644 (file)
@@ -44,6 +44,7 @@
  *         get/put helpers should be used when accessing an instance
  *         outside of a lifetime-guarded section.  In general, this
  *         is only needed for handling filters shared across tasks.
+ * @log: true if all actions except for SECCOMP_RET_ALLOW should be logged
  * @prev: points to a previously installed, or inherited, filter
  * @prog: the BPF program to evaluate
  *
@@ -59,6 +60,7 @@
  */
 struct seccomp_filter {
        refcount_t usage;
+       bool log;
        struct seccomp_filter *prev;
        struct bpf_prog *prog;
 };
@@ -452,6 +454,10 @@ static long seccomp_attach_filter(unsigned int flags,
                        return ret;
        }
 
+       /* Set log flag, if present. */
+       if (flags & SECCOMP_FILTER_FLAG_LOG)
+               filter->log = true;
+
        /*
         * If there is an existing filter, make it the prev and don't drop its
         * task reference.
@@ -527,20 +533,32 @@ static void seccomp_send_sigsys(int syscall, int reason)
 #define SECCOMP_LOG_TRAP               (1 << 2)
 #define SECCOMP_LOG_ERRNO              (1 << 3)
 #define SECCOMP_LOG_TRACE              (1 << 4)
-#define SECCOMP_LOG_ALLOW              (1 << 5)
+#define SECCOMP_LOG_LOG                        (1 << 5)
+#define SECCOMP_LOG_ALLOW              (1 << 6)
 
 static u32 seccomp_actions_logged = SECCOMP_LOG_KILL  | SECCOMP_LOG_TRAP  |
-                                   SECCOMP_LOG_ERRNO | SECCOMP_LOG_TRACE;
+                                   SECCOMP_LOG_ERRNO | SECCOMP_LOG_TRACE |
+                                   SECCOMP_LOG_LOG;
 
-static inline void seccomp_log(unsigned long syscall, long signr, u32 action)
+static inline void seccomp_log(unsigned long syscall, long signr, u32 action,
+                              bool requested)
 {
        bool log = false;
 
        switch (action) {
        case SECCOMP_RET_ALLOW:
+               break;
        case SECCOMP_RET_TRAP:
+               log = requested && seccomp_actions_logged & SECCOMP_LOG_TRAP;
+               break;
        case SECCOMP_RET_ERRNO:
+               log = requested && seccomp_actions_logged & SECCOMP_LOG_ERRNO;
+               break;
        case SECCOMP_RET_TRACE:
+               log = requested && seccomp_actions_logged & SECCOMP_LOG_TRACE;
+               break;
+       case SECCOMP_RET_LOG:
+               log = seccomp_actions_logged & SECCOMP_LOG_LOG;
                break;
        case SECCOMP_RET_KILL:
        default:
@@ -548,8 +566,9 @@ static inline void seccomp_log(unsigned long syscall, long signr, u32 action)
        }
 
        /*
-        * Force an audit message to be emitted when the action is RET_KILL and
-        * the action is allowed to be logged by the admin.
+        * Force an audit message to be emitted when the action is RET_KILL,
+        * RET_LOG, or the FILTER_FLAG_LOG bit was set and the action is
+        * allowed to be logged by the admin.
         */
        if (log)
                return __audit_seccomp(syscall, signr, action);
@@ -586,7 +605,7 @@ static void __secure_computing_strict(int this_syscall)
 #ifdef SECCOMP_DEBUG
        dump_stack();
 #endif
-       seccomp_log(this_syscall, SIGKILL, SECCOMP_RET_KILL);
+       seccomp_log(this_syscall, SIGKILL, SECCOMP_RET_KILL, true);
        do_exit(SIGKILL);
 }
 
@@ -685,6 +704,10 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
 
                return 0;
 
+       case SECCOMP_RET_LOG:
+               seccomp_log(this_syscall, 0, action, true);
+               return 0;
+
        case SECCOMP_RET_ALLOW:
                /*
                 * Note that the "match" filter will always be NULL for
@@ -695,7 +718,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
 
        case SECCOMP_RET_KILL:
        default:
-               seccomp_log(this_syscall, SIGSYS, action);
+               seccomp_log(this_syscall, SIGSYS, action, true);
                /* Dump core only if this is the last remaining thread. */
                if (get_nr_threads(current) == 1) {
                        siginfo_t info;
@@ -712,7 +735,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
        unreachable();
 
 skip:
-       seccomp_log(this_syscall, 0, action);
+       seccomp_log(this_syscall, 0, action, match ? match->log : false);
        return -1;
 }
 #else
@@ -859,6 +882,7 @@ static long seccomp_get_action_avail(const char __user *uaction)
        case SECCOMP_RET_TRAP:
        case SECCOMP_RET_ERRNO:
        case SECCOMP_RET_TRACE:
+       case SECCOMP_RET_LOG:
        case SECCOMP_RET_ALLOW:
                break;
        default:
@@ -1009,12 +1033,14 @@ out:
 #define SECCOMP_RET_TRAP_NAME          "trap"
 #define SECCOMP_RET_ERRNO_NAME         "errno"
 #define SECCOMP_RET_TRACE_NAME         "trace"
+#define SECCOMP_RET_LOG_NAME           "log"
 #define SECCOMP_RET_ALLOW_NAME         "allow"
 
 static const char seccomp_actions_avail[] = SECCOMP_RET_KILL_NAME      " "
                                            SECCOMP_RET_TRAP_NAME       " "
                                            SECCOMP_RET_ERRNO_NAME      " "
                                            SECCOMP_RET_TRACE_NAME      " "
+                                           SECCOMP_RET_LOG_NAME        " "
                                            SECCOMP_RET_ALLOW_NAME;
 
 struct seccomp_log_name {
@@ -1027,6 +1053,7 @@ static const struct seccomp_log_name seccomp_log_names[] = {
        { SECCOMP_LOG_TRAP, SECCOMP_RET_TRAP_NAME },
        { SECCOMP_LOG_ERRNO, SECCOMP_RET_ERRNO_NAME },
        { SECCOMP_LOG_TRACE, SECCOMP_RET_TRACE_NAME },
+       { SECCOMP_LOG_LOG, SECCOMP_RET_LOG_NAME },
        { SECCOMP_LOG_ALLOW, SECCOMP_RET_ALLOW_NAME },
        { }
 };