Compare commits

...
4 Commits
Author SHA1 Message Date
github-actions[bot] 700e89cc0e fix: xen: consider Xen dom0 as non-guest (#343 continued)
built from commit bc00a81526
 dated 2026-07-30 15:51:23 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)
2026-07-30 14:08:48 +00:00
github-actions[bot] 024e5a94b9 fix: another attempt to avoid sigpipe on grep (#519)
built from commit 5bbffaf053
 dated 2026-06-10 23:33:10 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)

 Take this opportunity to factorize all the greps in /proc/cpuinfo
into a helper that avoids using a pipe to entirely avoid SIGPIPE
on a possibly gigantic /proc/cpuinfo
2026-06-10 21:34:38 +00:00
github-actions[bot] 2ce3775287 fix: mmio: don't report "Intel never assessed this CPU" when the MSR is unreadable
built from commit 23ea5427b5
 dated 2026-06-08 22:55:45 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)

 When IA32_ARCH_CAPABILITIES (0x10a) can't be read from userspace (no msr
module, or kernel lockdown under Secure Boot), the FBSDP_NO/PSDP_NO/SBDR_SSDP_NO
bits were left at 0 ("explicitly not immune") instead of -1 ("unknown"). For a
recent CPU not in any kernel model list (e.g. Arrow Lake), this wrongly flipped
the MMIO Stale Data verdict into the "out of servicing period, Intel never
assessed this CPU" bucket.
2026-06-08 20:57:09 +00:00
github-actions[bot] 476ebe59fc fix: dmesg_grep: avoid sigpipe on some systems (#519)
built from commit cc159fe7fd
 dated 2026-06-08 21:41:08 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)

 Use 'grep -m 1' (works under Linux, busybox, BSD) instead of piping to head -n1
