From e67c9e42653c2d6b50f54caa6f513d38ca50d59a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lesimple?= Date: Fri, 10 Apr 2026 19:26:46 +0200 Subject: [PATCH] enh: use g_mode to explicitly save/load the current running mode --- DEVELOPMENT.md | 14 +-- dist/doc/batch_prometheus.md | 18 ++-- src/libs/002_core_globals.sh | 7 ++ src/libs/230_util_optparse.sh | 13 +++ src/libs/250_output_emitters.sh | 17 +-- src/libs/400_hw_check.sh | 26 ++--- src/main.sh | 34 +++--- src/vulns-helpers/check_mds.sh | 12 +-- src/vulns-helpers/check_mmio.sh | 4 +- src/vulns/CVE-2017-5715.sh | 24 ++--- src/vulns/CVE-2017-5753.sh | 186 +++++++++++++++----------------- src/vulns/CVE-2017-5754.sh | 6 +- src/vulns/CVE-2018-12207.sh | 4 +- src/vulns/CVE-2018-3620.sh | 4 +- src/vulns/CVE-2018-3639.sh | 6 +- src/vulns/CVE-2018-3646.sh | 21 ++-- src/vulns/CVE-2019-11135.sh | 4 +- src/vulns/CVE-2020-0543.sh | 6 +- src/vulns/CVE-2022-29900.sh | 4 +- src/vulns/CVE-2022-29901.sh | 4 +- src/vulns/CVE-2022-40982.sh | 2 +- src/vulns/CVE-2023-20588.sh | 4 +- src/vulns/CVE-2023-20593.sh | 4 +- src/vulns/CVE-2023-28746.sh | 4 +- 24 files changed, 218 insertions(+), 210 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 72d7470..82af7bd 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -118,7 +118,7 @@ The entire tool is a single bash script with no external script dependencies. Ke Two JSON formats are available via `--batch`: - **`--batch json`** (comprehensive): A top-level object with five sections: - - `meta` — script version, format version, timestamp, run mode flags (`run_as_root`, `reduced_accuracy`, `mocked`, `paranoid`, `sysfs_only`, `extra`) + - `meta` — script version, format version, timestamp, `mode` (`live`, `no-runtime`, `no-hw`, `hw-only`), run mode flags (`run_as_root`, `reduced_accuracy`, `mocked`, `paranoid`, `sysfs_only`, `extra`) - `system` — kernel release/version/arch/cmdline, CPU count, SMT status, hypervisor host detection - `cpu` — `arch` discriminator (`x86` or `arm`), vendor, friendly name, then an arch-specific sub-object (`cpu.x86` or `cpu.arm`) with identification fields (family/model/stepping/CPUID/codename for x86; part\_list/arch\_list for ARM) and a `capabilities` sub-object containing hardware flags as booleans/nulls - `cpu_microcode` — `installed_version`, `latest_version`, `microcode_up_to_date`, `is_blacklisted`, firmware DB source/info @@ -161,7 +161,7 @@ This works because the kernel always has direct access to CPUID (it doesn't need **Rules:** - This is strictly a fallback: `read_cpuid` via `/dev/cpu/N/cpuid` remains the primary method. - Only use it when `read_cpuid` returned `READ_CPUID_RET_ERR` (device unavailable), **never** when it returned `READ_CPUID_RET_KO` (device available but bit is 0 — meaning the CPU/hypervisor explicitly reports the feature as absent). -- Only in live mode (`$opt_runtime = 1`), since `/proc/cpuinfo` is not available in no-runtime mode. +- Only in live mode (`$g_mode = live`), since `/proc/cpuinfo` is not available in other modes. - Only for CPUID bits that the kernel exposes as `/proc/cpuinfo` flags. Not all bits have a corresponding flag — only those listed in the kernel's `capflags.c`. If a bit has no `/proc/cpuinfo` flag, no fallback is possible. - The fallback depends on the running kernel being recent enough to know about the CPUID bit in question. An older kernel won't expose a flag it doesn't know about, so the fallback will silently not trigger — which is fine (we just stay at UNKNOWN, same as the ERR case without fallback). @@ -184,7 +184,7 @@ read_cpuid 0x7 0x0 $EDX 31 1 1 ret=$? if [ $ret = $READ_CPUID_RET_OK ]; then cap_ssbd='Intel SSBD' -elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ]; then +elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$g_mode" = live ]; then # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then cap_ssbd='Intel SSBD (cpuinfo)' @@ -417,16 +417,16 @@ This is where the real detection lives. Check for mitigations at each layer: ``` The same applies to Phase 4 verdict messages: when the explanation or remediation advice differs between architectures (e.g. "CPU microcode update" vs "firmware/kernel update"), branch on `is_arm_kernel`/`is_x86_kernel` rather than on `cpu_vendor`, because `cpu_vendor` reflects the host, not the target kernel. -- **Runtime state** (live mode only): Read MSRs, check cpuinfo flags, parse dmesg, inspect debugfs. All runtime-only checks — including `/proc/cpuinfo` flags — must be guarded by `if [ "$opt_runtime" = 1 ]`, both when collecting the evidence in Phase 2 and when using it in Phase 4. In Phase 4, use explicit live/no-runtime branches so that live-only variables (e.g. cpuinfo flags, MSR values) are never referenced in the no-runtime path. +- **Runtime state** (live mode only): Read MSRs, check cpuinfo flags, parse dmesg, inspect debugfs. All runtime-only checks — including `/proc/cpuinfo` flags — must be guarded by `if [ "$g_mode" = live ]`, both when collecting the evidence in Phase 2 and when using it in Phase 4. In Phase 4, use explicit live/non-live branches so that live-only variables (e.g. cpuinfo flags, MSR values) are never referenced in the non-live path. ```sh - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then read_msr 0xADDRESS ret=$? if [ "$ret" = "$READ_MSR_RET_OK" ]; then # check specific bits in ret_read_msr_value_lo / ret_read_msr_value_hi fi else - pstatus blue N/A "not testable in no-runtime mode" + pstatus blue N/A "not testable in non-live mode" fi ``` @@ -811,7 +811,7 @@ CVEs that need VMM context should call `check_has_vmm` early in their `_linux()` - **Never hardcode kernel or microcode versions** - detect capabilities directly (design principles 2 and 3). Exception: when a microcode fix has no detectable indicator, hardcode fixing versions per CPU (see principle 3). - **Assume affected by default** - only mark a CPU as unaffected when there is positive evidence (design principle 4). -- **Always handle both live and no-runtime modes** - use `$opt_runtime` to branch, and print `N/A "not testable in no-runtime mode"` for runtime-only checks when in no-runtime mode. +- **Always handle both live and non-live modes** — use `$g_mode` to branch (`if [ "$g_mode" = live ]`), and print `N/A "not testable in non-live mode"` for runtime-only checks when not in live mode. Inside CVE checks, `live` is the only mode with runtime access (hw-only skips the CVE loop). Outside CVE checks (e.g. `check_cpu`), use the `has_runtime` helper which returns true for both `live` and `hw-only`. - **Use `explain()`** when reporting VULN to give actionable remediation advice (see "Cross-Cutting Features" above). - **Handle `--paranoid` and `--vmm`** when the CVE has stricter mitigation tiers or VMM-specific aspects (see "Cross-Cutting Features" above). - **Keep JSON output in sync** - when adding new `cap_*` variables, add them to `_build_json_cpu()` in `src/libs/250_output_emitters.sh` (see Step 2 JSON note above). Per-CVE fields are handled automatically. diff --git a/dist/doc/batch_prometheus.md b/dist/doc/batch_prometheus.md index 353b4fa..cd13c5a 100644 --- a/dist/doc/batch_prometheus.md +++ b/dist/doc/batch_prometheus.md @@ -59,7 +59,7 @@ Script metadata. Always value `1`; all data is in labels. | Label | Values | Meaning | |---|---|---| | `version` | string | Script version (e.g. `25.30.0250400123`) | -| `mode` | `live` / `offline` | `live` = running on the active kernel; `offline` = inspecting a kernel image | +| `mode` | `live` / `no-runtime` / `no-hw` / `hw-only` | Operating mode (see below) | | `run_as_root` | `true` / `false` | Whether the script ran as root. Non-root scans skip MSR reads and may miss mitigations | | `paranoid` | `true` / `false` | `--paranoid` mode: stricter criteria (e.g. requires SMT disabled) | | `sysfs_only` | `true` / `false` | `--sysfs-only` mode: only the kernel's own sysfs report was used, not independent detection | @@ -340,16 +340,22 @@ smc_vulnerability_status == 1 ## Caveats and edge cases -**Offline mode (`--kernel`)** +**No-runtime mode (`--no-runtime`)** `smc_system_info` will have no `kernel_release` or `kernel_arch` labels (those come from `uname`, which reports the running kernel, not the inspected one). -`mode="offline"` in `smc_build_info` signals this. Offline mode is primarily -useful for pre-deployment auditing, not fleet runtime monitoring. +`mode="no-runtime"` in `smc_build_info` signals this. No-runtime mode is +primarily useful for pre-deployment auditing, not fleet runtime monitoring. -**`--no-hw`** +**No-hardware mode (`--no-hw`)** `smc_cpu_info` is not emitted. CPU and microcode labels are absent from all queries. CVE checks that rely on hardware capability detection (`cap_*` flags, -MSR reads) will report `unknown` status. +MSR reads) will report `unknown` status. `mode="no-hw"` in `smc_build_info` +signals this. + +**Hardware-only mode (`--hw-only`)** +Only hardware detection is performed; CVE checks are skipped. `smc_cpu_info` +is emitted but no `smc_vuln` metrics appear. `mode="hw-only"` in +`smc_build_info` signals this. **`--sysfs-only`** The script trusts the kernel's sysfs report (`/sys/devices/system/cpu/vulnerabilities/`) diff --git a/src/libs/002_core_globals.sh b/src/libs/002_core_globals.sh index ab5f7f6..96d8710 100644 --- a/src/libs/002_core_globals.sh +++ b/src/libs/002_core_globals.sh @@ -125,6 +125,13 @@ opt_vmm=-1 opt_allow_msr_write=0 opt_cpu=0 opt_explain=0 +# Canonical run mode, set at the end of option parsing. +# Values: live, no-runtime, no-hw, hw-only +g_mode='live' + +# Return 0 (true) if runtime state is accessible (procfs, sysfs, dmesg, debugfs). +# True in live and hw-only modes; false in no-runtime and no-hw modes. +has_runtime() { [ "$g_mode" = live ] || [ "$g_mode" = hw-only ]; } opt_paranoid=0 opt_extra=0 opt_mock=0 diff --git a/src/libs/230_util_optparse.sh b/src/libs/230_util_optparse.sh index d40b04f..b327209 100644 --- a/src/libs/230_util_optparse.sh +++ b/src/libs/230_util_optparse.sh @@ -344,3 +344,16 @@ if [ "$opt_runtime" = 0 ] && [ -z "$opt_kernel" ] && [ -z "$opt_config" ] && [ - pr_warn "Option --no-runtime requires at least one of --kernel, --config, or --map" exit 255 fi + +# Derive the canonical run mode from the option flags. +# Modes: live (default), no-runtime (--no-runtime), no-hw (--no-hw), hw-only (--hw-only) +# shellcheck disable=SC2034 +if [ "$opt_hw_only" = 1 ]; then + g_mode='hw-only' +elif [ "$opt_no_hw" = 1 ]; then + g_mode='no-hw' +elif [ "$opt_runtime" = 0 ]; then + g_mode='no-runtime' +else + g_mode='live' +fi diff --git a/src/libs/250_output_emitters.sh b/src/libs/250_output_emitters.sh index c77fce8..b75db13 100644 --- a/src/libs/250_output_emitters.sh +++ b/src/libs/250_output_emitters.sh @@ -66,17 +66,8 @@ _json_bool() { # Sets: g_json_meta # shellcheck disable=SC2034 _build_json_meta() { - local timestamp mode + local timestamp timestamp=$(date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || echo "unknown") - if [ "$opt_hw_only" = 1 ]; then - mode="hw-only" - elif [ "$opt_no_hw" = 1 ]; then - mode="no-hw" - elif [ "$opt_runtime" = 0 ]; then - mode="no-runtime" - else - mode="live" - fi local run_as_root if [ "$(id -u)" -eq 0 ]; then run_as_root='true' @@ -87,7 +78,7 @@ _build_json_meta() { "$(_json_str "$VERSION")" \ "$(_json_str "$timestamp")" \ "$(_json_str "$g_os")" \ - "$mode" \ + "$g_mode" \ "$run_as_root" \ "$(_json_bool "${g_bad_accuracy:-0}")" \ "$(_json_bool "$opt_paranoid")" \ @@ -100,7 +91,7 @@ _build_json_meta() { # shellcheck disable=SC2034 _build_json_system() { local kernel_release kernel_version kernel_arch smt_val - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then kernel_release=$(uname -r) kernel_version=$(uname -v) kernel_arch=$(uname -m) @@ -404,7 +395,7 @@ _emit_prometheus() { # shellcheck disable=SC2034 _build_prometheus_system_info() { local kernel_release kernel_arch hypervisor_host sys_labels - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then kernel_release=$(uname -r 2>/dev/null || true) kernel_arch=$(uname -m 2>/dev/null || true) else diff --git a/src/libs/400_hw_check.sh b/src/libs/400_hw_check.sh index f923b36..66b6d1e 100644 --- a/src/libs/400_hw_check.sh +++ b/src/libs/400_hw_check.sh @@ -18,7 +18,7 @@ if [ "$g_os" = Darwin ] || [ "$g_os" = VMkernel ]; then fi # check for mode selection inconsistency -if [ "$opt_hw_only" = 1 ]; then +if [ "$g_mode" = hw-only ]; then if [ "$opt_cve_all" = 0 ]; then show_usage echo "$0: error: incompatible modes specified, --hw-only vs --variant" >&2 @@ -89,7 +89,7 @@ if [ "$opt_cpu" != all ] && [ "$opt_cpu" -gt "$g_max_core_id" ]; then exit 255 fi -if [ "$opt_runtime" = 1 ]; then +if has_runtime; then pr_info "Checking for vulnerabilities on current system" # try to find the image of the current running kernel @@ -226,7 +226,7 @@ if [ -e "$opt_kernel" ]; then if ! command -v "${opt_arch_prefix}readelf" >/dev/null 2>&1; then pr_debug "readelf not found" g_kernel_err="missing '${opt_arch_prefix}readelf' tool, please install it, usually it's in the 'binutils' package" - elif [ "$opt_sysfs_only" = 1 ] || [ "$opt_hw_only" = 1 ]; then + elif [ "$opt_sysfs_only" = 1 ] || [ "$g_mode" = hw-only ]; then g_kernel_err='kernel image decompression skipped' else extract_kernel "$opt_kernel" @@ -251,7 +251,7 @@ else fi if [ -n "$g_kernel_version" ]; then # in live mode, check if the img we found is the correct one - if [ "$opt_runtime" = 1 ]; then + if has_runtime; then pr_verbose "Kernel image is \033[35m$g_kernel_version" if ! echo "$g_kernel_version" | grep -qF "$(uname -r)"; then pr_warn "Possible discrepancy between your running kernel '$(uname -r)' and the image '$g_kernel_version' we found ($opt_kernel), results might be incorrect" @@ -283,7 +283,7 @@ sys_interface_check() { msg='' ret_sys_interface_check_fullmsg='' - if [ "$opt_runtime" = 1 ] && [ "$opt_no_sysfs" = 0 ] && [ -r "$file" ]; then + if has_runtime && [ "$opt_no_sysfs" = 0 ] && [ -r "$file" ]; then : else g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_SYSFS_$(basename "$file")_RET=1") @@ -352,7 +352,7 @@ sys_interface_check() { check_kernel_info() { local config_display pr_info "\033[1;34mKernel information\033[0m" - if [ "$opt_runtime" = 1 ]; then + if has_runtime; then pr_info "* Kernel is \033[35m$g_os $(uname -r) $(uname -v) $(uname -m)\033[0m" elif [ -n "$g_kernel_version" ]; then pr_info "* Kernel is \033[35m$g_kernel_version\033[0m" @@ -456,7 +456,7 @@ check_cpu() { ret=invalid pstatus yellow NO "unknown CPU" fi - if [ -z "$cap_ibrs" ] && [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ]; then + if [ -z "$cap_ibrs" ] && [ $ret = $READ_CPUID_RET_ERR ] && has_runtime; then # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo if grep ^flags "$g_procfs/cpuinfo" | grep -qw ibrs; then cap_ibrs='IBRS (cpuinfo)' @@ -533,7 +533,7 @@ check_cpu() { if [ $ret = $READ_CPUID_RET_OK ]; then cap_ibpb='IBPB_SUPPORT' pstatus green YES "IBPB_SUPPORT feature bit" - elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw ibpb; then + elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw ibpb; then # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo cap_ibpb='IBPB (cpuinfo)' pstatus green YES "ibpb flag in $g_procfs/cpuinfo" @@ -604,7 +604,7 @@ check_cpu() { ret=invalid pstatus yellow UNKNOWN "unknown CPU" fi - if [ -z "$cap_stibp" ] && [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ]; then + if [ -z "$cap_stibp" ] && [ $ret = $READ_CPUID_RET_ERR ] && has_runtime; then # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo if grep ^flags "$g_procfs/cpuinfo" | grep -qw stibp; then cap_stibp='STIBP (cpuinfo)' @@ -676,7 +676,7 @@ check_cpu() { fi fi - if [ -z "$cap_ssbd" ] && [ "$ret24" = $READ_CPUID_RET_ERR ] && [ "$ret25" = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ]; then + if [ -z "$cap_ssbd" ] && [ "$ret24" = $READ_CPUID_RET_ERR ] && [ "$ret25" = $READ_CPUID_RET_ERR ] && has_runtime; then # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then cap_ssbd='SSBD (cpuinfo)' @@ -740,7 +740,7 @@ check_cpu() { if [ $ret = $READ_CPUID_RET_OK ]; then pstatus green YES "L1D flush feature bit" cap_l1df=1 - elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw flush_l1d; then + elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw flush_l1d; then # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo pstatus green YES "flush_l1d flag in $g_procfs/cpuinfo" cap_l1df=1 @@ -760,7 +760,7 @@ check_cpu() { if [ $ret = $READ_CPUID_RET_OK ]; then cap_md_clear=1 pstatus green YES "MD_CLEAR feature bit" - elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw md_clear; then + elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw md_clear; then # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo cap_md_clear=1 pstatus green YES "md_clear flag in $g_procfs/cpuinfo" @@ -830,7 +830,7 @@ check_cpu() { if [ $ret = $READ_CPUID_RET_OK ]; then pstatus green YES cap_arch_capabilities=1 - elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw arch_capabilities; then + elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw arch_capabilities; then # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo pstatus green YES "arch_capabilities flag in $g_procfs/cpuinfo" cap_arch_capabilities=1 diff --git a/src/main.sh b/src/main.sh index 1f8d546..6be69cb 100644 --- a/src/main.sh +++ b/src/main.sh @@ -14,7 +14,7 @@ fi pr_info -if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then +if [ "$g_mode" != no-hw ] && [ -z "$opt_arch_prefix" ]; then pr_info "\033[1;34mHardware check\033[0m" check_cpu check_cpu_vulnerabilities @@ -24,7 +24,7 @@ fi # Build JSON system/cpu/microcode sections (after check_cpu has populated cap_* vars and VMM detection) if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json" ]; then _build_json_system - if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then + if [ "$g_mode" != no-hw ] && [ -z "$opt_arch_prefix" ]; then _build_json_cpu _build_json_cpu_microcode fi @@ -33,18 +33,22 @@ fi # Build Prometheus info metric lines (same timing requirement as JSON builders above) if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "prometheus" ]; then _build_prometheus_system_info - if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then + if [ "$g_mode" != no-hw ] && [ -z "$opt_arch_prefix" ]; then _build_prometheus_cpu_info fi fi -# now run the checks the user asked for -for cve in $g_supported_cve_list; do - if [ "$opt_cve_all" = 1 ] || echo "$opt_cve_list" | grep -qw "$cve"; then - check_"$(echo "$cve" | tr - _)" - pr_info - fi -done +# now run the checks the user asked for (hw-only mode skips CVE checks) +if [ "$g_mode" = hw-only ]; then + pr_info "Hardware-only mode, skipping vulnerability checks" +else + for cve in $g_supported_cve_list; do + if [ "$opt_cve_all" = 1 ] || echo "$opt_cve_list" | grep -qw "$cve"; then + check_"$(echo "$cve" | tr - _)" + pr_info + fi + done +fi # g_mode != hw-only if [ -n "$g_final_summary" ]; then pr_info "> \033[46m\033[30mSUMMARY:\033[0m$g_final_summary" @@ -171,15 +175,7 @@ fi if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "prometheus" ]; then prom_run_as_root='false' [ "$(id -u)" -eq 0 ] && prom_run_as_root='true' - if [ "$opt_hw_only" = 1 ]; then - prom_mode='hw-only' - elif [ "$opt_no_hw" = 1 ]; then - prom_mode='no-hw' - elif [ "$opt_runtime" = 0 ]; then - prom_mode='no-runtime' - else - prom_mode='live' - fi + prom_mode="$g_mode" prom_paranoid='false' [ "$opt_paranoid" = 1 ] && prom_paranoid='true' prom_sysfs_only='false' diff --git a/src/vulns-helpers/check_mds.sh b/src/vulns-helpers/check_mds.sh index 09b273e..e45c27b 100644 --- a/src/vulns-helpers/check_mds.sh +++ b/src/vulns-helpers/check_mds.sh @@ -3,7 +3,7 @@ check_mds_bsd() { local kernel_md_clear kernel_smt_allowed kernel_mds_enabled kernel_mds_state pr_info_nol "* Kernel supports using MD_CLEAR mitigation: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if sysctl hw.mds_disable >/dev/null 2>&1; then pstatus green YES kernel_md_clear=1 @@ -76,7 +76,7 @@ check_mds_bsd() { else if [ "$cap_md_clear" = 1 ]; then if [ "$kernel_md_clear" = 1 ]; then - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # mitigation must also be enabled if [ "$kernel_mds_enabled" -ge 1 ]; then if [ "$opt_paranoid" != 1 ] || [ "$kernel_smt_allowed" = 0 ]; then @@ -95,7 +95,7 @@ check_mds_bsd() { pvulnstatus "$cve" VULN "Your microcode supports mitigation, but your kernel doesn't, upgrade it to mitigate the vulnerability" fi else - if [ "$kernel_md_clear" = 1 ] && [ "$opt_runtime" = 1 ]; then + if [ "$kernel_md_clear" = 1 ] && [ "$g_mode" = live ]; then # no MD_CLEAR in microcode, but FreeBSD may still have software-only mitigation active case "$kernel_mds_state" in software*) @@ -138,7 +138,7 @@ check_mds_linux() { if is_x86_kernel; then pr_info_nol "* Kernel supports using MD_CLEAR mitigation: " kernel_md_clear_can_tell=1 - if [ "$opt_runtime" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw md_clear; then + if [ "$g_mode" = live ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw md_clear; then kernel_md_clear="md_clear found in $g_procfs/cpuinfo" pstatus green YES "$kernel_md_clear" fi @@ -161,7 +161,7 @@ check_mds_linux() { fi fi - if [ "$opt_runtime" = 1 ] && [ "$sys_interface_available" = 1 ]; then + if [ "$g_mode" = live ] && [ "$sys_interface_available" = 1 ]; then pr_info_nol "* Kernel mitigation is enabled and active: " if echo "$ret_sys_interface_check_fullmsg" | grep -qi ^mitigation; then mds_mitigated=1 @@ -194,7 +194,7 @@ check_mds_linux() { # compute mystatus and mymsg from our own logic if [ "$cap_md_clear" = 1 ]; then if [ -n "$kernel_md_clear" ]; then - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # mitigation must also be enabled if [ "$mds_mitigated" = 1 ]; then if [ "$opt_paranoid" != 1 ] || [ "$mds_smt_mitigated" = 1 ]; then diff --git a/src/vulns-helpers/check_mmio.sh b/src/vulns-helpers/check_mmio.sh index 122462b..c567cda 100644 --- a/src/vulns-helpers/check_mmio.sh +++ b/src/vulns-helpers/check_mmio.sh @@ -165,7 +165,7 @@ check_mmio_linux() { pstatus yellow NO fi - if [ "$opt_runtime" = 1 ] && [ "$sys_interface_available" = 1 ]; then + if [ "$g_mode" = live ] && [ "$sys_interface_available" = 1 ]; then pr_info_nol "* Kernel mitigation is enabled and active: " if echo "$ret_sys_interface_check_fullmsg" | grep -qi ^mitigation; then mmio_mitigated=1 @@ -198,7 +198,7 @@ check_mmio_linux() { # compute mystatus and mymsg from our own logic if [ "$cap_fb_clear" = 1 ]; then if [ -n "$kernel_mmio" ]; then - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # mitigation must also be enabled if [ "$mmio_mitigated" = 1 ]; then if [ "$opt_paranoid" != 1 ] || [ "$mmio_smt_mitigated" = 1 ]; then diff --git a/src/vulns/CVE-2017-5715.sh b/src/vulns/CVE-2017-5715.sh index eb1fc33..d672bb3 100644 --- a/src/vulns/CVE-2017-5715.sh +++ b/src/vulns/CVE-2017-5715.sh @@ -269,7 +269,7 @@ check_CVE_2017_5715_linux() { g_ibpb_supported='' g_ibpb_enabled='' - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # in live mode, we can check for the ibrs_enabled file in debugfs # all versions of the patches have it (NOT the case of IBPB or KPTI) g_ibrs_can_tell=1 @@ -420,7 +420,7 @@ check_CVE_2017_5715_linux() { fi pr_info_nol " * IBRS enabled and active: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ "$g_ibpb_enabled" = 2 ]; then # if ibpb=2, ibrs is forcefully=0 pstatus blue NO "IBPB used instead of IBRS in all kernel entrypoints" @@ -471,7 +471,7 @@ check_CVE_2017_5715_linux() { fi pr_info_nol " * IBPB enabled and active: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then case "$g_ibpb_enabled" in "") if [ "$g_ibrs_supported" = 1 ]; then @@ -554,7 +554,7 @@ check_CVE_2017_5715_linux() { # # since 5.15.28, this is now "Retpolines" as the implementation was switched to a generic one, # so we look for both "retpoline" and "retpolines" - if [ "$opt_runtime" = 1 ] && [ -n "$ret_sys_interface_check_fullmsg" ]; then + if [ "$g_mode" = live ] && [ -n "$ret_sys_interface_check_fullmsg" ]; then if echo "$ret_sys_interface_check_fullmsg" | grep -qwi -e retpoline -e retpolines; then if echo "$ret_sys_interface_check_fullmsg" | grep -qwi minimal; then retpoline_compiler=0 @@ -605,7 +605,7 @@ check_CVE_2017_5715_linux() { # only Red Hat has a tunable to disable it on runtime retp_enabled=-1 - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ -e "$g_specex_knob_dir/retp_enabled" ]; then retp_enabled=$(cat "$g_specex_knob_dir/retp_enabled" 2>/dev/null) pr_debug "retpoline: found $g_specex_knob_dir/retp_enabled=$retp_enabled" @@ -635,7 +635,7 @@ check_CVE_2017_5715_linux() { if is_vulnerable_to_empty_rsb || [ "$opt_verbose" -ge 2 ]; then pr_info_nol " * Kernel supports RSB filling: " rsb_filling=0 - if [ "$opt_runtime" = 1 ] && [ "$opt_no_sysfs" != 1 ]; then + if [ "$g_mode" = live ] && [ "$opt_no_sysfs" != 1 ]; then # if we're live and we aren't denied looking into /sys, let's do it if echo "$ret_sys_interface_check_fullmsg" | grep -qw RSB; then rsb_filling=1 @@ -728,7 +728,7 @@ check_CVE_2017_5715_linux() { *", IBPB"* | *"; IBPB"*) v2_ibpb_mode=conditional ;; *) v2_ibpb_mode=disabled ;; esac - elif [ "$opt_runtime" = 1 ]; then + elif [ "$g_mode" = live ]; then case "$g_ibpb_enabled" in 2) v2_ibpb_mode=always-on ;; 1) v2_ibpb_mode=conditional ;; @@ -826,7 +826,7 @@ check_CVE_2017_5715_linux() { *"PBRSB-eIBRS: Vulnerable"*) v2_pbrsb_status=vulnerable ;; *) v2_pbrsb_status=unknown ;; esac - elif [ "$opt_runtime" != 1 ] && [ -n "$g_kernel" ]; then + elif [ "$g_mode" != live ] && [ -n "$g_kernel" ]; then if grep -q 'PBRSB-eIBRS' "$g_kernel" 2>/dev/null; then v2_pbrsb_status=sw-sequence else @@ -857,7 +857,7 @@ check_CVE_2017_5715_linux() { *"BHI: Vulnerable"*) v2_bhi_status=vulnerable ;; *) v2_bhi_status=unknown ;; esac - elif [ "$opt_runtime" != 1 ] && [ -n "$opt_config" ] && [ -r "$opt_config" ]; then + elif [ "$g_mode" != live ] && [ -n "$opt_config" ] && [ -r "$opt_config" ]; then if grep -q '^CONFIG_\(MITIGATION_\)\?SPECTRE_BHI' "$opt_config"; then if [ "$cap_bhi" = 1 ]; then v2_bhi_status=bhi_dis_s @@ -881,7 +881,7 @@ check_CVE_2017_5715_linux() { esac # --- v2_vuln_module --- - if [ "$opt_runtime" = 1 ] && [ -n "$ret_sys_interface_check_fullmsg" ]; then + if [ "$g_mode" = live ] && [ -n "$ret_sys_interface_check_fullmsg" ]; then pr_info_nol " * Non-retpoline module loaded: " if echo "$ret_sys_interface_check_fullmsg" | grep -q 'vulnerable module loaded'; then v2_vuln_module=1 @@ -982,7 +982,7 @@ check_CVE_2017_5715_linux() { if [ -n "${SMC_MOCK_UNPRIVILEGED_BPF_DISABLED:-}" ]; then _ebpf_disabled="$SMC_MOCK_UNPRIVILEGED_BPF_DISABLED" g_mocked=1 - elif [ "$opt_runtime" = 1 ] && [ -r "$g_procfs/sys/kernel/unprivileged_bpf_disabled" ]; then + elif [ "$g_mode" = live ] && [ -r "$g_procfs/sys/kernel/unprivileged_bpf_disabled" ]; then _ebpf_disabled=$(cat "$g_procfs/sys/kernel/unprivileged_bpf_disabled" 2>/dev/null) g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_UNPRIVILEGED_BPF_DISABLED='$_ebpf_disabled'") fi @@ -1170,7 +1170,7 @@ check_CVE_2017_5715_linux() { pvulnstatus "$cve" OK "Full IBPB is mitigating the vulnerability" # No-runtime mode fallback - elif [ "$opt_runtime" != 1 ]; then + elif [ "$g_mode" != live ]; then if [ "$retpoline" = 1 ] && [ -n "$g_ibpb_supported" ]; then pvulnstatus "$cve" OK "no-runtime mode: kernel supports retpoline + IBPB to mitigate the vulnerability" elif [ -n "$g_ibrs_supported" ] && [ -n "$g_ibpb_supported" ]; then diff --git a/src/vulns/CVE-2017-5753.sh b/src/vulns/CVE-2017-5753.sh index 6750f7e..57dcf0a 100644 --- a/src/vulns/CVE-2017-5753.sh +++ b/src/vulns/CVE-2017-5753.sh @@ -101,60 +101,48 @@ check_CVE_2017_5753_linux() { # For no-runtime analysis of these old kernels, match the specific instruction patterns. if [ -z "$v1_kernel_mitigated" ]; then pr_info_nol "* Kernel has array_index_mask_nospec (v4.15 binary pattern): " - # vanilla: look for the Linus' mask aka array_index_mask_nospec() - # that is inlined at least in raw_copy_from_user (__get_user_X symbols) - #mov PER_CPU_VAR(current_task), %_ASM_DX - #cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX - #jae bad_get_user - # /* array_index_mask_nospec() are the 2 opcodes that follow */ - #+sbb %_ASM_DX, %_ASM_DX - #+and %_ASM_DX, %_ASM_AX - #ASM_STAC - # x86 64bits: jae(0x0f 0x83 0x?? 0x?? 0x?? 0x??) sbb(0x48 0x19 0xd2) and(0x48 0x21 0xd0) - # x86 32bits: cmp(0x3b 0x82 0x?? 0x?? 0x00 0x00) jae(0x73 0x??) sbb(0x19 0xd2) and(0x21 0xd0) - # - # arm32 - ##ifdef CONFIG_THUMB2_KERNEL - ##define CSDB ".inst.w 0xf3af8014" - ##else - ##define CSDB ".inst 0xe320f014" e320f014 - ##endif - #asm volatile( - # "cmp %1, %2\n" e1500003 - #" sbc %0, %1, %1\n" e0c03000 - #CSDB - #: "=r" (mask) - #: "r" (idx), "Ir" (sz) - #: "cc"); - # - # http://git.arm.linux.org.uk/cgit/linux-arm.git/commit/?h=spectre&id=a78d156587931a2c3b354534aa772febf6c9e855 v1_mask_nospec='' if [ -n "$g_kernel_err" ]; then pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)" - elif ! command -v perl >/dev/null 2>&1; then - pstatus yellow UNKNOWN "missing 'perl' binary, please install it" - else - perl -ne '/\x0f\x83....\x48\x19\xd2\x48\x21\xd0/ and $found++; END { exit($found ? 0 : 1) }' "$g_kernel" - ret=$? - if [ "$ret" -eq 0 ]; then - pstatus green YES "x86 64 bits array_index_mask_nospec()" - v1_mask_nospec="x86 64 bits array_index_mask_nospec" + elif is_x86_kernel; then + # x86: binary pattern matching for array_index_mask_nospec() + # x86 64bits: jae(0x0f 0x83 ....) sbb(0x48 0x19 0xd2) and(0x48 0x21 0xd0) + # x86 32bits: cmp(0x3b 0x82 .. .. 0x00 0x00) jae(0x73 ..) sbb(0x19 0xd2) and(0x21 0xd0) + if ! command -v perl >/dev/null 2>&1; then + pstatus yellow UNKNOWN "missing 'perl' binary, please install it" else - perl -ne '/\x3b\x82..\x00\x00\x73.\x19\xd2\x21\xd0/ and $found++; END { exit($found ? 0 : 1) }' "$g_kernel" + perl -ne '/\x0f\x83....\x48\x19\xd2\x48\x21\xd0/ and $found++; END { exit($found ? 0 : 1) }' "$g_kernel" ret=$? if [ "$ret" -eq 0 ]; then - pstatus green YES "x86 32 bits array_index_mask_nospec()" - v1_mask_nospec="x86 32 bits array_index_mask_nospec" + pstatus green YES "x86 64 bits array_index_mask_nospec()" + v1_mask_nospec="x86 64 bits array_index_mask_nospec" else - ret=$("${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | grep -w -e f3af8014 -e e320f014 -B2 | grep -B1 -w sbc | grep -w -c cmp) - if [ "$ret" -gt 0 ]; then - pstatus green YES "$ret occurrence(s) found of arm 32 bits array_index_mask_nospec()" - v1_mask_nospec="arm 32 bits array_index_mask_nospec" + perl -ne '/\x3b\x82..\x00\x00\x73.\x19\xd2\x21\xd0/ and $found++; END { exit($found ? 0 : 1) }' "$g_kernel" + ret=$? + if [ "$ret" -eq 0 ]; then + pstatus green YES "x86 32 bits array_index_mask_nospec()" + v1_mask_nospec="x86 32 bits array_index_mask_nospec" else pstatus yellow NO fi fi fi + elif is_arm_kernel; then + # arm32: match CSDB instruction (0xf3af8014 Thumb2 or 0xe320f014 ARM) preceded by sbc+cmp + # http://git.arm.linux.org.uk/cgit/linux-arm.git/commit/?h=spectre&id=a78d156587931a2c3b354534aa772febf6c9e855 + if ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then + pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package" + else + ret=$("${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | grep -w -e f3af8014 -e e320f014 -B2 | grep -B1 -w sbc | grep -w -c cmp) + if [ "$ret" -gt 0 ]; then + pstatus green YES "$ret occurrence(s) found of arm 32 bits array_index_mask_nospec()" + v1_mask_nospec="arm 32 bits array_index_mask_nospec" + else + pstatus yellow NO + fi + fi + else + pstatus yellow NO fi fi @@ -172,67 +160,69 @@ check_CVE_2017_5753_linux() { pstatus yellow NO fi - pr_info_nol "* Kernel has mask_nospec64 (arm64): " - #.macro mask_nospec64, idx, limit, tmp - #sub \tmp, \idx, \limit - #bic \tmp, \tmp, \idx - #and \idx, \idx, \tmp, asr #63 - #csdb - #.endm - #$ aarch64-linux-gnu-objdump -d vmlinux | grep -w bic -A1 -B1 | grep -w sub -A2 | grep -w and -B2 - #ffffff8008082e44: cb190353 sub x19, x26, x25 - #ffffff8008082e48: 8a3a0273 bic x19, x19, x26 - #ffffff8008082e4c: 8a93ff5a and x26, x26, x19, asr #63 - #ffffff8008082e50: d503229f hint #0x14 - # /!\ can also just be "csdb" instead of "hint #0x14" for native objdump - # - # if we already have a detection, don't bother disassembling the kernel, the answer is no. - if [ -n "$v1_kernel_mitigated" ] || [ -n "$v1_mask_nospec" ] || [ "$g_redhat_canonical_spectre" -gt 0 ]; then - pstatus yellow NO - elif [ -n "$g_kernel_err" ]; then - pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)" - elif ! command -v perl >/dev/null 2>&1; then - pstatus yellow UNKNOWN "missing 'perl' binary, please install it" - elif ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then - pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package" - else - "${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | perl -ne 'push @r, $_; /\s(hint|csdb)\s/ && $r[0]=~/\ssub\s+(x\d+)/ && $r[1]=~/\sbic\s+$1,\s+$1,/ && $r[2]=~/\sand\s/ && exit(9); shift @r if @r>3' - ret=$? - if [ "$ret" -eq 9 ]; then - pstatus green YES "mask_nospec64 macro is present and used" - v1_mask_nospec="arm64 mask_nospec64" - else + if is_arm_kernel; then + pr_info_nol "* Kernel has mask_nospec64 (arm64): " + #.macro mask_nospec64, idx, limit, tmp + #sub \tmp, \idx, \limit + #bic \tmp, \tmp, \idx + #and \idx, \idx, \tmp, asr #63 + #csdb + #.endm + #$ aarch64-linux-gnu-objdump -d vmlinux | grep -w bic -A1 -B1 | grep -w sub -A2 | grep -w and -B2 + #ffffff8008082e44: cb190353 sub x19, x26, x25 + #ffffff8008082e48: 8a3a0273 bic x19, x19, x26 + #ffffff8008082e4c: 8a93ff5a and x26, x26, x19, asr #63 + #ffffff8008082e50: d503229f hint #0x14 + # /!\ can also just be "csdb" instead of "hint #0x14" for native objdump + # + # if we already have a detection, don't bother disassembling the kernel, the answer is no. + if [ -n "$v1_kernel_mitigated" ] || [ -n "$v1_mask_nospec" ] || [ "$g_redhat_canonical_spectre" -gt 0 ]; then pstatus yellow NO + elif [ -n "$g_kernel_err" ]; then + pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)" + elif ! command -v perl >/dev/null 2>&1; then + pstatus yellow UNKNOWN "missing 'perl' binary, please install it" + elif ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then + pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package" + else + "${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | perl -ne 'push @r, $_; /\s(hint|csdb)\s/ && $r[0]=~/\ssub\s+(x\d+)/ && $r[1]=~/\sbic\s+$1,\s+$1,/ && $r[2]=~/\sand\s/ && exit(9); shift @r if @r>3' + ret=$? + if [ "$ret" -eq 9 ]; then + pstatus green YES "mask_nospec64 macro is present and used" + v1_mask_nospec="arm64 mask_nospec64" + else + pstatus yellow NO + fi fi - fi - pr_info_nol "* Kernel has array_index_nospec (arm64): " - # in 4.19+ kernels, the mask_nospec64 asm64 macro is replaced by array_index_nospec, defined in nospec.h, and used in invoke_syscall() - # ffffff8008090a4c: 2a0203e2 mov w2, w2 - # ffffff8008090a50: eb0200bf cmp x5, x2 - # ffffff8008090a54: da1f03e2 ngc x2, xzr - # ffffff8008090a58: d503229f hint #0x14 - # /!\ can also just be "csdb" instead of "hint #0x14" for native objdump - # - # if we already have a detection, don't bother disassembling the kernel, the answer is no. - if [ -n "$v1_kernel_mitigated" ] || [ -n "$v1_mask_nospec" ] || [ "$g_redhat_canonical_spectre" -gt 0 ]; then - pstatus yellow NO - elif [ -n "$g_kernel_err" ]; then - pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)" - elif ! command -v perl >/dev/null 2>&1; then - pstatus yellow UNKNOWN "missing 'perl' binary, please install it" - elif ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then - pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package" - else - "${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | perl -ne 'push @r, $_; /\s(hint|csdb)\s/ && $r[0]=~/\smov\s+(w\d+),\s+(w\d+)/ && $r[1]=~/\scmp\s+(x\d+),\s+(x\d+)/ && $r[2]=~/\sngc\s+$2,/ && exit(9); shift @r if @r>3' - ret=$? - if [ "$ret" -eq 9 ]; then - pstatus green YES "array_index_nospec macro is present and used" - v1_mask_nospec="arm64 array_index_nospec" - else + pr_info_nol "* Kernel has array_index_nospec (arm64): " + # in 4.19+ kernels, the mask_nospec64 asm64 macro is replaced by array_index_nospec, defined in nospec.h, and used in invoke_syscall() + # ffffff8008090a4c: 2a0203e2 mov w2, w2 + # ffffff8008090a50: eb0200bf cmp x5, x2 + # ffffff8008090a54: da1f03e2 ngc x2, xzr + # ffffff8008090a58: d503229f hint #0x14 + # /!\ can also just be "csdb" instead of "hint #0x14" for native objdump + # + # if we already have a detection, don't bother disassembling the kernel, the answer is no. + if [ -n "$v1_kernel_mitigated" ] || [ -n "$v1_mask_nospec" ] || [ "$g_redhat_canonical_spectre" -gt 0 ]; then pstatus yellow NO + elif [ -n "$g_kernel_err" ]; then + pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)" + elif ! command -v perl >/dev/null 2>&1; then + pstatus yellow UNKNOWN "missing 'perl' binary, please install it" + elif ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then + pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package" + else + "${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | perl -ne 'push @r, $_; /\s(hint|csdb)\s/ && $r[0]=~/\smov\s+(w\d+),\s+(w\d+)/ && $r[1]=~/\scmp\s+(x\d+),\s+(x\d+)/ && $r[2]=~/\sngc\s+$2,/ && exit(9); shift @r if @r>3' + ret=$? + if [ "$ret" -eq 9 ]; then + pstatus green YES "array_index_nospec macro is present and used" + v1_mask_nospec="arm64 array_index_nospec" + else + pstatus yellow NO + fi fi - fi + fi # is_arm_kernel elif [ "$sys_interface_available" = 0 ]; then msg="/sys vulnerability interface use forced, but it's not available!" diff --git a/src/vulns/CVE-2017-5754.sh b/src/vulns/CVE-2017-5754.sh index 8376197..bbb6b17 100644 --- a/src/vulns/CVE-2017-5754.sh +++ b/src/vulns/CVE-2017-5754.sh @@ -104,7 +104,7 @@ check_CVE_2017_5754_linux() { mount_debugfs pr_info_nol " * PTI enabled and active: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then dmesg_grep="Kernel/User page tables isolation: enabled" dmesg_grep="$dmesg_grep|Kernel page table isolation enabled" dmesg_grep="$dmesg_grep|x86/pti: Unmapping kernel while in userspace" @@ -170,7 +170,7 @@ check_CVE_2017_5754_linux() { is_xen_dom0 && xen_pv_domo=1 is_xen_domU && xen_pv_domu=1 - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # checking whether we're running under Xen PV 64 bits. If yes, we are affected by affected_variant3 # (unless we are a Dom0) pr_info_nol "* Running as a Xen PV DomU: " @@ -186,7 +186,7 @@ check_CVE_2017_5754_linux() { pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" elif [ -z "$msg" ]; then # if msg is empty, sysfs check didn't fill it, rely on our own test - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ "$kpti_enabled" = 1 ]; then pvulnstatus "$cve" OK "PTI mitigates the vulnerability" elif [ "$xen_pv_domo" = 1 ]; then diff --git a/src/vulns/CVE-2018-12207.sh b/src/vulns/CVE-2018-12207.sh index 2a072b8..10b2904 100644 --- a/src/vulns/CVE-2018-12207.sh +++ b/src/vulns/CVE-2018-12207.sh @@ -36,7 +36,7 @@ check_CVE_2018_12207_linux() { fi pr_info_nol "* iTLB Multihit mitigation enabled and active: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ -n "$ret_sys_interface_check_fullmsg" ]; then if echo "$ret_sys_interface_check_fullmsg" | grep -qF 'Mitigation'; then pstatus green YES "$ret_sys_interface_check_fullmsg" @@ -63,7 +63,7 @@ check_CVE_2018_12207_linux() { elif [ -z "$msg" ]; then # if msg is empty, sysfs check didn't fill it, rely on our own test if [ "$opt_sysfs_only" != 1 ]; then - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old pvulnstatus "$cve" VULN "Your kernel doesn't support iTLB Multihit mitigation, update it" else diff --git a/src/vulns/CVE-2018-3620.sh b/src/vulns/CVE-2018-3620.sh index 26737e1..58370d5 100644 --- a/src/vulns/CVE-2018-3620.sh +++ b/src/vulns/CVE-2018-3620.sh @@ -37,7 +37,7 @@ check_CVE_2018_3620_linux() { fi pr_info_nol "* PTE inversion enabled and active: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ -n "$ret_sys_interface_check_fullmsg" ]; then if echo "$ret_sys_interface_check_fullmsg" | grep -q 'Mitigation: PTE Inversion'; then pstatus green YES @@ -66,7 +66,7 @@ check_CVE_2018_3620_linux() { # if msg is empty, sysfs check didn't fill it, rely on our own test if [ "$opt_sysfs_only" != 1 ]; then if [ "$pteinv_supported" = 1 ]; then - if [ "$pteinv_active" = 1 ] || [ "$opt_runtime" != 1 ]; then + if [ "$pteinv_active" = 1 ] || [ "$g_mode" != live ]; then pvulnstatus "$cve" OK "PTE inversion mitigates the vulnerability" else pvulnstatus "$cve" VULN "Your kernel supports PTE inversion but it doesn't seem to be enabled" diff --git a/src/vulns/CVE-2018-3639.sh b/src/vulns/CVE-2018-3639.sh index 3762904..f6ca26f 100644 --- a/src/vulns/CVE-2018-3639.sh +++ b/src/vulns/CVE-2018-3639.sh @@ -18,7 +18,7 @@ check_CVE_2018_3639_linux() { fi if [ "$opt_sysfs_only" != 1 ]; then pr_info_nol "* Kernel supports disabling speculative store bypass (SSB): " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if grep -Eq 'Speculation.?Store.?Bypass:' "$g_procfs/self/status" 2>/dev/null; then kernel_ssb="found in $g_procfs/self/status" pr_debug "found Speculation.Store.Bypass: in $g_procfs/self/status" @@ -57,7 +57,7 @@ check_CVE_2018_3639_linux() { fi kernel_ssbd_enabled=-1 - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # https://elixir.bootlin.com/linux/v5.0/source/fs/proc/array.c#L340 pr_info_nol "* SSB mitigation is enabled and active: " if grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+thread' "$g_procfs/self/status" 2>/dev/null; then @@ -106,7 +106,7 @@ check_CVE_2018_3639_linux() { # if msg is empty, sysfs check didn't fill it, rely on our own test if [ -n "$cap_ssbd" ]; then if [ -n "$kernel_ssb" ]; then - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ "$kernel_ssbd_enabled" -gt 0 ]; then pvulnstatus "$cve" OK "your CPU and kernel both support SSBD and mitigation is enabled" else diff --git a/src/vulns/CVE-2018-3646.sh b/src/vulns/CVE-2018-3646.sh index dd70ca9..20f1fef 100644 --- a/src/vulns/CVE-2018-3646.sh +++ b/src/vulns/CVE-2018-3646.sh @@ -69,14 +69,19 @@ check_CVE_2018_3646_linux() { pr_info "* Mitigation 1 (KVM)" pr_info_nol " * EPT is disabled: " ept_disabled=-1 - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if ! [ -r "$SYS_MODULE_BASE/kvm_intel/parameters/ept" ]; then pstatus blue N/A "the kvm_intel module is not loaded" - elif [ "$(cat "$SYS_MODULE_BASE/kvm_intel/parameters/ept")" = N ]; then - pstatus green YES - ept_disabled=1 else - pstatus yellow NO + ept_value="$(cat "$SYS_MODULE_BASE/kvm_intel/parameters/ept" 2>/dev/null || echo ERROR)" + if [ "$ept_value" = N ]; then + pstatus green YES + ept_disabled=1 + elif [ "$ept_value" = ERROR ]; then + pstatus yellow UNK "Couldn't read $SYS_MODULE_BASE/kvm_intel/parameters/ept" + else + pstatus yellow NO + fi fi else pstatus blue N/A "not testable in no-runtime mode" @@ -84,7 +89,7 @@ check_CVE_2018_3646_linux() { pr_info "* Mitigation 2" pr_info_nol " * L1D flush is supported by kernel: " - if [ "$opt_runtime" = 1 ] && grep -qw flush_l1d "$g_procfs/cpuinfo"; then + if [ "$g_mode" = live ] && grep -qw flush_l1d "$g_procfs/cpuinfo"; then l1d_kernel="found flush_l1d in $g_procfs/cpuinfo" fi if [ -z "$l1d_kernel" ]; then @@ -106,7 +111,7 @@ check_CVE_2018_3646_linux() { fi pr_info_nol " * L1D flush enabled: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ -n "$ret_sys_interface_check_fullmsg" ]; then # vanilla: VMX: $l1dstatus, SMT $smtstatus # Red Hat: VMX: SMT $smtstatus, L1D $l1dstatus @@ -156,7 +161,7 @@ check_CVE_2018_3646_linux() { fi pr_info_nol " * Hardware-backed L1D flush supported: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if grep -qw flush_l1d "$g_procfs/cpuinfo" || [ -n "$l1d_xen_hardware" ]; then pstatus green YES "performance impact of the mitigation will be greatly reduced" else diff --git a/src/vulns/CVE-2019-11135.sh b/src/vulns/CVE-2019-11135.sh index 96fcdcd..0781bd5 100644 --- a/src/vulns/CVE-2019-11135.sh +++ b/src/vulns/CVE-2019-11135.sh @@ -33,7 +33,7 @@ check_CVE_2019_11135_linux() { fi pr_info_nol "* TAA mitigation enabled and active: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ -n "$ret_sys_interface_check_fullmsg" ]; then if echo "$ret_sys_interface_check_fullmsg" | grep -qE '^Mitigation'; then pstatus green YES "$ret_sys_interface_check_fullmsg" @@ -57,7 +57,7 @@ check_CVE_2019_11135_linux() { pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" elif [ -z "$msg" ]; then # if msg is empty, sysfs check didn't fill it, rely on our own test - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old pvulnstatus "$cve" VULN "Your kernel doesn't support TAA mitigation, update it" else diff --git a/src/vulns/CVE-2020-0543.sh b/src/vulns/CVE-2020-0543.sh index 195de65..75607f0 100644 --- a/src/vulns/CVE-2020-0543.sh +++ b/src/vulns/CVE-2020-0543.sh @@ -32,7 +32,7 @@ check_CVE_2020_0543_linux() { pstatus yellow NO fi pr_info_nol "* SRBDS mitigation control is enabled and active: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ -n "$ret_sys_interface_check_fullmsg" ]; then if echo "$ret_sys_interface_check_fullmsg" | grep -qE '^Mitigation'; then pstatus green YES "$ret_sys_interface_check_fullmsg" @@ -61,7 +61,7 @@ check_CVE_2020_0543_linux() { # SRBDS mitigation control is enabled if [ -z "$msg" ]; then # if msg is empty, sysfs check didn't fill it, rely on our own test - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old pvulnstatus "$cve" OK "Your microcode is up to date for SRBDS mitigation control. The kernel needs to be updated" fi @@ -75,7 +75,7 @@ check_CVE_2020_0543_linux() { elif [ "$cap_srbds_on" = 0 ]; then # SRBDS mitigation control is disabled if [ -z "$msg" ]; then - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old pvulnstatus "$cve" VULN "Your microcode is up to date for SRBDS mitigation control. The kernel needs to be updated. Mitigation is disabled" fi diff --git a/src/vulns/CVE-2022-29900.sh b/src/vulns/CVE-2022-29900.sh index 5728142..ebb83a0 100644 --- a/src/vulns/CVE-2022-29900.sh +++ b/src/vulns/CVE-2022-29900.sh @@ -174,7 +174,7 @@ check_CVE_2022_29900_linux() { # Zen/Zen+/Zen2: check IBPB microcode support and SMT if [ "$cpu_family" = $((0x17)) ]; then pr_info_nol "* CPU supports IBPB: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ -n "$cap_ibpb" ]; then pstatus green YES "$cap_ibpb" else @@ -217,7 +217,7 @@ check_CVE_2022_29900_linux() { "doesn't fully protect cross-thread speculation." elif [ -z "$kernel_unret" ] && [ -z "$kernel_ibpb_entry" ]; then pvulnstatus "$cve" VULN "Your kernel doesn't have either UNRET_ENTRY or IBPB_ENTRY compiled-in" - elif [ "$smt_enabled" = 0 ] && [ -z "$cap_ibpb" ] && [ "$opt_runtime" = 1 ]; then + elif [ "$smt_enabled" = 0 ] && [ -z "$cap_ibpb" ] && [ "$g_mode" = live ]; then pvulnstatus "$cve" VULN "SMT is enabled and your microcode doesn't support IBPB" explain "Update your CPU microcode to get IBPB support, or disable SMT by adding\n" \ "\`nosmt\` to your kernel command line." diff --git a/src/vulns/CVE-2022-29901.sh b/src/vulns/CVE-2022-29901.sh index b712556..069b8c3 100644 --- a/src/vulns/CVE-2022-29901.sh +++ b/src/vulns/CVE-2022-29901.sh @@ -84,7 +84,7 @@ check_CVE_2022_29901_linux() { fi pr_info_nol "* CPU supports Enhanced IBRS (IBRS_ALL): " - if [ "$opt_runtime" = 1 ] || [ "$cap_ibrs_all" != -1 ]; then + if [ "$g_mode" = live ] || [ "$cap_ibrs_all" != -1 ]; then if [ "$cap_ibrs_all" = 1 ]; then pstatus green YES elif [ "$cap_ibrs_all" = 0 ]; then @@ -97,7 +97,7 @@ check_CVE_2022_29901_linux() { fi pr_info_nol "* CPU has RSB Alternate Behavior (RSBA): " - if [ "$opt_runtime" = 1 ] || [ "$cap_rsba" != -1 ]; then + if [ "$g_mode" = live ] || [ "$cap_rsba" != -1 ]; then if [ "$cap_rsba" = 1 ]; then pstatus yellow YES "this CPU is affected by RSB underflow" elif [ "$cap_rsba" = 0 ]; then diff --git a/src/vulns/CVE-2022-40982.sh b/src/vulns/CVE-2022-40982.sh index b23279b..60e5abc 100644 --- a/src/vulns/CVE-2022-40982.sh +++ b/src/vulns/CVE-2022-40982.sh @@ -145,7 +145,7 @@ check_CVE_2022_40982_linux() { if [ -n "$kernel_gds" ]; then pr_info_nol "* Kernel has disabled AVX as a mitigation: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # Check dmesg message to see whether AVX has been disabled dmesg_grep 'Microcode update needed! Disabling AVX as mitigation' dmesgret=$? diff --git a/src/vulns/CVE-2023-20588.sh b/src/vulns/CVE-2023-20588.sh index ce1e466..9af287f 100644 --- a/src/vulns/CVE-2023-20588.sh +++ b/src/vulns/CVE-2023-20588.sh @@ -101,7 +101,7 @@ check_CVE_2023_20588_linux() { pr_info_nol "* DIV0 mitigation enabled and active: " cpuinfo_div0='' dmesg_div0='' - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ -e "$g_procfs/cpuinfo" ] && grep -qw 'div0' "$g_procfs/cpuinfo" 2>/dev/null; then cpuinfo_div0=1 pstatus green YES "div0 found in $g_procfs/cpuinfo bug flags" @@ -141,7 +141,7 @@ check_CVE_2023_20588_linux() { pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" elif [ -z "$msg" ]; then if [ "$opt_sysfs_only" != 1 ]; then - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # live mode: cpuinfo div0 flag is the strongest proof the mitigation is active if [ "$cpuinfo_div0" = 1 ] || [ "$dmesg_div0" = 1 ]; then _cve_2023_20588_pvulnstatus_smt diff --git a/src/vulns/CVE-2023-20593.sh b/src/vulns/CVE-2023-20593.sh index 26b46cf..93012b7 100644 --- a/src/vulns/CVE-2023-20593.sh +++ b/src/vulns/CVE-2023-20593.sh @@ -28,7 +28,7 @@ check_CVE_2023_20593_linux() { pstatus yellow NO fi pr_info_nol "* Zenbleed kernel mitigation enabled and active: " - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then # read the DE_CFG MSR, we want to check the 9th bit # don't do it on non-Zen2 AMD CPUs or later, aka Family 17h, # as the behavior could be unknown on others @@ -82,7 +82,7 @@ check_CVE_2023_20593_linux() { elif [ -z "$msg" ]; then # if msg is empty, sysfs check didn't fill it, rely on our own test zenbleed_print_vuln=0 - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ "$fp_backup_fix" = 1 ] && [ "$ucode_zenbleed" = 1 ]; then # this should never happen, but if it does, it's interesting to know pvulnstatus "$cve" OK "Both your CPU microcode and kernel are mitigating Zenbleed" diff --git a/src/vulns/CVE-2023-28746.sh b/src/vulns/CVE-2023-28746.sh index 922404b..f571a4a 100644 --- a/src/vulns/CVE-2023-28746.sh +++ b/src/vulns/CVE-2023-28746.sh @@ -106,7 +106,7 @@ check_CVE_2023_28746_linux() { pstatus yellow NO fi - if [ "$opt_runtime" = 1 ] && [ "$sys_interface_available" = 1 ]; then + if [ "$g_mode" = live ] && [ "$sys_interface_available" = 1 ]; then pr_info_nol "* RFDS mitigation is enabled and active: " if echo "$ret_sys_interface_check_fullmsg" | grep -qi '^Mitigation'; then rfds_mitigated=1 @@ -129,7 +129,7 @@ check_CVE_2023_28746_linux() { if [ "$opt_sysfs_only" != 1 ]; then if [ "$cap_rfds_clear" = 1 ]; then if [ -n "$kernel_rfds" ]; then - if [ "$opt_runtime" = 1 ]; then + if [ "$g_mode" = live ]; then if [ "$rfds_mitigated" = 1 ]; then pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled" else