Files
spectre-meltdown-checker/src/libs/210_cpu_detect.sh
Stéphane Lesimple 5e3033e2f5 enh: CVE-2022-40982 (Downfall) overhaul & Spectre V2 enhancements
Downfall:

- added `--kernel-config` support for all three Kconfig variants seen over all kernel versions up to now
- added `--kernel-map` support for `gds_select_mitigation` in `System.map`
- fixed the `--sysfs-only` mode
- added verbose information about remediation when `--explain` is used
- implemented `--paranoid mode`, requiring `GDS_MITIGATION_LOCKED` so that mitigation can't be disabled at runtime
- fixed offline mode (was wrongly looking at the system `dmesg`)
- better microcode status reporting (enabled, disabled, unsupported, unknown)
- fixed unknown (EOL) AVX-capable Intel family 6 CPUs now defaulting to affected
- fixed 2 missing known affected CPU models: INTEL_FAM6_SKYLAKE_L and INTEL_FAM6_SKYLAKE
- fixed case when we're running in a VM and the hypervisor doesn't let us read the MSR

Spectre V2:
- fix: affected_cpu: added Centaur family 7 (CentaurHauls) and Zhaoxin family 7 (Shanghai) as immune
- fix: added Centaur family 5 (CentaurHauls) and NSC family 5 (Geode by NSC) to is_cpu_specex_free()
- enh: offline mode: added detection logic by probing System.map and Kconfig
2026-04-02 21:00:30 +02:00

205 lines
8.4 KiB
Bash

# vim: set ts=4 sw=4 sts=4 et:
# Check whether the CPU is known to not perform speculative execution
# Returns: 0 if the CPU is speculation-free, 1 otherwise
is_cpu_specex_free() {
# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c#n882
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL_TABLET, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_BONNELL_MID, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL_MID, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_BONNELL, X86_FEATURE_ANY },
# { X86_VENDOR_CENTAUR, 5 },
# { X86_VENDOR_INTEL, 5 },
# { X86_VENDOR_NSC, 5 },
# { X86_VENDOR_ANY, 4 },
parse_cpu_details
if is_intel; then
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_TABLET" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL_MID" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_MID" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL" ]; then
return 0
fi
elif [ "$cpu_family" = 5 ]; then
return 0
fi
fi
# Centaur family 5 and NSC family 5 are also non-speculative
if [ "$cpu_vendor" = "CentaurHauls" ] && [ "$cpu_family" = 5 ]; then
return 0
fi
if [ "$cpu_vendor" = "Geode by NSC" ] && [ "$cpu_family" = 5 ]; then
return 0
fi
[ "$cpu_family" = 4 ] && return 0
return 1
}
# Check whether the CPU is known to be unaffected by microarchitectural data sampling (MDS)
# Returns: 0 if MDS-free, 1 if affected or unknown
is_cpu_mds_free() {
# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c
#VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF),
#VULNWL_INTEL(ATOM_GOLDMONT_X, NO_MDS | NO_L1TF),
#VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF),
#/* AMD Family 0xf - 0x12 */
#VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
#VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
#VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
#VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
#/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
#VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS),
#VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS),
parse_cpu_details
if is_intel; then
if [ "$cpu_family" = 6 ]; then
if [ "$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
[ "$cap_mds_no" = 1 ] && return 0
fi
# official statement from AMD says none of their CPUs are affected
# https://www.amd.com/en/corporate/product-security
# https://www.amd.com/system/files/documents/security-whitepaper.pdf
if is_amd; then
return 0
elif is_hygon; then
return 0
elif [ "$cpu_vendor" = CAVIUM ]; then
return 0
elif [ "$cpu_vendor" = PHYTIUM ]; then
return 0
elif [ "$cpu_vendor" = ARM ]; then
return 0
fi
return 1
}
# Check whether the CPU is known to be unaffected by TSX Asynchronous Abort (TAA)
# Returns: 0 if TAA-free, 1 if affected or unknown
is_cpu_taa_free() {
if ! is_intel; then
return 0
# is intel
elif [ "$cap_taa_no" = 1 ] || [ "$cap_rtm" = 0 ]; then
return 0
fi
return 1
}
# Check whether the CPU is known to be unaffected by Special Register Buffer Data Sampling (SRBDS)
# Returns: 0 if SRBDS-free, 1 if affected or unknown
is_cpu_srbds_free() {
# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c
#
# A processor is affected by SRBDS if its Family_Model and stepping is in the
# following list, with the exception of the listed processors
# exporting MDS_NO while Intel TSX is available yet not enabled. The
# latter class of processors are only affected when Intel TSX is enabled
# by software using TSX_CTRL_MSR otherwise they are not affected.
#
# ============= ============ ========
# common name Family_Model Stepping
# ============= ============ ========
# IvyBridge 06_3AH All (INTEL_FAM6_IVYBRIDGE)
#
# Haswell 06_3CH All (INTEL_FAM6_HASWELL)
# Haswell_L 06_45H All (INTEL_FAM6_HASWELL_L)
# Haswell_G 06_46H All (INTEL_FAM6_HASWELL_G)
#
# Broadwell_G 06_47H All (INTEL_FAM6_BROADWELL_G)
# Broadwell 06_3DH All (INTEL_FAM6_BROADWELL)
#
# Skylake_L 06_4EH All (INTEL_FAM6_SKYLAKE_L)
# Skylake 06_5EH All (INTEL_FAM6_SKYLAKE)
#
# Kabylake_L 06_8EH <=0xC (MDS_NO) (INTEL_FAM6_KABYLAKE_L)
#
# Kabylake 06_9EH <=0xD (MDS_NO) (INTEL_FAM6_KABYLAKE)
# ============= ============ ========
parse_cpu_details
if is_intel; then
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_IVYBRIDGE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_HASWELL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_HASWELL_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_HASWELL_G" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL_G" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ]; then
return 1
elif [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] && [ "$cpu_stepping" -le 12 ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] && [ "$cpu_stepping" -le 13 ]; then
if [ "$cap_mds_no" -eq 1 ] && { [ "$cap_rtm" -eq 0 ] || [ "$cap_tsx_ctrl_rtm_disable" -eq 1 ]; }; then
return 0
else
return 1
fi
fi
fi
fi
return 0
}
# Check whether the CPU is known to be unaffected by Speculative Store Bypass (SSB)
# Returns: 0 if SSB-free, 1 if affected or unknown
is_cpu_ssb_free() {
# source1: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c#n945
# source2: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/tree/arch/x86/kernel/cpu/common.c
# Only list CPUs that speculate but are immune, to avoid duplication of cpus listed in is_cpu_specex_free()
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_X },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_MID },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_CORE_YONAH },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM },
#{ X86_VENDOR_AMD, 0x12, },
#{ X86_VENDOR_AMD, 0x11, },
#{ X86_VENDOR_AMD, 0x10, },
#{ X86_VENDOR_AMD, 0xf, },
parse_cpu_details
if is_intel; then
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ]; then
return 0
elif [ "$cpu_model" = "$INTEL_FAM6_CORE_YONAH" ] ||
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ]; then
return 0
fi
fi
fi
if is_amd; then
if [ "$cpu_family" = "18" ] ||
[ "$cpu_family" = "17" ] ||
[ "$cpu_family" = "16" ] ||
[ "$cpu_family" = "15" ]; then
return 0
fi
fi
if is_hygon; then
return 1
fi
[ "$cpu_family" = 4 ] && return 0
return 1
}