diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 522b7f2..e1a8c36 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,6 +17,8 @@ jobs: persist-credentials: true - name: install prerequisites run: sudo apt-get update && sudo apt-get install -y shellcheck shfmt jq sqlite3 iucode-tool make + - name: update Intel model list + run: ./scripts/update_intel_models.sh - name: build and check run: | make build fmt-check shellcheck diff --git a/.github/workflows/expected_cve_count b/.github/workflows/expected_cve_count index aabe6ec..4099407 100644 --- a/.github/workflows/expected_cve_count +++ b/.github/workflows/expected_cve_count @@ -1 +1 @@ -21 +23 diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index a562e7f..0e3a12e 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -222,24 +222,29 @@ Before writing code, verify the CVE meets the inclusion criteria (see "CVE Inclu ### Step 1: Create the Vulnerability File -Create `src/vulns/CVE-YYYY-NNNNN.sh`. The file must contain exactly three functions: +Create `src/vulns/CVE-YYYY-NNNNN.sh`. The file header must follow this exact format: + +- **Line 1**: vim modeline (`# vim: set ts=4 sw=4 sts=4 et:`) +- **Line 2**: 31 `#` characters (`###############################`) +- **Line 3**: `# CVE-YYYY-NNNNN, Alias1, Alias2, Complete Name` — the CVE number followed by + all known aliases and the complete name as listed in the `dist/README.md` top table. +- **Line 4**: empty + +The file must contain exactly three functions: ```sh # vim: set ts=4 sw=4 sts=4 et: -#################### -# SHORT_NAME section +############################### +# CVE-YYYY-NNNNN, Short Name, Complete Name -# CVE-YYYY-NNNNN SHORT_NAME (one-line description) - entry point check_CVE_YYYY_NNNNN() { check_cve 'CVE-YYYY-NNNNN' } -# CVE-YYYY-NNNNN SHORT_NAME (one-line description) - Linux mitigation check check_CVE_YYYY_NNNNN_linux() { # ... (see Step 3) } -# CVE-YYYY-NNNNN SHORT_NAME (one-line description) - BSD mitigation check check_CVE_YYYY_NNNNN_bsd() { if ! is_cpu_affected "$cve"; then pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" @@ -409,24 +414,67 @@ reports vulnerable. Additionally, in Phase 2, add a kernel-image grep to inform whether their kernel has the corrected reporting (the post-fix kernel will contain the new vulnerability string in its image). -**Sysfs message inventory:** Before writing Phase 1 (and any sysfs overrides), audit **every -version** of the sysfs message that the kernel has ever produced for this vulnerability. The -script may run on any kernel - from early release candidates that first introduced the sysfs -file, through every stable release, up to the latest mainline. The inventory must catalogue -every string variant, including: +**Kernel source inventory:** Before writing any code, audit the kernel source history for +four categories of information that the script consumes in different modes: -- Messages that only existed briefly between two commits in the same release cycle. -- Format changes (e.g. field reordering, renamed labels). +1. **Sysfs messages** — every version of the string the kernel has ever produced for + `/sys/devices/system/cpu/vulnerabilities/`. Used in live mode to parse the + kernel's own assessment, and in offline mode to grep for known strings in `$g_kernel`. +2. **Kconfig option names** — every `CONFIG_*` symbol that enables or controls the + mitigation. Used in offline mode to check `$opt_config`. Kconfig names change over + time (e.g. `CONFIG_GDS_FORCE_MITIGATION` → `CONFIG_MITIGATION_GDS_FORCE` → + `CONFIG_MITIGATION_GDS`), and vendor kernels may use their own names, so all variants + must be catalogued. +3. **Kernel function names** — functions introduced specifically for the mitigation (e.g. + `gds_select_mitigation`, `gds_apply_mitigation`, `l1tf_select_mitigation`). Used in + offline mode to check `$opt_map` (System.map): the presence of a mitigation function + proves the kernel was compiled with the mitigation code, even if the config file is + unavailable. +4. **CPU affection logic** — the complete algorithm the kernel uses to decide whether a + CPU is affected by the vulnerability (i.e. whether it sets the `X86_BUG_*` flag). This + is what the script must replicate in `is_cpu_affected()`. The kernel typically uses a + combination of: + - **Model blacklists/whitelists**: explicit lists of CPU vendor/family/model/stepping + values (e.g. `cpu_vuln_blacklist[]` in `arch/x86/kernel/cpu/common.c`). These lists + can change between kernel versions — models may be added when new errata surface + (e.g. client Skylake was initially missing from GDS and added in a follow-up commit). + - **MSR/CPUID immunity bits**: hardware bits that the CPU vendor defines to declare + "this hardware is not affected" (e.g. `ARCH_CAP_GDS_NO`, `ARCH_CAP_RDCL_NO`). These + bits are already read in `check_cpu()` and stored as `cap_*_no` globals. + - **Feature dependencies**: some vulnerabilities only apply when a specific CPU feature + is present (e.g. GDS requires AVX because GATHER instructions need it; TAA requires + TSX). If the feature is absent or disabled, the CPU is immune. + - **Vendor scoping**: most vulnerabilities are vendor-specific (Intel-only, AMD-only), + but some span multiple vendors. Document which vendors are checked. + + The inventory must trace how this logic evolved across kernel versions, because models + are sometimes added in follow-up commits (as with Skylake for GDS) and the script must + include the most complete and up-to-date list. Document every commit that changed the + model list or the affection conditions. + +The script may run on any kernel — from early release candidates that first introduced +support, through every stable release, up to the latest mainline, as well as vendor kernels +(RHEL, SUSE, Ubuntu, etc.). The inventory must catalogue every variant across all of these, +including: + +- Messages/configs/functions that only existed briefly between two commits in the same + release cycle. +- Format changes (e.g. field reordering, renamed labels, renamed Kconfig symbols). - New states added in later kernels (e.g. new flush modes, new mitigation strategies). - Reporting corrections where a later kernel changed its assessment of what counts as mitigated (e.g. a message that said `"Mitigation: ..."` in kernel A is reclassified as `"Vulnerable: ..."` in kernel B under the same conditions). +- Functions that were added, renamed, or split across commits (e.g. a single + `gds_mitigation_update()` later split into `gds_select_mitigation()` + + `gds_apply_mitigation()`). +- CPU model list changes (models added or removed from the vulnerability blacklist in + follow-up commits or stable backports). Document all discovered variants as comments in the CVE file, grouped by the kernel commit that introduced or changed them, so future readers can understand the evolution at a glance. See `src/vulns/CVE-2018-3646.sh` (Phase 1 comment block) for a reference example. -This inventory matters because later kernels may have a different - and more accurate - view +This inventory matters because later kernels may have a different — and more accurate — view of what is vulnerable versus mitigated for a given vulnerability, as understanding progresses over time. The script must be able to reach the same conclusions as the most recent kernel, even when running under an old kernel that misreports a vulnerability as mitigated. This is @@ -437,17 +485,35 @@ corrected reporting. **How to build the inventory - git blame walkback method:** -The goal is to find every commit that changed the sysfs output strings for a given -vulnerability. The method uses `git blame` iteratively, walking backwards through history -until the vulnerability's sysfs reporting no longer exists. +The goal is to find every commit that changed the sysfs output strings, Kconfig symbols, +mitigation function names, or CPU affection logic for a given vulnerability. The method uses +`git blame` iteratively, walking backwards through history until the vulnerability's support +no longer exists. -1. **Locate the output function.** Most vulnerability sysfs files are generated from - `arch/x86/kernel/cpu/bugs.c`. Find the `*_show_state()` function for the vulnerability - (e.g. `l1tf_show_state()`, `mds_show_state()`) and the corresponding `case X86_BUG_*` - in `cpu_show_common()`. Both paths can produce messages: the show_state function handles - the mitigated cases, while `cpu_show_common()` handles `"Not affected"` (common to all - bugs) and `"Vulnerable"` (fallthrough). Some vulnerabilities also use string arrays - (e.g. `l1tf_vmx_states[]`, `spectre_v1_strings[]`) - include those in the audit. +1. **Locate the relevant code.** Most vulnerability code lives in two files: + `arch/x86/kernel/cpu/bugs.c` (mitigation logic and sysfs reporting) and + `arch/x86/kernel/cpu/common.c` (CPU affection detection). Find: + - The `*_show_state()` function for the vulnerability (e.g. `l1tf_show_state()`, + `mds_show_state()`) and the corresponding `case X86_BUG_*` in `cpu_show_common()`. + Both paths can produce messages: the show_state function handles the mitigated cases, + while `cpu_show_common()` handles `"Not affected"` (common to all bugs) and + `"Vulnerable"` (fallthrough). Some vulnerabilities also use string arrays (e.g. + `l1tf_vmx_states[]`, `spectre_v1_strings[]`) — include those in the audit. + - The `*_select_mitigation()` and `*_apply_mitigation()` functions (or a single + `*_update_mitigation()` in older code). These are the function names that appear in + System.map and can be checked via `$opt_map`. + - The `Kconfig` entries: search `arch/x86/Kconfig` (and `arch/x86/Kconfig.cpu` or + similar) for `CONFIG_*` symbols related to the mitigation. Note every name variant + across kernel versions. + - The **CPU affection detection** in `arch/x86/kernel/cpu/common.c`: find where + `X86_BUG_` is set. This typically involves a lookup in `cpu_vuln_blacklist[]` + (or `cpu_vuln_whitelist[]`) combined with checks on `IA32_ARCH_CAPABILITIES` MSR + bits and CPU feature flags. Document: + - The complete model list (vendor, family, model, stepping ranges). + - Which `ARCH_CAP_*` bits grant immunity (e.g. `ARCH_CAP_GDS_NO`). + - Which CPU features are prerequisites (e.g. AVX for GDS, TSX for TAA). + - Any other conditions (hypervisor detection, microcode version checks, etc.). + - How this logic evolved: models added/removed in follow-up commits. 2. **Blame the current code.** Run `git blame` on the relevant line range: @@ -535,12 +601,13 @@ until the vulnerability's sysfs reporting no longer exists. The inventory comment goes in Phase 1, right after `sys_interface_check` returns successfully. Group entries chronologically by commit, newest last. For each commit, show the hash, the -kernel version it appeared in, and the exact message(s) it introduced or changed. Use `+` to -indicate incremental additions to an enum or format. Example: +kernel version it appeared in, and the exact message(s)/config(s)/function(s) it introduced +or changed. Use `+` to indicate incremental additions to an enum or format. Example: ```sh - # Complete sysfs message inventory for , traced via git blame: + # Kernel source inventory for , traced via git blame: # + # --- sysfs messages --- # all versions: # "Not affected" (cpu_show_common, ) # "Vulnerable" (cpu_show_common fallthrough, ) @@ -554,10 +621,30 @@ indicate incremental additions to an enum or format. Example: # : + value4 # # all messages start with either "Not affected", "Mitigation", or "Vulnerable" + # + # --- Kconfig symbols --- + # (): CONFIG_ORIGINAL_NAME (y/n) + # (): renamed to CONFIG_NEW_NAME + # (): replaced by CONFIG_ANOTHER_NAME (on/off, no force) + # vendor kernels: CONFIG_VENDOR_SPECIFIC_NAME (RHEL 8.x) + # + # --- kernel functions (for $opt_map / System.map) --- + # (): _mitigation_update() + # (): split into _select_mitigation() + _apply_mitigation() + # + # --- CPU affection logic (for is_cpu_affected) --- + # (, initial model list): + # Intel: MODEL_A, MODEL_B, MODEL_C (all steppings) + # Intel: MODEL_D (stepping 0x0 - 0x5 only) + # (, added missing models): + # Intel: + MODEL_E, MODEL_F + # immunity: ARCH_CAP__NO (bit NN of IA32_ARCH_CAPABILITIES) + # feature dependency: requires (if absent, CPU is immune) + # vendor scope: Intel only (no AMD/Hygon/other entries) ``` -The final line (`all messages start with ...`) is a summary that helps verify the grep -patterns used to derive `status` from the message are complete. +The final line of the sysfs section (`all messages start with ...`) is a summary that helps +verify the grep patterns used to derive `status` from the message are complete. ### Cross-Cutting Features @@ -654,6 +741,7 @@ Every function must have a documentation header immediately above its definition - The `# Callers:` line is required for all `_`-prefixed functions. It documents which functions depend on this helper, making it safe to refactor. - Keep descriptions to one line when possible. If more context is needed, add continuation comment lines before the structured lines. - Parameter documentation uses `$1=name` format. Append `(optional, default X)` for optional parameters. +- **Exception**: `check_CVE_*` functions (`check_CVE_YYYY_NNNNN`, `_linux`, `_bsd`) are exempt from the documentation header requirement. They are self-explanatory, take no arguments, and live in dedicated `src/vulns/CVE-YYYY-NNNNN.sh` files whose line-3 header already describes the vulnerability. **Full example:** diff --git a/UNSUPPORTED_CVE_LIST.md b/UNSUPPORTED_CVE_LIST.md index 194b64b..f24ec69 100644 --- a/UNSUPPORTED_CVE_LIST.md +++ b/UNSUPPORTED_CVE_LIST.md @@ -1,11 +1,64 @@ # Unsupported CVEs -This document lists transient execution CVEs that have been evaluated and determined to be **out of scope** for this tool. See the "CVE Inclusion Criteria" section in [DEVELOPMENT.md](DEVELOPMENT.md) for the general policy. +This document lists transient execution CVEs that have been evaluated and determined to be **out of scope** for this tool. See the [Which rules are governing the support of a CVE in this tool?](dist/FAQ.md#which-rules-are-governing-the-support-of-a-cve-in-this-tool) section in the FAQ for the general policy. + +## CVE-2018-9056 — BranchScope + +- **Issue:** [#169](https://github.com/speed47/spectre-meltdown-checker/issues/169) +- **Research paper:** [BranchScope (ASPLOS 2018)](http://www.cs.ucr.edu/~nael/pubs/asplos18.pdf) +- **Red Hat bug:** [#1561794](https://bugzilla.redhat.com/show_bug.cgi?id=1561794) +- **CVSS:** 5.6 (Medium) + +A speculative execution attack exploiting the directional branch predictor, allowing an attacker to infer data by manipulating the shared branch prediction state (pattern history table). Initially demonstrated on Intel processors. + +**Why out of scope:** No kernel or microcode mitigations have been issued. Red Hat closed their tracking bug as "CLOSED CANTFIX", concluding that "this is a hardware processor issue, not a Linux kernel flaw" and that "it is specific to a target software which uses sensitive information in branching expressions." The mitigation responsibility falls on individual software to avoid using sensitive data in conditional branches, which is out of the scope of this tool. + +## CVE-2018-3693 — Bounds Check Bypass Store (Spectre v1.1) + +- **Issue:** [#236](https://github.com/speed47/spectre-meltdown-checker/issues/236) +- **Red Hat advisory:** [Speculative Store Bypass / Bounds Check Bypass (CVE-2018-3693)](https://access.redhat.com/solutions/3523601) +- **CVSS:** 5.6 (Medium) + +A subvariant of Spectre V1 where speculative store operations can write beyond validated buffer boundaries before the bounds check resolves, allowing an attacker to alter cache state and leak information via side channels. + +**Why out of scope:** The mitigations are identical to CVE-2017-5753 (Spectre V1): `lfence` instructions after bounds checks and `array_index_nospec()` barriers in kernel code. There is no separate sysfs entry, no new CPU feature flag, and no distinct microcode change. This tool's existing CVE-2017-5753 checks already detect these mitigations (`__user pointer sanitization`, `usercopy/swapgs barriers`), so CVE-2018-3693 is fully covered as part of Spectre V1. + +## CVE-2018-15572 — SpectreRSB (Return Stack Buffer) + +- **Issue:** [#224](https://github.com/speed47/spectre-meltdown-checker/issues/224) +- **Research paper:** [Spectre Returns! Speculation Attacks using the Return Stack Buffer (WOOT'18)](https://arxiv.org/abs/1807.07940) +- **Kernel fix:** [commit fdf82a7856b3](https://github.com/torvalds/linux/commit/fdf82a7856b32d905c39afc85e34364491e46346) (Linux 4.18.1) +- **CVSS:** 6.5 (Medium) + +The `spectre_v2_select_mitigation` function in the Linux kernel before 4.18.1 did not always fill the RSB upon a context switch, allowing userspace-to-userspace SpectreRSB attacks on Skylake+ CPUs where an empty RSB falls back to +he BTB. + +**Why out of scope:** This CVE is a Spectre V2 mitigation gap (missing RSB filling on context switch), not a distinct hardware vulnerability. It is already fully covered by this tool's CVE-2017-5715 (Spectre V2) checks, which dete +ct whether the kernel performs RSB filling on CPUs vulnerable to RSB underflow (Skylake+ and RSBA-capable CPUs). A missing RSB fill is flagged as a caveat ("RSB filling missing on Skylake+") in the Spectre V2 verdict. + +## CVE-2019-1125 — Spectre SWAPGS gadget + +- **Issue:** [#301](https://github.com/speed47/spectre-meltdown-checker/issues/301) +- **Kernel fix:** [commit 18ec54fdd6d1](https://github.com/torvalds/linux/commit/18ec54fdd6d18d92025af097cd042a75cf0ea24c) (Linux 5.3) +- **CVSS:** 5.6 (Medium) + +A Spectre V1 subvariant where the `SWAPGS` instruction can be speculatively executed on x86 CPUs, allowing an attacker to leak kernel memory via a side channel on the GS segment base value. + +**Why out of scope:** This is a Spectre V1 subvariant whose mitigation (SWAPGS barriers) shares the same sysfs entry as CVE-2017-5753. This tool's existing CVE-2017-5753 checks already detect SWAPGS barriers: a mitigated kernel reports `"Mitigation: usercopy/swapgs barriers and __user pointer sanitization"`, while a kernel lacking the fix reports `"Vulnerable: __user pointer sanitization and usercopy barriers only; no swapgs barriers"`. CVE-2019-1125 is therefore fully covered as part of Spectre V1. + +## CVE-2019-15902 — Spectre V1 backport regression + +- **Issue:** [#304](https://github.com/speed47/spectre-meltdown-checker/issues/304) +- **CVSS:** 5.6 (Medium) + +A backporting mistake in Linux stable/longterm kernel versions (4.4.x through 4.4.190, 4.9.x through 4.9.190, 4.14.x through 4.14.141, 4.19.x through 4.19.69, and 5.2.x through 5.2.11) swapped two code lines in `ptrace_get_debugreg()`, placing the `array_index_nospec()` call after the array access instead of before, reintroducing a Spectre V1 vulnerability. + +**Why out of scope:** This is a kernel bug (bad backport), not a hardware vulnerability. The flawed code is not detectable on a running kernel without hardcoding kernel version ranges, which is against this tool's design principles. As the tool author noted: "it's going to be almost impossible to detect it on a running kernel." ## CVE-2024-36348 — AMD Transient Scheduler Attack (UMIP bypass) -**Bulletin:** [AMD-SB-7029](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7029.html) -**CVSS:** 3.8 (Low) +- **Bulletin:** [AMD-SB-7029](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7029.html) +- **CVSS:** 3.8 (Low) A transient execution vulnerability in some AMD processors may allow a user process to speculatively infer CPU configuration registers even when UMIP is enabled. @@ -13,8 +66,8 @@ A transient execution vulnerability in some AMD processors may allow a user proc ## CVE-2024-36349 — AMD Transient Scheduler Attack (TSC_AUX leak) -**Bulletin:** [AMD-SB-7029](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7029.html) -**CVSS:** 3.8 (Low) +- **Bulletin:** [AMD-SB-7029](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7029.html) +- **CVSS:** 3.8 (Low) A transient execution vulnerability in some AMD processors may allow a user process to infer TSC_AUX even when such a read is disabled. diff --git a/dist/README.md b/dist/README.md index 9198503..7643ef6 100644 --- a/dist/README.md +++ b/dist/README.md @@ -22,6 +22,8 @@ CVE | Name | Aliases [CVE-2019-11135](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11135) | TSX Asynchronous Abort | TAA, ZombieLoad V2 [CVE-2018-12207](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12207) | Machine Check Exception on Page Size Changes | iTLB Multihit, No eXcuses [CVE-2020-0543](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0543) | Special Register Buffer Data Sampling | SRBDS, CROSSTalk +[CVE-2022-29900](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-29900) | Arbitrary Speculative Code Execution with Return Instructions | Retbleed (AMD) +[CVE-2022-29901](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-29901) | Arbitrary Speculative Code Execution with Return Instructions | Retbleed (Intel), RSBA [CVE-2022-40982](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-40982) | Gather Data Sampling | Downfall, GDS [CVE-2023-20569](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-20569) | Return Address Security | Inception, SRSO [CVE-2023-20593](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-20593) | Cross-Process Information Leak | Zenbleed @@ -51,6 +53,8 @@ CVE-2019-11091 (MDSUM, RIDL) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + k CVE-2019-11135 (TAA, ZombieLoad V2) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update CVE-2018-12207 (iTLB Multihit, No eXcuses) | ✅ | ✅ | ☠️ | ✅ | Hypervisor update (or disable hugepages) CVE-2020-0543 (SRBDS, CROSSTalk) | 💥 (2) | 💥 (2) | 💥 (2) | 💥 (2) | Microcode + kernel update +CVE-2022-29900 (Retbleed AMD) | 💥 | ✅ | 💥 | ✅ | Kernel update (+ microcode for IBPB) +CVE-2022-29901 (Retbleed Intel, RSBA) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update (eIBRS or IBRS) CVE-2022-40982 (Downfall, GDS) | 💥 | 💥 | 💥 | 💥 | Microcode update (or disable AVX) CVE-2023-20569 (Inception, SRSO) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update CVE-2023-20593 (Zenbleed) | 💥 | 💥 | 💥 | 💥 | Microcode update (or kernel workaround) @@ -129,6 +133,14 @@ A malicious guest VM can trigger a machine check exception (MCE) — crashing th Certain special CPU instructions (RDRAND, RDSEED, EGETKEY) read data through a shared staging buffer that is accessible across all cores via speculative execution. An attacker running code on any core can observe the output of these instructions from a victim on a different core, including extracting cryptographic keys from SGX enclaves (a complete ECDSA key was demonstrated). This is notable as one of the first cross-core speculative execution attacks. Mitigation requires a microcode update that serializes access to the staging buffer, plus a kernel update to manage the mitigation. Performance impact is low, mainly affecting workloads that heavily use RDRAND/RDSEED. +**CVE-2022-29900 — Arbitrary Speculative Code Execution with Return Instructions (Retbleed AMD)** + +On AMD processors from families 0x15 through 0x17 (Bulldozer through Zen 2) and Hygon family 0x18, an attacker can exploit return instructions to redirect speculative execution and leak kernel memory, bypassing retpoline mitigations that were effective against Spectre V2. Unlike Spectre V2 which targets indirect jumps and calls, Retbleed specifically targets return instructions, which were previously considered safe. Mitigation requires a kernel update providing either the untrained return thunk (safe RET) or IBPB-on-entry mechanism, plus a microcode update providing IBPB support on Zen 1/2. On Zen 1/2, SMT should be disabled for full protection when using IBPB-based mitigation. Performance impact is medium. + +**CVE-2022-29901 — Arbitrary Speculative Code Execution with Return Instructions (Retbleed Intel, RSBA)** + +On Intel Skylake through Rocket Lake processors with RSB Alternate Behavior (RSBA), return instructions can be speculatively redirected via the Branch Target Buffer when the Return Stack Buffer underflows, bypassing retpoline mitigations. Mitigation requires either Enhanced IBRS (eIBRS, via microcode update) or a kernel compiled with IBRS-on-entry support (Linux 5.19+). Call depth tracking (stuffing) is an alternative mitigation available from Linux 6.2+. Plain retpoline does NOT mitigate this vulnerability on RSBA-capable CPUs. Performance impact is medium to high. + **CVE-2022-40982 — Gather Data Sampling (GDS, Downfall)** The AVX GATHER instructions can leak data from previously used vector registers across privilege boundaries through the shared gather data buffer. This affects any software using AVX2 or AVX-512 on vulnerable Intel processors. Mitigation is provided by a microcode update that clears the gather buffer, or alternatively by disabling the AVX feature entirely. Performance impact is negligible for most workloads but can be significant (up to 50%) for AVX-heavy applications such as HPC and AI inference. @@ -155,6 +167,13 @@ On AMD Zen 3 and Zen 4 processors, the CPU's transient scheduler may speculative +## Unsupported CVEs + +Several transient execution CVEs are not covered by this tool, for various reasons (duplicates, only +affecting non-supported hardware or OS, theoretical with no known exploitation, etc.). +The complete list along with the reason for each exclusion is available in the +[UNSUPPORTED_CVE_LIST.md](https://github.com/speed47/spectre-meltdown-checker/blob/source/UNSUPPORTED_CVE_LIST.md) file. + ## Scope Supported operating systems: diff --git a/scripts/update_intel_models.sh b/scripts/update_intel_models.sh new file mode 100755 index 0000000..059be8a --- /dev/null +++ b/scripts/update_intel_models.sh @@ -0,0 +1,80 @@ +#!/bin/sh +# vim: set ts=4 sw=4 sts=4 et: +# Download and parse Linux kernel's intel-family.h to generate src/libs/003_intel_models.sh. +# Usage: scripts/update_intel_models.sh + +set -eu + +SCRIPTDIR="$(cd "$(dirname "$0")" && pwd)" +REPODIR="$(dirname "$SCRIPTDIR")" +OUTFILE="$REPODIR/src/libs/003_intel_models.sh" +URL="https://raw.githubusercontent.com/torvalds/linux/refs/heads/master/arch/x86/include/asm/intel-family.h" + +TMPFILE=$(mktemp /tmp/intel-family-XXXXXX.h) +trap 'rm -f "$TMPFILE"' EXIT INT TERM + +echo "Downloading $URL ..." +wget -q -O "$TMPFILE" "$URL" +echo "Parsing intel-family.h ..." + +{ + cat <<'HEADER' +# vim: set ts=4 sw=4 sts=4 et: +# AUTO-GENERATED FILE — DO NOT EDIT MANUALLY. +# Generated by scripts/update_intel_models.sh from: +# https://raw.githubusercontent.com/torvalds/linux/refs/heads/master/arch/x86/include/asm/intel-family.h +# Run scripts/update_intel_models.sh to refresh when new Intel CPU families are added to the kernel. +# shellcheck disable=SC2034 +{ +HEADER + + awk ' +/^#define INTEL_[A-Z0-9_]+[[:space:]]+IFM\(/ { + name = $2 + + # Skip wildcard and notational markers + if (name == "INTEL_ANY") next + if (name ~ /_START$/) next + if (name ~ /_LAST$/) next + + # Extract the IFM(...) argument string + line = $0 + sub(/.*IFM\(/, "", line) # line is now: "N, 0xNN) ..." + + # Extract family + family = line + sub(/,.*/, "", family) + gsub(/[[:space:]]/, "", family) + # Skip non-numeric families (e.g. X86_FAMILY_ANY) + if (family !~ /^[0-9]+$/) next + + # Extract model + rest = line + sub(/^[^,]+, */, "", rest) # remove "N, " + model = rest + sub(/\).*/, "", model) + gsub(/[[:space:]]/, "", model) + + # Extract optional C comment and convert to shell comment + comment = "" + if (index($0, "/*") > 0) { + c = $0 + sub(/.*\/\*/, "/* ", c) + gsub(/ +/, " ", c) + sub(/ *\*\/.*/, " */", c) + comment = "\t# " c + } + + # Strip INTEL_ prefix; prepend INTEL_FAM_ + sub(/^INTEL_/, "", name) + varname = "INTEL_FAM" family "_" name + + printf "\treadonly %s=$(( %s ))%s\n", varname, model, comment +} +' "$TMPFILE" + + printf '}\n' + +} | shfmt -i 4 -ci -ln bash > "$OUTFILE" + +echo "Generated $OUTFILE ($(wc -l < "$OUTFILE") lines)" diff --git a/src/libs/001_core_header.sh b/src/libs/001_core_header.sh index 6c3de60..f2f7e9b 100644 --- a/src/libs/001_core_header.sh +++ b/src/libs/001_core_header.sh @@ -46,6 +46,6 @@ exit_cleanup() { # if we were git clone'd, adjust VERSION if [ -d "$(dirname "$0")/.git" ] && command -v git >/dev/null 2>&1; then - g_describe=$(git -C "$(dirname "$0")" describe --tags --dirty 2>/dev/null) - [ -n "$g_describe" ] && VERSION=$(echo "$g_describe" | sed -e s/^v//) + g_commit=$(git -C "$(dirname "$0")" describe --always --dirty --abbrev=7 --match=- 2>/dev/null) + [ -n "$g_commit" ] && VERSION="$VERSION-git$g_commit" fi diff --git a/src/libs/002_core_globals.sh b/src/libs/002_core_globals.sh index 4328db9..fe91138 100644 --- a/src/libs/002_core_globals.sh +++ b/src/libs/002_core_globals.sh @@ -155,6 +155,8 @@ CVE-2018-12207|ITLBMH|itlbmh|No eXcuses, iTLB Multihit, machine check exception CVE-2020-0543|SRBDS|srbds|Special Register Buffer Data Sampling (SRBDS) 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) diff --git a/src/libs/200_cpu_affected.sh b/src/libs/200_cpu_affected.sh index 7206a39..a8ba650 100644 --- a/src/libs/200_cpu_affected.sh +++ b/src/libs/200_cpu_affected.sh @@ -104,6 +104,8 @@ is_cpu_affected() { _set_immune inception # TSA is AMD specific (Zen 3/4), look for "is_amd" below: _set_immune tsa + # Retbleed: AMD (CVE-2022-29900) and Intel (CVE-2022-29901) specific: + _set_immune retbleed # Downfall & Reptar are Intel specific, look for "is_intel" below: _set_immune downfall _set_immune reptar @@ -126,6 +128,14 @@ is_cpu_affected() { pr_debug "is_cpu_affected: cpu not affected by Special Register Buffer Data Sampling" fi + # NO_SPECTRE_V2: Centaur family 7 and Zhaoxin family 7 are immune to Spectre V2 + # kernel commit 1e41a766c98b (v5.6-rc1): added NO_SPECTRE_V2 exemption + # Zhaoxin vendor_id is " Shanghai " in cpuinfo (parsed as "Shanghai" by awk) + if { [ "$cpu_vendor" = "CentaurHauls" ] || [ "$cpu_vendor" = "Shanghai" ]; } && [ "$cpu_family" = 7 ]; then + _infer_immune variant2 + pr_debug "is_cpu_affected: Centaur/Zhaoxin family 7 immune to Spectre V2 (NO_SPECTRE_V2)" + fi + if is_cpu_specex_free; then _set_immune variant1 _set_immune variant2 @@ -195,7 +205,7 @@ is_cpu_affected() { [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_D" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] || - [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT_MID" ] || + [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID2" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT_NP" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] || @@ -222,9 +232,12 @@ is_cpu_affected() { pr_debug "is_cpu_affected: downfall: not affected (GDS_NO)" _set_immune downfall elif [ "$cpu_family" = 6 ]; then - # list from https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=64094e7e3118aff4b0be8ff713c242303e139834 + # model blacklist from the kernel (arch/x86/kernel/cpu/common.c cpu_vuln_blacklist): + # 8974eb588283 (initial list) + c9f4c45c8ec3 (added Skylake/Skylake_L client) set -u - if [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] || + if [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] || + [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ] || + [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] || [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] || [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] || [ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] || @@ -239,10 +252,12 @@ is_cpu_affected() { _set_vuln downfall elif [ "$cap_avx2" = 0 ] && [ "$cap_avx512" = 0 ]; then pr_debug "is_cpu_affected: downfall: no avx; immune" + _infer_immune downfall else - # old Intel CPU (not in their DB), not listed as being affected by the Linux kernel, - # but with AVX2 or AVX512: unclear for now - pr_debug "is_cpu_affected: downfall: unclear, defaulting to non-affected for now" + # Intel family 6 CPU with AVX2 or AVX512, not in the known-affected list + # and GDS_NO not set: assume affected (whitelist principle) + pr_debug "is_cpu_affected: downfall: unknown AVX-capable CPU, defaulting to affected" + _infer_vuln downfall fi set +u fi @@ -301,6 +316,27 @@ is_cpu_affected() { fi done + # Retbleed (Intel, CVE-2022-29901): Skylake through Rocket Lake, or any CPU with RSBA + # kernel cpu_vuln_blacklist for RETBLEED (6b80b59b3555, 6ad0ad2bf8a6, f54d45372c6a) + # plus ARCH_CAP_RSBA catch-all (bit 2 of IA32_ARCH_CAPABILITIES) + if [ "$cap_rsba" = 1 ]; then + _set_vuln retbleed + elif [ "$cpu_family" = 6 ]; then + if [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] || + [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ] || + [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] || + [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] || + [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] || + [ "$cpu_model" = "$INTEL_FAM6_CANNONLAKE_L" ] || + [ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] || + [ "$cpu_model" = "$INTEL_FAM6_COMETLAKE" ] || + [ "$cpu_model" = "$INTEL_FAM6_COMETLAKE_L" ] || + [ "$cpu_model" = "$INTEL_FAM6_LAKEFIELD" ] || + [ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ]; then + _set_vuln retbleed + fi + fi + elif is_amd || is_hygon; then # AMD revised their statement about affected_variant2 => affected # https://www.amd.com/en/corporate/speculative-execution @@ -337,6 +373,11 @@ is_cpu_affected() { _set_vuln tsa fi + # Retbleed (AMD, CVE-2022-29900): families 0x15-0x17 (kernel X86_BUG_RETBLEED) + if [ "$cpu_family" = $((0x15)) ] || [ "$cpu_family" = $((0x16)) ] || [ "$cpu_family" = $((0x17)) ]; then + _set_vuln retbleed + fi + elif [ "$cpu_vendor" = CAVIUM ]; then _set_immune variant3 _set_immune variant3a @@ -460,7 +501,7 @@ is_cpu_affected() { [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] || [ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] || [ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ] || - [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT_MID" ] || + [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID2" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ]; then @@ -479,12 +520,12 @@ is_cpu_affected() { _infer_immune itlbmh fi - # shellcheck disable=SC2154 # affected_zenbleed/inception/tsa/downfall/reptar set via eval (_set_immune) + # shellcheck disable=SC2154 # affected_zenbleed/inception/retbleed/tsa/downfall/reptar set via eval (_set_immune) { pr_debug "is_cpu_affected: final results: variant1=$affected_variant1 variant2=$affected_variant2 variant3=$affected_variant3 variant3a=$affected_variant3a" pr_debug "is_cpu_affected: final results: variant4=$affected_variant4 variantl1tf=$affected_variantl1tf msbds=$affected_msbds mfbds=$affected_mfbds" pr_debug "is_cpu_affected: final results: mlpds=$affected_mlpds mdsum=$affected_mdsum taa=$affected_taa itlbmh=$affected_itlbmh srbds=$affected_srbds" - pr_debug "is_cpu_affected: final results: zenbleed=$affected_zenbleed inception=$affected_inception tsa=$affected_tsa downfall=$affected_downfall reptar=$affected_reptar" + pr_debug "is_cpu_affected: final results: zenbleed=$affected_zenbleed inception=$affected_inception retbleed=$affected_retbleed tsa=$affected_tsa downfall=$affected_downfall reptar=$affected_reptar" } affected_variantl1tf_sgx="$affected_variantl1tf" # even if we are affected to L1TF, if there's no SGX, we're not affected to the original foreshadow diff --git a/src/libs/210_cpu_detect.sh b/src/libs/210_cpu_detect.sh index 2e0a637..13111dc 100644 --- a/src/libs/210_cpu_detect.sh +++ b/src/libs/210_cpu_detect.sh @@ -27,6 +27,13 @@ is_cpu_specex_free() { return 0 fi fi + # Centaur family 5 and NSC family 5 are also non-speculative + if [ "$cpu_vendor" = "CentaurHauls" ] && [ "$cpu_family" = 5 ]; then + return 0 + fi + if [ "$cpu_vendor" = "Geode by NSC" ] && [ "$cpu_family" = 5 ]; then + return 0 + fi [ "$cpu_family" = 4 ] && return 0 return 1 } diff --git a/src/libs/250_output_emitters.sh b/src/libs/250_output_emitters.sh index 0f61ff1..5d6b653 100644 --- a/src/libs/250_output_emitters.sh +++ b/src/libs/250_output_emitters.sh @@ -102,18 +102,28 @@ pvulnstatus() { shift 2 pr_info_nol "> \033[46m\033[30mSTATUS:\033[0m " : "${g_final_summary:=}" + : "${g_final_summary_count:=0}" + g_final_summary_count=$((g_final_summary_count + 1)) + # wrap to a new line every 4 entries for readability + if [ "$g_final_summary_count" -gt 1 ] && [ $((g_final_summary_count % 4)) -eq 1 ]; then + g_final_summary="$g_final_summary\n " + fi + # pad entry to fixed width so columns align despite varying CVE ID lengths case "$vulnstatus" in UNK) pstatus yellow 'UNKNOWN' "$@" - g_final_summary="$g_final_summary \033[43m\033[30m$g_pvulnstatus_last_cve:??\033[0m" + _summary_label=$(printf "%-17s" "$g_pvulnstatus_last_cve:??") + g_final_summary="$g_final_summary \033[43m\033[30m$_summary_label\033[0m" ;; VULN) pstatus red 'VULNERABLE' "$@" - g_final_summary="$g_final_summary \033[41m\033[30m$g_pvulnstatus_last_cve:KO\033[0m" + _summary_label=$(printf "%-17s" "$g_pvulnstatus_last_cve:KO") + g_final_summary="$g_final_summary \033[41m\033[30m$_summary_label\033[0m" ;; OK) pstatus green 'NOT VULNERABLE' "$@" - g_final_summary="$g_final_summary \033[42m\033[30m$g_pvulnstatus_last_cve:OK\033[0m" + _summary_label=$(printf "%-17s" "$g_pvulnstatus_last_cve:OK") + g_final_summary="$g_final_summary \033[42m\033[30m$_summary_label\033[0m" ;; *) echo "$0: error: unknown status '$vulnstatus' passed to pvulnstatus()" >&2 diff --git a/src/libs/350_cpu_detect2.sh b/src/libs/350_cpu_detect2.sh index 1ca7da4..8d6812c 100644 --- a/src/libs/350_cpu_detect2.sh +++ b/src/libs/350_cpu_detect2.sh @@ -163,76 +163,6 @@ parse_cpu_details() { g_ucode_found=$(printf "family 0x%x model 0x%x stepping 0x%x ucode 0x%x cpuid 0x%x pfid 0x%x" \ "$cpu_family" "$cpu_model" "$cpu_stepping" "$cpu_ucode" "$cpu_cpuid" "$cpu_platformid") - # also define those that we will need in other funcs - # taken from https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/include/asm/intel-family.h - # curl -s 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/arch/x86/include/asm/intel-family.h' | awk '/#define INTEL_FAM6/ {print $2"=$(( "$3" )) # "$4,$5,$6,$7,$8,$9}' | sed -Ee 's/ +$//' - # shellcheck disable=SC2034 - { - readonly INTEL_FAM6_CORE_YONAH=$((0x0E)) # - readonly INTEL_FAM6_CORE2_MEROM=$((0x0F)) # - readonly INTEL_FAM6_CORE2_MEROM_L=$((0x16)) # - readonly INTEL_FAM6_CORE2_PENRYN=$((0x17)) # - readonly INTEL_FAM6_CORE2_DUNNINGTON=$((0x1D)) # - readonly INTEL_FAM6_NEHALEM=$((0x1E)) # - readonly INTEL_FAM6_NEHALEM_G=$((0x1F)) # /* Auburndale / Havendale */ - readonly INTEL_FAM6_NEHALEM_EP=$((0x1A)) # - readonly INTEL_FAM6_NEHALEM_EX=$((0x2E)) # - readonly INTEL_FAM6_WESTMERE=$((0x25)) # - readonly INTEL_FAM6_WESTMERE_EP=$((0x2C)) # - readonly INTEL_FAM6_WESTMERE_EX=$((0x2F)) # - readonly INTEL_FAM6_SANDYBRIDGE=$((0x2A)) # - readonly INTEL_FAM6_SANDYBRIDGE_X=$((0x2D)) # - readonly INTEL_FAM6_IVYBRIDGE=$((0x3A)) # - readonly INTEL_FAM6_IVYBRIDGE_X=$((0x3E)) # - readonly INTEL_FAM6_HASWELL=$((0x3C)) # - readonly INTEL_FAM6_HASWELL_X=$((0x3F)) # - readonly INTEL_FAM6_HASWELL_L=$((0x45)) # - readonly INTEL_FAM6_HASWELL_G=$((0x46)) # - readonly INTEL_FAM6_BROADWELL=$((0x3D)) # - readonly INTEL_FAM6_BROADWELL_G=$((0x47)) # - readonly INTEL_FAM6_BROADWELL_X=$((0x4F)) # - readonly INTEL_FAM6_BROADWELL_D=$((0x56)) # - readonly INTEL_FAM6_SKYLAKE_L=$((0x4E)) # /* Sky Lake */ - readonly INTEL_FAM6_SKYLAKE=$((0x5E)) # /* Sky Lake */ - readonly INTEL_FAM6_SKYLAKE_X=$((0x55)) # /* Sky Lake */ - readonly INTEL_FAM6_KABYLAKE_L=$((0x8E)) # /* Sky Lake */ - readonly INTEL_FAM6_KABYLAKE=$((0x9E)) # /* Sky Lake */ - readonly INTEL_FAM6_COMETLAKE=$((0xA5)) # /* Sky Lake */ - readonly INTEL_FAM6_COMETLAKE_L=$((0xA6)) # /* Sky Lake */ - readonly INTEL_FAM6_CANNONLAKE_L=$((0x66)) # /* Palm Cove */ - readonly INTEL_FAM6_ICELAKE_X=$((0x6A)) # /* Sunny Cove */ - readonly INTEL_FAM6_ICELAKE_D=$((0x6C)) # /* Sunny Cove */ - readonly INTEL_FAM6_ICELAKE=$((0x7D)) # /* Sunny Cove */ - readonly INTEL_FAM6_ICELAKE_L=$((0x7E)) # /* Sunny Cove */ - readonly INTEL_FAM6_ICELAKE_NNPI=$((0x9D)) # /* Sunny Cove */ - readonly INTEL_FAM6_LAKEFIELD=$((0x8A)) # /* Sunny Cove / Tremont */ - readonly INTEL_FAM6_ROCKETLAKE=$((0xA7)) # /* Cypress Cove */ - readonly INTEL_FAM6_TIGERLAKE_L=$((0x8C)) # /* Willow Cove */ - readonly INTEL_FAM6_TIGERLAKE=$((0x8D)) # /* Willow Cove */ - readonly INTEL_FAM6_SAPPHIRERAPIDS_X=$((0x8F)) # /* Golden Cove */ - readonly INTEL_FAM6_ALDERLAKE=$((0x97)) # /* Golden Cove / Gracemont */ - readonly INTEL_FAM6_ALDERLAKE_L=$((0x9A)) # /* Golden Cove / Gracemont */ - readonly INTEL_FAM6_RAPTORLAKE=$((0xB7)) # - readonly INTEL_FAM6_ATOM_BONNELL=$((0x1C)) # /* Diamondville, Pineview */ - readonly INTEL_FAM6_ATOM_BONNELL_MID=$((0x26)) # /* Silverthorne, Lincroft */ - readonly INTEL_FAM6_ATOM_SALTWELL=$((0x36)) # /* Cedarview */ - readonly INTEL_FAM6_ATOM_SALTWELL_MID=$((0x27)) # /* Penwell */ - readonly INTEL_FAM6_ATOM_SALTWELL_TABLET=$((0x35)) # /* Cloverview */ - readonly INTEL_FAM6_ATOM_SILVERMONT=$((0x37)) # /* Bay Trail, Valleyview */ - readonly INTEL_FAM6_ATOM_SILVERMONT_D=$((0x4D)) # /* Avaton, Rangely */ - readonly INTEL_FAM6_ATOM_SILVERMONT_MID=$((0x4A)) # /* Merriefield */ - readonly INTEL_FAM6_ATOM_AIRMONT=$((0x4C)) # /* Cherry Trail, Braswell */ - readonly INTEL_FAM6_ATOM_AIRMONT_MID=$((0x5A)) # /* Moorefield */ - readonly INTEL_FAM6_ATOM_AIRMONT_NP=$((0x75)) # /* Lightning Mountain */ - readonly INTEL_FAM6_ATOM_GOLDMONT=$((0x5C)) # /* Apollo Lake */ - readonly INTEL_FAM6_ATOM_GOLDMONT_D=$((0x5F)) # /* Denverton */ - readonly INTEL_FAM6_ATOM_GOLDMONT_PLUS=$((0x7A)) # /* Gemini Lake */ - readonly INTEL_FAM6_ATOM_TREMONT_D=$((0x86)) # /* Jacobsville */ - readonly INTEL_FAM6_ATOM_TREMONT=$((0x96)) # /* Elkhart Lake */ - readonly INTEL_FAM6_ATOM_TREMONT_L=$((0x9C)) # /* Jasper Lake */ - readonly INTEL_FAM6_XEON_PHI_KNL=$((0x57)) # /* Knights Landing */ - readonly INTEL_FAM6_XEON_PHI_KNM=$((0x85)) # /* Knights Mill */ - } g_parse_cpu_details_done=1 } # Check whether the CPU vendor is Hygon diff --git a/src/vulns/CVE-2017-5715.sh b/src/vulns/CVE-2017-5715.sh index c911a39..8f59f4a 100644 --- a/src/vulns/CVE-2017-5715.sh +++ b/src/vulns/CVE-2017-5715.sh @@ -1,14 +1,12 @@ # vim: set ts=4 sw=4 sts=4 et: -################### -# SPECTRE 2 SECTION +############################### +# CVE-2017-5715, Spectre V2, Branch Target Injection -# CVE-2017-5715 Spectre Variant 2 (branch target injection) - entry point # Sets: vulnstatus check_CVE_2017_5715() { check_cve 'CVE-2017-5715' } -# CVE-2017-5715 Spectre Variant 2 (branch target injection) - Linux mitigation check # Sets: g_ibrs_can_tell, g_ibrs_supported, g_ibrs_enabled, g_ibrs_fw_enabled, # g_ibpb_can_tell, g_ibpb_supported, g_ibpb_enabled, g_specex_knob_dir check_CVE_2017_5715_linux() { @@ -208,6 +206,43 @@ check_CVE_2017_5715_linux() { # rocky9 (RHEL 9, kernel 5.14): matches mainline. Semicolons, BHI, all fields. # rocky10 (RHEL 10, kernel 6.12): matches mainline. # + # + # --- Kconfig symbols --- + # 76b043848fd2 (v4.15-rc8): CONFIG_RETPOLINE + # f43b9876e857 (v5.19-rc7): CONFIG_CPU_IBRS_ENTRY (kernel IBRS on entry) + # aefb2f2e619b (v6.9-rc1): renamed CONFIG_RETPOLINE => CONFIG_MITIGATION_RETPOLINE + # 1da8d2172ce5 (v6.9-rc1): renamed CONFIG_CPU_IBRS_ENTRY => CONFIG_MITIGATION_IBRS_ENTRY + # ec9404e40e8f (v6.9-rc4): CONFIG_SPECTRE_BHI_ON / CONFIG_SPECTRE_BHI_OFF + # 4f511739c54b (v6.9-rc4): replaced by CONFIG_MITIGATION_SPECTRE_BHI + # 72c70f480a70 (v6.12-rc1): CONFIG_MITIGATION_SPECTRE_V2 (top-level on/off) + # 8754e67ad4ac (v6.15-rc7): CONFIG_MITIGATION_ITS (indirect target selection) + # stable 5.4.y-6.6.y: CONFIG_RETPOLINE (pre-rename) + # stable 6.12.y: CONFIG_MITIGATION_RETPOLINE, CONFIG_MITIGATION_SPECTRE_V2 + # + # --- kernel functions (for $opt_map / System.map) --- + # da285121560e (v4.15-rc8): spectre_v2_select_mitigation(), + # spectre_v2_parse_cmdline(), nospectre_v2_parse_cmdline() + # 20ffa1caecca (v4.16-rc1): spectre_v2_module_string(), retpoline_module_ok() + # a8f76ae41cd6 (v4.20-rc5): spectre_v2_user_select_mitigation(), + # spectre_v2_user_parse_cmdline() + # 7c693f54c873 (v5.19-rc7): spectre_v2_in_ibrs_mode(), spectre_v2_in_eibrs_mode() + # 44a3918c8245 (v5.17-rc8): spectre_v2_show_state() + # 480e803dacf8 (v6.16-rc1): split into spectre_v2_select_mitigation() + + # spectre_v2_apply_mitigation() + spectre_v2_update_mitigation() + + # spectre_v2_user_apply_mitigation() + spectre_v2_user_update_mitigation() + # + # --- CPU affection logic (for is_cpu_affected) --- + # X86_BUG_SPECTRE_V2 is set for ALL x86 CPUs except: + # - CPUs matching NO_SPECULATION: family 4 (all vendors), Centaur/Intel/NSC/Vortex + # family 5, Intel Atom Bonnell/Saltwell + # - CPUs matching NO_SPECTRE_V2: Centaur family 7, Zhaoxin family 7 + # 99c6fa2511d8 (v4.15-rc8): unconditional for all x86 CPUs + # 1e41a766c98b (v5.6-rc1): added NO_SPECTRE_V2 exemption for Centaur/Zhaoxin + # 98c7a713db91 (v6.15-rc1): added X86_BUG_SPECTRE_V2_USER as separate bit + # No MSR/CPUID immunity bits — purely whitelist-based. + # vendor scope: all x86 vendors affected (Intel, AMD, Hygon, etc.) + # except Centaur family 7 and Zhaoxin family 7. + # # all messages start with either "Not affected", "Mitigation", or "Vulnerable" fi if [ "$opt_sysfs_only" != 1 ]; then @@ -332,6 +367,19 @@ check_CVE_2017_5715_linux() { if grep -q spec_ctrl "$opt_map"; then g_ibrs_supported="found spec_ctrl in symbols file" pr_debug "ibrs: found '*spec_ctrl*' symbol in $opt_map" + elif grep -q -e spectre_v2_select_mitigation -e spectre_v2_apply_mitigation "$opt_map"; then + # spectre_v2_select_mitigation exists since v4.15; split into + # spectre_v2_select_mitigation + spectre_v2_apply_mitigation in v6.16 + g_ibrs_supported="found spectre_v2 mitigation function in symbols file" + pr_debug "ibrs: found spectre_v2_*_mitigation symbol in $opt_map" + fi + fi + # CONFIG_CPU_IBRS_ENTRY (v5.19) / CONFIG_MITIGATION_IBRS_ENTRY (v6.9): kernel IBRS on entry + if [ -z "$g_ibrs_supported" ] && [ -n "$opt_config" ] && [ -r "$opt_config" ]; then + g_ibrs_can_tell=1 + if grep -q '^CONFIG_\(CPU_\|MITIGATION_\)IBRS_ENTRY=y' "$opt_config"; then + g_ibrs_supported="CONFIG_CPU_IBRS_ENTRY/CONFIG_MITIGATION_IBRS_ENTRY found in kernel config" + pr_debug "ibrs: found IBRS entry config option in $opt_config" fi fi # recent (4.15) vanilla kernels have IBPB but not IBRS, and without the debugfs tunables of Red Hat @@ -579,7 +627,7 @@ check_CVE_2017_5715_linux() { rsb_filling=0 if [ "$opt_live" = 1 ] && [ "$opt_no_sysfs" != 1 ]; then # if we're live and we aren't denied looking into /sys, let's do it - if echo "$msg" | grep -qw RSB; then + if echo "$ret_sys_interface_check_fullmsg" | grep -qw RSB; then rsb_filling=1 pstatus green YES fi @@ -679,6 +727,11 @@ check_CVE_2017_5715_linux() { *) pstatus yellow UNKNOWN ;; esac + # --- SMT state (used in STIBP inference and verdict) --- + is_cpu_smt_enabled + smt_enabled=$? + # smt_enabled: 0=enabled, 1=disabled, 2=unknown + # --- v2_stibp_status --- pr_info_nol " * STIBP status: " if [ -n "$ret_sys_interface_check_fullmsg" ]; then @@ -821,11 +874,6 @@ check_CVE_2017_5715_linux() { fi fi - # --- SMT state (used in verdict) --- - is_cpu_smt_enabled - smt_enabled=$? - # smt_enabled: 0=enabled, 1=disabled, 2=unknown - elif [ "$sys_interface_available" = 0 ]; then # we have no sysfs but were asked to use it only! msg="/sys vulnerability interface use forced, but it's not available!" @@ -840,6 +888,8 @@ check_CVE_2017_5715_linux() { # --- own logic using Phase 2 variables --- # Helper: collect caveats for the verdict message _v2_caveats='' + # Append a caveat string to the _v2_caveats list + # Callers: check_CVE_2017_5715_linux (eIBRS, IBRS, retpoline verdict paths) _v2_add_caveat() { _v2_caveats="${_v2_caveats:+$_v2_caveats; }$1"; } # ARM branch predictor hardening (unchanged) @@ -1107,6 +1157,9 @@ check_CVE_2017_5715_linux() { pvulnstatus "$cve" OK "offline mode: kernel supports IBRS + IBPB to mitigate the vulnerability" elif [ "$cap_ibrs_all" = 1 ] || [ "$cap_autoibrs" = 1 ]; then pvulnstatus "$cve" OK "offline mode: CPU supports Enhanced / Automatic IBRS" + # CONFIG_MITIGATION_SPECTRE_V2 (v6.12+): top-level on/off for all Spectre V2 mitigations + elif [ -n "$opt_config" ] && [ -r "$opt_config" ] && grep -q '^CONFIG_MITIGATION_SPECTRE_V2=y' "$opt_config"; then + pvulnstatus "$cve" OK "offline mode: kernel has Spectre V2 mitigation framework enabled (CONFIG_MITIGATION_SPECTRE_V2)" elif [ "$g_ibrs_can_tell" != 1 ]; then pvulnstatus "$cve" UNK "offline mode: not enough information" explain "Re-run this script with root privileges, and give it the kernel image (--kernel), the kernel configuration (--config) and the System.map file (--map) corresponding to the kernel you would like to inspect." @@ -1137,7 +1190,6 @@ check_CVE_2017_5715_linux() { fi } -# CVE-2017-5715 Spectre Variant 2 (branch target injection) - BSD mitigation check # Sets: vulnstatus check_CVE_2017_5715_bsd() { local ibrs_disabled ibrs_active retpoline nb_thunks diff --git a/src/vulns/CVE-2017-5753.sh b/src/vulns/CVE-2017-5753.sh index 167c776..693fac1 100644 --- a/src/vulns/CVE-2017-5753.sh +++ b/src/vulns/CVE-2017-5753.sh @@ -1,14 +1,12 @@ # vim: set ts=4 sw=4 sts=4 et: -################### -# SPECTRE 1 SECTION +############################### +# CVE-2017-5753, Spectre V1, Bounds Check Bypass -# CVE-2017-5753 Spectre Variant 1 (bounds check bypass) - entry point # Sets: (none directly, delegates to check_cve) check_CVE_2017_5753() { check_cve 'CVE-2017-5753' } -# CVE-2017-5753 Spectre Variant 1 (bounds check bypass) - Linux mitigation check # Sets: g_redhat_canonical_spectre (via check_redhat_canonical_spectre) check_CVE_2017_5753_linux() { local status sys_interface_available msg v1_kernel_mitigated v1_kernel_mitigated_err v1_mask_nospec ret explain_text @@ -279,7 +277,6 @@ check_CVE_2017_5753_linux() { fi } -# CVE-2017-5753 Spectre Variant 1 (bounds check bypass) - BSD mitigation check check_CVE_2017_5753_bsd() { if ! is_cpu_affected "$cve"; then pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" diff --git a/src/vulns/CVE-2017-5754.sh b/src/vulns/CVE-2017-5754.sh index 218e209..2265b55 100644 --- a/src/vulns/CVE-2017-5754.sh +++ b/src/vulns/CVE-2017-5754.sh @@ -1,6 +1,6 @@ # vim: set ts=4 sw=4 sts=4 et: -################## -# MELTDOWN SECTION +############################### +# CVE-2017-5754, Meltdown, Rogue Data Cache Load # no security impact but give a hint to the user in verbose mode # about PCID/INVPCID cpuid features that must be present to avoid @@ -40,12 +40,10 @@ pti_performance_check() { fi } -# CVE-2017-5754 Meltdown (rogue data cache load) - entry point check_CVE_2017_5754() { check_cve 'CVE-2017-5754' } -# CVE-2017-5754 Meltdown (rogue data cache load) - Linux mitigation check check_CVE_2017_5754_linux() { local status sys_interface_available msg kpti_support kpti_can_tell kpti_enabled dmesg_grep pti_xen_pv_domU xen_pv_domo xen_pv_domu explain_text status=UNK @@ -248,7 +246,6 @@ check_CVE_2017_5754_linux() { fi } -# CVE-2017-5754 Meltdown (rogue data cache load) - BSD mitigation check check_CVE_2017_5754_bsd() { local kpti_enabled pr_info_nol "* Kernel supports Page Table Isolation (PTI): " diff --git a/src/vulns/CVE-2018-12126.sh b/src/vulns/CVE-2018-12126.sh index ed6fcf5..b47f5e4 100644 --- a/src/vulns/CVE-2018-12126.sh +++ b/src/vulns/CVE-2018-12126.sh @@ -1,8 +1,7 @@ # vim: set ts=4 sw=4 sts=4 et: -################### -# MSBDS SECTION +############################### +# CVE-2018-12126, MSBDS, Fallout, Microarchitectural Store Buffer Data Sampling -# CVE-2018-12126 MSBDS (microarchitectural store buffer data sampling) - entry point check_CVE_2018_12126() { check_cve 'CVE-2018-12126' check_mds } diff --git a/src/vulns/CVE-2018-12127.sh b/src/vulns/CVE-2018-12127.sh index 18e4e09..84920ce 100644 --- a/src/vulns/CVE-2018-12127.sh +++ b/src/vulns/CVE-2018-12127.sh @@ -1,8 +1,7 @@ # vim: set ts=4 sw=4 sts=4 et: -################### -# MLPDS SECTION +############################### +# CVE-2018-12127, MLPDS, RIDL, Microarchitectural Load Port Data Sampling -# CVE-2018-12127 MLPDS (microarchitectural load port data sampling) - entry point check_CVE_2018_12127() { check_cve 'CVE-2018-12127' check_mds } diff --git a/src/vulns/CVE-2018-12130.sh b/src/vulns/CVE-2018-12130.sh index e225f42..efbd169 100644 --- a/src/vulns/CVE-2018-12130.sh +++ b/src/vulns/CVE-2018-12130.sh @@ -1,8 +1,7 @@ # vim: set ts=4 sw=4 sts=4 et: -################### -# MFBDS SECTION +############################### +# CVE-2018-12130, MFBDS, ZombieLoad, Microarchitectural Fill Buffer Data Sampling -# CVE-2018-12130 MFBDS (microarchitectural fill buffer data sampling) - entry point check_CVE_2018_12130() { check_cve 'CVE-2018-12130' check_mds } diff --git a/src/vulns/CVE-2018-12207.sh b/src/vulns/CVE-2018-12207.sh index c8c4af4..0065b3a 100644 --- a/src/vulns/CVE-2018-12207.sh +++ b/src/vulns/CVE-2018-12207.sh @@ -1,13 +1,11 @@ # vim: set ts=4 sw=4 sts=4 et: -####################### -# iTLB Multihit section +############################### +# CVE-2018-12207, iTLB Multihit, No eXcuses, Machine Check Exception on Page Size Changes -# CVE-2018-12207 iTLB multihit (machine check exception on page size changes) - entry point check_CVE_2018_12207() { check_cve 'CVE-2018-12207' } -# CVE-2018-12207 iTLB multihit (machine check exception on page size changes) - Linux mitigation check check_CVE_2018_12207_linux() { local status sys_interface_available msg kernel_itlbmh kernel_itlbmh_err status=UNK @@ -85,7 +83,6 @@ check_CVE_2018_12207_linux() { fi } -# CVE-2018-12207 iTLB multihit (machine check exception on page size changes) - BSD mitigation check check_CVE_2018_12207_bsd() { local kernel_2m_x_ept pr_info_nol "* Kernel supports disabling superpages for executable mappings under EPT: " diff --git a/src/vulns/CVE-2018-3615.sh b/src/vulns/CVE-2018-3615.sh index b0f5832..6db32df 100644 --- a/src/vulns/CVE-2018-3615.sh +++ b/src/vulns/CVE-2018-3615.sh @@ -1,8 +1,7 @@ # vim: set ts=4 sw=4 sts=4 et: -########################### -# L1TF / FORESHADOW SECTION +############################### +# CVE-2018-3615, Foreshadow (SGX), L1 Terminal Fault -# CVE-2018-3615 Foreshadow (L1 terminal fault SGX) - entry point check_CVE_2018_3615() { local cve cve='CVE-2018-3615' diff --git a/src/vulns/CVE-2018-3620.sh b/src/vulns/CVE-2018-3620.sh index 186a1d9..835f212 100644 --- a/src/vulns/CVE-2018-3620.sh +++ b/src/vulns/CVE-2018-3620.sh @@ -1,10 +1,11 @@ # vim: set ts=4 sw=4 sts=4 et: -# CVE-2018-3620 Foreshadow-NG OS (L1 terminal fault OS) - entry point +############################### +# CVE-2018-3620, Foreshadow-NG (OS/SMM), L1 Terminal Fault + check_CVE_2018_3620() { check_cve 'CVE-2018-3620' } -# CVE-2018-3620 Foreshadow-NG OS (L1 terminal fault OS) - Linux mitigation check check_CVE_2018_3620_linux() { local status sys_interface_available msg pteinv_supported pteinv_active status=UNK @@ -83,7 +84,6 @@ check_CVE_2018_3620_linux() { fi } -# CVE-2018-3620 Foreshadow-NG OS (L1 terminal fault OS) - BSD mitigation check check_CVE_2018_3620_bsd() { local bsd_zero_reserved pr_info_nol "* Kernel reserved the memory page at physical address 0x0: " diff --git a/src/vulns/CVE-2018-3639.sh b/src/vulns/CVE-2018-3639.sh index 11de567..b0d1bae 100644 --- a/src/vulns/CVE-2018-3639.sh +++ b/src/vulns/CVE-2018-3639.sh @@ -1,13 +1,11 @@ # vim: set ts=4 sw=4 sts=4 et: -################### -# VARIANT 4 SECTION +############################### +# CVE-2018-3639, Variant 4, SSB, Speculative Store Bypass -# CVE-2018-3639 Variant 4 (speculative store bypass) - entry point check_CVE_2018_3639() { check_cve 'CVE-2018-3639' } -# CVE-2018-3639 Variant 4 (speculative store bypass) - Linux mitigation check check_CVE_2018_3639_linux() { local status sys_interface_available msg kernel_ssb kernel_ssbd_enabled mitigated_processes status=UNK @@ -135,7 +133,6 @@ check_CVE_2018_3639_linux() { fi } -# CVE-2018-3639 Variant 4 (speculative store bypass) - BSD mitigation check check_CVE_2018_3639_bsd() { local kernel_ssb ssb_enabled ssb_active pr_info_nol "* Kernel supports speculation store bypass: " diff --git a/src/vulns/CVE-2018-3640.sh b/src/vulns/CVE-2018-3640.sh index ed9d445..42a23e4 100644 --- a/src/vulns/CVE-2018-3640.sh +++ b/src/vulns/CVE-2018-3640.sh @@ -1,8 +1,7 @@ # vim: set ts=4 sw=4 sts=4 et: -#################### -# VARIANT 3A SECTION +############################### +# CVE-2018-3640, Variant 3a, Rogue System Register Read -# CVE-2018-3640 Variant 3a (rogue system register read) - entry point check_CVE_2018_3640() { local status sys_interface_available msg cve cve='CVE-2018-3640' diff --git a/src/vulns/CVE-2018-3646.sh b/src/vulns/CVE-2018-3646.sh index 60e3531..0fb3ab3 100644 --- a/src/vulns/CVE-2018-3646.sh +++ b/src/vulns/CVE-2018-3646.sh @@ -1,10 +1,11 @@ # vim: set ts=4 sw=4 sts=4 et: -# CVE-2018-3646 Foreshadow-NG VMM (L1 terminal fault VMM) - entry point +############################### +# CVE-2018-3646, Foreshadow-NG (VMM), L1 Terminal Fault + check_CVE_2018_3646() { check_cve 'CVE-2018-3646' } -# CVE-2018-3646 Foreshadow-NG VMM (L1 terminal fault VMM) - Linux mitigation check check_CVE_2018_3646_linux() { local status sys_interface_available msg l1d_mode ept_disabled l1d_kernel l1d_kernel_err l1d_xen_hardware l1d_xen_hypervisor l1d_xen_pv_domU smt_enabled status=UNK @@ -234,7 +235,6 @@ check_CVE_2018_3646_linux() { fi } -# CVE-2018-3646 Foreshadow-NG VMM (L1 terminal fault VMM) - BSD mitigation check check_CVE_2018_3646_bsd() { local kernel_l1d_supported kernel_l1d_enabled pr_info_nol "* Kernel supports L1D flushing: " diff --git a/src/vulns/CVE-2019-11091.sh b/src/vulns/CVE-2019-11091.sh index 59c86c2..414d8e4 100644 --- a/src/vulns/CVE-2019-11091.sh +++ b/src/vulns/CVE-2019-11091.sh @@ -1,8 +1,7 @@ # vim: set ts=4 sw=4 sts=4 et: -################### -# MDSUM SECTION +############################### +# CVE-2019-11091, MDSUM, RIDL, Microarchitectural Data Sampling Uncacheable Memory -# CVE-2019-11091 MDSUM (microarchitectural data sampling uncacheable memory) - entry point check_CVE_2019_11091() { check_cve 'CVE-2019-11091' check_mds } diff --git a/src/vulns/CVE-2019-11135.sh b/src/vulns/CVE-2019-11135.sh index 6528862..8ff17f0 100644 --- a/src/vulns/CVE-2019-11135.sh +++ b/src/vulns/CVE-2019-11135.sh @@ -1,13 +1,11 @@ # vim: set ts=4 sw=4 sts=4 et: -################### -# TAA SECTION +############################### +# CVE-2019-11135, TAA, ZombieLoad V2, TSX Asynchronous Abort -# CVE-2019-11135 TAA (TSX asynchronous abort) - entry point check_CVE_2019_11135() { check_cve 'CVE-2019-11135' } -# CVE-2019-11135 TAA (TSX asynchronous abort) - Linux mitigation check check_CVE_2019_11135_linux() { local status sys_interface_available msg kernel_taa kernel_taa_err status=UNK @@ -85,7 +83,6 @@ check_CVE_2019_11135_linux() { fi } -# CVE-2019-11135 TAA (TSX asynchronous abort) - BSD mitigation check check_CVE_2019_11135_bsd() { local taa_enable taa_state mds_disable kernel_taa kernel_mds pr_info_nol "* Kernel supports TAA mitigation (machdep.mitigations.taa.enable): " diff --git a/src/vulns/CVE-2020-0543.sh b/src/vulns/CVE-2020-0543.sh index 69fc020..c2ef667 100644 --- a/src/vulns/CVE-2020-0543.sh +++ b/src/vulns/CVE-2020-0543.sh @@ -1,13 +1,11 @@ # vim: set ts=4 sw=4 sts=4 et: -################### -# SRBDS SECTION +############################### +# CVE-2020-0543, SRBDS, CROSSTalk, Special Register Buffer Data Sampling -# CVE-2020-0543 SRBDS (special register buffer data sampling) - entry point check_CVE_2020_0543() { check_cve 'CVE-2020-0543' } -# CVE-2020-0543 SRBDS (special register buffer data sampling) - Linux mitigation check check_CVE_2020_0543_linux() { local status sys_interface_available msg kernel_srbds kernel_srbds_err status=UNK @@ -104,7 +102,6 @@ check_CVE_2020_0543_linux() { fi } -# CVE-2020-0543 SRBDS (special register buffer data sampling) - BSD mitigation check # FreeBSD uses the name "rngds" (Random Number Generator Data Sampling) for SRBDS check_CVE_2020_0543_bsd() { local rngds_enable rngds_state kernel_rngds diff --git a/src/vulns/CVE-2022-29900.sh b/src/vulns/CVE-2022-29900.sh new file mode 100644 index 0000000..9a9f40a --- /dev/null +++ b/src/vulns/CVE-2022-29900.sh @@ -0,0 +1,254 @@ +# vim: set ts=4 sw=4 sts=4 et: +############################### +# CVE-2022-29900, Retbleed (AMD), Arbitrary Speculative Code Execution with Return Instructions + +check_CVE_2022_29900() { + check_cve 'CVE-2022-29900' +} + +check_CVE_2022_29900_linux() { + local status sys_interface_available msg kernel_retbleed kernel_retbleed_err kernel_unret kernel_ibpb_entry smt_enabled + status=UNK + sys_interface_available=0 + msg='' + + # + # Kernel source inventory for retbleed (CVE-2022-29900 / CVE-2022-29901) + # + # --- sysfs messages --- + # all versions: + # "Not affected" (cpu_show_common, pre-existing) + # + # --- mainline --- + # 6b80b59b3555 (v5.19-rc7, initial retbleed sysfs): + # "Vulnerable\n" (hardcoded, no enum yet) + # 7fbf47c7ce50 (v5.19-rc7, retbleed= boot parameter): + # "Vulnerable" (RETBLEED_MITIGATION_NONE) + # "Mitigation: untrained return thunk" (RETBLEED_MITIGATION_UNRET) + # "Vulnerable: untrained return thunk on non-Zen uarch" (UNRET on non-AMD/Hygon) + # 6ad0ad2bf8a6 (v5.19-rc7, Intel mitigations): + # "Mitigation: IBRS" (RETBLEED_MITIGATION_IBRS) + # "Mitigation: Enhanced IBRS" (RETBLEED_MITIGATION_EIBRS) + # 3ebc17006888 (v5.19-rc7, retbleed=ibpb): + # "Mitigation: IBPB" (RETBLEED_MITIGATION_IBPB) + # e8ec1b6e08a2 (v5.19-rc7, STIBP for JMP2RET): + # UNRET now appends SMT status: + # "Mitigation: untrained return thunk; SMT disabled" + # "Mitigation: untrained return thunk; SMT enabled with STIBP protection" + # "Mitigation: untrained return thunk; SMT vulnerable" + # e6cfcdda8cbe (v6.0-rc1, STIBP for IBPB): + # IBPB now appends SMT status, non-AMD message changed: + # "Vulnerable: untrained return thunk / IBPB on non-AMD based uarch" + # "Mitigation: IBPB; SMT disabled" + # "Mitigation: IBPB; SMT enabled with STIBP protection" + # "Mitigation: IBPB; SMT vulnerable" + # d82a0345cf21 (v6.2-rc1, call depth tracking): + # "Mitigation: Stuffing" (RETBLEED_MITIGATION_STUFF) + # e3b78a7ad5ea (v6.16-rc1, restructure): + # added RETBLEED_MITIGATION_AUTO (internal, resolved before display) + # no new sysfs strings + # + # all messages start with either "Not affected", "Vulnerable", or "Mitigation" + # + # --- stable backports --- + # 4.14.y, 4.19.y, 5.4.y: Intel-only mitigations (IBRS, eIBRS); no UNRET, IBPB, STUFF; + # no SMT status display; simplified retbleed_show_state(). + # 5.10.y, 5.15.y, 6.1.y: full mitigations (NONE, UNRET, IBPB, IBRS, EIBRS); + # SMT status appended for UNRET/IBPB; no STUFF. + # 6.6.y, 6.12.y: adds STUFF (call depth tracking). 6.12.y uses INTEL_ model prefix. + # all stable: single retbleed_select_mitigation() (no update/apply split). + # + # --- RHEL/CentOS --- + # centos7 (~4.18): NONE, UNRET, IBPB, IBRS, EIBRS; no STUFF; SMT status for UNRET; + # no Hygon check; no UNRET_ENTRY/IBPB_ENTRY/IBRS_ENTRY Kconfig symbols; + # unique cpu_in_retbleed_whitelist() function for Intel. + # rocky8 (~4.18/5.14): NONE, UNRET, IBPB, IBRS, EIBRS; no STUFF; + # CONFIG_CPU_UNRET_ENTRY, CONFIG_CPU_IBPB_ENTRY, CONFIG_CPU_IBRS_ENTRY (old names). + # rocky9 (~6.x): same as mainline; CONFIG_MITIGATION_* names; has STUFF. + # rocky10 (~6.12+): same as mainline; has select/update/apply split. + # + # --- Kconfig symbols --- + # f43b9876e857 (v5.19-rc7): CONFIG_CPU_UNRET_ENTRY, CONFIG_CPU_IBPB_ENTRY, + # CONFIG_CPU_IBRS_ENTRY + # 80e4c1cd42ff (v6.2-rc1): CONFIG_CALL_DEPTH_TRACKING + # ac61d43983a4 (v6.9-rc1): renamed to CONFIG_MITIGATION_UNRET_ENTRY, + # CONFIG_MITIGATION_IBPB_ENTRY, CONFIG_MITIGATION_IBRS_ENTRY, + # CONFIG_MITIGATION_CALL_DEPTH_TRACKING + # 894e28857c11 (v6.12-rc1): CONFIG_MITIGATION_RETBLEED (master switch) + # + # --- kernel functions (for $opt_map / System.map) --- + # 7fbf47c7ce50 (v5.19-rc7): retbleed_select_mitigation() + # e3b78a7ad5ea (v6.16-rc1): split into retbleed_select_mitigation() + + # retbleed_update_mitigation() + retbleed_apply_mitigation() + # vendor kernels: centos7/rocky8/rocky9 have retbleed_select_mitigation() only; + # rocky10 has the full split. + # + # --- CPU affection logic (for is_cpu_affected) --- + # X86_BUG_RETBLEED is set when X86_FEATURE_BTC_NO is NOT set AND either: + # (a) CPU matches cpu_vuln_blacklist[] RETBLEED entries, OR + # (b) ARCH_CAP_RSBA is set in IA32_ARCH_CAPABILITIES MSR + # 6b80b59b3555 (v5.19-rc7, initial AMD): + # AMD: family 0x15, 0x16, 0x17; Hygon: family 0x18 + # 6ad0ad2bf8a6 (v5.19-rc7, Intel): + # Intel: SKYLAKE_L, SKYLAKE, SKYLAKE_X, KABYLAKE_L, KABYLAKE, + # ICELAKE_L, COMETLAKE, COMETLAKE_L, LAKEFIELD, ROCKETLAKE + # + any Intel with ARCH_CAP_RSBA set + # 26aae8ccbc19 (v5.19-rc7, BTC_NO): + # AMD Zen 3+ with BTC_NO are excluded + # f54d45372c6a (post-v5.19, Cannon Lake): + # Intel: + CANNONLAKE_L + # immunity: X86_FEATURE_BTC_NO (AMD) — Zen 3+ declare not affected + # vendor scope: AMD (0x15-0x17), Hygon (0x18), Intel (Skylake through Rocket Lake + RSBA) + # + + if sys_interface_check "$VULN_SYSFS_BASE/retbleed"; then + # this kernel has the /sys interface, trust it over everything + sys_interface_available=1 + status=$ret_sys_interface_check_status + fi + + if [ "$opt_sysfs_only" != 1 ]; then + pr_info_nol "* Kernel supports mitigation: " + if [ -n "$g_kernel_err" ]; then + kernel_retbleed_err="$g_kernel_err" + elif grep -q 'retbleed' "$g_kernel"; then + kernel_retbleed="found retbleed mitigation logic in kernel image" + fi + if [ -z "$kernel_retbleed" ] && [ -n "$opt_map" ]; then + if grep -q 'retbleed_select_mitigation' "$opt_map"; then + kernel_retbleed="found retbleed_select_mitigation in System.map" + fi + fi + if [ -n "$kernel_retbleed" ]; then + pstatus green YES "$kernel_retbleed" + elif [ -n "$kernel_retbleed_err" ]; then + pstatus yellow UNKNOWN "$kernel_retbleed_err" + else + pstatus yellow NO + fi + + pr_info_nol "* Kernel compiled with UNRET_ENTRY support (untrained return thunk): " + if [ -r "$opt_config" ]; then + # CONFIG_CPU_UNRET_ENTRY: Linux < 6.9 + # CONFIG_MITIGATION_UNRET_ENTRY: Linux >= 6.9 + if grep -Eq '^CONFIG_(CPU|MITIGATION)_UNRET_ENTRY=y' "$opt_config"; then + pstatus green YES + kernel_unret="CONFIG_(CPU|MITIGATION)_UNRET_ENTRY=y found in kernel config" + else + pstatus yellow NO + fi + else + if [ -n "$g_kernel_err" ]; then + pstatus yellow UNKNOWN "$g_kernel_err" + elif [ -n "$kernel_retbleed" ]; then + # if the kernel has retbleed logic, assume UNRET_ENTRY is likely compiled in + # (we can't tell for certain without the config) + kernel_unret="retbleed mitigation logic present in kernel (UNRET_ENTRY status unknown)" + pstatus yellow UNKNOWN "kernel has retbleed mitigation but config not available to verify" + else + pstatus yellow NO "your kernel is too old and doesn't have the retbleed mitigation logic" + fi + fi + + pr_info_nol "* Kernel compiled with IBPB_ENTRY support: " + if [ -r "$opt_config" ]; then + # CONFIG_CPU_IBPB_ENTRY: Linux < 6.9 + # CONFIG_MITIGATION_IBPB_ENTRY: Linux >= 6.9 + if grep -Eq '^CONFIG_(CPU|MITIGATION)_IBPB_ENTRY=y' "$opt_config"; then + pstatus green YES + kernel_ibpb_entry="CONFIG_(CPU|MITIGATION)_IBPB_ENTRY=y found in kernel config" + else + pstatus yellow NO + fi + else + if [ -n "$g_kernel_err" ]; then + pstatus yellow UNKNOWN "$g_kernel_err" + elif [ -n "$kernel_retbleed" ]; then + kernel_ibpb_entry="retbleed mitigation logic present in kernel (IBPB_ENTRY status unknown)" + pstatus yellow UNKNOWN "kernel has retbleed mitigation but config not available to verify" + else + pstatus yellow NO "your kernel is too old and doesn't have the retbleed mitigation logic" + fi + fi + + # Zen/Zen+/Zen2: check IBPB microcode support and SMT + if [ "$cpu_family" = $((0x17)) ]; then + pr_info_nol "* CPU supports IBPB: " + if [ "$opt_live" = 1 ]; then + if [ -n "$cap_ibpb" ]; then + pstatus green YES "$cap_ibpb" + else + pstatus yellow NO + fi + else + pstatus blue N/A "not testable in offline mode" + fi + + pr_info_nol "* Hyper-Threading (SMT) is enabled: " + is_cpu_smt_enabled + smt_enabled=$? + if [ "$smt_enabled" = 0 ]; then + pstatus yellow YES + else + pstatus green NO + fi + fi + + elif [ "$sys_interface_available" = 0 ]; then + # we have no sysfs but were asked to use it only! + msg="/sys vulnerability interface use forced, but it's not available!" + status=UNK + fi + + if ! is_cpu_affected "$cve"; then + # override status & msg in case CPU is not vulnerable after all + 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_sysfs_only" != 1 ]; then + if [ "$cpu_family" = $((0x17)) ]; then + # Zen/Zen+/Zen2 + if [ -z "$kernel_retbleed" ]; then + pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the retbleed mitigation logic" + elif [ "$opt_paranoid" = 1 ] && [ "$smt_enabled" = 0 ]; then + pvulnstatus "$cve" VULN "SMT is enabled, which weakens the IBPB-based mitigation" + explain "For Zen/Zen+/Zen2 CPUs in paranoid mode, proper mitigation needs SMT to be disabled\n" \ + "(this can be done by adding \`nosmt\` to your kernel command line), because IBPB alone\n" \ + "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_live" = 1 ]; 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." + else + pvulnstatus "$cve" OK "Your kernel and CPU support mitigation" + fi + elif [ "$cpu_family" = $((0x15)) ] || [ "$cpu_family" = $((0x16)) ]; then + # older AMD families: basic mitigation check + if [ -z "$kernel_retbleed" ]; then + pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the retbleed mitigation logic" + elif [ -n "$kernel_unret" ] || [ -n "$kernel_ibpb_entry" ]; then + pvulnstatus "$cve" OK "Your kernel supports mitigation" + else + pvulnstatus "$cve" VULN "Your kernel doesn't have UNRET_ENTRY or IBPB_ENTRY compiled-in" + fi + else + # not supposed to happen + pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" + fi + else + pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg" + fi + else + pvulnstatus "$cve" "$status" "$msg" + fi +} + +check_CVE_2022_29900_bsd() { + if ! is_cpu_affected "$cve"; then + pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" + else + pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script" + fi +} diff --git a/src/vulns/CVE-2022-29901.sh b/src/vulns/CVE-2022-29901.sh new file mode 100644 index 0000000..1a76f05 --- /dev/null +++ b/src/vulns/CVE-2022-29901.sh @@ -0,0 +1,157 @@ +# vim: set ts=4 sw=4 sts=4 et: +############################### +# CVE-2022-29901, Retbleed (Intel), RSB Alternate Behavior (RSBA) + +check_CVE_2022_29901() { + check_cve 'CVE-2022-29901' +} + +check_CVE_2022_29901_linux() { + local status sys_interface_available msg kernel_retbleed kernel_retbleed_err kernel_ibrs_entry + status=UNK + sys_interface_available=0 + msg='' + + # + # Kernel source inventory for retbleed (CVE-2022-29900 / CVE-2022-29901) + # + # See CVE-2022-29900.sh for the full sysfs/Kconfig/function/stable/vendor inventory. + # + # Intel-specific notes: + # - eIBRS (IBRS_ALL) mitigates the vulnerability on Intel + # - plain retpoline does NOT mitigate on RSBA-capable CPUs (Retbleed bypasses retpoline) + # - IBRS entry also mitigates + # - call depth tracking / stuffing mitigates (v6.2+) + # + # --- Kconfig symbols (Intel-relevant) --- + # CONFIG_CPU_IBRS_ENTRY (< 6.9) / CONFIG_MITIGATION_IBRS_ENTRY (>= 6.9): Intel IBRS + # CONFIG_CALL_DEPTH_TRACKING (< 6.9) / CONFIG_MITIGATION_CALL_DEPTH_TRACKING (>= 6.9): stuffing + # + # --- CPU affection logic (Intel) --- + # 6ad0ad2bf8a6 (v5.19-rc7, initial Intel list): + # SKYLAKE_L, SKYLAKE, SKYLAKE_X, KABYLAKE_L, KABYLAKE, + # ICELAKE_L, COMETLAKE, COMETLAKE_L, LAKEFIELD, ROCKETLAKE + # f54d45372c6a (post-v5.19): + CANNONLAKE_L + # + any Intel with ARCH_CAP_RSBA set in IA32_ARCH_CAPABILITIES MSR (bit 2) + # immunity: none (no _NO bit for RETBLEED on Intel; eIBRS is a mitigation, not immunity) + # + + if sys_interface_check "$VULN_SYSFS_BASE/retbleed"; then + # this kernel has the /sys interface, trust it over everything + sys_interface_available=1 + status=$ret_sys_interface_check_status + fi + + if [ "$opt_sysfs_only" != 1 ]; then + pr_info_nol "* Kernel supports mitigation: " + if [ -n "$g_kernel_err" ]; then + kernel_retbleed_err="$g_kernel_err" + elif grep -q 'retbleed' "$g_kernel"; then + kernel_retbleed="found retbleed mitigation logic in kernel image" + fi + if [ -z "$kernel_retbleed" ] && [ -n "$opt_map" ]; then + if grep -q 'retbleed_select_mitigation' "$opt_map"; then + kernel_retbleed="found retbleed_select_mitigation in System.map" + fi + fi + if [ -n "$kernel_retbleed" ]; then + pstatus green YES "$kernel_retbleed" + elif [ -n "$kernel_retbleed_err" ]; then + pstatus yellow UNKNOWN "$kernel_retbleed_err" + else + pstatus yellow NO + fi + + pr_info_nol "* Kernel compiled with IBRS_ENTRY support: " + if [ -r "$opt_config" ]; then + # CONFIG_CPU_IBRS_ENTRY: Linux < 6.9 + # CONFIG_MITIGATION_IBRS_ENTRY: Linux >= 6.9 + if grep -Eq '^CONFIG_(CPU|MITIGATION)_IBRS_ENTRY=y' "$opt_config"; then + pstatus green YES + kernel_ibrs_entry="CONFIG_(CPU|MITIGATION)_IBRS_ENTRY=y found in kernel config" + else + pstatus yellow NO + fi + else + if [ -n "$g_kernel_err" ]; then + pstatus yellow UNKNOWN "$g_kernel_err" + elif [ -n "$kernel_retbleed" ]; then + kernel_ibrs_entry="retbleed mitigation logic present in kernel (IBRS_ENTRY status unknown)" + pstatus yellow UNKNOWN "kernel has retbleed mitigation but config not available to verify" + else + pstatus yellow NO "your kernel is too old and doesn't have the retbleed mitigation logic" + fi + fi + + pr_info_nol "* CPU supports Enhanced IBRS (IBRS_ALL): " + if [ "$opt_live" = 1 ] || [ "$cap_ibrs_all" != -1 ]; then + if [ "$cap_ibrs_all" = 1 ]; then + pstatus green YES + elif [ "$cap_ibrs_all" = 0 ]; then + pstatus yellow NO + else + pstatus yellow UNKNOWN + fi + else + pstatus blue N/A "not testable in offline mode" + fi + + pr_info_nol "* CPU has RSB Alternate Behavior (RSBA): " + if [ "$opt_live" = 1 ] || [ "$cap_rsba" != -1 ]; then + if [ "$cap_rsba" = 1 ]; then + pstatus yellow YES "this CPU is affected by RSB underflow" + elif [ "$cap_rsba" = 0 ]; then + pstatus green NO + else + pstatus yellow UNKNOWN + fi + else + pstatus blue N/A "not testable in offline mode" + fi + + elif [ "$sys_interface_available" = 0 ]; then + # we have no sysfs but were asked to use it only! + msg="/sys vulnerability interface use forced, but it's not available!" + status=UNK + fi + + if ! is_cpu_affected "$cve"; then + # override status & msg in case CPU is not vulnerable after all + 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_sysfs_only" != 1 ]; then + if [ -z "$kernel_retbleed" ]; then + pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the retbleed mitigation logic" + elif [ "$cap_ibrs_all" = 1 ]; then + if [ "$opt_paranoid" = 1 ] && [ "$cap_rrsba" = 1 ]; then + pvulnstatus "$cve" VULN "eIBRS is enabled but RRSBA is present, which may weaken the mitigation" + explain "In paranoid mode, the combination of eIBRS and RRSBA (Restricted RSB Alternate Behavior)\n" \ + "is flagged because RRSBA means the RSB can still be influenced in some scenarios.\n" \ + "Check if your firmware/kernel supports disabling RRSBA via RRSBA_CTRL." + else + pvulnstatus "$cve" OK "Enhanced IBRS (IBRS_ALL) mitigates the vulnerability" + fi + elif [ -n "$kernel_ibrs_entry" ]; then + pvulnstatus "$cve" OK "Your kernel has IBRS_ENTRY mitigation compiled-in" + else + pvulnstatus "$cve" VULN "Your kernel has retbleed mitigation but IBRS_ENTRY is not compiled-in and eIBRS is not available" + explain "Retpoline alone does NOT mitigate Retbleed on RSBA-capable Intel CPUs.\n" \ + "You need either Enhanced IBRS (eIBRS, via firmware/microcode update) or a kernel\n" \ + "compiled with IBRS_ENTRY support (Linux 5.19+, CONFIG_(CPU|MITIGATION)_IBRS_ENTRY)." + fi + else + pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg" + fi + else + pvulnstatus "$cve" "$status" "$msg" + fi +} + +check_CVE_2022_29901_bsd() { + if ! is_cpu_affected "$cve"; then + pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" + else + pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script" + fi +} diff --git a/src/vulns/CVE-2022-40982.sh b/src/vulns/CVE-2022-40982.sh index 5a07460..8de3d1a 100644 --- a/src/vulns/CVE-2022-40982.sh +++ b/src/vulns/CVE-2022-40982.sh @@ -1,13 +1,11 @@ # vim: set ts=4 sw=4 sts=4 et: -######################### -# Downfall section +############################### +# CVE-2022-40982, Downfall, GDS, Gather Data Sampling -# CVE-2022-40982 Downfall (gather data sampling) - entry point check_CVE_2022_40982() { check_cve 'CVE-2022-40982' } -# CVE-2022-40982 Downfall (gather data sampling) - Linux mitigation check check_CVE_2022_40982_linux() { local status sys_interface_available msg kernel_gds kernel_gds_err kernel_avx_disabled dmesgret ret status=UNK @@ -17,6 +15,90 @@ check_CVE_2022_40982_linux() { if sys_interface_check "$VULN_SYSFS_BASE/gather_data_sampling"; then # this kernel has the /sys interface, trust it over everything sys_interface_available=1 + # + # Kernel source inventory for gather_data_sampling (GDS/Downfall) + # + # --- sysfs messages --- + # all versions: + # "Not affected" (cpu_show_common, pre-existing) + # + # --- mainline --- + # 8974eb588283 (v6.5-rc6, initial GDS sysfs): + # "Vulnerable" (GDS_MITIGATION_OFF) + # "Vulnerable: No microcode" (GDS_MITIGATION_UCODE_NEEDED) + # "Mitigation: Microcode" (GDS_MITIGATION_FULL) + # "Mitigation: Microcode (locked)" (GDS_MITIGATION_FULL_LOCKED) + # "Unknown: Dependent on hypervisor status" (GDS_MITIGATION_HYPERVISOR) + # 553a5c03e90a (v6.5-rc6, added force option): + # "Mitigation: AVX disabled, no microcode" (GDS_MITIGATION_FORCE) + # 53cf5797f114 (v6.5-rc6, added CONFIG_GDS_FORCE_MITIGATION): + # no string changes; default becomes FORCE when Kconfig enabled + # 81ac7e5d7417 (v6.5-rc6, KVM GDS_NO plumbing): + # no string changes + # be83e809ca67 (v6.9-rc1, Kconfig rename): + # no string changes; CONFIG_GDS_FORCE_MITIGATION => CONFIG_MITIGATION_GDS_FORCE + # 03267a534bb3 (v6.12-rc1, removed force Kconfig): + # no string changes; CONFIG_MITIGATION_GDS_FORCE removed + # 225f2bd064c3 (v6.12-rc1, added on/off Kconfig): + # no string changes; added CONFIG_MITIGATION_GDS (default y) + # 9dcad2fb31bd (v6.16-rc1, restructured select/apply): + # no string changes; added GDS_MITIGATION_AUTO (internal, resolved before display) + # split gds_select_mitigation() + gds_apply_mitigation() + # d4932a1b148b (v6.17-rc3, bug fix): + # no string changes; CPUs without ARCH_CAP_GDS_CTRL were incorrectly classified + # as OFF ("Vulnerable") instead of UCODE_NEEDED ("Vulnerable: No microcode"), + # and locked-mitigation detection was skipped. + # NOT backported to any stable or RHEL branch as of 2026-04. + # + # --- stable backports --- + # 5.4.y, 5.10.y, 5.15.y, 6.1.y, 6.6.y: same 7 strings as mainline. + # use CONFIG_GDS_FORCE_MITIGATION; no GDS_MITIGATION_AUTO enum; + # missing d4932a1b148b bug fix (UCODE_NEEDED vs OFF misclassification). + # 6.12.y: same 7 strings as mainline. + # uses CONFIG_MITIGATION_GDS; no GDS_MITIGATION_AUTO enum; + # missing d4932a1b148b bug fix. + # + # --- RHEL/CentOS --- + # centos7 (3.10), rocky8 (4.18): same 7 strings; CONFIG_GDS_FORCE_MITIGATION. + # centos7 uses sprintf (not sysfs_emit) and __read_mostly. + # rocky9 (5.14): same 7 strings; CONFIG_MITIGATION_GDS (skipped FORCE rename). + # rocky10 (6.12): same 7 strings; CONFIG_MITIGATION_GDS; has gds_apply_mitigation(). + # + # --- Kconfig symbols --- + # 53cf5797f114 (v6.5-rc6): CONFIG_GDS_FORCE_MITIGATION (default n) + # be83e809ca67 (v6.9-rc1): renamed to CONFIG_MITIGATION_GDS_FORCE + # 03267a534bb3 (v6.12-rc1): CONFIG_MITIGATION_GDS_FORCE removed + # 225f2bd064c3 (v6.12-rc1): CONFIG_MITIGATION_GDS (default y) + # vendor kernels: rocky9 uses CONFIG_MITIGATION_GDS on 5.14-based kernel + # + # --- kernel functions (for $opt_map / System.map) --- + # 8974eb588283 (v6.5-rc6): gds_select_mitigation(), update_gds_msr(), + # gds_parse_cmdline(), gds_show_state() + # 81ac7e5d7417 (v6.5-rc6): gds_ucode_mitigated() (exported for KVM) + # 9dcad2fb31bd (v6.16-rc1): split into gds_select_mitigation() + gds_apply_mitigation() + # stable 5.4.y-6.12.y: same 5 functions (no gds_apply_mitigation) + # rocky10 (6.12): has gds_apply_mitigation() + # + # --- CPU affection logic (for is_cpu_affected) --- + # X86_BUG_GDS is set when ALL three conditions are true: + # 1. CPU matches model blacklist (cpu_vuln_blacklist[] in common.c) + # 2. ARCH_CAP_GDS_NO (bit 26 of IA32_ARCH_CAPABILITIES) is NOT set + # 3. X86_FEATURE_AVX is present (GATHER instructions require AVX) + # 8974eb588283 (v6.5-rc6, initial model list): + # Intel: SKYLAKE_X, KABYLAKE_L, KABYLAKE, ICELAKE_L, ICELAKE_D, + # ICELAKE_X, COMETLAKE, COMETLAKE_L, TIGERLAKE_L, TIGERLAKE, + # ROCKETLAKE (all steppings) + # c9f4c45c8ec3 (v6.5-rc6, added missing client Skylake): + # Intel: + SKYLAKE_L, SKYLAKE + # 159013a7ca18 (v6.10-rc1, ITS stepping splits): + # no GDS model changes; some entries split by stepping for ITS but + # GDS flag remains on all stepping ranges for these models + # immunity: ARCH_CAP_GDS_NO (bit 26 of IA32_ARCH_CAPABILITIES) + # feature dependency: requires AVX (if AVX absent, CPU is immune) + # vendor scope: Intel only + # + # all messages start with either "Not affected", "Vulnerable", "Mitigation", + # or "Unknown" status=$ret_sys_interface_check_status fi @@ -24,15 +106,34 @@ check_CVE_2022_40982_linux() { pr_info_nol "* GDS is mitigated by microcode: " if [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then pstatus green OK "microcode mitigation is supported and enabled" + elif [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 1 ]; then + pstatus yellow NO "microcode mitigation is supported but disabled" + elif [ "$cap_gds_ctrl" = 0 ]; then + pstatus yellow NO "microcode doesn't support GDS mitigation" else - pstatus yellow NO + pstatus yellow UNKNOWN "couldn't read MSR for GDS capability" fi + pr_info_nol "* Kernel supports software mitigation by disabling AVX: " + kernel_gds='' + kernel_gds_err='' if [ -n "$g_kernel_err" ]; then kernel_gds_err="$g_kernel_err" elif grep -q 'gather_data_sampling' "$g_kernel"; then kernel_gds="found gather_data_sampling in kernel image" fi + if [ -z "$kernel_gds" ] && [ -r "$opt_config" ]; then + if grep -q '^CONFIG_GDS_FORCE_MITIGATION=y' "$opt_config" || + grep -q '^CONFIG_MITIGATION_GDS_FORCE=y' "$opt_config" || + grep -q '^CONFIG_MITIGATION_GDS=y' "$opt_config"; then + kernel_gds="GDS mitigation config option found enabled in kernel config" + fi + fi + if [ -z "$kernel_gds" ] && [ -n "$opt_map" ]; then + if grep -q 'gds_select_mitigation' "$opt_map"; then + kernel_gds="found gds_select_mitigation in System.map" + fi + fi if [ -n "$kernel_gds" ]; then pstatus green YES "$kernel_gds" elif [ -n "$kernel_gds_err" ]; then @@ -44,30 +145,34 @@ check_CVE_2022_40982_linux() { if [ -n "$kernel_gds" ]; then pr_info_nol "* Kernel has disabled AVX as a mitigation: " - # Check dmesg message to see whether AVX has been disabled - dmesg_grep 'Microcode update needed! Disabling AVX as mitigation' - dmesgret=$? - if [ "$dmesgret" -eq 0 ]; then - kernel_avx_disabled="AVX disabled by the kernel (dmesg)" - pstatus green YES "$kernel_avx_disabled" - elif [ "$cap_avx2" = 0 ]; then - # Find out by ourselves - # cpuinfo says we don't have AVX2, query - # the CPU directly about AVX2 support - read_cpuid 0x7 0x0 "$EBX" 5 1 1 - ret=$? - if [ "$ret" -eq "$READ_CPUID_RET_OK" ]; then - kernel_avx_disabled="AVX disabled by the kernel (cpuid)" + if [ "$opt_live" = 1 ]; then + # Check dmesg message to see whether AVX has been disabled + dmesg_grep 'Microcode update needed! Disabling AVX as mitigation' + dmesgret=$? + if [ "$dmesgret" -eq 0 ]; then + kernel_avx_disabled="AVX disabled by the kernel (dmesg)" pstatus green YES "$kernel_avx_disabled" - elif [ "$ret" -eq "$READ_CPUID_RET_KO" ]; then - pstatus yellow NO "CPU doesn't support AVX" - elif [ "$dmesgret" -eq 2 ]; then - pstatus yellow UNKNOWN "dmesg truncated, can't tell whether mitigation is active, please reboot and relaunch this script" + elif [ "$cap_avx2" = 0 ]; then + # Find out by ourselves + # cpuinfo says we don't have AVX2, query + # the CPU directly about AVX2 support + read_cpuid 0x7 0x0 "$EBX" 5 1 1 + ret=$? + if [ "$ret" -eq "$READ_CPUID_RET_OK" ]; then + kernel_avx_disabled="AVX disabled by the kernel (cpuid)" + pstatus green YES "$kernel_avx_disabled" + elif [ "$ret" -eq "$READ_CPUID_RET_KO" ]; then + pstatus yellow NO "CPU doesn't support AVX" + elif [ "$dmesgret" -eq 2 ]; then + pstatus yellow UNKNOWN "dmesg truncated, can't tell whether mitigation is active, please reboot and relaunch this script" + else + pstatus yellow UNKNOWN "No sign of mitigation in dmesg and couldn't read cpuid info" + fi else - pstatus yellow UNKNOWN "No sign of mitigation in dmesg and couldn't read cpuid info" + pstatus yellow NO "AVX support is enabled" fi else - pstatus yellow NO "AVX support is enabled" + pstatus blue N/A "not testable in offline mode" fi fi @@ -82,23 +187,39 @@ check_CVE_2022_40982_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 [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then - pvulnstatus "$cve" OK "Your microcode is up to date and mitigation is enabled" - elif [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 1 ]; then - pvulnstatus "$cve" VULN "Your microcode is up to date but mitigation is disabled" - elif [ -z "$kernel_gds" ]; then - pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, and your kernel doesn't support mitigation" - elif [ -z "$kernel_avx_disabled" ]; then - pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, your kernel support the mitigation but the script did not detect AVX as disabled by the kernel" + if [ "$opt_sysfs_only" != 1 ]; then + if [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then + if [ "$opt_paranoid" = 1 ] && [ "$cap_gds_mitg_lock" != 1 ]; then + pvulnstatus "$cve" VULN "Microcode mitigation is enabled but not locked" + explain "In paranoid mode, the GDS mitigation must be locked to prevent a privileged attacker\n " \ + "(e.g. in a guest VM) from disabling it. Check your firmware/BIOS for an option to lock the\n " \ + "GDS mitigation, or update your microcode." + else + pvulnstatus "$cve" OK "Your microcode is up to date and mitigation is enabled" + fi + elif [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 1 ]; then + pvulnstatus "$cve" VULN "Your microcode is up to date but mitigation is disabled" + explain "The GDS mitigation has been explicitly disabled (gather_data_sampling=off or mitigations=off).\n " \ + "Remove the kernel parameter to re-enable it." + elif [ -z "$kernel_gds" ]; then + pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, and your kernel doesn't support mitigation" + explain "Update both your CPU microcode (via BIOS/firmware update from your OEM) and your kernel\n " \ + "to a version that supports GDS mitigation (Linux 6.5+, or check if your distro has a backport)." + elif [ -z "$kernel_avx_disabled" ]; then + pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, your kernel supports the mitigation but AVX was not disabled" + explain "Update your CPU microcode (via BIOS/firmware update from your OEM). If no microcode update\n " \ + "is available, use gather_data_sampling=force on the kernel command line to disable AVX as a workaround." + else + pvulnstatus "$cve" OK "Your microcode doesn't mitigate the vulnerability, but your kernel has disabled AVX support" + fi else - pvulnstatus "$cve" OK "Your microcode doesn't mitigate the vulnerability, but your kernel has disabled AVX support" + pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg" fi else pvulnstatus "$cve" "$status" "$msg" fi } -# CVE-2022-40982 Downfall (gather data sampling) - BSD mitigation check check_CVE_2022_40982_bsd() { if ! is_cpu_affected "$cve"; then pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" diff --git a/src/vulns/CVE-2023-20569.sh b/src/vulns/CVE-2023-20569.sh index d438d4b..b05ad94 100644 --- a/src/vulns/CVE-2023-20569.sh +++ b/src/vulns/CVE-2023-20569.sh @@ -1,13 +1,11 @@ # vim: set ts=4 sw=4 sts=4 et: -####################### -# Inception section +############################### +# CVE-2023-20569, Inception, SRSO, Return Address Security -# CVE-2023-20569 Inception (SRSO, speculative return stack overflow) - entry point check_CVE_2023_20569() { check_cve 'CVE-2023-20569' } -# CVE-2023-20569 Inception (SRSO, speculative return stack overflow) - Linux mitigation check check_CVE_2023_20569_linux() { local status sys_interface_available msg kernel_sro kernel_sro_err kernel_srso kernel_ibpb_entry smt_enabled status=UNK @@ -206,7 +204,6 @@ check_CVE_2023_20569_linux() { fi } -# CVE-2023-20569 Inception (SRSO, speculative return stack overflow) - BSD mitigation check check_CVE_2023_20569_bsd() { if ! is_cpu_affected "$cve"; then pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" diff --git a/src/vulns/CVE-2023-20593.sh b/src/vulns/CVE-2023-20593.sh index 4003265..2669ecd 100644 --- a/src/vulns/CVE-2023-20593.sh +++ b/src/vulns/CVE-2023-20593.sh @@ -1,13 +1,11 @@ # vim: set ts=4 sw=4 sts=4 et: -#################### -# Zenbleed section +############################### +# CVE-2023-20593, Zenbleed, Cross-Process Information Leak -# CVE-2023-20593 Zenbleed (cross-process information leak via AVX2) - entry point check_CVE_2023_20593() { check_cve 'CVE-2023-20593' } -# CVE-2023-20593 Zenbleed (cross-process information leak via AVX2) - Linux mitigation check check_CVE_2023_20593_linux() { local status sys_interface_available msg kernel_zenbleed kernel_zenbleed_err fp_backup_fix ucode_zenbleed zenbleed_print_vuln ret status=UNK @@ -119,7 +117,6 @@ check_CVE_2023_20593_linux() { fi } -# CVE-2023-20593 Zenbleed (cross-process information leak via AVX2) - BSD mitigation check check_CVE_2023_20593_bsd() { local zenbleed_enable zenbleed_state kernel_zenbleed pr_info_nol "* Kernel supports Zenbleed mitigation (machdep.mitigations.zenbleed.enable): " diff --git a/src/vulns/CVE-2023-23583.sh b/src/vulns/CVE-2023-23583.sh index 1df1ea6..afb9719 100644 --- a/src/vulns/CVE-2023-23583.sh +++ b/src/vulns/CVE-2023-23583.sh @@ -1,13 +1,11 @@ # vim: set ts=4 sw=4 sts=4 et: -####################### -# Reptar section +############################### +# CVE-2023-23583, Reptar, Redundant Prefix Issue -# CVE-2023-23583 Reptar (redundant prefix issue) - entry point check_CVE_2023_23583() { check_cve 'CVE-2023-23583' } -# CVE-2023-23583 Reptar (redundant prefix issue) - Linux mitigation check check_CVE_2023_23583_linux() { local status sys_interface_available msg status=UNK @@ -31,7 +29,6 @@ check_CVE_2023_23583_linux() { fi } -# CVE-2023-23583 Reptar (redundant prefix issue) - BSD mitigation check check_CVE_2023_23583_bsd() { if ! is_cpu_affected "$cve"; then pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" diff --git a/src/vulns/CVE-2024-36350.sh b/src/vulns/CVE-2024-36350.sh index 7a24f09..4aec907 100644 --- a/src/vulns/CVE-2024-36350.sh +++ b/src/vulns/CVE-2024-36350.sh @@ -1,13 +1,11 @@ # vim: set ts=4 sw=4 sts=4 et: -#################### -# TSA-SQ section +############################### +# CVE-2024-36350, TSA-SQ, Transient Scheduler Attack Store Queue -# CVE-2024-36350 TSA-SQ (transient scheduler attack - store queue) - entry point check_CVE_2024_36350() { check_cve 'CVE-2024-36350' } -# CVE-2024-36350 TSA-SQ (transient scheduler attack - store queue) - Linux mitigation check check_CVE_2024_36350_linux() { local status sys_interface_available msg kernel_tsa kernel_tsa_err smt_enabled status=UNK @@ -167,7 +165,6 @@ check_CVE_2024_36350_linux() { fi } -# CVE-2024-36350 TSA-SQ (transient scheduler attack - store queue) - BSD mitigation check check_CVE_2024_36350_bsd() { if ! is_cpu_affected "$cve"; then pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" diff --git a/src/vulns/CVE-2024-36357.sh b/src/vulns/CVE-2024-36357.sh index a5cc825..858b50e 100644 --- a/src/vulns/CVE-2024-36357.sh +++ b/src/vulns/CVE-2024-36357.sh @@ -1,13 +1,11 @@ # vim: set ts=4 sw=4 sts=4 et: -#################### -# TSA-L1 section +############################### +# CVE-2024-36357, TSA-L1, Transient Scheduler Attack L1 -# CVE-2024-36357 TSA-L1 (transient scheduler attack - L1 cache) - entry point check_CVE_2024_36357() { check_cve 'CVE-2024-36357' } -# CVE-2024-36357 TSA-L1 (transient scheduler attack - L1 cache) - Linux mitigation check check_CVE_2024_36357_linux() { local status sys_interface_available msg kernel_tsa kernel_tsa_err status=UNK @@ -160,7 +158,6 @@ check_CVE_2024_36357_linux() { fi } -# CVE-2024-36357 TSA-L1 (transient scheduler attack - L1 cache) - BSD mitigation check check_CVE_2024_36357_bsd() { if ! is_cpu_affected "$cve"; then pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"