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

Commit 6481835a authored by Josh Poimboeuf's avatar Josh Poimboeuf Committed by Greg Kroah-Hartman
Browse files

x86/speculation: Include unprivileged eBPF status in Spectre v2 mitigation reporting



commit 44a3918c8245ab10c6c9719dd12e7a8d291980d8 upstream.

With unprivileged eBPF enabled, eIBRS (without retpoline) is vulnerable
to Spectre v2 BHB-based attacks.

When both are enabled, print a warning message and report it in the
'spectre_v2' sysfs vulnerabilities file.

Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.de>
[fllinden@amazon.com: backported to 4.19]
Signed-off-by: default avatarFrank van der Linden <fllinden@amazon.com>
[bwh: Backported to 4.9: adjust context]
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f9238d33
Loading
Loading
Loading
Loading
+29 −6
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <asm/cacheflush.h>
#include <asm/intel-family.h>
#include <asm/e820.h>
#include <linux/bpf.h>

#include "cpu.h"

@@ -606,6 +607,16 @@ static inline const char *spectre_v2_module_string(void)
static inline const char *spectre_v2_module_string(void) { return ""; }
#endif

#define SPECTRE_V2_EIBRS_EBPF_MSG "WARNING: Unprivileged eBPF is enabled with eIBRS on, data leaks possible via Spectre v2 BHB attacks!\n"

#ifdef CONFIG_BPF_SYSCALL
void unpriv_ebpf_notify(int new_state)
{
	if (spectre_v2_enabled == SPECTRE_V2_EIBRS && !new_state)
		pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
}
#endif

static inline bool match_option(const char *arg, int arglen, const char *opt)
{
	int len = strlen(opt);
@@ -949,6 +960,9 @@ static void __init spectre_v2_select_mitigation(void)
		break;
	}

	if (mode == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
		pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);

	if (spectre_v2_in_eibrs_mode(mode)) {
		/* Force it so VMEXIT will restore correctly */
		x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
@@ -1686,6 +1700,20 @@ static char *ibpb_state(void)
	return "";
}

static ssize_t spectre_v2_show_state(char *buf)
{
	if (spectre_v2_enabled == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
		return sprintf(buf, "Vulnerable: Unprivileged eBPF enabled\n");

	return sprintf(buf, "%s%s%s%s%s%s\n",
		       spectre_v2_strings[spectre_v2_enabled],
		       ibpb_state(),
		       boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
		       stibp_state(),
		       boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
		       spectre_v2_module_string());
}

static ssize_t srbds_show_state(char *buf)
{
	return sprintf(buf, "%s\n", srbds_strings[srbds_mitigation]);
@@ -1708,12 +1736,7 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
		return sprintf(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]);

	case X86_BUG_SPECTRE_V2:
		return sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
			       ibpb_state(),
			       boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
			       stibp_state(),
			       boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
			       spectre_v2_module_string());
		return spectre_v2_show_state(buf);

	case X86_BUG_SPEC_STORE_BYPASS:
		return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
+11 −0
Original line number Diff line number Diff line
@@ -295,6 +295,11 @@ static inline void bpf_long_memcpy(void *dst, const void *src, u32 size)

/* verify correctness of eBPF program */
int bpf_check(struct bpf_prog **fp, union bpf_attr *attr);

static inline bool unprivileged_ebpf_enabled(void)
{
	return !sysctl_unprivileged_bpf_disabled;
}
#else
static inline void bpf_register_prog_type(struct bpf_prog_type_list *tl)
{
@@ -322,6 +327,12 @@ static inline struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
{
	return ERR_PTR(-EOPNOTSUPP);
}

static inline bool unprivileged_ebpf_enabled(void)
{
	return false;
}

#endif /* CONFIG_BPF_SYSCALL */

/* verifier prototypes for helper functions called from eBPF programs */
+8 −0
Original line number Diff line number Diff line
@@ -222,6 +222,11 @@ static int sysrq_sysctl_handler(struct ctl_table *table, int write,
#endif

#ifdef CONFIG_BPF_SYSCALL

void __weak unpriv_ebpf_notify(int new_state)
{
}

static int bpf_unpriv_handler(struct ctl_table *table, int write,
                             void *buffer, size_t *lenp, loff_t *ppos)
{
@@ -239,6 +244,9 @@ static int bpf_unpriv_handler(struct ctl_table *table, int write,
			return -EPERM;
		*(int *)table->data = unpriv_enable;
	}

	unpriv_ebpf_notify(unpriv_enable);

	return ret;
}
#endif