Compare commits

..

4 Commits

Author SHA1 Message Date
github-actions[bot]
e844f9cff3 feat: hide CVE checks that arebirrelevant for current arch
built from commit 7329c1fd2f
 dated 2026-04-21 08:53:08 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)

 CVE_REGISTRY gains an optional fifth field that tags checks as x86-only or
arm-only, untagged entries apply everywhere. The main CVE dispatcher and the
affectedness summary both skip gated entries in default "all CVEs" runs,
removing the noise of arm64 errata on x86 hosts and of x86 CVEs on ARM hosts
across text, json, nrpe and prometheus outputs. Explicit --cve/--variant/--errata
selection bypasses the gate so manual queries still run anywhere.
The gate honours no-hw mode by ignoring the host CPU and keying off the
inspected kernel's architecture only, which handles cross-arch offline
analysis driven by --kernel/--config/--map.
2026-04-21 06:56:29 +00:00
github-actions[bot]
5262efbf55 fix: mmio stale data: EOL Intel CPUs may be vulnerable (#437)
built from commit 03b1787d69
 dated 2026-04-20 22:42:04 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)
2026-04-20 20:44:06 +00:00
github-actions[bot]
440424f524 doc: readme: correct markdown indentation for unordered list items (#569)
built from commit 8a417e5579
 dated 2026-04-21 00:02:47 +0800
 by 林博仁 Buo-ren Lin (Buo.Ren.Lin@gmail.com)

 Signed-off-by: 林博仁(Buo-ren Lin) <buo.ren.lin@gmail.com>
2026-04-20 16:05:45 +00:00
github-actions[bot]
b7b0efa773 doc: add Jump Conditional Code (JCC) Erratum to the unsupported list
built from commit b7a6182a65
 dated 2026-04-20 17:47:50 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)
2026-04-20 15:49:22 +00:00
3 changed files with 618 additions and 104 deletions

View File

@@ -40,6 +40,14 @@ CVE | Name | Aliases
[CVE-2024-45332](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-45332) | Branch Privilege Injection | BPI
[CVE-2025-54505](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-54505) | AMD Zen1 Floating-Point Divider Stale Data Leak | FPDSS
The following entries are ARM64 silicon errata that the kernel actively works around. They have no assigned CVE; they are tracked only by ARM's erratum numbers. Select them with `--errata <number>` or the associated `--variant` mnemonic.
ID | Name | Affected cores
-- | ---- | --------------
CVE-0001-0001 | Speculative AT TLB corruption (errata 1165522, 1319367, 1319537, 1530923) | Cortex-A55/A57/A72/A76
CVE-0001-0002 | Speculative unprivileged load (errata 2966298, 3117295) | Cortex-A510/A520
CVE-0001-0003 | MSR SSBS not self-synchronizing (erratum 3194386 + siblings) | Cortex-A76/A77/A78/A78C/A710/A715/A720/A720AE/A725, X1/X1C/X2/X3/X4/X925, Neoverse-N1/N2/N3/V1/V2/V3/V3AE
## Am I at risk?
Depending on your situation, the table below answers whether an attacker in a given position can extract data from a given target.
@@ -272,23 +280,23 @@ In **Hardware-only** mode, the script only reports CPU information and per-CVE h
- Get the latest version of the script using `curl` *or* `wget`
```bash
curl -L https://meltdown.ovh -o spectre-meltdown-checker.sh
wget https://meltdown.ovh -O spectre-meltdown-checker.sh
```
```bash
curl -L https://meltdown.ovh -o spectre-meltdown-checker.sh
wget https://meltdown.ovh -O spectre-meltdown-checker.sh
```
- Inspect the script. You never blindly run scripts you downloaded from the Internet, do you?
```bash
vim spectre-meltdown-checker.sh
```
```bash
vim spectre-meltdown-checker.sh
```
- When you're ready, run the script as root
```bash
chmod +x spectre-meltdown-checker.sh
sudo ./spectre-meltdown-checker.sh
```
```bash
chmod +x spectre-meltdown-checker.sh
sudo ./spectre-meltdown-checker.sh
```
### Using a docker container

View File

