]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
f5f42eebd481bbc8dbb2b9dbf97d9b1f94e392c2
[thirdparty/kernel/stable-queue.git] /
1 From foo@baz Tue Mar 8 07:44:38 PM CET 2022
2 From: Josh Poimboeuf <jpoimboe@redhat.com>
3 Date: Fri, 18 Feb 2022 11:49:08 -0800
4 Subject: x86/speculation: Include unprivileged eBPF status in Spectre v2 mitigation reporting
5
6 From: Josh Poimboeuf <jpoimboe@redhat.com>
7
8 commit 44a3918c8245ab10c6c9719dd12e7a8d291980d8 upstream.
9
10 With unprivileged eBPF enabled, eIBRS (without retpoline) is vulnerable
11 to Spectre v2 BHB-based attacks.
12
13 When both are enabled, print a warning message and report it in the
14 'spectre_v2' sysfs vulnerabilities file.
15
16 Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
17 Signed-off-by: Borislav Petkov <bp@suse.de>
18 Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
19 [fllinden@amazon.com: backported to 5.10]
20 Signed-off-by: Frank van der Linden <fllinden@amazon.com>
21 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
22 ---
23 arch/x86/kernel/cpu/bugs.c | 35 +++++++++++++++++++++++++++++------
24 include/linux/bpf.h | 12 ++++++++++++
25 kernel/sysctl.c | 7 +++++++
26 3 files changed, 48 insertions(+), 6 deletions(-)
27
28 --- a/arch/x86/kernel/cpu/bugs.c
29 +++ b/arch/x86/kernel/cpu/bugs.c
30 @@ -16,6 +16,7 @@
31 #include <linux/prctl.h>
32 #include <linux/sched/smt.h>
33 #include <linux/pgtable.h>
34 +#include <linux/bpf.h>
35
36 #include <asm/spec-ctrl.h>
37 #include <asm/cmdline.h>
38 @@ -613,6 +614,16 @@ static inline const char *spectre_v2_mod
39 static inline const char *spectre_v2_module_string(void) { return ""; }
40 #endif
41
42 +#define SPECTRE_V2_EIBRS_EBPF_MSG "WARNING: Unprivileged eBPF is enabled with eIBRS on, data leaks possible via Spectre v2 BHB attacks!\n"
43 +
44 +#ifdef CONFIG_BPF_SYSCALL
45 +void unpriv_ebpf_notify(int new_state)
46 +{
47 + if (spectre_v2_enabled == SPECTRE_V2_EIBRS && !new_state)
48 + pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
49 +}
50 +#endif
51 +
52 static inline bool match_option(const char *arg, int arglen, const char *opt)
53 {
54 int len = strlen(opt);
55 @@ -957,6 +968,9 @@ static void __init spectre_v2_select_mit
56 break;
57 }
58
59 + if (mode == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
60 + pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
61 +
62 if (spectre_v2_in_eibrs_mode(mode)) {
63 /* Force it so VMEXIT will restore correctly */
64 x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
65 @@ -1710,6 +1724,20 @@ static char *ibpb_state(void)
66 return "";
67 }
68
69 +static ssize_t spectre_v2_show_state(char *buf)
70 +{
71 + if (spectre_v2_enabled == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
72 + return sprintf(buf, "Vulnerable: Unprivileged eBPF enabled\n");
73 +
74 + return sprintf(buf, "%s%s%s%s%s%s\n",
75 + spectre_v2_strings[spectre_v2_enabled],
76 + ibpb_state(),
77 + boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
78 + stibp_state(),
79 + boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
80 + spectre_v2_module_string());
81 +}
82 +
83 static ssize_t srbds_show_state(char *buf)
84 {
85 return sprintf(buf, "%s\n", srbds_strings[srbds_mitigation]);
86 @@ -1735,12 +1763,7 @@ static ssize_t cpu_show_common(struct de
87 return sprintf(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]);
88
89 case X86_BUG_SPECTRE_V2:
90 - return sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
91 - ibpb_state(),
92 - boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
93 - stibp_state(),
94 - boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
95 - spectre_v2_module_string());
96 + return spectre_v2_show_state(buf);
97
98 case X86_BUG_SPEC_STORE_BYPASS:
99 return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
100 --- a/include/linux/bpf.h
101 +++ b/include/linux/bpf.h
102 @@ -1485,6 +1485,12 @@ struct bpf_prog *bpf_prog_by_id(u32 id);
103 struct bpf_link *bpf_link_by_id(u32 id);
104
105 const struct bpf_func_proto *bpf_base_func_proto(enum bpf_func_id func_id);
106 +
107 +static inline bool unprivileged_ebpf_enabled(void)
108 +{
109 + return !sysctl_unprivileged_bpf_disabled;
110 +}
111 +
112 #else /* !CONFIG_BPF_SYSCALL */
113 static inline struct bpf_prog *bpf_prog_get(u32 ufd)
114 {
115 @@ -1679,6 +1685,12 @@ bpf_base_func_proto(enum bpf_func_id fun
116 {
117 return NULL;
118 }
119 +
120 +static inline bool unprivileged_ebpf_enabled(void)
121 +{
122 + return false;
123 +}
124 +
125 #endif /* CONFIG_BPF_SYSCALL */
126
127 static inline struct bpf_prog *bpf_prog_get_type(u32 ufd,
128 --- a/kernel/sysctl.c
129 +++ b/kernel/sysctl.c
130 @@ -234,6 +234,10 @@ static int bpf_stats_handler(struct ctl_
131 return ret;
132 }
133
134 +void __weak unpriv_ebpf_notify(int new_state)
135 +{
136 +}
137 +
138 static int bpf_unpriv_handler(struct ctl_table *table, int write,
139 void *buffer, size_t *lenp, loff_t *ppos)
140 {
141 @@ -251,6 +255,9 @@ static int bpf_unpriv_handler(struct ctl
142 return -EPERM;
143 *(int *)table->data = unpriv_enable;
144 }
145 +
146 + unpriv_ebpf_notify(unpriv_enable);
147 +
148 return ret;
149 }
150 #endif /* CONFIG_BPF_SYSCALL && CONFIG_SYSCTL */