# vim: set ts=4 sw=4 sts=4 et: # Print command-line usage information to stdout show_usage() { # shellcheck disable=SC2086 cat <] [--config ] [--map ] Inspect the currently running kernel within the context of the CPU it's running on. You can optionally specify --kernel, --config, or --map to help the script locate files it couldn't auto-detect * No-runtime mode: $(basename $0) [options] --no-runtime <--kernel > [--config ] [--map ] Inspect the CPU hardware, but skips all running-kernel artifacts (/sys, /proc, dmesg). Use this when you have a kernel image different from the kernel you're running but want to check it against this CPU. * No-hardware mode: $(basename $0) [options] --no-hw <--kernel > [--config ] [--map ] Ignore both CPU hardware and running-kernel artifacts. Use this for pure static analysis of a kernel image, for example when inspecting a kernel targeted for another system or CPU. * Hardware-only mode: $(basename $0) [options] --hw-only Only inspect the CPU hardware, and report information and affectedness per vulnerability. Vulnerability selection: --variant VARIANT specify which variant you'd like to check, by default all variants are checked. can be used multiple times (e.g. --variant 3a --variant l1tf). For a list use 'help'. --cve CVE specify which CVE you'd like to check, by default all supported CVEs are checked can be used multiple times (e.g. --cve CVE-2017-5753 --cve CVE-2020-0543) --errata NUMBER specify a vendor-numbered erratum (e.g. ARM64 erratum 1530923) that has no CVE assigned. Maps the erratum to the corresponding check. For a list use 'help'. Can be used multiple times (e.g. --errata 1530923 --errata 3194386). Check scope: --no-sysfs don't use the /sys interface even if present [Linux] --sysfs-only only use the /sys interface, don't run our own checks [Linux] Strictness: --paranoid require all mitigations to be enabled to the fullest extent, including those that are not strictly necessary but provide defense in depth (e.g. SMT disabled, IBPB always-on); without this flag, the script follows the security community consensus --extra run additional checks for issues that don't have a CVE but are still security-relevant, such as compile-time mitigations not enabled by default (e.g. Straight-Line Speculation) Hardware and platform: --cpu [#,all] interact with CPUID and MSR of CPU core number #, or all (default: CPU core 0) --vmm [auto,yes,no] override the detection of the presence of a hypervisor, default: auto --allow-msr-write allow probing for write-only MSRs, this might produce kernel logs or be blocked by your system --arch-prefix PREFIX specify a prefix for cross-inspecting a kernel of a different arch, for example "aarch64-linux-gnu-", so that invoked tools will be prefixed with this (i.e. aarch64-linux-gnu-objdump) --coreos special mode for CoreOS (use an ephemeral toolbox to inspect kernel) [Linux] Output: --batch FORMAT produce machine readable output; FORMAT is one of: text (default), short, json, json-terse, nrpe, prometheus --no-color don't use color codes --verbose, -v increase verbosity level, possibly several times --explain produce an additional human-readable explanation of actions to take to mitigate a vulnerability Firmware database: --update-fwdb update our local copy of the CPU microcodes versions database (using the awesome MCExtractor project and the Intel firmwares GitHub repository) --update-builtin-fwdb same as --update-fwdb but update builtin DB inside the script itself Debug: --dump-mock-data used to mimick a CPU on an other system, mainly used to help debugging this script Return codes: 0 (not vulnerable), 2 (vulnerable), 3 (unknown), 255 (error) IMPORTANT: A false sense of security is worse than no security at all. Please use the --disclaimer option to understand exactly what this script does. EOF } # Print the legal disclaimer about tool accuracy and limitations show_disclaimer() { cat <. # CVE-9999-NNNN: temporary placeholder for real vulnerabilities awaiting CVE # assignment. Rename across the codebase once the real CVE is issued. readonly CVE_REGISTRY=' CVE-2017-5753|SPECTRE VARIANT 1|variant1|Spectre Variant 1, bounds check bypass CVE-2017-5715|SPECTRE VARIANT 2|variant2|Spectre Variant 2, branch target injection CVE-2017-5754|MELTDOWN|variant3|Variant 3, Meltdown, rogue data cache load CVE-2018-3640|VARIANT 3A|variant3a|Variant 3a, rogue system register read CVE-2018-3639|VARIANT 4|variant4|Variant 4, speculative store bypass CVE-2018-3615|L1TF SGX|variantl1tf_sgx|Foreshadow (SGX), L1 terminal fault CVE-2018-3620|L1TF OS|variantl1tf|Foreshadow-NG (OS), L1 terminal fault CVE-2018-3646|L1TF VMM|variantl1tf|Foreshadow-NG (VMM), L1 terminal fault CVE-2018-12126|MSBDS|msbds|Fallout, microarchitectural store buffer data sampling (MSBDS) CVE-2018-12130|MFBDS|mfbds|ZombieLoad, microarchitectural fill buffer data sampling (MFBDS) CVE-2018-12127|MLPDS|mlpds|RIDL, microarchitectural load port data sampling (MLPDS) CVE-2019-11091|MDSUM|mdsum|RIDL, microarchitectural data sampling uncacheable memory (MDSUM) CVE-2019-11135|TAA|taa|ZombieLoad V2, TSX Asynchronous Abort (TAA) CVE-2018-12207|ITLBMH|itlbmh|No eXcuses, iTLB Multihit, machine check exception on page size changes (MCEPSC) CVE-2020-0543|SRBDS|srbds|Special Register Buffer Data Sampling (SRBDS) CVE-2022-21123|SBDR|mmio|Shared Buffers Data Read (SBDR), MMIO Stale Data CVE-2022-21125|SBDS|mmio|Shared Buffers Data Sampling (SBDS), MMIO Stale Data CVE-2022-21166|DRPW|mmio|Device Register Partial Write (DRPW), MMIO Stale Data CVE-2023-20588|DIV0|div0|Division by Zero, AMD Zen1 speculative data leak CVE-2023-20593|ZENBLEED|zenbleed|Zenbleed, cross-process information leak CVE-2022-40982|DOWNFALL|downfall|Downfall, gather data sampling (GDS) CVE-2022-29900|RETBLEED AMD|retbleed|Retbleed, arbitrary speculative code execution with return instructions (AMD) CVE-2022-29901|RETBLEED INTEL|retbleed|Retbleed, arbitrary speculative code execution with return instructions (Intel) CVE-2023-20569|INCEPTION|inception|Inception, return address security (RAS) CVE-2023-23583|REPTAR|reptar|Reptar, redundant prefix issue CVE-2024-36350|TSA_SQ|tsa|Transient Scheduler Attack - Store Queue (TSA-SQ) CVE-2024-36357|TSA_L1|tsa|Transient Scheduler Attack - L1 (TSA-L1) CVE-2024-28956|ITS|its|Indirect Target Selection (ITS) CVE-2025-40300|VMSCAPE|vmscape|VMScape, VM-exit stale branch prediction CVE-2023-28746|RFDS|rfds|Register File Data Sampling (RFDS) CVE-2024-45332|BPI|bpi|Branch Privilege Injection (BPI) CVE-0000-0001|SLS|sls|Straight-Line Speculation (SLS) CVE-2025-54505|FPDSS|fpdss|FPDSS, AMD Zen1 Floating-Point Divider Stale Data Leak CVE-0001-0001|ARM SPEC AT|arm_spec_at|ARM64 errata 1165522/1319367/1319537/1530923, Speculative AT TLB corruption CVE-0001-0002|ARM SPEC UNPRIV LOAD|arm_spec_unpriv_load|ARM64 errata 2966298/3117295, Speculative unprivileged load CVE-0001-0003|ARM SSBS NOSYNC|arm_ssbs_nosync|ARM64 erratum 3194386, MSR SSBS not self-synchronizing ' # Derive the supported CVE list from the registry g_supported_cve_list=$(echo "$CVE_REGISTRY" | grep '^CVE-' | cut -d'|' -f1) # Look up a field from the CVE registry # Args: $1=cve_id $2=field_number (see CVE_REGISTRY format above) # Callers: cve2name, _is_cpu_affected_cached, pvulnstatus _cve_registry_field() { local line line=$(echo "$CVE_REGISTRY" | grep -E "^$1\|") if [ -z "$line" ]; then echo "$0: error: invalid CVE '$1' passed to _cve_registry_field()" >&2 exit 255 fi echo "$line" | cut -d'|' -f"$2" } # find a sane command to print colored messages, we prefer `printf` over `echo` # because `printf` behavior is more standard across Linux/BSD # we'll try to avoid using shell builtins that might not take options g_echo_cmd_type='echo' # ignore SC2230 here because `which` ignores builtins while `command -v` doesn't, and # we don't want builtins here. Even if `which` is not installed, we'll fallback to the # `echo` builtin anyway, so this is safe. # shellcheck disable=SC2230 if command -v printf >/dev/null 2>&1; then g_echo_cmd=$(command -v printf) g_echo_cmd_type='printf' elif which echo >/dev/null 2>&1; then g_echo_cmd=$(which echo) else # maybe the `which` command is broken? [ -x /bin/echo ] && g_echo_cmd=/bin/echo # for Android [ -x /system/bin/echo ] && g_echo_cmd=/system/bin/echo fi # still empty? fallback to builtin [ -z "$g_echo_cmd" ] && g_echo_cmd='echo'