@@ -307,3 +307,13 @@ A weakness in AMD's microcode signature verification (AES-CMAC hash) allows load
Exploits a synchronization failure in the AMD stack engine via an undocumented MSR bit, targeting AMD SEV-SNP confidential VMs. Requires hypervisor-level (ring 0) access.
**Why out of scope:** Not a transient/speculative execution side channel. This is an architectural attack on AMD SEV-SNP confidential computing that requires hypervisor access, which is outside the threat model of this tool.
## No CVE — Jump Conditional Code (JCC) Erratum
- **Issue:** [#329](https://github.com/speed47/spectre-meltdown-checker/issues/329)
- **Intel whitepaper:** [Mitigations for Jump Conditional Code Erratum](https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf)
- **Affected CPUs:** Intel 6th through 10th generation Core and Xeon processors (Skylake through Cascade Lake)
A microarchitectural correctness erratum where a conditional jump instruction that straddles or ends at a 64-byte instruction fetch boundary can corrupt the branch predictor state, potentially causing incorrect execution. Intel addressed this in a November 2019 microcode update. Compilers and assemblers (GCC, LLVM, binutils) also introduced alignment options (`-mbranch-alignment`, `-x86-branches-within-32B-boundaries`) to pad jump instructions away from boundary conditions, preserving performance on CPUs with updated microcode.
**Why out of scope:** The JCC erratum is a microarchitectural correctness bug, not a transient or speculative execution side-channel vulnerability. No CVE was ever assigned. Red Hat noted that privilege escalation "has not been ruled out" but made no definitive security finding, and no exploit has been demonstrated. There is no Linux sysfs entry, no CPUID bit, and no MSR flag exposing the mitigation status. The microcode fix introduces no detectable hardware indicator, so checking for it would require maintaining a per-CPU-stepping minimum microcode version table (the design principle 3 exception) — costly to maintain without a CVE anchor or confirmed exploitability to justify the ongoing work. The kernel compiler mitigation is a build-time-only change (instruction alignment) with no observable runtime state.

View File

@@ -13,7 +13,7 @@
#
# Stephane Lesimple
#
VERSION='26.33.0420455'
VERSION='26.36.0421288'
# --- Common paths and basedirs ---
readonly VULN_SYSFS_BASE="/sys/devices/system/cpu/vulnerabilities"
@@ -79,6 +79,9 @@ show_usage() {
can be used multiple times (e.g. --variant 3a --variant l1tf). For a list use 'help'.
--cve CVE specify which CVE you'd like to check, by default all supported CVEs are checked
can be used multiple times (e.g. --cve CVE-2017-5753 --cve CVE-2020-0543)
--errata NUMBER specify a vendor-numbered erratum (e.g. ARM64 erratum 1530923) that has no CVE
assigned. Maps the erratum to the corresponding check. For a list use 'help'.
Can be used multiple times (e.g. --errata 1530923 --errata 3194386).
Check scope:
--no-sysfs don't use the /sys interface even if present [Linux]
@@ -207,47 +210,61 @@ g_smc_system_info_line=''
g_smc_cpu_info_line=''
# CVE Registry: single source of truth for all CVE metadata.
# Fields: cve_id|json_key_name|affected_var_suffix|complete_name_and_aliases
# Fields: cve_id|json_key_name|affected_var_suffix|complete_name_and_aliases|arch
#
# Two ranges of placeholder IDs are reserved when no real CVE applies:
# The optional `arch` field gates whether the check is run at all, based on the
# host CPU architecture and the inspected kernel architecture. Values:
# x86 - only relevant when host CPU or inspected kernel is x86/amd64
# arm - only relevant when host CPU or inspected kernel is ARM/ARM64
# (empty) - always relevant (shared logic across architectures, e.g. Spectre V1-V4)
# The gate only applies to default "all CVEs" runs; explicit --cve/--variant/--errata
# selection bypasses it (if the user asks for it, they get it regardless of arch).
#
# Three ranges of placeholder IDs are reserved when no real CVE applies:
# CVE-0000-NNNN: permanent placeholder for supplementary checks (--extra only)
# that will never receive a real CVE (e.g. SLS, compile-time hardening).
# CVE-0001-NNNN: permanent placeholder for vendor-numbered errata that will never
# receive a CVE (e.g. ARM64 silicon errata tracked only by erratum ID).
# Selectable via --errata <number>.
# CVE-9999-NNNN: temporary placeholder for real vulnerabilities awaiting CVE
# assignment. Rename across the codebase once the real CVE is issued.
readonly CVE_REGISTRY='
CVE-2017-5753|SPECTRE VARIANT 1|variant1|Spectre Variant 1, bounds check bypass
CVE-2017-5715|SPECTRE VARIANT 2|variant2|Spectre Variant 2, branch target injection
CVE-2017-5754|MELTDOWN|variant3|Variant 3, Meltdown, rogue data cache load
CVE-2018-3640|VARIANT 3A|variant3a|Variant 3a, rogue system register read
CVE-2018-3639|VARIANT 4|variant4|Variant 4, speculative store bypass
CVE-2018-3615|L1TF SGX|variantl1tf_sgx|Foreshadow (SGX), L1 terminal fault
CVE-2018-3620|L1TF OS|variantl1tf|Foreshadow-NG (OS), L1 terminal fault
CVE-2018-3646|L1TF VMM|variantl1tf|Foreshadow-NG (VMM), L1 terminal fault
CVE-2018-12126|MSBDS|msbds|Fallout, microarchitectural store buffer data sampling (MSBDS)
CVE-2018-12130|MFBDS|mfbds|ZombieLoad, microarchitectural fill buffer data sampling (MFBDS)
CVE-2018-12127|MLPDS|mlpds|RIDL, microarchitectural load port data sampling (MLPDS)
CVE-2019-11091|MDSUM|mdsum|RIDL, microarchitectural data sampling uncacheable memory (MDSUM)
CVE-2019-11135|TAA|taa|ZombieLoad V2, TSX Asynchronous Abort (TAA)
CVE-2018-12207|ITLBMH|itlbmh|No eXcuses, iTLB Multihit, machine check exception on page size changes (MCEPSC)
CVE-2020-0543|SRBDS|srbds|Special Register Buffer Data Sampling (SRBDS)
CVE-2022-21123|SBDR|mmio|Shared Buffers Data Read (SBDR), MMIO Stale Data
CVE-2022-21125|SBDS|mmio|Shared Buffers Data Sampling (SBDS), MMIO Stale Data
CVE-2022-21166|DRPW|mmio|Device Register Partial Write (DRPW), MMIO Stale Data
CVE-2023-20588|DIV0|div0|Division by Zero, AMD Zen1 speculative data leak
CVE-2023-20593|ZENBLEED|zenbleed|Zenbleed, cross-process information leak
CVE-2022-40982|DOWNFALL|downfall|Downfall, gather data sampling (GDS)
CVE-2022-29900|RETBLEED AMD|retbleed|Retbleed, arbitrary speculative code execution with return instructions (AMD)
CVE-2022-29901|RETBLEED INTEL|retbleed|Retbleed, arbitrary speculative code execution with return instructions (Intel)
CVE-2023-20569|INCEPTION|inception|Inception, return address security (RAS)
CVE-2023-23583|REPTAR|reptar|Reptar, redundant prefix issue
CVE-2024-36350|TSA_SQ|tsa|Transient Scheduler Attack - Store Queue (TSA-SQ)
CVE-2024-36357|TSA_L1|tsa|Transient Scheduler Attack - L1 (TSA-L1)
CVE-2024-28956|ITS|its|Indirect Target Selection (ITS)
CVE-2025-40300|VMSCAPE|vmscape|VMScape, VM-exit stale branch prediction
CVE-2023-28746|RFDS|rfds|Register File Data Sampling (RFDS)
CVE-2024-45332|BPI|bpi|Branch Privilege Injection (BPI)
CVE-0000-0001|SLS|sls|Straight-Line Speculation (SLS)
CVE-2025-54505|FPDSS|fpdss|FPDSS, AMD Zen1 Floating-Point Divider Stale Data Leak
CVE-2017-5753|SPECTRE VARIANT 1|variant1|Spectre Variant 1, bounds check bypass|
CVE-2017-5715|SPECTRE VARIANT 2|variant2|Spectre Variant 2, branch target injection|
CVE-2017-5754|MELTDOWN|variant3|Variant 3, Meltdown, rogue data cache load|
CVE-2018-3640|VARIANT 3A|variant3a|Variant 3a, rogue system register read|
CVE-2018-3639|VARIANT 4|variant4|Variant 4, speculative store bypass|
CVE-2018-3615|L1TF SGX|variantl1tf_sgx|Foreshadow (SGX), L1 terminal fault|x86
CVE-2018-3620|L1TF OS|variantl1tf|Foreshadow-NG (OS), L1 terminal fault|x86
CVE-2018-3646|L1TF VMM|variantl1tf|Foreshadow-NG (VMM), L1 terminal fault|x86
CVE-2018-12126|MSBDS|msbds|Fallout, microarchitectural store buffer data sampling (MSBDS)|x86
CVE-2018-12130|MFBDS|mfbds|ZombieLoad, microarchitectural fill buffer data sampling (MFBDS)|x86
CVE-2018-12127|MLPDS|mlpds|RIDL, microarchitectural load port data sampling (MLPDS)|x86
CVE-2019-11091|MDSUM|mdsum|RIDL, microarchitectural data sampling uncacheable memory (MDSUM)|x86
CVE-2019-11135|TAA|taa|ZombieLoad V2, TSX Asynchronous Abort (TAA)|x86
CVE-2018-12207|ITLBMH|itlbmh|No eXcuses, iTLB Multihit, machine check exception on page size changes (MCEPSC)|x86
CVE-2020-0543|SRBDS|srbds|Special Register Buffer Data Sampling (SRBDS)|x86
CVE-2022-21123|SBDR|mmio|Shared Buffers Data Read (SBDR), MMIO Stale Data|x86
CVE-2022-21125|SBDS|mmio|Shared Buffers Data Sampling (SBDS), MMIO Stale Data|x86
CVE-2022-21166|DRPW|mmio|Device Register Partial Write (DRPW), MMIO Stale Data|x86
CVE-2023-20588|DIV0|div0|Division by Zero, AMD Zen1 speculative data leak|x86
CVE-2023-20593|ZENBLEED|zenbleed|Zenbleed, cross-process information leak|x86
CVE-2022-40982|DOWNFALL|downfall|Downfall, gather data sampling (GDS)|x86
CVE-2022-29900|RETBLEED AMD|retbleed|Retbleed, arbitrary speculative code execution with return instructions (AMD)|x86
CVE-2022-29901|RETBLEED INTEL|retbleed|Retbleed, arbitrary speculative code execution with return instructions (Intel)|x86
CVE-2023-20569|INCEPTION|inception|Inception, return address security (RAS)|x86
CVE-2023-23583|REPTAR|reptar|Reptar, redundant prefix issue|x86
CVE-2024-36350|TSA_SQ|tsa|Transient Scheduler Attack - Store Queue (TSA-SQ)|x86
CVE-2024-36357|TSA_L1|tsa|Transient Scheduler Attack - L1 (TSA-L1)|x86
CVE-2024-28956|ITS|its|Indirect Target Selection (ITS)|x86
CVE-2025-40300|VMSCAPE|vmscape|VMScape, VM-exit stale branch prediction|x86
CVE-2023-28746|RFDS|rfds|Register File Data Sampling (RFDS)|x86
CVE-2024-45332|BPI|bpi|Branch Privilege Injection (BPI)|x86
CVE-0000-0001|SLS|sls|Straight-Line Speculation (SLS)|
CVE-2025-54505|FPDSS|fpdss|FPDSS, AMD Zen1 Floating-Point Divider Stale Data Leak|x86
CVE-0001-0001|ARM SPEC AT|arm_spec_at|ARM64 errata 1165522/1319367/1319537/1530923, Speculative AT TLB corruption|arm
CVE-0001-0002|ARM SPEC UNPRIV LOAD|arm_spec_unpriv_load|ARM64 errata 2966298/3117295, Speculative unprivileged load|arm
CVE-0001-0003|ARM SSBS NOSYNC|arm_ssbs_nosync|ARM64 erratum 3194386, MSR SSBS not self-synchronizing|arm
'
# Derive the supported CVE list from the registry
@@ -666,6 +683,36 @@ _infer_immune() { eval "[ -z \"\$affected_$1\" ] && affected_$1=1 || :"; }
# Use for: family-level catch-all fallbacks (Intel L1TF non-whitelist, itlbmh non-whitelist).
_infer_vuln() { eval "[ -z \"\$affected_$1\" ] && affected_$1=0 || :"; }
# Return 0 (true) if a CVE's arch tag matches the current context (host CPU
# and/or target kernel), so the check is worth running. Untagged CVEs are
# always relevant.
# - In no-hw mode the host CPU is ignored: gate only on target kernel arch.
# - Otherwise a match on either the host CPU or the target kernel is enough
# (they normally agree in live mode; if they disagree, check_kernel_cpu_arch_mismatch
# has already forced no-hw, handled by the branch above).
# Args: $1=cve_id
# Callers: src/main.sh (CVE dispatch loop), check_cpu_vulnerabilities
_is_cve_relevant_arch() {
local arch
arch=$(_cve_registry_field "$1" 5)
# Untagged CVE: always relevant
[ -z "$arch" ] && return 0
case "$arch" in
x86)
[ "$g_mode" != no-hw ] && is_x86_cpu && return 0
is_x86_kernel && return 0
return 1
;;
arm)
[ "$g_mode" != no-hw ] && is_arm_cpu && return 0
is_arm_kernel && return 0
return 1
;;
esac
# Unknown tag value: don't gate (fail open)
return 0
}
# Return the cached affected_* status for a given CVE
# Args: $1=cve_id
# Returns: 0 if affected, 1 if not affected
@@ -745,6 +792,10 @@ is_cpu_affected() {
affected_srbds=''
affected_mmio=''
affected_sls=''
# ARM64 speculation-related errata (ARM Ltd, implementer 0x41); non-ARM systems are immune below.
affected_arm_spec_at=''
affected_arm_spec_unpriv_load=''
affected_arm_ssbs_nosync=''
# DIV0, FPDSS, Zenbleed and Inception are all AMD specific, look for "is_amd" below:
_set_immune div0
_set_immune fpdss
@@ -1466,6 +1517,77 @@ is_cpu_affected() {
_infer_immune sls
fi
# ARM64 silicon errata (speculation/security-relevant, no CVE assignments).
# References: arch/arm64/Kconfig (ARM64_ERRATUM_*), arch/arm64/kernel/cpu_errata.c MIDR lists.
# Iterates per-core (impl, part, variant, revision) tuples. Implementers currently handled:
# 0x41 ARM Ltd; 0x51 Qualcomm (Kryo4xx Silver for erratum 1530923).
# Revision ranges mirror the kernel's MIDR_RANGE/MIDR_REV_RANGE/MIDR_REV macros. A variant
# 'v' and revision 'p' are packed as (v<<4)|p for range compares — equivalent to the kernel's
# layout (MIDR_VARIANT_SHIFT=20, MIDR_REVISION_MASK=0xf) under the same order semantics.
# Unknown variant/revision ⇒ treat as in range (whitelist principle, DEVELOPMENT.md rule 5).
if [ -n "$cpu_part_list" ]; then
i=0
for cpupart in $cpu_part_list; do
i=$((i + 1))
# shellcheck disable=SC2086
cpuimpl=$(echo $cpu_impl_list | awk '{print $'$i'}')
# shellcheck disable=SC2086
cpuvar=$(echo $cpu_variant_list | awk '{print $'$i'}')
# shellcheck disable=SC2086
cpurev=$(echo $cpu_revision_list | awk '{print $'$i'}')
packed=''
[ -n "$cpuvar" ] && [ -n "$cpurev" ] && packed=$(((cpuvar << 4) | cpurev))
# Speculative AT TLB corruption (errata 1165522, 1319367, 1319537, 1530923)
if [ "$cpuimpl" = 0x41 ]; then
if echo "$cpupart" | grep -q -w -e 0xd07 -e 0xd08; then
# Cortex-A57 (0xd07) / A72 (0xd08): all revisions
_set_vuln arm_spec_at
elif echo "$cpupart" | grep -q -w -e 0xd05 -e 0xd0b; then
# Cortex-A55 (0xd05) / A76 (0xd0b): r0p0..r2p0 (packed 0..32)
if [ -z "$packed" ] || [ "$packed" -le 32 ]; then
_set_vuln arm_spec_at
fi
fi
elif [ "$cpuimpl" = 0x51 ] && [ "$cpupart" = 0x805 ]; then
# Qualcomm Kryo4xx Silver: kernel matches MIDR_REV(var 0xd, rev 0xe) only — packed 0xde = 222
if [ -z "$packed" ] || [ "$packed" = 222 ]; then
_set_vuln arm_spec_at
fi
fi
# Speculative unprivileged load (errata 2966298 A520, 3117295 A510) — ARM Ltd only
if [ "$cpuimpl" = 0x41 ]; then
if [ "$cpupart" = 0xd46 ]; then
# Cortex-A510: all revisions
_set_vuln arm_spec_unpriv_load
elif [ "$cpupart" = 0xd80 ]; then
# Cortex-A520: r0p0..r0p1 (packed 0..1)
if [ -z "$packed" ] || [ "$packed" -le 1 ]; then
_set_vuln arm_spec_unpriv_load
fi
fi
fi
# MSR SSBS not self-synchronizing (erratum 3194386 + siblings) — ARM Ltd only, all revisions.
# A76/A77/A78/A78C/A710/A715/A720/A720AE/A725, X1/X1C/X2/X3/X4/X925, N1/N2/N3, V1/V2/V3/V3AE
if [ "$cpuimpl" = 0x41 ]; then
if echo "$cpupart" | grep -q -w \
-e 0xd0b -e 0xd0d -e 0xd41 -e 0xd4b \
-e 0xd47 -e 0xd4d -e 0xd81 -e 0xd89 -e 0xd87 \
-e 0xd44 -e 0xd4c -e 0xd48 -e 0xd4e -e 0xd82 -e 0xd85 \
-e 0xd0c -e 0xd49 -e 0xd8e \
-e 0xd40 -e 0xd4f -e 0xd84 -e 0xd83; then
_set_vuln arm_ssbs_nosync
fi
fi
done
fi
# Default everything else to immune (covers non-ARM, and ARM cores not in the affected lists)
_infer_immune arm_spec_at
_infer_immune arm_spec_unpriv_load
_infer_immune arm_ssbs_nosync
# shellcheck disable=SC2154
{
pr_debug "is_cpu_affected: final results: variant1=$affected_variant1 variant2=$affected_variant2 variant3=$affected_variant3 variant3a=$affected_variant3a"
@@ -1473,6 +1595,7 @@ is_cpu_affected() {
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: div0=$affected_div0 fpdss=$affected_fpdss zenbleed=$affected_zenbleed inception=$affected_inception retbleed=$affected_retbleed tsa=$affected_tsa downfall=$affected_downfall reptar=$affected_reptar rfds=$affected_rfds its=$affected_its"
pr_debug "is_cpu_affected: final results: vmscape=$affected_vmscape bpi=$affected_bpi sls=$affected_sls mmio=$affected_mmio"
pr_debug "is_cpu_affected: final results: arm_spec_at=$affected_arm_spec_at arm_spec_unpriv_load=$affected_arm_spec_unpriv_load arm_ssbs_nosync=$affected_arm_ssbs_nosync"
}
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
@@ -1674,58 +1797,76 @@ is_cpu_srbds_free() {
}
# Check whether the CPU is architecturally immune to MMIO Stale Data
# Mirrors the kernel's arch_cap_mmio_immune() helper: ALL THREE ARCH_CAP bits must be set:
# ARCH_CAP_SBDR_SSDP_NO (bit 13), ARCH_CAP_FBSDP_NO (bit 14), ARCH_CAP_PSDP_NO (bit 15)
# Returns: 0 if immune, 1 otherwise
is_arch_cap_mmio_immune() {
[ "$cap_sbdr_ssdp_no" = 1 ] && [ "$cap_fbsdp_no" = 1 ] && [ "$cap_psdp_no" = 1 ]
}
# Check whether the CPU is known to be unaffected by MMIO Stale Data (CVE-2022-21123/21125/21166)
# Matches the kernel's NO_MMIO whitelist plus arch_cap_mmio_immune().
# Model inventory and kernel-commit history are documented in check_mmio_linux().
# Returns: 0 if MMIO-free, 1 if affected or unknown
is_cpu_mmio_free() {
# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c
#
# CPU affection logic from kernel (51802186158c, v5.19):
# Bug is set when: cpu_matches(blacklist, MMIO) AND NOT arch_cap_mmio_immune()
# arch_cap_mmio_immune() requires ALL THREE bits set:
# ARCH_CAP_FBSDP_NO (bit 14) AND ARCH_CAP_PSDP_NO (bit 15) AND ARCH_CAP_SBDR_SSDP_NO (bit 13)
#
# Intel Family 6 model blacklist (unchanged since v5.19):
# HASWELL_X (0x3F)
# BROADWELL_D (0x56), BROADWELL_X (0x4F)
# SKYLAKE_X (0x55), SKYLAKE_L (0x4E), SKYLAKE (0x5E)
# KABYLAKE_L (0x8E), KABYLAKE (0x9E)
# ICELAKE_L (0x7E), ICELAKE_D (0x6C), ICELAKE_X (0x6A)
# COMETLAKE (0xA5), COMETLAKE_L (0xA6)
# LAKEFIELD (0x8A)
# ROCKETLAKE (0xA7)
# ATOM_TREMONT (0x96), ATOM_TREMONT_D (0x86), ATOM_TREMONT_L (0x9C)
#
# Vendor scope: Intel only. Non-Intel CPUs are not affected.
parse_cpu_details
# ARCH_CAP immunity: all three bits must be set
if [ "$cap_sbdr_ssdp_no" = 1 ] && [ "$cap_fbsdp_no" = 1 ] && [ "$cap_psdp_no" = 1 ]; then
is_arch_cap_mmio_immune && return 0
# Non-Intel x86 vendors the kernel unconditionally whitelists (AMD/Hygon all
# families; Centaur/Zhaoxin fam 7 only).
if is_amd || is_hygon; then
return 0
fi
if is_intel; then
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_HASWELL_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_LAKEFIELD" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_L" ]; then
return 1
fi
if { [ "$cpu_vendor" = "CentaurHauls" ] || [ "$cpu_vendor" = "Shanghai" ]; } && [ "$cpu_family" = 7 ]; then
return 0
fi
# Intel NO_MMIO whitelist
if is_intel && [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ]; then
return 0
fi
fi
return 1
}
# Check whether the CPU's MMIO Stale Data status is unknown ("out of servicing period")
# Matches the kernel's X86_BUG_MMIO_UNKNOWN: Intel CPU not MMIO-free and not in the
# MMIO blacklist. The kernel reports "Unknown: No mitigations" for such CPUs.
# Callers: check_mmio_linux, check_mmio_bsd
# Returns: 0 if unknown, 1 if known (either affected or not affected)
is_cpu_mmio_unknown() {
parse_cpu_details
# Only Intel can reach the unknown bucket — other x86 vendors are whitelisted by vendor-id.
is_intel || return 1
is_cpu_mmio_free && return 1
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_HASWELL_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_LAKEFIELD" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_L" ]; then
return 1
fi
fi
return 0
}
@@ -2167,7 +2308,7 @@ while [ -n "${1:-}" ]; do
case "$2" in
help)
echo "The following parameters are supported for --variant (can be used multiple times):"
echo "1, 2, 3, 3a, 4, msbds, mfbds, mlpds, mdsum, l1tf, taa, mcepsc, srbds, mmio, sbdr, sbds, drpw, div0, fpdss, zenbleed, downfall, retbleed, inception, reptar, rfds, tsa, tsa-sq, tsa-l1, its, vmscape, bpi, sls"
echo "1, 2, 3, 3a, 4, msbds, mfbds, mlpds, mdsum, l1tf, taa, mcepsc, srbds, mmio, sbdr, sbds, drpw, div0, fpdss, zenbleed, downfall, retbleed, inception, reptar, rfds, tsa, tsa-sq, tsa-l1, its, vmscape, bpi, sls, arm-spec-at, arm-spec-unpriv-load, arm-ssbs-nosync"
exit 0
;;
1)
@@ -2298,12 +2439,60 @@ while [ -n "${1:-}" ]; do
opt_cve_list="$opt_cve_list CVE-0000-0001"
opt_cve_all=0
;;
arm-spec-at)
opt_cve_list="$opt_cve_list CVE-0001-0001"
opt_cve_all=0
;;
arm-spec-unpriv-load)
opt_cve_list="$opt_cve_list CVE-0001-0002"
opt_cve_all=0
;;
arm-ssbs-nosync)
opt_cve_list="$opt_cve_list CVE-0001-0003"
opt_cve_all=0
;;
*)
echo "$0: error: invalid parameter '$2' for --variant, see --variant help for a list" >&2
exit 255
;;
esac
shift 2
elif [ "$1" = "--errata" ]; then
# Vendor-numbered errata selector (currently ARM64). Maps an erratum number
# (e.g. 1530923) to the CVE-0001-NNNN check that covers it.
if [ -z "$2" ]; then
echo "$0: error: option --errata expects a parameter (an erratum number, e.g. 1530923, or 'help')" >&2
exit 255
fi
case "$2" in
help)
echo "The following erratum numbers are supported for --errata (can be used multiple times):"
echo " Speculative AT TLB corruption: 1165522, 1319367, 1319537, 1530923"
echo " Speculative unprivileged load: 2966298, 3117295"
echo " MSR SSBS not self-synchronizing: 3194386 (and siblings: 3312417, 3324334, 3324335,"
echo " 3324336, 3324338, 3324339, 3324341, 3324344, 3324346,"
echo " 3324347, 3324348, 3324349, 3456084, 3456091, 3456106,"
echo " 3456111)"
exit 0
;;
1165522 | 1319367 | 1319537 | 1530923)
opt_cve_list="$opt_cve_list CVE-0001-0001"
opt_cve_all=0
;;
2966298 | 3117295)
opt_cve_list="$opt_cve_list CVE-0001-0002"
opt_cve_all=0
;;
3194386 | 3312417 | 3324334 | 3324335 | 3324336 | 3324338 | 3324339 | 3324341 | 3324344 | 3324346 | 3324347 | 3324348 | 3324349 | 3456084 | 3456091 | 3456106 | 3456111)
opt_cve_list="$opt_cve_list CVE-0001-0003"
opt_cve_all=0
;;
*)
echo "$0: error: unsupported erratum number '$2' for --errata, see --errata help for a list" >&2
exit 255
;;
esac
shift 2
elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
show_header
show_usage
@@ -3738,13 +3927,22 @@ parse_cpu_details() {
if grep -qw avx512 "$g_procfs/cpuinfo" 2>/dev/null; then cap_avx512=1; fi
cpu_vendor=$(grep '^vendor_id' "$g_procfs/cpuinfo" | awk '{print $3}' | head -n1)
cpu_friendly_name=$(grep '^model name' "$g_procfs/cpuinfo" | cut -d: -f2- | head -n1 | sed -e 's/^ *//')
# special case for ARM follows
if grep -qi 'CPU implementer[[:space:]]*:[[:space:]]*0x41' "$g_procfs/cpuinfo"; then
cpu_vendor='ARM'
# some devices (phones or other) have several ARMs and as such different part numbers,
# an example is "bigLITTLE", so we need to store the whole list, this is needed for is_cpu_affected
# ARM-style cpuinfo: parse per-core implementer/part/arch/variant/revision lists
# (big.LITTLE / heterogeneous systems have different values per core).
# cpu_variant_list and cpu_revision_list are consumed by ARM64 errata affection checks
# that need to match a specific revision range.
if grep -q 'CPU implementer' "$g_procfs/cpuinfo"; then
cpu_impl_list=$(awk '/CPU implementer/ {print $4}' "$g_procfs/cpuinfo")
cpu_part_list=$(awk '/CPU part/ {print $4}' "$g_procfs/cpuinfo")
cpu_arch_list=$(awk '/CPU architecture/ {print $3}' "$g_procfs/cpuinfo")
cpu_variant_list=$(awk '/CPU variant/ {print $4}' "$g_procfs/cpuinfo")
cpu_revision_list=$(awk '/CPU revision/ {print $4}' "$g_procfs/cpuinfo")
fi
# Map first-seen implementer to cpu_vendor; note that heterogeneous systems
# (e.g. DynamIQ with ARM+Kryo cores) would all map to one vendor here, but
# per-core vendor decisions are made via cpu_impl_list where needed.
if grep -qi 'CPU implementer[[:space:]]*:[[:space:]]*0x41' "$g_procfs/cpuinfo"; then
cpu_vendor='ARM'
# take the first one to fill the friendly name, do NOT quote the vars below
# shellcheck disable=SC2086
arch=$(echo $cpu_arch_list | awk '{ print $1 }')
@@ -5540,7 +5738,7 @@ check_cpu() {
pr_info_nol " * CPU explicitly indicates not being affected by MMIO Stale Data (FBSDP_NO & PSDP_NO & SBDR_SSDP_NO): "
if [ "$cap_sbdr_ssdp_no" = -1 ]; then
pstatus yellow UNKNOWN "couldn't read MSR"
elif [ "$cap_sbdr_ssdp_no" = 1 ] && [ "$cap_fbsdp_no" = 1 ] && [ "$cap_psdp_no" = 1 ]; then
elif is_arch_cap_mmio_immune; then
pstatus green YES
else
pstatus yellow NO
@@ -5814,11 +6012,19 @@ check_cpu() {
fi
}
# Display per-CVE CPU vulnerability status based on CPU model/family
# Display per-CVE CPU vulnerability status based on CPU model/family.
# Mirrors the main dispatch gate: under a default "all CVEs" run, skip CVEs
# whose arch tag doesn't match this system. Explicit selection via
# --cve/--variant/--errata bypasses the gate.
check_cpu_vulnerabilities() {
local cve
pr_info "* CPU vulnerability to the speculative execution attack variants"
for cve in $g_supported_cve_list; do
if [ "$opt_cve_all" = 1 ]; then
_is_cve_relevant_arch "$cve" || continue
elif ! echo "$opt_cve_list" | grep -qw "$cve"; then
continue
fi
pr_info_nol " * Affected by $cve ($(cve2name "$cve")): "
if is_cpu_affected "$cve"; then
pstatus yellow YES
@@ -6230,16 +6436,30 @@ check_mds_linux() {
# vim: set ts=4 sw=4 sts=4 et:
# MMIO Stale Data (Processor MMIO Stale Data Vulnerabilities) - BSD mitigation check
check_mmio_bsd() {
# No BSD (FreeBSD, OpenBSD, NetBSD, DragonFlyBSD) has implemented an OS-level
# MMIO Stale Data mitigation. All four stopped at MDS/TAA. Microcode update is
# the only partial defense available, and without OS-level VERW invocation it
# cannot close the vulnerability.
local unk
unk="your CPU's MMIO Stale Data status is unknown (Intel never officially assessed this CPU, its servicing period has ended)"
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif is_cpu_mmio_unknown; then
if [ "$opt_paranoid" = 1 ]; then
pvulnstatus "$cve" VULN "$unk, and no BSD mitigation exists"
explain "There is no known mitigation for this CPU model. Even with up-to-date microcode, BSD kernels do not invoke VERW for MMIO Stale Data clearing. Only a hardware replacement can fully address this."
else
pvulnstatus "$cve" UNK "$unk; no BSD mitigation exists in any case"
fi
else
pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script"
pvulnstatus "$cve" VULN "your CPU is affected and no BSD has implemented an MMIO Stale Data mitigation"
explain "No BSD kernel currently implements an MMIO Stale Data mitigation (which would require invoking VERW at context switches and VM-entries). Updating CPU microcode alone does not mitigate this vulnerability without OS cooperation."
fi
}
# MMIO Stale Data (Processor MMIO Stale Data Vulnerabilities) - Linux mitigation check
check_mmio_linux() {
local status sys_interface_available msg kernel_mmio kernel_mmio_can_tell mmio_mitigated mmio_smt_mitigated mystatus mymsg
local status sys_interface_available msg kernel_mmio kernel_mmio_can_tell mmio_mitigated mmio_smt_mitigated mystatus mymsg unk
status=UNK
sys_interface_available=0
msg=''
@@ -6341,9 +6561,33 @@ check_mmio_linux() {
#
# No models have been added to or removed from the MMIO blacklist since v5.19.
#
# 7df548840c49 (v6.0, NO_MMIO whitelist added, Pawan Gupta 2022-08-03):
# Intel Family 6:
# TIGERLAKE (0x8D), TIGERLAKE_L (0x8C)
# ALDERLAKE (0x97), ALDERLAKE_L (0x9A)
# ATOM_GOLDMONT (0x5C), ATOM_GOLDMONT_D (0x5F), ATOM_GOLDMONT_PLUS (0x7A)
# AMD: fam 0x0f-0x12 + X86_FAMILY_ANY (all families)
# Hygon: all families
# Centaur fam 7, Zhaoxin fam 7
#
# Kernel logic (v6.0+):
# if (!arch_cap_mmio_immune(ia32_cap)) {
# if (cpu_matches(cpu_vuln_blacklist, MMIO))
# setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
# else if (!cpu_matches(cpu_vuln_whitelist, NO_MMIO))
# setup_force_cpu_bug(X86_BUG_MMIO_UNKNOWN);
# }
# => Intel CPUs that are neither blacklisted nor whitelisted (e.g. Ivy Bridge,
# Haswell client, Broadwell client, Sandy Bridge, pre-Goldmont Atom, etc.) get
# X86_BUG_MMIO_UNKNOWN and report "Unknown: No mitigations" in sysfs. Intel
# never published an affected-processor evaluation for these models because
# their servicing period had already ended.
# => is_cpu_mmio_unknown() matches this set so the script can report UNK (or
# VULN under --paranoid) rather than the misleading "not affected" that
# a plain blacklist check would produce.
#
# immunity: ARCH_CAP_SBDR_SSDP_NO (bit 13) AND ARCH_CAP_FBSDP_NO (bit 14) AND ARCH_CAP_PSDP_NO (bit 15)
# All three must be set. Checked via arch_cap_mmio_immune() in common.c.
# Bug is set only when: cpu_matches(blacklist, MMIO) AND NOT arch_cap_mmio_immune().
#
# microcode mitigation: ARCH_CAP_FB_CLEAR (bit 17) -- VERW clears fill buffers.
# Alternative: MD_CLEAR CPUID + FLUSH_L1D CPUID when MDS_NO is not set (legacy path).
@@ -6422,6 +6666,17 @@ check_mmio_linux() {
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 [ "$opt_sysfs_only" != 1 ] && is_cpu_mmio_unknown; then
# Bypass the normal sysfs reconciliation: sysfs reports "Unknown: No mitigations"
# only on v6.0-v6.15. On earlier and on v6.16+ kernels it wrongly says "Not affected"
# for these CPUs (which predate FB_CLEAR microcode and Intel's affected-processor list).
unk="your CPU's MMIO Stale Data status is unknown (Intel never officially assessed this CPU, its servicing period has ended)"
if [ "$opt_paranoid" = 1 ]; then
pvulnstatus "$cve" VULN "$unk, and no mitigation is available"
explain "There is no known mitigation for this CPU model. Intel ended its servicing period without evaluating whether it is affected by MMIO Stale Data vulnerabilities, so no FB_CLEAR-capable microcode was released. Consider replacing affected hardware."
else
pvulnstatus "$cve" UNK "$unk; no mitigation is available in any case"
fi
else
if [ "$opt_sysfs_only" != 1 ]; then
# compute mystatus and mymsg from our own logic
@@ -6791,6 +7046,238 @@ check_CVE_0000_0001() {
check_cve 'CVE-0000-0001'
}
# >>>>>> vulns/CVE-0001-0001.sh <<<<<<
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-0001-0001, ARM SPEC AT, ARM64 errata 1165522/1319367/1319537/1530923, Speculative AT TLB corruption
check_CVE_0001_0001() {
check_cve 'CVE-0001-0001'
}
# On affected cores, a speculative address translation (AT) instruction issued from the hypervisor
# using an out-of-context translation regime may poison the TLB, causing a subsequent guest-context
# request to see an incorrect translation. Relevant mainly to KVM hosts. Kernel workaround:
# invalidate TLB state across world-switch for affected cores (ARM64_WORKAROUND_SPECULATIVE_AT).
# * Cortex-A76 r0p0..r2p0 erratum 1165522 CONFIG_ARM64_ERRATUM_1165522
# * Cortex-A72 all revs erratum 1319367 CONFIG_ARM64_ERRATUM_1319367
# * Cortex-A57 all revs erratum 1319537 CONFIG_ARM64_ERRATUM_1319367 (same kconfig)
# * Cortex-A55 r0p0..r2p0 erratum 1530923 CONFIG_ARM64_ERRATUM_1530923
# References:
# arch/arm64/Kconfig (ARM64_ERRATUM_{1165522,1319367,1530923})
# arch/arm64/kernel/cpu_errata.c (erratum_speculative_at_list, "ARM errata 1165522, 1319367, or 1530923")
# Cortex-A55 SDEN: https://developer.arm.com/documentation/SDEN-1301074/latest
check_CVE_0001_0001_linux() {
local cve kernel_mitigated config_found
cve='CVE-0001-0001'
kernel_mitigated=''
config_found=''
if [ "$opt_sysfs_only" != 1 ] && is_arm_kernel; then
# kconfig: any of the three erratum config options implies the workaround is compiled in
if [ -n "$opt_config" ]; then
for erratum in 1165522 1319367 1530923; do
if grep -q "^CONFIG_ARM64_ERRATUM_$erratum=y" "$opt_config"; then
config_found="${config_found:+$config_found, }$erratum"
fi
done
[ -n "$config_found" ] && kernel_mitigated="found CONFIG_ARM64_ERRATUM_$config_found=y in kernel config"
fi
# kernel image: look for the descriptor string the kernel prints at boot
if [ -z "$kernel_mitigated" ] && [ -n "$g_kernel" ]; then
if "${opt_arch_prefix}strings" "$g_kernel" 2>/dev/null | grep -qE 'ARM errata 1165522, 1319367'; then
kernel_mitigated="found erratum descriptor string in kernel image"
fi
fi
# live mode: dmesg prints the workaround once at boot
if [ -z "$kernel_mitigated" ] && [ "$g_mode" = live ]; then
if dmesg 2>/dev/null | grep -qE 'ARM errata 1165522, 1319367'; then
kernel_mitigated="erratum workaround reported as applied in dmesg"
fi
fi
pr_info_nol "* Kernel has the ARM64 Speculative-AT workaround compiled in: "
if [ -n "$kernel_mitigated" ]; then
pstatus green YES "$kernel_mitigated"
else
pstatus yellow NO
fi
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected by this erratum family"
elif [ "$opt_sysfs_only" = 1 ]; then
pvulnstatus "$cve" UNK "no sysfs interface exists for this erratum, own checks have been skipped (--sysfs-only)"
elif [ -n "$kernel_mitigated" ]; then
pvulnstatus "$cve" OK "your kernel includes the erratum workaround"
else
pvulnstatus "$cve" VULN "your CPU is affected by this erratum family and the kernel does not appear to include the workaround"
explain "Run a kernel built with CONFIG_ARM64_ERRATUM_1165522=y, CONFIG_ARM64_ERRATUM_1319367=y, and/or CONFIG_ARM64_ERRATUM_1530923=y (matching your CPU core). These options are 'default y' in mainline and enabled by most distro kernels. Refer to the ARM Software Developers Errata Notice for your core for full details."
fi
}
check_CVE_0001_0001_bsd() {
local cve
cve='CVE-0001-0001'
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected by this erratum family"
else
pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script"
fi
}
# >>>>>> vulns/CVE-0001-0002.sh <<<<<<
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-0001-0002, ARM SPEC UNPRIV LOAD, ARM64 errata 2966298/3117295, Speculative unprivileged load
check_CVE_0001_0002() {
check_cve 'CVE-0001-0002'
}
# On affected cores, a speculatively-executed unprivileged load from a page that is mapped as
# privileged can leak the loaded value into the cache hierarchy, allowing a Spectre-style
# cache side-channel to expose privileged kernel data to userspace. Kernel workaround:
# sandwich kernel-exit sequences with an additional speculation barrier/DSB so that
# speculative unprivileged loads cannot observe privileged state
# (ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD).
# * Cortex-A510 all revs erratum 3117295 CONFIG_ARM64_ERRATUM_3117295
# * Cortex-A520 r0p0..r0p1 erratum 2966298 CONFIG_ARM64_ERRATUM_2966298
# References:
# arch/arm64/Kconfig (ARM64_ERRATUM_{2966298,3117295})
# arch/arm64/kernel/cpu_errata.c (erratum_spec_unpriv_load_list, "ARM errata 2966298, 3117295")
# Cortex-A510 SDEN: https://developer.arm.com/documentation/SDEN-2397239/latest
check_CVE_0001_0002_linux() {
local cve kernel_mitigated config_found erratum
cve='CVE-0001-0002'
kernel_mitigated=''
config_found=''
if [ "$opt_sysfs_only" != 1 ] && is_arm_kernel; then
if [ -n "$opt_config" ]; then
for erratum in 2966298 3117295; do
if grep -q "^CONFIG_ARM64_ERRATUM_$erratum=y" "$opt_config"; then
config_found="${config_found:+$config_found, }$erratum"
fi
done
[ -n "$config_found" ] && kernel_mitigated="found CONFIG_ARM64_ERRATUM_$config_found=y in kernel config"
fi
if [ -z "$kernel_mitigated" ] && [ -n "$g_kernel" ]; then
if "${opt_arch_prefix}strings" "$g_kernel" 2>/dev/null | grep -qE 'ARM errata 2966298, 3117295'; then
kernel_mitigated="found erratum descriptor string in kernel image"
fi
fi
if [ -z "$kernel_mitigated" ] && [ "$g_mode" = live ]; then
if dmesg 2>/dev/null | grep -qE 'ARM errata 2966298, 3117295'; then
kernel_mitigated="erratum workaround reported as applied in dmesg"
fi
fi
pr_info_nol "* Kernel has the ARM64 Speculative-Unprivileged-Load workaround compiled in: "
if [ -n "$kernel_mitigated" ]; then
pstatus green YES "$kernel_mitigated"
else
pstatus yellow NO
fi
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected by this erratum family"
elif [ "$opt_sysfs_only" = 1 ]; then
pvulnstatus "$cve" UNK "no sysfs interface exists for this erratum, own checks have been skipped (--sysfs-only)"
elif [ -n "$kernel_mitigated" ]; then
pvulnstatus "$cve" OK "your kernel includes the erratum workaround"
else
pvulnstatus "$cve" VULN "your CPU is affected by this erratum family and the kernel does not appear to include the workaround"
explain "Run a kernel built with CONFIG_ARM64_ERRATUM_2966298=y (Cortex-A520) and/or CONFIG_ARM64_ERRATUM_3117295=y (Cortex-A510). These options are 'default y' in mainline and enabled by most distro kernels. Refer to the ARM Software Developers Errata Notice for your core for full details."
fi
}
check_CVE_0001_0002_bsd() {
local cve
cve='CVE-0001-0002'
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected by this erratum family"
else
pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script"
fi
}
# >>>>>> vulns/CVE-0001-0003.sh <<<<<<
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-0001-0003, ARM SSBS NOSYNC, ARM64 erratum 3194386, MSR SSBS not self-synchronizing
check_CVE_0001_0003() {
check_cve 'CVE-0001-0003'
}
# On affected cores, the "MSR SSBS, #x" instruction is not self-synchronizing, so subsequent
# speculative instructions may execute without observing the new SSBS state. This can permit
# unintended speculative store bypass (Spectre V4 / CVE-2018-3639) even when software thinks
# the mitigation is in effect. Kernel workaround (ARM64_WORKAROUND_SPECULATIVE_SSBS):
# - place a Speculation Barrier (SB) or ISB after every kernel-side SSBS change
# - hide SSBS from userspace hwcaps and EL0 reads of ID_AA64PFR1_EL1 so that userspace
# routes SSB mitigation changes through the prctl(PR_SET_SPECULATION_CTRL) path
# Affected cores (via ARM64_ERRATUM_3194386, with individual sub-errata numbers):
# Cortex-A76/A77/A78/A78C/A710/A715/A720/A720AE/A725, X1/X1C/X2/X3/X4/X925,
# Neoverse-N1/N2/N3, Neoverse-V1/V2/V3/V3AE
# References:
# arch/arm64/Kconfig (ARM64_ERRATUM_3194386)
# arch/arm64/kernel/cpu_errata.c (erratum_spec_ssbs_list, "SSBS not fully self-synchronizing")
check_CVE_0001_0003_linux() {
local cve kernel_mitigated
cve='CVE-0001-0003'
kernel_mitigated=''
if [ "$opt_sysfs_only" != 1 ] && is_arm_kernel; then
if [ -n "$opt_config" ] && grep -q '^CONFIG_ARM64_ERRATUM_3194386=y' "$opt_config"; then
kernel_mitigated="found CONFIG_ARM64_ERRATUM_3194386=y in kernel config"
fi
if [ -z "$kernel_mitigated" ] && [ -n "$g_kernel" ]; then
if "${opt_arch_prefix}strings" "$g_kernel" 2>/dev/null | grep -qE 'SSBS not fully self-synchronizing'; then
kernel_mitigated="found erratum descriptor string in kernel image"
fi
fi
if [ -z "$kernel_mitigated" ] && [ "$g_mode" = live ]; then
if dmesg 2>/dev/null | grep -qE 'SSBS not fully self-synchronizing'; then
kernel_mitigated="erratum workaround reported as applied in dmesg"
fi
fi
pr_info_nol "* Kernel has the ARM64 SSBS self-sync workaround compiled in: "
if [ -n "$kernel_mitigated" ]; then
pstatus green YES "$kernel_mitigated"
else
pstatus yellow NO
fi
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected by this erratum"
elif [ "$opt_sysfs_only" = 1 ]; then
pvulnstatus "$cve" UNK "no sysfs interface exists for this erratum, own checks have been skipped (--sysfs-only)"
elif [ -n "$kernel_mitigated" ]; then
pvulnstatus "$cve" OK "your kernel includes the erratum workaround"
else
pvulnstatus "$cve" VULN "your CPU is affected by this erratum and the kernel does not appear to include the workaround; Spectre V4 (CVE-2018-3639) mitigation may be unreliable on this system"
explain "Run a kernel built with CONFIG_ARM64_ERRATUM_3194386=y. This option is 'default y' in mainline and enabled by most distro kernels. Without it, the Spectre V4 / speculative-store-bypass mitigation advertised by SSBS is not reliably applied. Userspace should use prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, ...) to request the mitigation rather than rely on the SSBS hwcap."
fi
}
check_CVE_0001_0003_bsd() {
local cve
cve='CVE-0001-0003'
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected by this erratum"
else
pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script"
fi
}
# >>>>>> vulns/CVE-2017-5715.sh <<<<<<
# vim: set ts=4 sw=4 sts=4 et:
@@ -12214,10 +12701,19 @@ if [ "$g_mode" = hw-only ]; then
pr_info "Hardware-only mode, skipping vulnerability checks"
else
for cve in $g_supported_cve_list; do
if [ "$opt_cve_all" = 1 ] || echo "$opt_cve_list" | grep -qw "$cve"; then
check_"$(echo "$cve" | tr - _)"
pr_info
# In a default "all CVEs" run, skip checks whose arch tag doesn't match
# the host CPU or the inspected kernel. Explicit --cve/--variant/--errata
# selection bypasses the gate.
if [ "$opt_cve_all" = 1 ]; then
if ! _is_cve_relevant_arch "$cve"; then
pr_debug "main: skipping $cve (arch tag not relevant)"
continue
fi
elif ! echo "$opt_cve_list" | grep -qw "$cve"; then
continue
fi
check_"$(echo "$cve" | tr - _)"
pr_info
done
fi # g_mode != hw-only