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 */