enh: CVE-2022-40982 (Downfall) overhaul

built from commit c4c4ea8c0a5f2ffde852a22f26b9801bca61139a
 dated 2026-04-02 19:55:25 +0200
 by Stéphane Lesimple (speed47_github@speed47.net)

 - 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
This commit is contained in:
github-actions[bot]
2026-04-02 18:03:22 +00:00
parent f46c743cad
commit 6f8112c700

View File

@@ -13,7 +13,7 @@
# #
# Stephane Lesimple # Stephane Lesimple
# #
VERSION='26.21.0402699' VERSION='26.21.0402751'
# --- 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"
@@ -588,9 +588,12 @@ is_cpu_affected() {
pr_debug "is_cpu_affected: downfall: not affected (GDS_NO)" pr_debug "is_cpu_affected: downfall: not affected (GDS_NO)"
_set_immune downfall _set_immune downfall
elif [ "$cpu_family" = 6 ]; then elif [ "$cpu_family" = 6 ]; then
# list from https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=64094e7e3118aff4b0be8ff713c242303e139834 # model blacklist from the kernel (arch/x86/kernel/cpu/common.c cpu_vuln_blacklist):
# 8974eb588283 (initial list) + c9f4c45c8ec3 (added Skylake/Skylake_L client)
set -u set -u
if [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] || if [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] || [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] || [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] || [ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] ||
@@ -605,10 +608,12 @@ is_cpu_affected() {
_set_vuln downfall _set_vuln downfall
elif [ "$cap_avx2" = 0 ] && [ "$cap_avx512" = 0 ]; then elif [ "$cap_avx2" = 0 ] && [ "$cap_avx512" = 0 ]; then
pr_debug "is_cpu_affected: downfall: no avx; immune" pr_debug "is_cpu_affected: downfall: no avx; immune"
_infer_immune downfall
else else
# old Intel CPU (not in their DB), not listed as being affected by the Linux kernel, # Intel family 6 CPU with AVX2 or AVX512, not in the known-affected list
# but with AVX2 or AVX512: unclear for now # and GDS_NO not set: assume affected (whitelist principle)
pr_debug "is_cpu_affected: downfall: unclear, defaulting to non-affected for now" pr_debug "is_cpu_affected: downfall: unknown AVX-capable CPU, defaulting to affected"
_infer_vuln downfall
fi fi
set +u set +u
fi fi
@@ -7475,6 +7480,90 @@ check_CVE_2022_40982_linux() {
if sys_interface_check "$VULN_SYSFS_BASE/gather_data_sampling"; then if sys_interface_check "$VULN_SYSFS_BASE/gather_data_sampling"; then
# this kernel has the /sys interface, trust it over everything # this kernel has the /sys interface, trust it over everything
sys_interface_available=1 sys_interface_available=1
#
# Kernel source inventory for gather_data_sampling (GDS/Downfall)
#
# --- sysfs messages ---
# all versions:
# "Not affected" (cpu_show_common, pre-existing)
#
# --- mainline ---
# 8974eb588283 (v6.5-rc6, initial GDS sysfs):
# "Vulnerable" (GDS_MITIGATION_OFF)
# "Vulnerable: No microcode" (GDS_MITIGATION_UCODE_NEEDED)
# "Mitigation: Microcode" (GDS_MITIGATION_FULL)
# "Mitigation: Microcode (locked)" (GDS_MITIGATION_FULL_LOCKED)
# "Unknown: Dependent on hypervisor status" (GDS_MITIGATION_HYPERVISOR)
# 553a5c03e90a (v6.5-rc6, added force option):
# "Mitigation: AVX disabled, no microcode" (GDS_MITIGATION_FORCE)
# 53cf5797f114 (v6.5-rc6, added CONFIG_GDS_FORCE_MITIGATION):
# no string changes; default becomes FORCE when Kconfig enabled
# 81ac7e5d7417 (v6.5-rc6, KVM GDS_NO plumbing):
# no string changes
# be83e809ca67 (v6.9-rc1, Kconfig rename):
# no string changes; CONFIG_GDS_FORCE_MITIGATION => CONFIG_MITIGATION_GDS_FORCE
# 03267a534bb3 (v6.12-rc1, removed force Kconfig):
# no string changes; CONFIG_MITIGATION_GDS_FORCE removed
# 225f2bd064c3 (v6.12-rc1, added on/off Kconfig):
# no string changes; added CONFIG_MITIGATION_GDS (default y)
# 9dcad2fb31bd (v6.16-rc1, restructured select/apply):
# no string changes; added GDS_MITIGATION_AUTO (internal, resolved before display)
# split gds_select_mitigation() + gds_apply_mitigation()
# d4932a1b148b (v6.17-rc3, bug fix):
# no string changes; CPUs without ARCH_CAP_GDS_CTRL were incorrectly classified
# as OFF ("Vulnerable") instead of UCODE_NEEDED ("Vulnerable: No microcode"),
# and locked-mitigation detection was skipped.
# NOT backported to any stable or RHEL branch as of 2026-04.
#
# --- stable backports ---
# 5.4.y, 5.10.y, 5.15.y, 6.1.y, 6.6.y: same 7 strings as mainline.
# use CONFIG_GDS_FORCE_MITIGATION; no GDS_MITIGATION_AUTO enum;
# missing d4932a1b148b bug fix (UCODE_NEEDED vs OFF misclassification).
# 6.12.y: same 7 strings as mainline.
# uses CONFIG_MITIGATION_GDS; no GDS_MITIGATION_AUTO enum;
# missing d4932a1b148b bug fix.
#
# --- RHEL/CentOS ---
# centos7 (3.10), rocky8 (4.18): same 7 strings; CONFIG_GDS_FORCE_MITIGATION.
# centos7 uses sprintf (not sysfs_emit) and __read_mostly.
# rocky9 (5.14): same 7 strings; CONFIG_MITIGATION_GDS (skipped FORCE rename).
# rocky10 (6.12): same 7 strings; CONFIG_MITIGATION_GDS; has gds_apply_mitigation().
#
# --- Kconfig symbols ---
# 53cf5797f114 (v6.5-rc6): CONFIG_GDS_FORCE_MITIGATION (default n)
# be83e809ca67 (v6.9-rc1): renamed to CONFIG_MITIGATION_GDS_FORCE
# 03267a534bb3 (v6.12-rc1): CONFIG_MITIGATION_GDS_FORCE removed
# 225f2bd064c3 (v6.12-rc1): CONFIG_MITIGATION_GDS (default y)
# vendor kernels: rocky9 uses CONFIG_MITIGATION_GDS on 5.14-based kernel
#
# --- kernel functions (for $opt_map / System.map) ---
# 8974eb588283 (v6.5-rc6): gds_select_mitigation(), update_gds_msr(),
# gds_parse_cmdline(), gds_show_state()
# 81ac7e5d7417 (v6.5-rc6): gds_ucode_mitigated() (exported for KVM)
# 9dcad2fb31bd (v6.16-rc1): split into gds_select_mitigation() + gds_apply_mitigation()
# stable 5.4.y-6.12.y: same 5 functions (no gds_apply_mitigation)
# rocky10 (6.12): has gds_apply_mitigation()
#
# --- CPU affection logic (for is_cpu_affected) ---
# X86_BUG_GDS is set when ALL three conditions are true:
# 1. CPU matches model blacklist (cpu_vuln_blacklist[] in common.c)
# 2. ARCH_CAP_GDS_NO (bit 26 of IA32_ARCH_CAPABILITIES) is NOT set
# 3. X86_FEATURE_AVX is present (GATHER instructions require AVX)
# 8974eb588283 (v6.5-rc6, initial model list):
# Intel: SKYLAKE_X, KABYLAKE_L, KABYLAKE, ICELAKE_L, ICELAKE_D,
# ICELAKE_X, COMETLAKE, COMETLAKE_L, TIGERLAKE_L, TIGERLAKE,
# ROCKETLAKE (all steppings)
# c9f4c45c8ec3 (v6.5-rc6, added missing client Skylake):
# Intel: + SKYLAKE_L, SKYLAKE
# 159013a7ca18 (v6.10-rc1, ITS stepping splits):
# no GDS model changes; some entries split by stepping for ITS but
# GDS flag remains on all stepping ranges for these models
# immunity: ARCH_CAP_GDS_NO (bit 26 of IA32_ARCH_CAPABILITIES)
# feature dependency: requires AVX (if AVX absent, CPU is immune)
# vendor scope: Intel only
#
# all messages start with either "Not affected", "Vulnerable", "Mitigation",
# or "Unknown"
status=$ret_sys_interface_check_status status=$ret_sys_interface_check_status
fi fi
@@ -7482,15 +7571,34 @@ check_CVE_2022_40982_linux() {
pr_info_nol "* GDS is mitigated by microcode: " pr_info_nol "* GDS is mitigated by microcode: "
if [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then if [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then
pstatus green OK "microcode mitigation is supported and enabled" pstatus green OK "microcode mitigation is supported and enabled"
elif [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 1 ]; then
pstatus yellow NO "microcode mitigation is supported but disabled"
elif [ "$cap_gds_ctrl" = 0 ]; then
pstatus yellow NO "microcode doesn't support GDS mitigation"
else else
pstatus yellow NO pstatus yellow UNKNOWN "couldn't read MSR for GDS capability"
fi fi
pr_info_nol "* Kernel supports software mitigation by disabling AVX: " pr_info_nol "* Kernel supports software mitigation by disabling AVX: "
kernel_gds=''
kernel_gds_err=''
if [ -n "$g_kernel_err" ]; then if [ -n "$g_kernel_err" ]; then
kernel_gds_err="$g_kernel_err" kernel_gds_err="$g_kernel_err"
elif grep -q 'gather_data_sampling' "$g_kernel"; then elif grep -q 'gather_data_sampling' "$g_kernel"; then
kernel_gds="found gather_data_sampling in kernel image" kernel_gds="found gather_data_sampling in kernel image"
fi fi
if [ -z "$kernel_gds" ] && [ -r "$opt_config" ]; then
if grep -q '^CONFIG_GDS_FORCE_MITIGATION=y' "$opt_config" ||
grep -q '^CONFIG_MITIGATION_GDS_FORCE=y' "$opt_config" ||
grep -q '^CONFIG_MITIGATION_GDS=y' "$opt_config"; then
kernel_gds="GDS mitigation config option found enabled in kernel config"
fi
fi
if [ -z "$kernel_gds" ] && [ -n "$opt_map" ]; then
if grep -q 'gds_select_mitigation' "$opt_map"; then
kernel_gds="found gds_select_mitigation in System.map"
fi
fi
if [ -n "$kernel_gds" ]; then if [ -n "$kernel_gds" ]; then
pstatus green YES "$kernel_gds" pstatus green YES "$kernel_gds"
elif [ -n "$kernel_gds_err" ]; then elif [ -n "$kernel_gds_err" ]; then
@@ -7502,30 +7610,34 @@ check_CVE_2022_40982_linux() {
if [ -n "$kernel_gds" ]; then if [ -n "$kernel_gds" ]; then
pr_info_nol "* Kernel has disabled AVX as a mitigation: " pr_info_nol "* Kernel has disabled AVX as a mitigation: "
# Check dmesg message to see whether AVX has been disabled if [ "$opt_live" = 1 ]; then
dmesg_grep 'Microcode update needed! Disabling AVX as mitigation' # Check dmesg message to see whether AVX has been disabled
dmesgret=$? dmesg_grep 'Microcode update needed! Disabling AVX as mitigation'
if [ "$dmesgret" -eq 0 ]; then dmesgret=$?
kernel_avx_disabled="AVX disabled by the kernel (dmesg)" if [ "$dmesgret" -eq 0 ]; then
pstatus green YES "$kernel_avx_disabled" kernel_avx_disabled="AVX disabled by the kernel (dmesg)"
elif [ "$cap_avx2" = 0 ]; then
# Find out by ourselves
# cpuinfo says we don't have AVX2, query
# the CPU directly about AVX2 support
read_cpuid 0x7 0x0 "$EBX" 5 1 1
ret=$?
if [ "$ret" -eq "$READ_CPUID_RET_OK" ]; then
kernel_avx_disabled="AVX disabled by the kernel (cpuid)"
pstatus green YES "$kernel_avx_disabled" pstatus green YES "$kernel_avx_disabled"
elif [ "$ret" -eq "$READ_CPUID_RET_KO" ]; then elif [ "$cap_avx2" = 0 ]; then
pstatus yellow NO "CPU doesn't support AVX" # Find out by ourselves
elif [ "$dmesgret" -eq 2 ]; then # cpuinfo says we don't have AVX2, query
pstatus yellow UNKNOWN "dmesg truncated, can't tell whether mitigation is active, please reboot and relaunch this script" # the CPU directly about AVX2 support
read_cpuid 0x7 0x0 "$EBX" 5 1 1
ret=$?
if [ "$ret" -eq "$READ_CPUID_RET_OK" ]; then
kernel_avx_disabled="AVX disabled by the kernel (cpuid)"
pstatus green YES "$kernel_avx_disabled"
elif [ "$ret" -eq "$READ_CPUID_RET_KO" ]; then
pstatus yellow NO "CPU doesn't support AVX"
elif [ "$dmesgret" -eq 2 ]; then
pstatus yellow UNKNOWN "dmesg truncated, can't tell whether mitigation is active, please reboot and relaunch this script"
else
pstatus yellow UNKNOWN "No sign of mitigation in dmesg and couldn't read cpuid info"
fi
else else
pstatus yellow UNKNOWN "No sign of mitigation in dmesg and couldn't read cpuid info" pstatus yellow NO "AVX support is enabled"
fi fi
else else
pstatus yellow NO "AVX support is enabled" pstatus blue N/A "not testable in offline mode"
fi fi
fi fi
@@ -7540,16 +7652,33 @@ check_CVE_2022_40982_linux() {
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 [ -z "$msg" ]; then elif [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test # if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then if [ "$opt_sysfs_only" != 1 ]; then
pvulnstatus "$cve" OK "Your microcode is up to date and mitigation is enabled" if [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then
elif [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 1 ]; then if [ "$opt_paranoid" = 1 ] && [ "$cap_gds_mitg_lock" != 1 ]; then
pvulnstatus "$cve" VULN "Your microcode is up to date but mitigation is disabled" pvulnstatus "$cve" VULN "Microcode mitigation is enabled but not locked"
elif [ -z "$kernel_gds" ]; then explain "In paranoid mode, the GDS mitigation must be locked to prevent a privileged attacker\n " \
pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, and your kernel doesn't support mitigation" "(e.g. in a guest VM) from disabling it. Check your firmware/BIOS for an option to lock the\n " \
elif [ -z "$kernel_avx_disabled" ]; then "GDS mitigation, or update your microcode."
pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, your kernel support the mitigation but the script did not detect AVX as disabled by the kernel" else
pvulnstatus "$cve" OK "Your microcode is up to date and mitigation is enabled"
fi
elif [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 1 ]; then
pvulnstatus "$cve" VULN "Your microcode is up to date but mitigation is disabled"
explain "The GDS mitigation has been explicitly disabled (gather_data_sampling=off or mitigations=off).\n " \
"Remove the kernel parameter to re-enable it."
elif [ -z "$kernel_gds" ]; then
pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, and your kernel doesn't support mitigation"
explain "Update both your CPU microcode (via BIOS/firmware update from your OEM) and your kernel\n " \
"to a version that supports GDS mitigation (Linux 6.5+, or check if your distro has a backport)."
elif [ -z "$kernel_avx_disabled" ]; then
pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, your kernel supports the mitigation but AVX was not disabled"
explain "Update your CPU microcode (via BIOS/firmware update from your OEM). If no microcode update\n " \
"is available, use gather_data_sampling=force on the kernel command line to disable AVX as a workaround."
else
pvulnstatus "$cve" OK "Your microcode doesn't mitigate the vulnerability, but your kernel has disabled AVX support"
fi
else else
pvulnstatus "$cve" OK "Your microcode doesn't mitigate the vulnerability, but your kernel has disabled AVX support" pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi fi
else else
pvulnstatus "$cve" "$status" "$msg" pvulnstatus "$cve" "$status" "$msg"