|
Borislav Petkov |
902686 |
From: Josh Poimboeuf <jpoimboe@redhat.com>
|
|
Borislav Petkov |
902686 |
Date: Fri, 18 Feb 2022 11:49:08 -0800
|
|
Borislav Petkov |
902686 |
Subject: x86/speculation: Include unprivileged eBPF status in Spectre v2
|
|
Borislav Petkov |
902686 |
mitigation reporting
|
|
Borislav Petkov |
902686 |
Git-commit: 44a3918c8245ab10c6c9719dd12e7a8d291980d8
|
|
Borislav Petkov |
902686 |
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
|
|
Borislav Petkov |
902686 |
Patch-mainline: Queued in a subsystem tree
|
|
Borislav Petkov |
902686 |
References: bsc#1191580 CVE-2022-0001 CVE-2022-0002
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
With unprivileged eBPF enabled, eIBRS (without retpoline) is vulnerable
|
|
Borislav Petkov |
902686 |
to Spectre v2 BHB-based attacks.
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
When both are enabled, print a warning message and report it in the
|
|
Borislav Petkov |
902686 |
'spectre_v2' sysfs vulnerabilities file.
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
|
|
Borislav Petkov |
902686 |
Signed-off-by: Borislav Petkov <bp@suse.de>
|
|
Borislav Petkov |
902686 |
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Borislav Petkov |
902686 |
---
|
|
Borislav Petkov |
902686 |
arch/x86/kernel/cpu/bugs.c | 35 +++++++++++++++++++++++++++++------
|
|
Borislav Petkov |
902686 |
include/linux/bpf.h | 11 +++++++++++
|
|
Borislav Petkov |
902686 |
kernel/sysctl.c | 8 ++++++++
|
|
Borislav Petkov |
902686 |
3 files changed, 48 insertions(+), 6 deletions(-)
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
--- a/arch/x86/kernel/cpu/bugs.c
|
|
Borislav Petkov |
902686 |
+++ b/arch/x86/kernel/cpu/bugs.c
|
|
Borislav Petkov |
902686 |
@@ -14,6 +14,7 @@
|
|
Borislav Petkov |
902686 |
#include <linux/nospec.h>
|
|
Borislav Petkov |
902686 |
#include <linux/prctl.h>
|
|
Borislav Petkov |
902686 |
#include <linux/sched/smt.h>
|
|
Borislav Petkov |
902686 |
+#include <linux/bpf.h>
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
#include <asm/spec-ctrl.h>
|
|
Borislav Petkov |
902686 |
#include <asm/cmdline.h>
|
|
Borislav Petkov |
902686 |
@@ -637,6 +638,16 @@ static inline const char *spectre_v2_mod
|
|
Borislav Petkov |
902686 |
static inline const char *spectre_v2_module_string(void) { return ""; }
|
|
Borislav Petkov |
902686 |
#endif
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
+#define SPECTRE_V2_EIBRS_EBPF_MSG "WARNING: Unprivileged eBPF is enabled with eIBRS on, data leaks possible via Spectre v2 BHB attacks!\n"
|
|
Borislav Petkov |
902686 |
+
|
|
Borislav Petkov |
902686 |
+#ifdef CONFIG_BPF_SYSCALL
|
|
Borislav Petkov |
902686 |
+void unpriv_ebpf_notify(int new_state)
|
|
Borislav Petkov |
902686 |
+{
|
|
Borislav Petkov |
902686 |
+ if (spectre_v2_enabled == SPECTRE_V2_EIBRS && !new_state)
|
|
Borislav Petkov |
902686 |
+ pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
|
|
Borislav Petkov |
902686 |
+}
|
|
Borislav Petkov |
902686 |
+#endif
|
|
Borislav Petkov |
902686 |
+
|
|
Borislav Petkov |
902686 |
static inline bool match_option(const char *arg, int arglen, const char *opt)
|
|
Borislav Petkov |
902686 |
{
|
|
Borislav Petkov |
902686 |
int len = strlen(opt);
|
|
Borislav Petkov |
902686 |
@@ -971,6 +982,9 @@ static void __init spectre_v2_select_mit
|
|
Borislav Petkov |
902686 |
break;
|
|
Borislav Petkov |
902686 |
}
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
+ if (mode == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
|
|
Borislav Petkov |
902686 |
+ pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
|
|
Borislav Petkov |
902686 |
+
|
|
Borislav Petkov |
902686 |
if (spectre_v2_in_eibrs_mode(mode)) {
|
|
Borislav Petkov |
902686 |
/* Force it so VMEXIT will restore correctly */
|
|
Borislav Petkov |
902686 |
x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
|
|
Borislav Petkov |
902686 |
@@ -1578,6 +1592,20 @@ static char *ibpb_state(void)
|
|
Borislav Petkov |
902686 |
return "";
|
|
Borislav Petkov |
902686 |
}
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
+static ssize_t spectre_v2_show_state(char *buf)
|
|
Borislav Petkov |
902686 |
+{
|
|
Borislav Petkov |
902686 |
+ if (spectre_v2_enabled == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
|
|
Borislav Petkov |
902686 |
+ return sprintf(buf, "Vulnerable: Unprivileged eBPF enabled\n");
|
|
Borislav Petkov |
902686 |
+
|
|
Borislav Petkov |
902686 |
+ return sprintf(buf, "%s%s%s%s%s%s\n",
|
|
Borislav Petkov |
902686 |
+ spectre_v2_strings[spectre_v2_enabled],
|
|
Borislav Petkov |
902686 |
+ ibpb_state(),
|
|
Borislav Petkov |
902686 |
+ boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
|
|
Borislav Petkov |
902686 |
+ stibp_state(),
|
|
Borislav Petkov |
902686 |
+ boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
|
|
Borislav Petkov |
902686 |
+ spectre_v2_module_string());
|
|
Borislav Petkov |
902686 |
+}
|
|
Borislav Petkov |
902686 |
+
|
|
Borislav Petkov |
902686 |
static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
|
|
Borislav Petkov |
902686 |
char *buf, unsigned int bug)
|
|
Borislav Petkov |
902686 |
{
|
|
Borislav Petkov |
902686 |
@@ -1599,12 +1627,7 @@ static ssize_t cpu_show_common(struct de
|
|
Borislav Petkov |
902686 |
return sprintf(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]);
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
case X86_BUG_SPECTRE_V2:
|
|
Borislav Petkov |
902686 |
- return sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
|
|
Borislav Petkov |
902686 |
- ibpb_state(),
|
|
Borislav Petkov |
902686 |
- boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
|
|
Borislav Petkov |
902686 |
- stibp_state(),
|
|
Borislav Petkov |
902686 |
- boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
|
|
Borislav Petkov |
902686 |
- spectre_v2_module_string());
|
|
Borislav Petkov |
902686 |
+ return spectre_v2_show_state(buf);
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
case X86_BUG_SPEC_STORE_BYPASS:
|
|
Borislav Petkov |
902686 |
return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
|
|
Borislav Petkov |
902686 |
--- a/include/linux/bpf.h
|
|
Borislav Petkov |
902686 |
+++ b/include/linux/bpf.h
|
|
Borislav Petkov |
902686 |
@@ -529,6 +529,11 @@ static inline int bpf_map_attr_numa_node
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
struct bpf_prog *bpf_prog_get_type_path(const char *name, enum bpf_prog_type type);
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
+static inline bool unprivileged_ebpf_enabled(void)
|
|
Borislav Petkov |
902686 |
+{
|
|
Borislav Petkov |
902686 |
+ return !sysctl_unprivileged_bpf_disabled;
|
|
Borislav Petkov |
902686 |
+}
|
|
Borislav Petkov |
902686 |
+
|
|
Borislav Petkov |
902686 |
#else /* !CONFIG_BPF_SYSCALL */
|
|
Borislav Petkov |
902686 |
static inline struct bpf_prog *bpf_prog_get(u32 ufd)
|
|
Borislav Petkov |
902686 |
{
|
|
Borislav Petkov |
902686 |
@@ -582,6 +587,12 @@ static inline struct net_device *__dev_
|
|
Borislav Petkov |
902686 |
return NULL;
|
|
Borislav Petkov |
902686 |
}
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
+static inline bool unprivileged_ebpf_enabled(void)
|
|
Borislav Petkov |
902686 |
+{
|
|
Borislav Petkov |
902686 |
+ return false;
|
|
Borislav Petkov |
902686 |
+}
|
|
Borislav Petkov |
902686 |
+
|
|
Borislav Petkov |
902686 |
+
|
|
Borislav Petkov |
902686 |
static inline void __dev_map_insert_ctx(struct bpf_map *map, u32 index)
|
|
Borislav Petkov |
902686 |
{
|
|
Borislav Petkov |
902686 |
}
|
|
Borislav Petkov |
902686 |
--- a/kernel/sysctl.c
|
|
Borislav Petkov |
902686 |
+++ b/kernel/sysctl.c
|
|
Borislav Petkov |
902686 |
@@ -307,6 +307,11 @@ static int max_extfrag_threshold = 1000;
|
|
Borislav Petkov |
902686 |
#endif
|
|
Borislav Petkov |
902686 |
|
|
Borislav Petkov |
902686 |
#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_SYSCTL)
|
|
Borislav Petkov |
902686 |
+
|
|
Borislav Petkov |
902686 |
+void __weak unpriv_ebpf_notify(int new_state)
|
|
Borislav Petkov |
902686 |
+{
|
|
Borislav Petkov |
902686 |
+}
|
|
Borislav Petkov |
902686 |
+
|
|
Borislav Petkov |
902686 |
static int bpf_unpriv_handler(struct ctl_table *table, int write,
|
|
Borislav Petkov |
902686 |
void *buffer, size_t *lenp, loff_t *ppos)
|
|
Borislav Petkov |
902686 |
{
|
|
Borislav Petkov |
902686 |
@@ -324,6 +329,9 @@ static int bpf_unpriv_handler(struct ctl
|
|
Borislav Petkov |
902686 |
return -EPERM;
|
|
Borislav Petkov |
902686 |
*(int *)table->data = unpriv_enable;
|
|
Borislav Petkov |
902686 |
}
|
|
Borislav Petkov |
902686 |
+
|
|
Borislav Petkov |
902686 |
+ unpriv_ebpf_notify(unpriv_enable);
|
|
Borislav Petkov |
902686 |
+
|
|
Borislav Petkov |
902686 |
return ret;
|
|
Borislav Petkov |
902686 |
}
|
|
Borislav Petkov |
902686 |
#endif /* CONFIG_BPF_SYSCALL && CONFIG_SYSCTL */
|