Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 00a02d0c authored by Kees Cook's avatar Kees Cook Committed by Thomas Gleixner
Browse files

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: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent b849a812
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -5,7 +5,8 @@
#include <uapi/linux/seccomp.h>

#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

+3 −2
Original line number Diff line number Diff line
@@ -17,8 +17,9 @@
#define SECCOMP_GET_ACTION_AVAIL	2

/* Valid flags for SECCOMP_SET_MODE_FILTER */
#define SECCOMP_FILTER_FLAG_TSYNC	1
#define SECCOMP_FILTER_FLAG_LOG		2
#define SECCOMP_FILTER_FLAG_TSYNC	(1UL << 0)
#define SECCOMP_FILTER_FLAG_LOG		(1UL << 1)
#define SECCOMP_FILTER_FLAG_SPEC_ALLOW	(1UL << 2)

/*
 * All BPF programs must return a 32-bit value.
+11 −8
Original line number Diff line number Diff line
@@ -243,7 +243,8 @@ static inline void spec_mitigate(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);

@@ -253,7 +254,8 @@ static inline void seccomp_assign_mode(struct task_struct *task,
	 * filter) is set.
	 */
	smp_mb__before_atomic();
	/* Assume seccomp processes want speculation flaw mitigation. */
	/* Assume default seccomp processes want spec flaw mitigation. */
	if ((flags & SECCOMP_FILTER_FLAG_SPEC_ALLOW) == 0)
		spec_mitigate(task, PR_SPEC_STORE_BYPASS);
	set_tsk_thread_flag(task, TIF_SECCOMP);
}
@@ -322,7 +324,7 @@ static inline pid_t seccomp_can_sync_threads(void)
 * 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;

@@ -363,7 +365,8 @@ static inline void seccomp_sync_threads(void)
		 * allow one thread to transition the other.
		 */
		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. */
	if (flags & SECCOMP_FILTER_FLAG_TSYNC)
		seccomp_sync_threads();
		seccomp_sync_threads(flags);

	return 0;
}
@@ -835,7 +838,7 @@ static long seccomp_set_mode_strict(void)
#ifdef TIF_NOTSC
	disable_TSC();
#endif
	seccomp_assign_mode(current, seccomp_mode);
	seccomp_assign_mode(current, seccomp_mode, 0);
	ret = 0;

out:
@@ -893,7 +896,7 @@ static long seccomp_set_mode_filter(unsigned int flags,
	/* Do not free the successfully attached filter. */
	prepared = NULL;

	seccomp_assign_mode(current, seccomp_mode);
	seccomp_assign_mode(current, seccomp_mode, flags);
out:
	spin_unlock_irq(&current->sighand->siglock);
	if (flags & SECCOMP_FILTER_FLAG_TSYNC)
+19 −3
Original line number Diff line number Diff line
@@ -134,11 +134,15 @@ struct seccomp_data {
#endif

#ifndef SECCOMP_FILTER_FLAG_TSYNC
#define SECCOMP_FILTER_FLAG_TSYNC 1
#define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0)
#endif

#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

#ifndef PTRACE_SECCOMP_GET_METADATA
@@ -2072,14 +2076,26 @@ TEST(seccomp_syscall_mode_lock)
TEST(detect_seccomp_filter_flags)
{
	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;
	int i;
	long ret;

	/* Test detection of known-good filter flags */
	for (i = 0, all_flags = 0; i < ARRAY_SIZE(flags); i++) {
		int bits = 0;

		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);
		ASSERT_NE(ENOSYS, errno) {
			TH_LOG("Kernel does not support seccomp syscall!");