Commit 6c3b2514 authored by Kees Cook's avatar Kees Cook Committed by Juerg Haefliger

UBUNTU: SAUCE: seccomp: Add filter flag to opt-out of SSB mitigation

CVE-2018-3639 (x86)

If a seccomp user is not interested in Speculative Store Bypass mitigation
by default, it can set the new SECCOMP_FILTER_FLAG_SPEC_ALLOW flag when
adding filters.
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarStefan Bader <stefan.bader@canonical.com>
[juergh: Context adjustments.]
Signed-off-by: default avatarJuerg Haefliger <juergh@canonical.com>
parent 5bf417c0
...@@ -3,8 +3,9 @@ ...@@ -3,8 +3,9 @@
#include <uapi/linux/seccomp.h> #include <uapi/linux/seccomp.h>
#define SECCOMP_FILTER_FLAG_MASK (SECCOMP_FILTER_FLAG_TSYNC | \ #define SECCOMP_FILTER_FLAG_MASK (SECCOMP_FILTER_FLAG_TSYNC | \
SECCOMP_FILTER_FLAG_LOG) SECCOMP_FILTER_FLAG_LOG | \
SECCOMP_FILTER_FLAG_SPEC_ALLOW)
#ifdef CONFIG_SECCOMP #ifdef CONFIG_SECCOMP
......
...@@ -16,8 +16,9 @@ ...@@ -16,8 +16,9 @@
#define SECCOMP_GET_ACTION_AVAIL 2 #define SECCOMP_GET_ACTION_AVAIL 2
/* Valid flags for SECCOMP_SET_MODE_FILTER */ /* Valid flags for SECCOMP_SET_MODE_FILTER */
#define SECCOMP_FILTER_FLAG_TSYNC 1 #define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0)
#define SECCOMP_FILTER_FLAG_LOG 2 #define SECCOMP_FILTER_FLAG_LOG (1UL << 1)
#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2)
/* /*
* All BPF programs must return a 32-bit value. * All BPF programs must return a 32-bit value.
......
...@@ -240,7 +240,8 @@ static inline void spec_mitigate(struct task_struct *task, ...@@ -240,7 +240,8 @@ static inline void spec_mitigate(struct task_struct *task,
} }
static inline void seccomp_assign_mode(struct task_struct *task, static inline void seccomp_assign_mode(struct task_struct *task,
unsigned long seccomp_mode) unsigned long seccomp_mode,
unsigned long flags)
{ {
assert_spin_locked(&task->sighand->siglock); assert_spin_locked(&task->sighand->siglock);
...@@ -250,8 +251,9 @@ static inline void seccomp_assign_mode(struct task_struct *task, ...@@ -250,8 +251,9 @@ static inline void seccomp_assign_mode(struct task_struct *task,
* filter) is set. * filter) is set.
*/ */
smp_mb__before_atomic(); smp_mb__before_atomic();
/* Assume seccomp processes want speculation flaw mitigation. */ /* Assume default seccomp processes want spec flaw mitigation. */
spec_mitigate(task, PR_SPEC_STORE_BYPASS); if ((flags & SECCOMP_FILTER_FLAG_SPEC_ALLOW) == 0)
spec_mitigate(task, PR_SPEC_STORE_BYPASS);
set_tsk_thread_flag(task, TIF_SECCOMP); set_tsk_thread_flag(task, TIF_SECCOMP);
} }
...@@ -319,7 +321,7 @@ static inline pid_t seccomp_can_sync_threads(void) ...@@ -319,7 +321,7 @@ static inline pid_t seccomp_can_sync_threads(void)
* without dropping the locks. * without dropping the locks.
* *
*/ */
static inline void seccomp_sync_threads(void) static inline void seccomp_sync_threads(unsigned long flags)
{ {
struct task_struct *thread, *caller; struct task_struct *thread, *caller;
...@@ -360,7 +362,8 @@ static inline void seccomp_sync_threads(void) ...@@ -360,7 +362,8 @@ static inline void seccomp_sync_threads(void)
* allow one thread to transition the other. * allow one thread to transition the other.
*/ */
if (thread->seccomp.mode == SECCOMP_MODE_DISABLED) if (thread->seccomp.mode == SECCOMP_MODE_DISABLED)
seccomp_assign_mode(thread, SECCOMP_MODE_FILTER); seccomp_assign_mode(thread, SECCOMP_MODE_FILTER,
flags);
} }
} }
...@@ -483,7 +486,7 @@ static long seccomp_attach_filter(unsigned int flags, ...@@ -483,7 +486,7 @@ static long seccomp_attach_filter(unsigned int flags,
/* Now that the new filter is in place, synchronize to all threads. */ /* Now that the new filter is in place, synchronize to all threads. */
if (flags & SECCOMP_FILTER_FLAG_TSYNC) if (flags & SECCOMP_FILTER_FLAG_TSYNC)
seccomp_sync_threads(); seccomp_sync_threads(flags);
return 0; return 0;
} }
...@@ -846,7 +849,7 @@ static long seccomp_set_mode_strict(void) ...@@ -846,7 +849,7 @@ static long seccomp_set_mode_strict(void)
#ifdef TIF_NOTSC #ifdef TIF_NOTSC
disable_TSC(); disable_TSC();
#endif #endif
seccomp_assign_mode(current, seccomp_mode); seccomp_assign_mode(current, seccomp_mode, 0);
ret = 0; ret = 0;
out: out:
...@@ -904,7 +907,7 @@ static long seccomp_set_mode_filter(unsigned int flags, ...@@ -904,7 +907,7 @@ static long seccomp_set_mode_filter(unsigned int flags,
/* Do not free the successfully attached filter. */ /* Do not free the successfully attached filter. */
prepared = NULL; prepared = NULL;
seccomp_assign_mode(current, seccomp_mode); seccomp_assign_mode(current, seccomp_mode, flags);
out: out:
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
if (flags & SECCOMP_FILTER_FLAG_TSYNC) if (flags & SECCOMP_FILTER_FLAG_TSYNC)
......
...@@ -1576,11 +1576,15 @@ TEST_F(TRACE_syscall, syscall_dropped) ...@@ -1576,11 +1576,15 @@ TEST_F(TRACE_syscall, syscall_dropped)
#endif #endif
#ifndef SECCOMP_FILTER_FLAG_TSYNC #ifndef SECCOMP_FILTER_FLAG_TSYNC
#define SECCOMP_FILTER_FLAG_TSYNC 1 #define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0)
#endif #endif
#ifndef SECCOMP_FILTER_FLAG_LOG #ifndef SECCOMP_FILTER_FLAG_LOG
#define SECCOMP_FILTER_FLAG_LOG 2 #define SECCOMP_FILTER_FLAG_LOG (1UL << 1)
#endif
#ifndef SECCOMP_FILTER_FLAG_SPEC_ALLOW
#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2)
#endif #endif
#ifndef seccomp #ifndef seccomp
...@@ -1689,14 +1693,26 @@ TEST(seccomp_syscall_mode_lock) ...@@ -1689,14 +1693,26 @@ TEST(seccomp_syscall_mode_lock)
TEST(detect_seccomp_filter_flags) TEST(detect_seccomp_filter_flags)
{ {
unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC, unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC,
SECCOMP_FILTER_FLAG_LOG }; SECCOMP_FILTER_FLAG_LOG,
SECCOMP_FILTER_FLAG_SPEC_ALLOW };
unsigned int flag, all_flags; unsigned int flag, all_flags;
int i; int i;
long ret; long ret;
/* Test detection of known-good filter flags */ /* Test detection of known-good filter flags */
for (i = 0, all_flags = 0; i < ARRAY_SIZE(flags); i++) { for (i = 0, all_flags = 0; i < ARRAY_SIZE(flags); i++) {
int bits = 0;
flag = flags[i]; flag = flags[i];
/* Make sure the flag is a single bit! */
while (flag) {
if (flag & 0x1)
bits ++;
flag >>= 1;
}
ASSERT_EQ(1, bits);
flag = flags[i];
ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL); ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
ASSERT_NE(ENOSYS, errno) { ASSERT_NE(ENOSYS, errno) {
TH_LOG("Kernel does not support seccomp syscall!"); TH_LOG("Kernel does not support seccomp syscall!");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment