aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2018-05-03 17:56:12 -0400
committerThomas Gleixner <tglx@linutronix.de>2018-05-04 18:51:44 -0400
commit00a02d0c502a06d15e07b857f8ff921e3e402675 (patch)
treed1f2bd8ff6733e43840a199d11e455790d7c21c8
parentb849a812f7eb92e96d1c8239b06581b2cfd8b275 (diff)
seccomp: Add filter flag to opt-out of SSB mitigation
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: Kees Cook <keescook@chromium.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--include/linux/seccomp.h5
-rw-r--r--include/uapi/linux/seccomp.h5
-rw-r--r--kernel/seccomp.c19
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c22
4 files changed, 36 insertions, 15 deletions
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index c723a5c4e3ff..e5320f6c8654 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -4,8 +4,9 @@
4 4
5#include <uapi/linux/seccomp.h> 5#include <uapi/linux/seccomp.h>
6 6
7#define SECCOMP_FILTER_FLAG_MASK (SECCOMP_FILTER_FLAG_TSYNC | \ 7#define SECCOMP_FILTER_FLAG_MASK (SECCOMP_FILTER_FLAG_TSYNC | \
8 SECCOMP_FILTER_FLAG_LOG) 8 SECCOMP_FILTER_FLAG_LOG | \
9 SECCOMP_FILTER_FLAG_SPEC_ALLOW)
9 10
10#ifdef CONFIG_SECCOMP 11#ifdef CONFIG_SECCOMP
11 12
diff --git a/include/uapi/linux/seccomp.h b/include/uapi/linux/seccomp.h
index 2a0bd9dd104d..9efc0e73d50b 100644
--- a/include/uapi/linux/seccomp.h
+++ b/include/uapi/linux/seccomp.h
@@ -17,8 +17,9 @@
17#define SECCOMP_GET_ACTION_AVAIL 2 17#define SECCOMP_GET_ACTION_AVAIL 2
18 18
19/* Valid flags for SECCOMP_SET_MODE_FILTER */ 19/* Valid flags for SECCOMP_SET_MODE_FILTER */
20#define SECCOMP_FILTER_FLAG_TSYNC 1 20#define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0)
21#define SECCOMP_FILTER_FLAG_LOG 2 21#define SECCOMP_FILTER_FLAG_LOG (1UL << 1)
22#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2)
22 23
23/* 24/*
24 * All BPF programs must return a 32-bit value. 25 * All BPF programs must return a 32-bit value.
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 2c819d65e15f..53eb946120c1 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -243,7 +243,8 @@ static inline void spec_mitigate(struct task_struct *task,
243} 243}
244 244
245static inline void seccomp_assign_mode(struct task_struct *task, 245static inline void seccomp_assign_mode(struct task_struct *task,
246 unsigned long seccomp_mode) 246 unsigned long seccomp_mode,
247 unsigned long flags)
247{ 248{
248 assert_spin_locked(&task->sighand->siglock); 249 assert_spin_locked(&task->sighand->siglock);
249 250
@@ -253,8 +254,9 @@ static inline void seccomp_assign_mode(struct task_struct *task,
253 * filter) is set. 254 * filter) is set.
254 */ 255 */
255 smp_mb__before_atomic(); 256 smp_mb__before_atomic();
256 /* Assume seccomp processes want speculation flaw mitigation. */ 257 /* Assume default seccomp processes want spec flaw mitigation. */
257 spec_mitigate(task, PR_SPEC_STORE_BYPASS); 258 if ((flags & SECCOMP_FILTER_FLAG_SPEC_ALLOW) == 0)
259 spec_mitigate(task, PR_SPEC_STORE_BYPASS);
258 set_tsk_thread_flag(task, TIF_SECCOMP); 260 set_tsk_thread_flag(task, TIF_SECCOMP);
259} 261}
260 262
@@ -322,7 +324,7 @@ static inline pid_t seccomp_can_sync_threads(void)
322 * without dropping the locks. 324 * without dropping the locks.
323 * 325 *
324 */ 326 */
325static inline void seccomp_sync_threads(void) 327static inline void seccomp_sync_threads(unsigned long flags)
326{ 328{
327 struct task_struct *thread, *caller; 329 struct task_struct *thread, *caller;
328 330
@@ -363,7 +365,8 @@ static inline void seccomp_sync_threads(void)
363 * allow one thread to transition the other. 365 * allow one thread to transition the other.
364 */ 366 */
365 if (thread->seccomp.mode == SECCOMP_MODE_DISABLED) 367 if (thread->seccomp.mode == SECCOMP_MODE_DISABLED)
366 seccomp_assign_mode(thread, SECCOMP_MODE_FILTER); 368 seccomp_assign_mode(thread, SECCOMP_MODE_FILTER,
369 flags);
367 } 370 }
368} 371}
369 372
@@ -486,7 +489,7 @@ static long seccomp_attach_filter(unsigned int flags,
486 489
487 /* Now that the new filter is in place, synchronize to all threads. */ 490 /* Now that the new filter is in place, synchronize to all threads. */
488 if (flags & SECCOMP_FILTER_FLAG_TSYNC) 491 if (flags & SECCOMP_FILTER_FLAG_TSYNC)
489 seccomp_sync_threads(); 492 seccomp_sync_threads(flags);
490 493
491 return 0; 494 return 0;
492} 495}
@@ -835,7 +838,7 @@ static long seccomp_set_mode_strict(void)
835#ifdef TIF_NOTSC 838#ifdef TIF_NOTSC
836 disable_TSC(); 839 disable_TSC();
837#endif 840#endif
838 seccomp_assign_mode(current, seccomp_mode); 841 seccomp_assign_mode(current, seccomp_mode, 0);
839 ret = 0; 842 ret = 0;
840 843
841out: 844out:
@@ -893,7 +896,7 @@ static long seccomp_set_mode_filter(unsigned int flags,
893 /* Do not free the successfully attached filter. */ 896 /* Do not free the successfully attached filter. */
894 prepared = NULL; 897 prepared = NULL;
895 898
896 seccomp_assign_mode(current, seccomp_mode); 899 seccomp_assign_mode(current, seccomp_mode, flags);
897out: 900out:
898 spin_unlock_irq(&current->sighand->siglock); 901 spin_unlock_irq(&current->sighand->siglock);
899 if (flags & SECCOMP_FILTER_FLAG_TSYNC) 902 if (flags & SECCOMP_FILTER_FLAG_TSYNC)
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 168c66d74fc5..e1473234968d 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -134,11 +134,15 @@ struct seccomp_data {
134#endif 134#endif
135 135
136#ifndef SECCOMP_FILTER_FLAG_TSYNC 136#ifndef SECCOMP_FILTER_FLAG_TSYNC
137#define SECCOMP_FILTER_FLAG_TSYNC 1 137#define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0)
138#endif 138#endif
139 139
140#ifndef SECCOMP_FILTER_FLAG_LOG 140#ifndef SECCOMP_FILTER_FLAG_LOG
141#define SECCOMP_FILTER_FLAG_LOG 2 141#define SECCOMP_FILTER_FLAG_LOG (1UL << 1)
142#endif
143
144#ifndef SECCOMP_FILTER_FLAG_SPEC_ALLOW
145#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2)
142#endif 146#endif
143 147
144#ifndef PTRACE_SECCOMP_GET_METADATA 148#ifndef PTRACE_SECCOMP_GET_METADATA
@@ -2072,14 +2076,26 @@ TEST(seccomp_syscall_mode_lock)
2072TEST(detect_seccomp_filter_flags) 2076TEST(detect_seccomp_filter_flags)
2073{ 2077{
2074 unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC, 2078 unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC,
2075 SECCOMP_FILTER_FLAG_LOG }; 2079 SECCOMP_FILTER_FLAG_LOG,
2080 SECCOMP_FILTER_FLAG_SPEC_ALLOW };
2076 unsigned int flag, all_flags; 2081 unsigned int flag, all_flags;
2077 int i; 2082 int i;
2078 long ret; 2083 long ret;
2079 2084
2080 /* Test detection of known-good filter flags */ 2085 /* Test detection of known-good filter flags */
2081 for (i = 0, all_flags = 0; i < ARRAY_SIZE(flags); i++) { 2086 for (i = 0, all_flags = 0; i < ARRAY_SIZE(flags); i++) {
2087 int bits = 0;
2088
2082 flag = flags[i]; 2089 flag = flags[i];
2090 /* Make sure the flag is a single bit! */
2091 while (flag) {
2092 if (flag & 0x1)
2093 bits ++;
2094 flag >>= 1;
2095 }
2096 ASSERT_EQ(1, bits);
2097 flag = flags[i];
2098
2083 ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL); 2099 ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
2084 ASSERT_NE(ENOSYS, errno) { 2100 ASSERT_NE(ENOSYS, errno) {
2085 TH_LOG("Kernel does not support seccomp syscall!"); 2101 TH_LOG("Kernel does not support seccomp syscall!");