提交 44a3918c 编写于 作者: J Josh Poimboeuf 提交者: Borislav Petkov

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

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: NJosh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: NBorislav Petkov <bp@suse.de>
Reviewed-by: NThomas Gleixner <tglx@linutronix.de>
上级 5ad3eb11
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/prctl.h> #include <linux/prctl.h>
#include <linux/sched/smt.h> #include <linux/sched/smt.h>
#include <linux/pgtable.h> #include <linux/pgtable.h>
#include <linux/bpf.h>
#include <asm/spec-ctrl.h> #include <asm/spec-ctrl.h>
#include <asm/cmdline.h> #include <asm/cmdline.h>
...@@ -650,6 +651,16 @@ static inline const char *spectre_v2_module_string(void) ...@@ -650,6 +651,16 @@ static inline const char *spectre_v2_module_string(void)
static inline const char *spectre_v2_module_string(void) { return ""; } static inline const char *spectre_v2_module_string(void) { return ""; }
#endif #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) static inline bool match_option(const char *arg, int arglen, const char *opt)
{ {
int len = strlen(opt); int len = strlen(opt);
...@@ -994,6 +1005,9 @@ static void __init spectre_v2_select_mitigation(void) ...@@ -994,6 +1005,9 @@ static void __init spectre_v2_select_mitigation(void)
break; break;
} }
if (mode == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
if (spectre_v2_in_eibrs_mode(mode)) { if (spectre_v2_in_eibrs_mode(mode)) {
/* Force it so VMEXIT will restore correctly */ /* Force it so VMEXIT will restore correctly */
x86_spec_ctrl_base |= SPEC_CTRL_IBRS; x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
...@@ -1780,6 +1794,20 @@ static char *ibpb_state(void) ...@@ -1780,6 +1794,20 @@ static char *ibpb_state(void)
return ""; 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) static ssize_t srbds_show_state(char *buf)
{ {
return sprintf(buf, "%s\n", srbds_strings[srbds_mitigation]); return sprintf(buf, "%s\n", srbds_strings[srbds_mitigation]);
...@@ -1805,12 +1833,7 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr ...@@ -1805,12 +1833,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]); return sprintf(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]);
case X86_BUG_SPECTRE_V2: case X86_BUG_SPECTRE_V2:
return sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled], return spectre_v2_show_state(buf);
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());
case X86_BUG_SPEC_STORE_BYPASS: case X86_BUG_SPEC_STORE_BYPASS:
return sprintf(buf, "%s\n", ssb_strings[ssb_mode]); return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
......
...@@ -1793,6 +1793,11 @@ struct bpf_core_ctx { ...@@ -1793,6 +1793,11 @@ struct bpf_core_ctx {
int bpf_core_apply(struct bpf_core_ctx *ctx, const struct bpf_core_relo *relo, int bpf_core_apply(struct bpf_core_ctx *ctx, const struct bpf_core_relo *relo,
int relo_idx, void *insn); int relo_idx, void *insn);
static inline bool unprivileged_ebpf_enabled(void)
{
return !sysctl_unprivileged_bpf_disabled;
}
#else /* !CONFIG_BPF_SYSCALL */ #else /* !CONFIG_BPF_SYSCALL */
static inline struct bpf_prog *bpf_prog_get(u32 ufd) static inline struct bpf_prog *bpf_prog_get(u32 ufd)
{ {
...@@ -2012,6 +2017,12 @@ bpf_jit_find_kfunc_model(const struct bpf_prog *prog, ...@@ -2012,6 +2017,12 @@ bpf_jit_find_kfunc_model(const struct bpf_prog *prog,
{ {
return NULL; return NULL;
} }
static inline bool unprivileged_ebpf_enabled(void)
{
return false;
}
#endif /* CONFIG_BPF_SYSCALL */ #endif /* CONFIG_BPF_SYSCALL */
void __bpf_free_used_btfs(struct bpf_prog_aux *aux, void __bpf_free_used_btfs(struct bpf_prog_aux *aux,
......
...@@ -180,6 +180,10 @@ static int bpf_stats_handler(struct ctl_table *table, int write, ...@@ -180,6 +180,10 @@ static int bpf_stats_handler(struct ctl_table *table, int write,
return ret; return ret;
} }
void __weak unpriv_ebpf_notify(int new_state)
{
}
static int bpf_unpriv_handler(struct ctl_table *table, int write, static int bpf_unpriv_handler(struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos) void *buffer, size_t *lenp, loff_t *ppos)
{ {
...@@ -197,6 +201,9 @@ static int bpf_unpriv_handler(struct ctl_table *table, int write, ...@@ -197,6 +201,9 @@ static int bpf_unpriv_handler(struct ctl_table *table, int write,
return -EPERM; return -EPERM;
*(int *)table->data = unpriv_enable; *(int *)table->data = unpriv_enable;
} }
unpriv_ebpf_notify(unpriv_enable);
return ret; return ret;
} }
#endif /* CONFIG_BPF_SYSCALL && CONFIG_SYSCTL */ #endif /* CONFIG_BPF_SYSCALL && CONFIG_SYSCTL */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册