mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-07 22:42:04 +00:00
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>
This commit is contained in:
parent
b849a812f7
commit
00a02d0c50
@ -4,8 +4,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
|
||||||
|
|
||||||
|
@ -17,8 +17,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.
|
||||||
|
@ -243,7 +243,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);
|
||||||
|
|
||||||
@ -253,8 +254,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,7 +324,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;
|
||||||
|
|
||||||
@ -363,7 +365,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,7 +489,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;
|
||||||
}
|
}
|
||||||
@ -835,7 +838,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:
|
||||||
@ -893,7 +896,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(¤t->sighand->siglock);
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
if (flags & SECCOMP_FILTER_FLAG_TSYNC)
|
if (flags & SECCOMP_FILTER_FLAG_TSYNC)
|
||||||
|
@ -134,11 +134,15 @@ struct seccomp_data {
|
|||||||
#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 PTRACE_SECCOMP_GET_METADATA
|
#ifndef PTRACE_SECCOMP_GET_METADATA
|
||||||
@ -2072,14 +2076,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!");
|
||||||
|
Loading…
Reference in New Issue
Block a user