Skip to content

Commit 3e45213

Browse files
committed
selftests/bpf: more precise cpu_mitigations state detection
test_progs and test_verifier binaries execute unpriv tests under the following conditions: - unpriv BPF is enabled; - CPU mitigations are enabled (see [1] for details). The detection of the "mitigations enabled" state is performed by unpriv_helpers.c:get_mitigations_off() via inspecting kernel boot command line, looking for a parameter "mitigations=off". Such detection scheme won't work for certain configurations, e.g. when CONFIG_CPU_MIGITGATIONS is disabled and boot parameter is not supplied. Miss-detection leads to test_progs executing tests meant to be run only with mitigations enabled, e.g. verifier_and.c:known_subreg_with_unknown_reg(), and reporting false failures. Internally, verifier sets bpf_verifier_env->bypass_spec_{v1,v4} basing on the value returned by kernel/cpu.c:cpu_mitigations_off(). This function is backed by a variable kernel/cpu.c:cpu_mitigations. This state is not fully introspect-able via sysfs. The closest proxy is /sys/devices/system/cpu/vulnerabilities/spectre_v1, but it reports "vulnerable" state only if mitigations are disabled *and* current cpu is vulnerable, while verifier does not check cpu state. There are only two ways the kernel/cpu.c:cpu_mitigations can be set: - via boot parameter; - via CONFIG_CPU_MIGITGATIONS option. This commit updates unpriv_helpers.c:get_mitigations_off() to scan /proc/config.gz for CONFIG_CPU_MIGITGATIONS value in addition to boot command line check. Tested using the following configurations: - mitigations enabled (unpriv tests are enabled) - mitigations disabled via boot cmdline (unpriv tests skipped) - mitigations disabled via CONFIG_CPU_MIGITGATIONS (unpriv tests skipped) [1] https://lore.kernel.org/bpf/[email protected]/ Signed-off-by: Eduard Zingerman <[email protected]>
1 parent 2d72dd1 commit 3e45213

File tree

1 file changed

+43
-2
lines changed

1 file changed

+43
-2
lines changed

tools/testing/selftests/bpf/unpriv_helpers.c

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,46 @@
66
#include <string.h>
77
#include <unistd.h>
88
#include <fcntl.h>
9+
#include <zlib.h>
910

1011
#include "unpriv_helpers.h"
1112

12-
static bool get_mitigations_off(void)
13+
static bool scan_config(const char *pat)
14+
{
15+
bool ret = false;
16+
const char *msg;
17+
char buf[1024];
18+
gzFile config;
19+
int n, err;
20+
21+
config = gzopen("/proc/config.gz", "rb");
22+
if (!config) {
23+
perror("gzopen /proc/config.gz");
24+
goto out;
25+
}
26+
for (;;) {
27+
if (!gzgets(config, buf, sizeof(buf))) {
28+
msg = gzerror(config, &err);
29+
if (err == Z_ERRNO)
30+
perror("gzgets /proc/config.gz");
31+
else if (err != Z_OK)
32+
fprintf(stderr, "gzgets /proc/config.gz: %s", msg);
33+
goto out;
34+
}
35+
n = strlen(buf);
36+
if (buf[n - 1] == '\n')
37+
buf[n - 1] = 0;
38+
if (strcmp(buf, pat) == 0) {
39+
ret = true;
40+
goto out;
41+
}
42+
}
43+
out:
44+
gzclose(config);
45+
return ret;
46+
}
47+
48+
static bool scan_cmdline(const char *pat)
1349
{
1450
char cmdline[4096], *c;
1551
int fd, ret = false;
@@ -27,7 +63,7 @@ static bool get_mitigations_off(void)
2763

2864
cmdline[sizeof(cmdline) - 1] = '\0';
2965
for (c = strtok(cmdline, " \n"); c; c = strtok(NULL, " \n")) {
30-
if (strncmp(c, "mitigations=off", strlen(c)))
66+
if (strncmp(c, pat, strlen(c)))
3167
continue;
3268
ret = true;
3369
break;
@@ -37,6 +73,11 @@ static bool get_mitigations_off(void)
3773
return ret;
3874
}
3975

76+
static bool get_mitigations_off(void)
77+
{
78+
return scan_cmdline("mitigations=off") || !scan_config("CONFIG_CPU_MITIGATIONS=y");
79+
}
80+
4081
bool get_unpriv_disabled(void)
4182
{
4283
bool disabled;

0 commit comments

Comments
 (0)