2026-06-08 19:42:39 +00:00
+166 -44
View File
@@ -13,7 +13,7 @@
# #
# Stephane Lesimple # Stephane Lesimple
# #
VERSION='26.36.0606627' VERSION='26.36.0730588'
# --- Common paths and basedirs --- # --- Common paths and basedirs ---
readonly VULN_SYSFS_BASE="/sys/devices/system/cpu/vulnerabilities" readonly VULN_SYSFS_BASE="/sys/devices/system/cpu/vulnerabilities"
@@ -381,6 +381,7 @@ fi
readonly INTEL_FAM6_ARROWLAKE_U=$((0xB5)) readonly INTEL_FAM6_ARROWLAKE_U=$((0xB5))
readonly INTEL_FAM6_LUNARLAKE_M=$((0xBD)) # /* Lion Cove / Skymont */ readonly INTEL_FAM6_LUNARLAKE_M=$((0xBD)) # /* Lion Cove / Skymont */
readonly INTEL_FAM6_PANTHERLAKE_L=$((0xCC)) # /* Cougar Cove / Darkmont */ readonly INTEL_FAM6_PANTHERLAKE_L=$((0xCC)) # /* Cougar Cove / Darkmont */
readonly INTEL_FAM6_PANTHERLAKE_R=$((0xE5)) # /* Cougar Cove / Darkmont */
readonly INTEL_FAM6_WILDCATLAKE_L=$((0xD5)) readonly INTEL_FAM6_WILDCATLAKE_L=$((0xD5))
readonly INTEL_FAM18_NOVALAKE=$((0x01)) # /* Coyote Cove / Arctic Wolf */ readonly INTEL_FAM18_NOVALAKE=$((0x01)) # /* Coyote Cove / Arctic Wolf */
readonly INTEL_FAM18_NOVALAKE_L=$((0x03)) # /* Coyote Cove / Arctic Wolf */ readonly INTEL_FAM18_NOVALAKE_L=$((0x03)) # /* Coyote Cove / Arctic Wolf */
@@ -1805,6 +1806,14 @@ is_arch_cap_mmio_immune() {
[ "$cap_sbdr_ssdp_no" = 1 ] && [ "$cap_fbsdp_no" = 1 ] && [ "$cap_psdp_no" = 1 ] [ "$cap_sbdr_ssdp_no" = 1 ] && [ "$cap_fbsdp_no" = 1 ] && [ "$cap_psdp_no" = 1 ]
} }
# Whether the MMIO arch-cap immunity bits are undetermined because the
# IA32_ARCH_CAPABILITIES MSR couldn't be read (msr module unavailable or kernel
# lockdown).
# Returns: 0 if undetermined, 1 otherwise
is_arch_cap_mmio_undetermined() {
[ "$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) # 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(). # Matches the kernel's NO_MMIO whitelist plus arch_cap_mmio_immune().
# Model inventory and kernel-commit history are documented in check_mmio_linux(). # Model inventory and kernel-commit history are documented in check_mmio_linux().
@@ -3535,7 +3544,7 @@ dmesg_grep() {
# dmesg truncated # dmesg truncated
return 2 return 2
fi fi
ret_dmesg_grep_grepped=$(dmesg 2>/dev/null | grep -E "$1" | head -n1) ret_dmesg_grep_grepped=$(dmesg 2>/dev/null | grep -m 1 -E "$1")
# not found: # not found:
[ -z "$ret_dmesg_grep_grepped" ] && return 1 [ -z "$ret_dmesg_grep_grepped" ] && return 1
# found, output is in $ret_dmesg_grep_grepped # found, output is in $ret_dmesg_grep_grepped
@@ -3549,6 +3558,12 @@ is_coreos() {
return 1 return 1
} }
# Check whether /proc/cpuinfo has $1 in the flags line
# Returns: 0 if flag found, 1 otherwise
cpuinfo_has_flag() {
grep -Eq '^flags\b.+\b'"$1"'\b' "$g_procfs/cpuinfo" 2>/dev/null
}
# >>>>>> libs/340_cpu_msr.sh <<<<<< # >>>>>> libs/340_cpu_msr.sh <<<<<<
# vim: set ts=4 sw=4 sts=4 et: # vim: set ts=4 sw=4 sts=4 et:
@@ -3927,8 +3942,8 @@ parse_cpu_details() {
cap_avx2=0 cap_avx2=0
cap_avx512=0 cap_avx512=0
if [ -e "$g_procfs/cpuinfo" ]; then if [ -e "$g_procfs/cpuinfo" ]; then
if grep -qw avx2 "$g_procfs/cpuinfo" 2>/dev/null; then cap_avx2=1; fi if cpuinfo_has_flag avx2; then cap_avx2=1; fi
if grep -qw avx512 "$g_procfs/cpuinfo" 2>/dev/null; then cap_avx512=1; fi if cpuinfo_has_flag avx512; then cap_avx512=1; fi
cpu_vendor=$(grep '^vendor_id' "$g_procfs/cpuinfo" | awk '{print $3}' | head -n1) 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/^ *//') cpu_friendly_name=$(grep '^model name' "$g_procfs/cpuinfo" | cut -d: -f2- | head -n1 | sed -e 's/^ *//')
# ARM-style cpuinfo: parse per-core implementer/part/arch/variant/revision lists # ARM-style cpuinfo: parse per-core implementer/part/arch/variant/revision lists
@@ -4170,8 +4185,18 @@ is_arm_cpu() {
# Check whether SMT (HyperThreading) is enabled on the system # Check whether SMT (HyperThreading) is enabled on the system
# Returns: 0 if SMT enabled, 1 otherwise # Returns: 0 if SMT enabled, 1 otherwise
is_cpu_smt_enabled() { is_cpu_smt_enabled() {
local siblings cpucores local siblings cpucores smt_active
# SMT / HyperThreading is enabled if siblings != cpucores # Most reliable: /sys/devices/system/cpu/smt/active mirrors the kernel's
# sched_smt_active() (1=SMT active, 0=not), which is exactly what the kernel
# itself uses to derive the "SMT (disabled|vulnerable)" vulnerability strings.
if [ -r /sys/devices/system/cpu/smt/active ]; then
smt_active=$(cat /sys/devices/system/cpu/smt/active 2>/dev/null)
case "$smt_active" in
1) return 0 ;;
0) return 1 ;;
esac
fi
# Fallback: SMT / HyperThreading is enabled if siblings != cpucores
if [ -e "$g_procfs/cpuinfo" ]; then if [ -e "$g_procfs/cpuinfo" ]; then
siblings=$(awk '/^siblings/ {print $3;exit}' "$g_procfs/cpuinfo") siblings=$(awk '/^siblings/ {print $3;exit}' "$g_procfs/cpuinfo")
cpucores=$(awk '/^cpu cores/ {print $4;exit}' "$g_procfs/cpuinfo") cpucores=$(awk '/^cpu cores/ {print $4;exit}' "$g_procfs/cpuinfo")
@@ -4623,7 +4648,14 @@ is_running_as_guest() {
if [ "${g_is_guest_vm_cached:-0}" != 1 ]; then if [ "${g_is_guest_vm_cached:-0}" != 1 ]; then
g_is_guest_vm=0 g_is_guest_vm=0
g_is_guest_vm_reason='' g_is_guest_vm_reason=''
if [ -e "$g_procfs/cpuinfo" ] && grep -qw 'hypervisor' "$g_procfs/cpuinfo" 2>/dev/null; then # A Xen dom0 runs on top of the hypervisor and therefore also has the
# 'hypervisor' CPUID flag set, but it's the privileged control domain:
# it has direct hardware access and a truthful view of the host CPU
# topology, so it must not be classified as a guest (#343). Check it
# before the cpuinfo probe below, which would otherwise match.
if is_xen_dom0; then
g_is_guest_vm=0
elif [ -e "$g_procfs/cpuinfo" ] && grep -qw 'hypervisor' "$g_procfs/cpuinfo" 2>/dev/null; then
g_is_guest_vm=1 g_is_guest_vm=1
g_is_guest_vm_reason="'hypervisor' flag in $g_procfs/cpuinfo" g_is_guest_vm_reason="'hypervisor' flag in $g_procfs/cpuinfo"
fi fi
@@ -5256,7 +5288,7 @@ check_cpu() {
fi fi
if [ -z "$cap_ibrs" ] && [ $ret = $READ_CPUID_RET_ERR ] && has_runtime; then if [ -z "$cap_ibrs" ] && [ $ret = $READ_CPUID_RET_ERR ] && has_runtime; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
if grep ^flags "$g_procfs/cpuinfo" | grep -qw ibrs; then if cpuinfo_has_flag ibrs; then
cap_ibrs='IBRS (cpuinfo)' cap_ibrs='IBRS (cpuinfo)'
cap_spec_ctrl=1 cap_spec_ctrl=1
pstatus green YES "ibrs flag in $g_procfs/cpuinfo" pstatus green YES "ibrs flag in $g_procfs/cpuinfo"
@@ -5331,7 +5363,7 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
cap_ibpb='IBPB_SUPPORT' cap_ibpb='IBPB_SUPPORT'
pstatus green YES "IBPB_SUPPORT feature bit" pstatus green YES "IBPB_SUPPORT feature bit"
elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw ibpb; then elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && cpuinfo_has_flag ibpb; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
cap_ibpb='IBPB (cpuinfo)' cap_ibpb='IBPB (cpuinfo)'
pstatus green YES "ibpb flag in $g_procfs/cpuinfo" pstatus green YES "ibpb flag in $g_procfs/cpuinfo"
@@ -5404,7 +5436,7 @@ check_cpu() {
fi fi
if [ -z "$cap_stibp" ] && [ $ret = $READ_CPUID_RET_ERR ] && has_runtime; then if [ -z "$cap_stibp" ] && [ $ret = $READ_CPUID_RET_ERR ] && has_runtime; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
if grep ^flags "$g_procfs/cpuinfo" | grep -qw stibp; then if cpuinfo_has_flag stibp; then
cap_stibp='STIBP (cpuinfo)' cap_stibp='STIBP (cpuinfo)'
pstatus green YES "stibp flag in $g_procfs/cpuinfo" pstatus green YES "stibp flag in $g_procfs/cpuinfo"
ret=$READ_CPUID_RET_OK ret=$READ_CPUID_RET_OK
@@ -5476,9 +5508,9 @@ check_cpu() {
if [ -z "$cap_ssbd" ] && [ "$ret24" = $READ_CPUID_RET_ERR ] && [ "$ret25" = $READ_CPUID_RET_ERR ] && has_runtime; then if [ -z "$cap_ssbd" ] && [ "$ret24" = $READ_CPUID_RET_ERR ] && [ "$ret25" = $READ_CPUID_RET_ERR ] && has_runtime; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then if cpuinfo_has_flag ssbd; then
cap_ssbd='SSBD (cpuinfo)' cap_ssbd='SSBD (cpuinfo)'
elif grep ^flags "$g_procfs/cpuinfo" | grep -qw virt_ssbd; then elif cpuinfo_has_flag virt_ssbd; then
cap_ssbd='SSBD in VIRT_SPEC_CTRL (cpuinfo)' cap_ssbd='SSBD in VIRT_SPEC_CTRL (cpuinfo)'
fi fi
fi fi
@@ -5538,7 +5570,7 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
pstatus green YES "L1D flush feature bit" pstatus green YES "L1D flush feature bit"
cap_l1df=1 cap_l1df=1
elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw flush_l1d; then elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && cpuinfo_has_flag flush_l1d; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
pstatus green YES "flush_l1d flag in $g_procfs/cpuinfo" pstatus green YES "flush_l1d flag in $g_procfs/cpuinfo"
cap_l1df=1 cap_l1df=1
@@ -5558,7 +5590,7 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
cap_md_clear=1 cap_md_clear=1
pstatus green YES "MD_CLEAR feature bit" pstatus green YES "MD_CLEAR feature bit"
elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw md_clear; then elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && cpuinfo_has_flag md_clear; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
cap_md_clear=1 cap_md_clear=1
pstatus green YES "md_clear flag in $g_procfs/cpuinfo" pstatus green YES "md_clear flag in $g_procfs/cpuinfo"
@@ -5628,7 +5660,7 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
pstatus green YES pstatus green YES
cap_arch_capabilities=1 cap_arch_capabilities=1
elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw arch_capabilities; then elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && cpuinfo_has_flag arch_capabilities; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
pstatus green YES "arch_capabilities flag in $g_procfs/cpuinfo" pstatus green YES "arch_capabilities flag in $g_procfs/cpuinfo"
cap_arch_capabilities=1 cap_arch_capabilities=1
@@ -5730,8 +5762,33 @@ check_cpu() {
pstatus yellow NO pstatus yellow NO
fi fi
elif [ $ret = $READ_MSR_RET_KO ]; then elif [ $ret = $READ_MSR_RET_KO ]; then
# the MSR access faulted: the register is genuinely absent, so the
# pre-seeded 0 ("not advertised") values are correct.
pstatus yellow NO pstatus yellow NO
else else
# RET_ERR (no msr module) or RET_LOCKDOWN (MSR reads restricted):
# CPUID told us the MSR exists but we couldn't read it, so its bits
# are undetermined, not 0. Leaving them at 0 would falsely claim the
# CPU "explicitly indicates not immune".
# Reset every arch-cap-derived value to -1 (UNKNOWN) instead.
cap_rdcl_no=-1
cap_taa_no=-1
cap_mds_no=-1
cap_ibrs_all=-1
cap_rsba=-1
cap_l1dflush_no=-1
cap_ssb_no=-1
cap_pschange_msc_no=-1
cap_tsx_ctrl_msr=-1
cap_gds_ctrl=-1
cap_gds_no=-1
cap_rfds_no=-1
cap_rfds_clear=-1
cap_its_no=-1
cap_sbdr_ssdp_no=-1
cap_fbsdp_no=-1
cap_psdp_no=-1
cap_fb_clear=-1
pstatus yellow UNKNOWN "$ret_read_msr_msg" pstatus yellow UNKNOWN "$ret_read_msr_msg"
fi fi
fi fi
@@ -6482,7 +6539,7 @@ check_mds_linux() {
if is_x86_kernel; then if is_x86_kernel; then
pr_info_nol "* Kernel supports using MD_CLEAR mitigation: " pr_info_nol "* Kernel supports using MD_CLEAR mitigation: "
kernel_md_clear_can_tell=1 kernel_md_clear_can_tell=1
if [ "$g_mode" = live ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw md_clear; then if [ "$g_mode" = live ] && cpuinfo_has_flag md_clear; then
kernel_md_clear="md_clear found in $g_procfs/cpuinfo" kernel_md_clear="md_clear found in $g_procfs/cpuinfo"
pstatus green YES "$kernel_md_clear" pstatus green YES "$kernel_md_clear"
fi fi
@@ -6519,11 +6576,21 @@ check_mds_linux() {
mds_smt_mitigated=1 mds_smt_mitigated=1
pstatus green YES pstatus green YES
elif echo "$ret_sys_interface_check_fullmsg" | grep -q 'SMT Host state unknown'; then elif echo "$ret_sys_interface_check_fullmsg" | grep -q 'SMT Host state unknown'; then
# The kernel appends "SMT Host state unknown" when running under # The kernel appends "SMT Host state unknown" whenever the
# a hypervisor (X86_FEATURE_HYPERVISOR): the host controls SMT # HYPERVISOR CPUID bit is set. That's true both inside a guest
# scheduling, so it can't be determined from inside the guest (#343). # AND on a Xen dom0 (#343). In a guest we genuinely can't see
# the host's SMT scheduling; on dom0/bare metal the local SMT
# state is authoritative, so trust it there.
if is_running_as_guest; then
mds_smt_mitigated=2 mds_smt_mitigated=2
pstatus yellow UNKNOWN "running in a VM guest, the hypervisor host controls SMT" pstatus yellow UNKNOWN "running in a VM guest, the hypervisor host controls SMT"
elif is_cpu_smt_enabled; then
mds_smt_mitigated=0
pstatus yellow NO
else
mds_smt_mitigated=1
pstatus green YES
fi
else else
mds_smt_mitigated=0 mds_smt_mitigated=0
pstatus yellow NO pstatus yellow NO
@@ -6610,16 +6677,23 @@ check_mmio_bsd() {
# the only partial defense available, and without OS-level VERW invocation it # the only partial defense available, and without OS-level VERW invocation it
# cannot close the vulnerability. # cannot close the vulnerability.
local unk 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 if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif is_cpu_mmio_unknown; then elif is_cpu_mmio_unknown; then
if is_arch_cap_mmio_undetermined; then
# We only landed in the "unknown" bucket because the IA32_ARCH_CAPABILITIES
# MSR couldn't be read: the CPU might actually advertise MMIO immunity.
unk="your CPU's MMIO Stale Data status could not be determined: the IA32_ARCH_CAPABILITIES MSR (0x10a) couldn't be read"
pvulnstatus "$cve" UNK "$unk; load the cpuctl module and/or re-run as root to get a definitive answer"
else
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 if [ "$opt_paranoid" = 1 ]; then
pvulnstatus "$cve" VULN "$unk, and no BSD mitigation exists" 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." 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 else
pvulnstatus "$cve" UNK "$unk; no BSD mitigation exists in any case" pvulnstatus "$cve" UNK "$unk; no BSD mitigation exists in any case"
fi fi
fi
else else
pvulnstatus "$cve" VULN "your CPU is affected and no BSD has implemented an MMIO Stale Data mitigation" 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." 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."
@@ -6628,7 +6702,7 @@ check_mmio_bsd() {
# MMIO Stale Data (Processor MMIO Stale Data Vulnerabilities) - Linux mitigation check # MMIO Stale Data (Processor MMIO Stale Data Vulnerabilities) - Linux mitigation check
check_mmio_linux() { check_mmio_linux() {
local status sys_interface_available msg kernel_mmio kernel_mmio_can_tell mmio_mitigated mmio_smt_mitigated mystatus mymsg unk local status sys_interface_available msg kernel_mmio kernel_mmio_can_tell kernel_mmio_unknown_aware mmio_mitigated mmio_smt_mitigated mystatus mymsg unk
status=UNK status=UNK
sys_interface_available=0 sys_interface_available=0
msg='' msg=''
@@ -6770,6 +6844,11 @@ check_mmio_linux() {
# MMIO Stale Data is Intel-only; skip x86-specific kernel/MSR checks on non-x86 kernels # MMIO Stale Data is Intel-only; skip x86-specific kernel/MSR checks on non-x86 kernels
kernel_mmio='' kernel_mmio=''
kernel_mmio_can_tell=0 kernel_mmio_can_tell=0
# Whether this kernel implements the X86_BUG_MMIO_UNKNOWN distinction, i.e. can
# report "Unknown: No mitigations" for CPUs Intel never assessed. Only such kernels
# emit a *trustworthy* "Not affected": they would have said "Unknown" instead if the
# CPU were in the unknown bucket. Detected by the presence of the literal sysfs string in the kernel image.
kernel_mmio_unknown_aware=0
if is_x86_kernel; then if is_x86_kernel; then
pr_info_nol "* Kernel supports MMIO Stale Data mitigation: " pr_info_nol "* Kernel supports MMIO Stale Data mitigation: "
kernel_mmio_can_tell=1 kernel_mmio_can_tell=1
@@ -6780,6 +6859,10 @@ check_mmio_linux() {
kernel_mmio='found MMIO Stale Data mitigation evidence in kernel image' kernel_mmio='found MMIO Stale Data mitigation evidence in kernel image'
pstatus green YES "$kernel_mmio" pstatus green YES "$kernel_mmio"
fi fi
if [ -z "$g_kernel_err" ] && grep -qF 'Unknown: No mitigations' "$g_kernel" 2>/dev/null; then
pr_debug "mmio: kernel image knows the 'Unknown: No mitigations' state (X86_BUG_MMIO_UNKNOWN-aware)"
kernel_mmio_unknown_aware=1
fi
if [ -z "$kernel_mmio" ] && [ -n "$opt_config" ] && grep -q '^CONFIG_MITIGATION_MMIO_STALE_DATA=y' "$opt_config"; then 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' kernel_mmio='found MMIO Stale Data mitigation config option enabled'
pstatus green YES "$kernel_mmio" pstatus green YES "$kernel_mmio"
@@ -6821,11 +6904,21 @@ check_mmio_linux() {
mmio_smt_mitigated=1 mmio_smt_mitigated=1
pstatus green YES pstatus green YES
elif echo "$ret_sys_interface_check_fullmsg" | grep -q 'SMT Host state unknown'; then elif echo "$ret_sys_interface_check_fullmsg" | grep -q 'SMT Host state unknown'; then
# The kernel appends "SMT Host state unknown" when running under # The kernel appends "SMT Host state unknown" whenever the
# a hypervisor (X86_FEATURE_HYPERVISOR): the host controls SMT # HYPERVISOR CPUID bit is set. That's true both inside a guest
# scheduling, so it can't be determined from inside the guest (#343). # AND on a Xen dom0 (#343). In a guest we genuinely can't see
# the host's SMT scheduling; on dom0/bare metal the local SMT
# state is authoritative, so trust it there.
if is_running_as_guest; then
mmio_smt_mitigated=2 mmio_smt_mitigated=2
pstatus yellow UNKNOWN "running in a VM guest, the hypervisor host controls SMT" pstatus yellow UNKNOWN "running in a VM guest, the hypervisor host controls SMT"
elif is_cpu_smt_enabled; then
mmio_smt_mitigated=0
pstatus yellow NO
else
mmio_smt_mitigated=1
pstatus green YES
fi
else else
mmio_smt_mitigated=0 mmio_smt_mitigated=0
pstatus yellow NO pstatus yellow NO
@@ -6845,13 +6938,33 @@ check_mmio_linux() {
# Bypass the normal sysfs reconciliation: sysfs reports "Unknown: No mitigations" # 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" # 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). # for these CPUs (which predate FB_CLEAR microcode and Intel's affected-processor list).
if is_arch_cap_mmio_undetermined; then
# We landed in the "unknown" bucket only because the IA32_ARCH_CAPABILITIES
# MSR couldn't be read from userspace (no msr module, or kernel lockdown under
# Secure Boot): the CPU might actually advertise MMIO immunity
# through FBSDP_NO/PSDP_NO/SBDR_SSDP_NO, but we can't read it, however the kernel can.
#
# We can trust a sysfs "Not affected" only if this kernel is X86_BUG_MMIO_UNKNOWN-aware:
# such a kernel would have reported "Unknown: No mitigations" instead if the CPU were in
# the unknown bucket, so "Not affected" genuinely means arch-cap immune.
# On kernels that lack that distinction, a "Not affected" is not trustworthy for these CPUs,
# so we keep UNK.
if [ "$g_mode" = live ] && [ "$sys_interface_available" = 1 ] &&
[ "$kernel_mmio_unknown_aware" = 1 ] && [ "$status" = OK ]; then
pvulnstatus "$cve" OK "your kernel reports your CPU as not affected, and this kernel distinguishes the MMIO 'unknown' state, so its verdict is trustworthy (we couldn't read the IA32_ARCH_CAPABILITIES MSR ourselves)"
else
unk="your CPU's MMIO Stale Data status could not be determined: the IA32_ARCH_CAPABILITIES MSR (0x10a) couldn't be read"
pvulnstatus "$cve" UNK "$unk; load the msr module and/or disable kernel lockdown, then re-run as root to get a definitive answer"
fi
else
unk="your CPU's MMIO Stale Data status is unknown (Intel never officially assessed this CPU, its servicing period has ended)" 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 if [ "$opt_paranoid" = 1 ]; then
pvulnstatus "$cve" VULN "$unk, and no mitigation is available" 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." 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."
else else
pvulnstatus "$cve" UNK "$unk; no mitigation is available in any case" pvulnstatus "$cve" UNK "$unk; no mitigation is available in any case"
fi fi
fi
else else
if [ "$opt_sysfs_only" != 1 ]; then if [ "$opt_sysfs_only" != 1 ]; then
# compute mystatus and mymsg from our own logic # compute mystatus and mymsg from our own logic
@@ -7766,7 +7879,7 @@ check_CVE_2017_5715_linux() {
# which in that case means ibrs is supported *and* enabled for kernel & user # which in that case means ibrs is supported *and* enabled for kernel & user
# as per the ibrs patch series v3 # as per the ibrs patch series v3
if [ -z "$g_ibrs_supported" ]; then if [ -z "$g_ibrs_supported" ]; then
if grep ^flags "$g_procfs/cpuinfo" | grep -qw spec_ctrl_ibrs; then if cpuinfo_has_flag spec_ctrl_ibrs; then
pr_debug "ibrs: found spec_ctrl_ibrs flag in $g_procfs/cpuinfo" pr_debug "ibrs: found spec_ctrl_ibrs flag in $g_procfs/cpuinfo"
g_ibrs_supported="spec_ctrl_ibrs flag in $g_procfs/cpuinfo" g_ibrs_supported="spec_ctrl_ibrs flag in $g_procfs/cpuinfo"
# enabled=2 -> kernel & user # enabled=2 -> kernel & user
@@ -9022,7 +9135,7 @@ check_CVE_2017_5753_bsd() {
pti_performance_check() { pti_performance_check() {
local ret pcid invpcid local ret pcid invpcid
pr_info_nol " * Reduced performance impact of PTI: " pr_info_nol " * Reduced performance impact of PTI: "
if [ -e "$g_procfs/cpuinfo" ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw pcid; then if cpuinfo_has_flag pcid; then
pcid=1 pcid=1
else else
read_cpuid 0x1 0x0 "$ECX" 17 1 1 read_cpuid 0x1 0x0 "$ECX" 17 1 1
@@ -9032,7 +9145,7 @@ pti_performance_check() {
fi fi
fi fi
if [ -e "$g_procfs/cpuinfo" ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw invpcid; then if cpuinfo_has_flag invpcid; then
invpcid=1 invpcid=1
else else
read_cpuid 0x7 0x0 "$EBX" 10 1 1 read_cpuid 0x7 0x0 "$EBX" 10 1 1
@@ -9121,11 +9234,11 @@ check_CVE_2017_5754_linux() {
dmesg_grep="$dmesg_grep|x86/pti: Unmapping kernel while in userspace" dmesg_grep="$dmesg_grep|x86/pti: Unmapping kernel while in userspace"
# aarch64 # aarch64
dmesg_grep="$dmesg_grep|CPU features: detected( feature)?: Kernel page table isolation \(KPTI\)" dmesg_grep="$dmesg_grep|CPU features: detected( feature)?: Kernel page table isolation \(KPTI\)"
if grep ^flags "$g_procfs/cpuinfo" | grep -qw pti; then if cpuinfo_has_flag pti; then
# vanilla PTI patch sets the 'pti' flag in cpuinfo # vanilla PTI patch sets the 'pti' flag in cpuinfo
pr_debug "kpti_enabled: found 'pti' flag in $g_procfs/cpuinfo" pr_debug "kpti_enabled: found 'pti' flag in $g_procfs/cpuinfo"
kpti_enabled=1 kpti_enabled=1
elif grep ^flags "$g_procfs/cpuinfo" | grep -qw kaiser; then elif cpuinfo_has_flag kaiser; then
# kernel line 4.9 sets the 'kaiser' flag in cpuinfo # kernel line 4.9 sets the 'kaiser' flag in cpuinfo
pr_debug "kpti_enabled: found 'kaiser' flag in $g_procfs/cpuinfo" pr_debug "kpti_enabled: found 'kaiser' flag in $g_procfs/cpuinfo"
kpti_enabled=1 kpti_enabled=1
@@ -9960,7 +10073,7 @@ check_CVE_2018_3646_linux() {
pr_info "* Mitigation 2" pr_info "* Mitigation 2"
pr_info_nol " * L1D flush is supported by kernel: " pr_info_nol " * L1D flush is supported by kernel: "
if [ "$g_mode" = live ] && grep -qw flush_l1d "$g_procfs/cpuinfo"; then if [ "$g_mode" = live ] && cpuinfo_has_flag flush_l1d; then
l1d_kernel="found flush_l1d in $g_procfs/cpuinfo" l1d_kernel="found flush_l1d in $g_procfs/cpuinfo"
fi fi
if [ -z "$l1d_kernel" ]; then if [ -z "$l1d_kernel" ]; then
@@ -10033,7 +10146,7 @@ check_CVE_2018_3646_linux() {
pr_info_nol " * Hardware-backed L1D flush supported: " pr_info_nol " * Hardware-backed L1D flush supported: "
if [ "$g_mode" = live ]; then if [ "$g_mode" = live ]; then
if grep -qw flush_l1d "$g_procfs/cpuinfo" || [ -n "$l1d_xen_hardware" ]; then if cpuinfo_has_flag flush_l1d || [ -n "$l1d_xen_hardware" ]; then
pstatus green YES "performance impact of the mitigation will be greatly reduced" pstatus green YES "performance impact of the mitigation will be greatly reduced"
else else
pstatus blue NO "flush will be done in software, this is slower" pstatus blue NO "flush will be done in software, this is slower"
@@ -10245,10 +10358,18 @@ check_CVE_2019_11135_linux() {
elif echo "$ret_sys_interface_check_fullmsg" | grep -qF 'SMT vulnerable'; then elif echo "$ret_sys_interface_check_fullmsg" | grep -qF 'SMT vulnerable'; then
pvulnstatus "$cve" VULN "SMT (HyperThreading) must be disabled for full mitigation" pvulnstatus "$cve" VULN "SMT (HyperThreading) must be disabled for full mitigation"
elif echo "$ret_sys_interface_check_fullmsg" | grep -qF 'SMT Host state unknown'; then elif echo "$ret_sys_interface_check_fullmsg" | grep -qF 'SMT Host state unknown'; then
# The kernel appends "SMT Host state unknown" when running under a # "SMT Host state unknown" is emitted whenever the HYPERVISOR
# hypervisor (X86_FEATURE_HYPERVISOR): the host controls SMT # CPUID bit is set -- true both inside a guest AND on a Xen dom0
# scheduling, so it can't be determined from inside the guest (#343). # (#343). In a guest we can't see the host's SMT scheduling; on
# dom0/bare metal the local SMT state is authoritative, so trust
# it there.
if is_running_as_guest; then
pvulnstatus "$cve" UNK "TAA is mitigated and TSX is disabled, but SMT (Hyper-Threading) cross-thread protection can't be verified from inside a VM guest: it depends on the hypervisor host's SMT/core-scheduling configuration" pvulnstatus "$cve" UNK "TAA is mitigated and TSX is disabled, but SMT (Hyper-Threading) cross-thread protection can't be verified from inside a VM guest: it depends on the hypervisor host's SMT/core-scheduling configuration"
elif is_cpu_smt_enabled; then
pvulnstatus "$cve" VULN "SMT (HyperThreading) must be disabled for full mitigation"
else
pvulnstatus "$cve" "$status" "$msg"
fi
else else
pvulnstatus "$cve" "$status" "$msg" pvulnstatus "$cve" "$status" "$msg"
fi fi
@@ -13264,7 +13385,7 @@ exit 0 # ok
# with X being either I for Intel, or A for AMD # with X being either I for Intel, or A for AMD
# When the date is unknown it defaults to 20000101 # When the date is unknown it defaults to 20000101
# %%% MCEDB v350+i20260512+1cce # %%% MCEDB v351+i20260512+16e5
# I,0x00000611,0xFF,0x00000B27,19961218 # I,0x00000611,0xFF,0x00000B27,19961218
# I,0x00000612,0xFF,0x000000C6,19961210 # I,0x00000612,0xFF,0x000000C6,19961210
# I,0x00000616,0xFF,0x000000C6,19961210 # I,0x00000616,0xFF,0x000000C6,19961210
@@ -13713,10 +13834,11 @@ exit 0 # ok
# I,0x000C06C3,0x90,0x0000011B,20260324 # I,0x000C06C3,0x90,0x0000011B,20260324
# I,0x000C06F1,0x87,0x210002E0,20251217 # I,0x000C06F1,0x87,0x210002E0,20251217
# I,0x000C06F2,0x87,0x210002E0,20251217 # I,0x000C06F2,0x87,0x210002E0,20251217
# I,0x000D0650,0xFF,0x00000008,20260208 # I,0x000D0650,0xFF,0x00000009,20260309
# I,0x000D0651,0xFF,0x00000008,20260208 # I,0x000D0651,0xFF,0x00000009,20260309
# I,0x000D0670,0xFF,0x00000137,20260218 # I,0x000D0670,0xFF,0x00000137,20260218
# I,0x000D06D0,0xFF,0x80000370,20250917 # I,0x000D06D0,0xFF,0x80000370,20250917
# I,0x000D06D1,0xFF,0x01000120,20260325
# I,0x00FF0671,0xFF,0x0000010E,20220907 # I,0x00FF0671,0xFF,0x0000010E,20220907
# I,0x00FF0672,0xFF,0x0000000D,20210816 # I,0x00FF0672,0xFF,0x0000000D,20210816
# I,0x00FF0675,0xFF,0x0000000D,20210816 # I,0x00FF0675,0xFF,0x0000000D,20210816
@@ -13818,8 +13940,8 @@ exit 0 # ok
# A,0x008A0F00,0xFF,0x08A0000B,20241125 # A,0x008A0F00,0xFF,0x08A0000B,20241125
# A,0x00A00F00,0xFF,0x0A000033,20200413 # A,0x00A00F00,0xFF,0x0A000033,20200413
# A,0x00A00F10,0xFF,0x0A00107A,20240226 # A,0x00A00F10,0xFF,0x0A00107A,20240226
# A,0x00A00F11,0xFF,0x0A0011DE,20250418 # A,0x00A00F11,0xFF,0x0A0011DF,20260312
# A,0x00A00F12,0xFF,0x0A001247,20250327 # A,0x00A00F12,0xFF,0x0A00124B,20260305
# A,0x00A00F80,0xFF,0x0A008005,20230707 # A,0x00A00F80,0xFF,0x0A008005,20230707
# A,0x00A00F82,0xFF,0x0A00820F,20241111 # A,0x00A00F82,0xFF,0x0A00820F,20241111
# A,0x00A10F00,0xFF,0x0A10004B,20220309 # A,0x00A10F00,0xFF,0x0A10004B,20220309
@@ -13865,8 +13987,8 @@ exit 0 # ok
# A,0x00B10F10,0xFF,0x0B101059,20251105 # A,0x00B10F10,0xFF,0x0B101059,20251105
# A,0x00B20F40,0xFF,0x0B204037,20251019 # A,0x00B20F40,0xFF,0x0B204037,20251019
# A,0x00B40F00,0xFF,0x0B400034,20240318 # A,0x00B40F00,0xFF,0x0B400034,20240318
# A,0x00B40F40,0xFF,0x0B404035,20251020 # A,0x00B40F40,0xFF,0x0B404038,20260408
# A,0x00B40F41,0xFF,0x0B404108,20251020 # A,0x00B40F41,0xFF,0x0B40410B,20260408
# A,0x00B60F00,0xFF,0x0B600037,20251019 # A,0x00B60F00,0xFF,0x0B60003C,20260401
# A,0x00B60F80,0xFF,0x0B608038,20251019 # A,0x00B60F80,0xFF,0x0B60803C,20260401
# A,0x00B70F00,0xFF,0x0B700037,20251019 # A,0x00B70F00,0xFF,0x0B700037,20251019