// SPDX-License-Identifier: GPL-2.0-only #include #include #include #include #include #include #include #include #include #include #include "unpriv_helpers.h" static gzFile open_config(void) { struct utsname uts; char buf[PATH_MAX]; gzFile config; if (uname(&uts)) { perror("uname"); goto config_gz; } snprintf(buf, sizeof(buf), "/boot/config-%s", uts.release); config = gzopen(buf, "rb"); if (config) return config; fprintf(stderr, "gzopen %s: %s\n", buf, strerror(errno)); config_gz: config = gzopen("/proc/config.gz", "rb"); if (!config) perror("gzopen /proc/config.gz"); return config; } static int config_contains(const char *pat) { const char *msg; char buf[1024]; gzFile config; int n, err; config = open_config(); if (!config) return -1; for (;;) { if (!gzgets(config, buf, sizeof(buf))) { msg = gzerror(config, &err); if (err == Z_ERRNO) perror("gzgets /proc/config.gz"); else if (err != Z_OK) fprintf(stderr, "gzgets /proc/config.gz: %s", msg); gzclose(config); return -1; } n = strlen(buf); if (buf[n - 1] == '\n') buf[n - 1] = 0; if (strcmp(buf, pat) == 0) { gzclose(config); return 1; } } gzclose(config); return 0; } static bool cmdline_contains(const char *pat) { char cmdline[4096], *c; int fd, ret = false; fd = open("/proc/cmdline", O_RDONLY); if (fd < 0) { perror("open /proc/cmdline"); return false; } if (read(fd, cmdline, sizeof(cmdline) - 1) < 0) { perror("read /proc/cmdline"); goto out; } cmdline[sizeof(cmdline) - 1] = '\0'; for (c = strtok(cmdline, " \n"); c; c = strtok(NULL, " \n")) { if (strncmp(c, pat, strlen(c))) continue; ret = true; break; } out: close(fd); return ret; } static int get_mitigations_off(void) { int enabled_in_config; if (cmdline_contains("mitigations=off")) return 1; enabled_in_config = config_contains("CONFIG_CPU_MITIGATIONS=y"); if (enabled_in_config < 0) return -1; return !enabled_in_config; } bool get_unpriv_disabled(void) { int mitigations_off; bool disabled; char buf[2]; FILE *fd; fd = fopen("/proc/sys/" UNPRIV_SYSCTL, "r"); if (fd) { disabled = (fgets(buf, 2, fd) == buf && atoi(buf)); fclose(fd); } else { perror("fopen /proc/sys/" UNPRIV_SYSCTL); disabled = true; } if (disabled) return true; /* * Some unpriv tests rely on spectre mitigations being on. * If mitigations are off or status can't be determined * assume that unpriv tests are disabled. */ mitigations_off = get_mitigations_off(); if (mitigations_off < 0) { fprintf(stderr, "Can't determine if mitigations are enabled, disabling unpriv tests."); return true; } return mitigations_off; }