feat: implement check for MMIO Stale Data (CVE-2022-21123 CVE-2022-21125 CVE-2022-21166) (#437)

This commit is contained in:
Stéphane Lesimple
2026-04-06 11:25:51 +02:00
parent 59a887dea0
commit 435f72de25
11 changed files with 402 additions and 4 deletions

View File

@@ -1 +1 @@
28 31

10
dist/README.md vendored
View File

@@ -22,6 +22,9 @@ CVE | Name | Aliases
[CVE-2019-11091](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11091) | Microarchitectural Data Sampling Uncacheable Memory | MDSUM, RIDL [CVE-2019-11091](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11091) | Microarchitectural Data Sampling Uncacheable Memory | MDSUM, RIDL
[CVE-2019-11135](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11135) | TSX Asynchronous Abort | TAA, ZombieLoad V2 [CVE-2019-11135](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11135) | TSX Asynchronous Abort | TAA, ZombieLoad V2
[CVE-2020-0543](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0543) | Special Register Buffer Data Sampling | SRBDS, CROSSTalk [CVE-2020-0543](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0543) | Special Register Buffer Data Sampling | SRBDS, CROSSTalk
[CVE-2022-21123](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21123) | Shared Buffers Data Read | SBDR, MMIO Stale Data
[CVE-2022-21125](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21125) | Shared Buffers Data Sampling | SBDS, MMIO Stale Data
[CVE-2022-21166](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21166) | Device Register Partial Write | DRPW, MMIO Stale Data
[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-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-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-2022-40982](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-40982) | Gather Data Sampling | Downfall, GDS
@@ -58,6 +61,9 @@ CVE-2018-12207 (iTLB Multihit, No eXcuses) | ✅ | ✅ | ☠️ | ✅ | Hypervis
CVE-2019-11091 (MDSUM, RIDL) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update CVE-2019-11091 (MDSUM, RIDL) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2019-11135 (TAA, ZombieLoad V2) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update CVE-2019-11135 (TAA, ZombieLoad V2) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2020-0543 (SRBDS, CROSSTalk) | 💥 (2) | 💥 (2) | 💥 (2) | 💥 (2) | Microcode + kernel update CVE-2020-0543 (SRBDS, CROSSTalk) | 💥 (2) | 💥 (2) | 💥 (2) | 💥 (2) | Microcode + kernel update
CVE-2022-21123 (SBDR, MMIO Stale Data) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2022-21125 (SBDS, MMIO Stale Data) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2022-21166 (DRPW, MMIO Stale Data) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2022-29900 (Retbleed AMD) | 💥 | ✅ | 💥 | ✅ | Kernel update (+ microcode for IBPB) CVE-2022-29900 (Retbleed AMD) | 💥 | ✅ | 💥 | ✅ | Kernel update (+ microcode for IBPB)
CVE-2022-29901 (Retbleed Intel, RSBA) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update (eIBRS or IBRS) CVE-2022-29901 (Retbleed Intel, RSBA) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update (eIBRS or IBRS)
CVE-2022-40982 (Downfall, GDS) | 💥 | 💥 | 💥 | 💥 | Microcode update (or disable AVX) CVE-2022-40982 (Downfall, GDS) | 💥 | 💥 | 💥 | 💥 | Microcode update (or disable AVX)
@@ -145,6 +151,10 @@ On CPUs with Intel TSX, a transactional abort can leave data from the line fill
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. 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-21123, CVE-2022-21125, CVE-2022-21166 — Processor MMIO Stale Data (SBDR, SBDS, DRPW)**
A class of MMIO (Memory-Mapped I/O) vulnerabilities where stale data from CPU internal fill buffers can be inferred through side-channel attacks during MMIO operations. Three sub-vulnerabilities are covered: Shared Buffers Data Read (SBDR, CVE-2022-21123), Shared Buffers Data Sampling (SBDS, CVE-2022-21125), and Device Register Partial Write (DRPW, CVE-2022-21166). Affected Intel CPUs include Haswell through Rocket Lake server and client processors, plus Tremont Atom cores. Mitigation requires a microcode update providing the FB_CLEAR capability (VERW instruction clears fill buffers) plus a kernel update (Linux 5.19+) that invokes VERW at kernel/user transitions and VM entry/exit. When SMT is enabled, sibling threads can still exploit the vulnerability even with mitigations active. Performance impact is low, as the VERW mechanism is shared with the existing MDS mitigation.
**CVE-2022-29900 — Arbitrary Speculative Code Execution with Return Instructions (Retbleed AMD)** **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. 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.

View File

@@ -156,6 +156,9 @@ CVE-2019-11091|MDSUM|mdsum|RIDL, microarchitectural data sampling uncacheable me
CVE-2019-11135|TAA|taa|ZombieLoad V2, TSX Asynchronous Abort (TAA) 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-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-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-20588|DIV0|div0|Division by Zero, AMD Zen1 speculative data leak
CVE-2023-20593|ZENBLEED|zenbleed|Zenbleed, cross-process information leak CVE-2023-20593|ZENBLEED|zenbleed|Zenbleed, cross-process information leak
CVE-2022-40982|DOWNFALL|downfall|Downfall, gather data sampling (GDS) CVE-2022-40982|DOWNFALL|downfall|Downfall, gather data sampling (GDS)

View File

@@ -99,6 +99,7 @@ is_cpu_affected() {
affected_taa='' affected_taa=''
affected_itlbmh='' affected_itlbmh=''
affected_srbds='' affected_srbds=''
affected_mmio=''
affected_sls='' affected_sls=''
# DIV0, Zenbleed and Inception are all AMD specific, look for "is_amd" below: # DIV0, Zenbleed and Inception are all AMD specific, look for "is_amd" below:
_set_immune div0 _set_immune div0
@@ -135,6 +136,11 @@ is_cpu_affected() {
pr_debug "is_cpu_affected: cpu not affected by Special Register Buffer Data Sampling" pr_debug "is_cpu_affected: cpu not affected by Special Register Buffer Data Sampling"
fi fi
if is_cpu_mmio_free; then
_infer_immune mmio
pr_debug "is_cpu_affected: cpu not affected by MMIO Stale Data"
fi
# NO_SPECTRE_V2: Centaur family 7 and Zhaoxin family 7 are immune to Spectre V2 # 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 # kernel commit 1e41a766c98b (v5.6-rc1): added NO_SPECTRE_V2 exemption
# Zhaoxin vendor_id is " Shanghai " in cpuinfo (parsed as "Shanghai" by awk) # Zhaoxin vendor_id is " Shanghai " in cpuinfo (parsed as "Shanghai" by awk)
@@ -156,6 +162,7 @@ is_cpu_affected() {
_set_immune mdsum _set_immune mdsum
_set_immune taa _set_immune taa
_set_immune srbds _set_immune srbds
_set_immune mmio
elif is_intel; then elif is_intel; then
# Intel # Intel
# https://github.com/crozone/SpectrePoC/issues/1 ^F E5200 => spectre 2 not affected # https://github.com/crozone/SpectrePoC/issues/1 ^F E5200 => spectre 2 not affected
@@ -805,7 +812,7 @@ is_cpu_affected() {
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: 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: 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 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: div0=$affected_div0 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" pr_debug "is_cpu_affected: final results: vmscape=$affected_vmscape bpi=$affected_bpi sls=$affected_sls mmio=$affected_mmio"
} }
affected_variantl1tf_sgx="$affected_variantl1tf" 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 # even if we are affected to L1TF, if there's no SGX, we're not affected to the original foreshadow

View File

@@ -156,6 +156,61 @@ is_cpu_srbds_free() {
} }
# Check whether the CPU is known to be unaffected by MMIO Stale Data (CVE-2022-21123/21125/21166)
# 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
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
fi
fi
return 0
}
# Check whether the CPU is known to be unaffected by Speculative Store Bypass (SSB) # Check whether the CPU is known to be unaffected by Speculative Store Bypass (SSB)
# Returns: 0 if SSB-free, 1 if affected or unknown # Returns: 0 if SSB-free, 1 if affected or unknown
is_cpu_ssb_free() { is_cpu_ssb_free() {

View File

@@ -169,7 +169,7 @@ while [ -n "${1:-}" ]; do
case "$2" in case "$2" in
help) help)
echo "The following parameters are supported for --variant (can be used multiple times):" 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, div0, 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, zenbleed, downfall, retbleed, inception, reptar, rfds, tsa, tsa-sq, tsa-l1, its, vmscape, bpi, sls"
exit 0 exit 0
;; ;;
1) 1)
@@ -224,6 +224,22 @@ while [ -n "${1:-}" ]; do
opt_cve_list="$opt_cve_list CVE-2020-0543" opt_cve_list="$opt_cve_list CVE-2020-0543"
opt_cve_all=0 opt_cve_all=0
;; ;;
mmio)
opt_cve_list="$opt_cve_list CVE-2022-21123 CVE-2022-21125 CVE-2022-21166"
opt_cve_all=0
;;
sbdr)
opt_cve_list="$opt_cve_list CVE-2022-21123"
opt_cve_all=0
;;
sbds)
opt_cve_list="$opt_cve_list CVE-2022-21125"
opt_cve_all=0
;;
drpw)
opt_cve_list="$opt_cve_list CVE-2022-21166"
opt_cve_all=0
;;
div0) div0)
opt_cve_list="$opt_cve_list CVE-2023-20588" opt_cve_list="$opt_cve_list CVE-2023-20588"
opt_cve_all=0 opt_cve_all=0

View File

@@ -757,6 +757,10 @@ check_cpu() {
cap_rfds_no=-1 cap_rfds_no=-1
cap_rfds_clear=-1 cap_rfds_clear=-1
cap_its_no=-1 cap_its_no=-1
cap_sbdr_ssdp_no=-1
cap_fbsdp_no=-1
cap_psdp_no=-1
cap_fb_clear=-1
if [ "$cap_arch_capabilities" = -1 ]; then if [ "$cap_arch_capabilities" = -1 ]; then
pstatus yellow UNKNOWN pstatus yellow UNKNOWN
elif [ "$cap_arch_capabilities" != 1 ]; then elif [ "$cap_arch_capabilities" != 1 ]; then
@@ -774,6 +778,10 @@ check_cpu() {
cap_rfds_no=0 cap_rfds_no=0
cap_rfds_clear=0 cap_rfds_clear=0
cap_its_no=0 cap_its_no=0
cap_sbdr_ssdp_no=0
cap_fbsdp_no=0
cap_psdp_no=0
cap_fb_clear=0
pstatus yellow NO pstatus yellow NO
else else
read_msr $MSR_IA32_ARCH_CAPABILITIES read_msr $MSR_IA32_ARCH_CAPABILITIES
@@ -792,6 +800,10 @@ check_cpu() {
cap_rfds_no=0 cap_rfds_no=0
cap_rfds_clear=0 cap_rfds_clear=0
cap_its_no=0 cap_its_no=0
cap_sbdr_ssdp_no=0
cap_fbsdp_no=0
cap_psdp_no=0
cap_fb_clear=0
if [ $ret = $READ_MSR_RET_OK ]; then if [ $ret = $READ_MSR_RET_OK ]; then
capabilities=$ret_read_msr_value capabilities=$ret_read_msr_value
# https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/include/asm/msr-index.h#n82 # https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/include/asm/msr-index.h#n82
@@ -805,12 +817,16 @@ check_cpu() {
[ $((ret_read_msr_value_lo >> 6 & 1)) -eq 1 ] && cap_pschange_msc_no=1 [ $((ret_read_msr_value_lo >> 6 & 1)) -eq 1 ] && cap_pschange_msc_no=1
[ $((ret_read_msr_value_lo >> 7 & 1)) -eq 1 ] && cap_tsx_ctrl_msr=1 [ $((ret_read_msr_value_lo >> 7 & 1)) -eq 1 ] && cap_tsx_ctrl_msr=1
[ $((ret_read_msr_value_lo >> 8 & 1)) -eq 1 ] && cap_taa_no=1 [ $((ret_read_msr_value_lo >> 8 & 1)) -eq 1 ] && cap_taa_no=1
[ $((ret_read_msr_value_lo >> 13 & 1)) -eq 1 ] && cap_sbdr_ssdp_no=1
[ $((ret_read_msr_value_lo >> 14 & 1)) -eq 1 ] && cap_fbsdp_no=1
[ $((ret_read_msr_value_lo >> 15 & 1)) -eq 1 ] && cap_psdp_no=1
[ $((ret_read_msr_value_lo >> 17 & 1)) -eq 1 ] && cap_fb_clear=1
[ $((ret_read_msr_value_lo >> 25 & 1)) -eq 1 ] && cap_gds_ctrl=1 [ $((ret_read_msr_value_lo >> 25 & 1)) -eq 1 ] && cap_gds_ctrl=1
[ $((ret_read_msr_value_lo >> 26 & 1)) -eq 1 ] && cap_gds_no=1 [ $((ret_read_msr_value_lo >> 26 & 1)) -eq 1 ] && cap_gds_no=1
[ $((ret_read_msr_value_lo >> 27 & 1)) -eq 1 ] && cap_rfds_no=1 [ $((ret_read_msr_value_lo >> 27 & 1)) -eq 1 ] && cap_rfds_no=1
[ $((ret_read_msr_value_lo >> 28 & 1)) -eq 1 ] && cap_rfds_clear=1 [ $((ret_read_msr_value_lo >> 28 & 1)) -eq 1 ] && cap_rfds_clear=1
[ $((ret_read_msr_value_hi >> 30 & 1)) -eq 1 ] && cap_its_no=1 [ $((ret_read_msr_value_hi >> 30 & 1)) -eq 1 ] && cap_its_no=1
pr_debug "capabilities says rdcl_no=$cap_rdcl_no ibrs_all=$cap_ibrs_all rsba=$cap_rsba l1dflush_no=$cap_l1dflush_no ssb_no=$cap_ssb_no mds_no=$cap_mds_no taa_no=$cap_taa_no pschange_msc_no=$cap_pschange_msc_no rfds_no=$cap_rfds_no rfds_clear=$cap_rfds_clear its_no=$cap_its_no" pr_debug "capabilities says rdcl_no=$cap_rdcl_no ibrs_all=$cap_ibrs_all rsba=$cap_rsba l1dflush_no=$cap_l1dflush_no ssb_no=$cap_ssb_no mds_no=$cap_mds_no taa_no=$cap_taa_no pschange_msc_no=$cap_pschange_msc_no rfds_no=$cap_rfds_no rfds_clear=$cap_rfds_clear its_no=$cap_its_no sbdr_ssdp_no=$cap_sbdr_ssdp_no fbsdp_no=$cap_fbsdp_no psdp_no=$cap_psdp_no fb_clear=$cap_fb_clear"
if [ "$cap_ibrs_all" = 1 ]; then if [ "$cap_ibrs_all" = 1 ]; then
pstatus green YES pstatus green YES
else else
@@ -971,6 +987,24 @@ check_cpu() {
pstatus yellow NO pstatus yellow NO
fi fi
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
pstatus green YES
else
pstatus yellow NO
fi
pr_info_nol " * CPU microcode supports Fill Buffer clearing (FB_CLEAR): "
if [ "$cap_fb_clear" = -1 ]; then
pstatus yellow UNKNOWN "couldn't read MSR"
elif [ "$cap_fb_clear" = 1 ]; then
pstatus green YES
else
pstatus yellow NO
fi
pr_info_nol " * CPU explicitly indicates not being affected by RFDS (RFDS_NO): " pr_info_nol " * CPU explicitly indicates not being affected by RFDS (RFDS_NO): "
if [ "$cap_rfds_no" = -1 ]; then if [ "$cap_rfds_no" = -1 ]; then
pstatus yellow UNKNOWN "couldn't read MSR" pstatus yellow UNKNOWN "couldn't read MSR"

View File

@@ -0,0 +1,252 @@
# vim: set ts=4 sw=4 sts=4 et:
# MMIO Stale Data (Processor MMIO Stale Data Vulnerabilities) - BSD mitigation check
check_mmio_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
}
# 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
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/mmio_stale_data" '^[^;]+'; then
# Kernel source inventory for MMIO Stale Data, traced via git blame walkback
# across /shared/linux, /shared/linux-stable, and /shared/linux-centos-redhat:
#
# --- sysfs messages ---
# all versions:
# "Not affected" (cpu_show_common, generic)
#
# 8cb861e9e3c9 (v5.19, initial MMIO mitigation, Pawan Gupta 2022-05-19):
# enum mmio_mitigations: MMIO_MITIGATION_OFF, MMIO_MITIGATION_UCODE_NEEDED, MMIO_MITIGATION_VERW
# mmio_strings[]:
# "Vulnerable" (MMIO_MITIGATION_OFF)
# "Vulnerable: Clear CPU buffers attempted, no microcode" (MMIO_MITIGATION_UCODE_NEEDED)
# "Mitigation: Clear CPU buffers" (MMIO_MITIGATION_VERW)
#
# 8d50cdf8b834 (v5.19, sysfs reporting, Pawan Gupta 2022-05-19):
# mmio_stale_data_show_state() added with SMT suffix:
# "{mmio_strings[state]}; SMT vulnerable" (sched_smt_active() true)
# "{mmio_strings[state]}; SMT disabled" (sched_smt_active() false)
# "{mmio_strings[state]}; SMT Host state unknown" (boot_cpu_has(HYPERVISOR))
# No SMT suffix when MMIO_MITIGATION_OFF.
# Uses sysfs_emit() in mainline. CentOS 7 backport uses sprintf().
#
# 7df548840c49 (v6.0, "unknown" reporting, Pawan Gupta 2022-08-03):
# Added X86_BUG_MMIO_UNKNOWN handling:
# "Unknown: No mitigations" (X86_BUG_MMIO_UNKNOWN set)
# Present in: v6.0 through v6.15, stable 5.10.y/5.15.y/6.1.y/6.6.y, rocky8, rocky9
#
# dd86a1d013e0 (v6.16, removed MMIO_UNKNOWN, Borislav Petkov 2025-04-14):
# Removed X86_BUG_MMIO_UNKNOWN -- "Unknown" message no longer produced.
# Replaced by general X86_BUG_OLD_MICROCODE mechanism.
#
# 4a5a04e61d7f (v6.16, restructured, David Kaplan 2025-04-18):
# Split into select/update/apply pattern. Same strings, same output.
#
# all messages start with "Not affected", "Vulnerable", "Mitigation", or "Unknown"
#
# --- stable backports ---
# Stable branches 5.4.y through 6.15.y: identical mmio_strings[] array.
# 5.4.y uses sprintf(); 5.10.y+ uses sysfs_emit().
# v6.0.y through v6.15.y include "Unknown: No mitigations" branch.
# v6.16.y+: restructured, no "Unknown" message.
#
# --- RHEL/CentOS ---
# centos7: sprintf() instead of sysfs_emit(), otherwise identical strings.
# rocky8: sysfs_emit(), includes X86_BUG_MMIO_UNKNOWN.
# rocky9: sysfs_emit(), includes X86_BUG_MMIO_UNKNOWN.
# rocky10: restructured, matches mainline v6.16+.
# All RHEL branches use identical mmio_strings[] array.
#
# --- Kconfig symbols ---
# No Kconfig symbol: v5.19 through v6.11 (mitigation always compiled in when CPU_SUP_INTEL)
# 163f9fe6b625 (v6.12, Breno Leitao 2024-07-29): CONFIG_MITIGATION_MMIO_STALE_DATA (bool, default y, depends CPU_SUP_INTEL)
# No other name variants exist (no renames). Single symbol throughout history.
#
# --- stable ---
# Only linux-rolling-lts and linux-rolling-stable have the Kconfig symbol.
# Stable branches 5.x through 6.11.y: no Kconfig (always compiled in).
#
# --- RHEL ---
# rocky9, rocky10: CONFIG_MITIGATION_MMIO_STALE_DATA present.
# rocky8, centos7: no Kconfig symbol.
#
# --- kernel functions (for $opt_map / System.map) ---
# 8cb861e9e3c9 (v5.19): mmio_select_mitigation() [static __init]
# 8cb861e9e3c9 (v5.19): mmio_stale_data_parse_cmdline() [static __init]
# 8d50cdf8b834 (v5.19): mmio_stale_data_show_state() [static]
# 8d50cdf8b834 (v5.19): cpu_show_mmio_stale_data() [global, non-static -- visible in System.map]
# 4a5a04e61d7f (v6.16): + mmio_update_mitigation() [static __init]
# 4a5a04e61d7f (v6.16): + mmio_apply_mitigation() [static __init]
#
# Best grep targets for $opt_map: mmio_select_mitigation, cpu_show_mmio_stale_data
# Best grep targets for $g_kernel: mmio_stale_data (appears in sysfs strings and parameter name)
#
# --- stable ---
# 5.4.y-6.15.y: mmio_select_mitigation, mmio_stale_data_parse_cmdline, mmio_stale_data_show_state
# 6.16.y+: + mmio_update_mitigation, mmio_apply_mitigation
#
# --- RHEL ---
# rocky8/rocky9: mmio_select_mitigation, mmio_stale_data_parse_cmdline, mmio_stale_data_show_state
# rocky10: + mmio_update_mitigation, mmio_apply_mitigation
#
# --- CPU affection logic (for is_cpu_affected) ---
# 51802186158c (v5.19, initial model list, Pawan Gupta 2022-05-19):
# Intel Family 6:
# 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)
# All steppings. No stepping restrictions for MMIO flag itself.
#
# No models have been added to or removed from the MMIO blacklist since v5.19.
#
# 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).
#
# vendor scope: Intel only. Non-Intel CPUs never set X86_BUG_MMIO_STALE_DATA.
sys_interface_available=1
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports MMIO Stale Data mitigation: "
kernel_mmio=''
kernel_mmio_can_tell=1
if [ -n "$g_kernel_err" ]; then
kernel_mmio_can_tell=0
elif grep -q 'mmio_stale_data' "$g_kernel" 2>/dev/null; then
pr_debug "mmio: found 'mmio_stale_data' string in kernel image"
kernel_mmio='found MMIO Stale Data mitigation evidence in kernel image'
pstatus green YES "$kernel_mmio"
fi
if [ -z "$kernel_mmio" ] && [ -n "$opt_config" ] && grep -q '^CONFIG_MITIGATION_MMIO_STALE_DATA=y' "$opt_config"; then
kernel_mmio='found MMIO Stale Data mitigation config option enabled'
pstatus green YES "$kernel_mmio"
fi
if [ -z "$kernel_mmio" ] && [ -n "$opt_map" ]; then
if grep -qE 'mmio_select_mitigation|cpu_show_mmio_stale_data' "$opt_map"; then
kernel_mmio='found MMIO Stale Data mitigation function in System.map'
pstatus green YES "$kernel_mmio"
fi
fi
if [ -z "$kernel_mmio" ]; then
if [ "$kernel_mmio_can_tell" = 1 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN
fi
fi
pr_info_nol "* CPU microcode supports Fill Buffer clearing: "
if [ "$cap_fb_clear" = -1 ]; then
pstatus yellow UNKNOWN
elif [ "$cap_fb_clear" = 1 ]; then
pstatus green YES
else
pstatus yellow NO
fi
if [ "$opt_live" = 1 ] && [ "$sys_interface_available" = 1 ]; then
pr_info_nol "* Kernel mitigation is enabled and active: "
if echo "$ret_sys_interface_check_fullmsg" | grep -qi ^mitigation; then
mmio_mitigated=1
pstatus green YES
else
mmio_mitigated=0
pstatus yellow NO
fi
pr_info_nol "* SMT is either mitigated or disabled: "
if echo "$ret_sys_interface_check_fullmsg" | grep -Eq 'SMT (disabled|mitigated)'; then
mmio_smt_mitigated=1
pstatus green YES
else
mmio_smt_mitigated=0
pstatus yellow 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"
else
if [ "$opt_sysfs_only" != 1 ]; then
# compute mystatus and mymsg from our own logic
if [ "$cap_fb_clear" = 1 ]; then
if [ -n "$kernel_mmio" ]; then
if [ "$opt_live" = 1 ]; then
# mitigation must also be enabled
if [ "$mmio_mitigated" = 1 ]; then
if [ "$opt_paranoid" != 1 ] || [ "$mmio_smt_mitigated" = 1 ]; then
mystatus=OK
mymsg="Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled"
else
mystatus=VULN
mymsg="Your microcode and kernel are both up to date for this mitigation, but you must disable SMT (Hyper-Threading) for a complete mitigation"
fi
else
mystatus=VULN
mymsg="Your microcode and kernel are both up to date for this mitigation, but the mitigation is not active"
fi
else
mystatus=OK
mymsg="Your microcode and kernel are both up to date for this mitigation"
fi
else
mystatus=VULN
mymsg="Your microcode supports mitigation, but your kernel doesn't, upgrade it to mitigate the vulnerability"
fi
else
if [ -n "$kernel_mmio" ]; then
mystatus=VULN
mymsg="Your kernel supports mitigation, but your CPU microcode also needs to be updated to mitigate the vulnerability"
else
mystatus=VULN
mymsg="Neither your kernel or your microcode support mitigation, upgrade both to mitigate the vulnerability"
fi
fi
else
# sysfs only: return the status/msg we got
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
return
fi
# if we didn't get a msg+status from sysfs, use ours
if [ -z "$msg" ]; then
pvulnstatus "$cve" "$mystatus" "$mymsg"
elif [ "$opt_paranoid" = 1 ]; then
# if paranoid mode is enabled, we know that we won't agree on status, so take ours
pvulnstatus "$cve" "$mystatus" "$mymsg"
elif [ "$status" = "$mystatus" ]; then
# if we agree on status, we'll print the common status and our message (more detailed than the sysfs one)
pvulnstatus "$cve" "$status" "$mymsg"
else
# if we don't agree on status, maybe our logic is flawed due to a new kernel/mitigation? use the one from sysfs
pvulnstatus "$cve" "$status" "$msg"
fi
if [ "$mystatus" = VULN ]; then
explain "Update your kernel to a version that includes MMIO Stale Data mitigation (Linux 5.19+), and update your CPU microcode. If you are using a distribution kernel, make sure you are up to date. To enforce full mitigation including SMT, boot with 'mmio_stale_data=full,nosmt'."
fi
fi
}

View File

@@ -0,0 +1,7 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2022-21123, SBDR, Shared Buffers Data Read, MMIO Stale Data
check_CVE_2022_21123() {
check_cve 'CVE-2022-21123' check_mmio
}

View File

@@ -0,0 +1,7 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2022-21125, SBDS, Shared Buffers Data Sampling, MMIO Stale Data
check_CVE_2022_21125() {
check_cve 'CVE-2022-21125' check_mmio
}

View File

@@ -0,0 +1,7 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2022-21166, DRPW, Device Register Partial Write, MMIO Stale Data
check_CVE_2022_21166() {
check_cve 'CVE-2022-21166' check_mmio
}