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
This commit is contained in:
Stéphane Lesimple
2026-04-02 19:55:25 +02:00
parent 37204869f8
commit 5e3033e2f5
4 changed files with 256 additions and 46 deletions

View File

@@ -126,6 +126,14 @@ 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
# 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
# Zhaoxin vendor_id is " Shanghai " in cpuinfo (parsed as "Shanghai" by awk)
if { [ "$cpu_vendor" = "CentaurHauls" ] || [ "$cpu_vendor" = "Shanghai" ]; } && [ "$cpu_family" = 7 ]; then
_infer_immune variant2
pr_debug "is_cpu_affected: Centaur/Zhaoxin family 7 immune to Spectre V2 (NO_SPECTRE_V2)"
fi
if is_cpu_specex_free; then if is_cpu_specex_free; then
_set_immune variant1 _set_immune variant1
_set_immune variant2 _set_immune variant2
@@ -222,9 +230,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" ] ||
@@ -239,10 +250,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

View File

@@ -27,6 +27,13 @@ is_cpu_specex_free() {
return 0 return 0
fi fi
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 [ "$cpu_family" = 4 ] && return 0
return 1 return 1
} }

View File

@@ -1,14 +1,12 @@
# vim: set ts=4 sw=4 sts=4 et: # vim: set ts=4 sw=4 sts=4 et:
################### ###############################
# SPECTRE 2 SECTION # CVE-2017-5715, Spectre V2, Branch Target Injection
# CVE-2017-5715 Spectre Variant 2 (branch target injection) - entry point
# Sets: vulnstatus # Sets: vulnstatus
check_CVE_2017_5715() { check_CVE_2017_5715() {
check_cve 'CVE-2017-5715' check_cve 'CVE-2017-5715'
} }
# CVE-2017-5715 Spectre Variant 2 (branch target injection) - Linux mitigation check
# Sets: g_ibrs_can_tell, g_ibrs_supported, g_ibrs_enabled, g_ibrs_fw_enabled, # Sets: g_ibrs_can_tell, g_ibrs_supported, g_ibrs_enabled, g_ibrs_fw_enabled,
# g_ibpb_can_tell, g_ibpb_supported, g_ibpb_enabled, g_specex_knob_dir # g_ibpb_can_tell, g_ibpb_supported, g_ibpb_enabled, g_specex_knob_dir
check_CVE_2017_5715_linux() { check_CVE_2017_5715_linux() {
@@ -208,6 +206,43 @@ check_CVE_2017_5715_linux() {
# rocky9 (RHEL 9, kernel 5.14): matches mainline. Semicolons, BHI, all fields. # rocky9 (RHEL 9, kernel 5.14): matches mainline. Semicolons, BHI, all fields.
# rocky10 (RHEL 10, kernel 6.12): matches mainline. # rocky10 (RHEL 10, kernel 6.12): matches mainline.
# #
#
# --- Kconfig symbols ---
# 76b043848fd2 (v4.15-rc8): CONFIG_RETPOLINE
# f43b9876e857 (v5.19-rc7): CONFIG_CPU_IBRS_ENTRY (kernel IBRS on entry)
# aefb2f2e619b (v6.9-rc1): renamed CONFIG_RETPOLINE => CONFIG_MITIGATION_RETPOLINE
# 1da8d2172ce5 (v6.9-rc1): renamed CONFIG_CPU_IBRS_ENTRY => CONFIG_MITIGATION_IBRS_ENTRY
# ec9404e40e8f (v6.9-rc4): CONFIG_SPECTRE_BHI_ON / CONFIG_SPECTRE_BHI_OFF
# 4f511739c54b (v6.9-rc4): replaced by CONFIG_MITIGATION_SPECTRE_BHI
# 72c70f480a70 (v6.12-rc1): CONFIG_MITIGATION_SPECTRE_V2 (top-level on/off)
# 8754e67ad4ac (v6.15-rc7): CONFIG_MITIGATION_ITS (indirect target selection)
# stable 5.4.y-6.6.y: CONFIG_RETPOLINE (pre-rename)
# stable 6.12.y: CONFIG_MITIGATION_RETPOLINE, CONFIG_MITIGATION_SPECTRE_V2
#
# --- kernel functions (for $opt_map / System.map) ---
# da285121560e (v4.15-rc8): spectre_v2_select_mitigation(),
# spectre_v2_parse_cmdline(), nospectre_v2_parse_cmdline()
# 20ffa1caecca (v4.16-rc1): spectre_v2_module_string(), retpoline_module_ok()
# a8f76ae41cd6 (v4.20-rc5): spectre_v2_user_select_mitigation(),
# spectre_v2_user_parse_cmdline()
# 7c693f54c873 (v5.19-rc7): spectre_v2_in_ibrs_mode(), spectre_v2_in_eibrs_mode()
# 44a3918c8245 (v5.17-rc8): spectre_v2_show_state()
# 480e803dacf8 (v6.16-rc1): split into spectre_v2_select_mitigation() +
# spectre_v2_apply_mitigation() + spectre_v2_update_mitigation() +
# spectre_v2_user_apply_mitigation() + spectre_v2_user_update_mitigation()
#
# --- CPU affection logic (for is_cpu_affected) ---
# X86_BUG_SPECTRE_V2 is set for ALL x86 CPUs except:
# - CPUs matching NO_SPECULATION: family 4 (all vendors), Centaur/Intel/NSC/Vortex
# family 5, Intel Atom Bonnell/Saltwell
# - CPUs matching NO_SPECTRE_V2: Centaur family 7, Zhaoxin family 7
# 99c6fa2511d8 (v4.15-rc8): unconditional for all x86 CPUs
# 1e41a766c98b (v5.6-rc1): added NO_SPECTRE_V2 exemption for Centaur/Zhaoxin
# 98c7a713db91 (v6.15-rc1): added X86_BUG_SPECTRE_V2_USER as separate bit
# No MSR/CPUID immunity bits — purely whitelist-based.
# vendor scope: all x86 vendors affected (Intel, AMD, Hygon, etc.)
# except Centaur family 7 and Zhaoxin family 7.
#
# all messages start with either "Not affected", "Mitigation", or "Vulnerable" # all messages start with either "Not affected", "Mitigation", or "Vulnerable"
fi fi
if [ "$opt_sysfs_only" != 1 ]; then if [ "$opt_sysfs_only" != 1 ]; then
@@ -332,6 +367,19 @@ check_CVE_2017_5715_linux() {
if grep -q spec_ctrl "$opt_map"; then if grep -q spec_ctrl "$opt_map"; then
g_ibrs_supported="found spec_ctrl in symbols file" g_ibrs_supported="found spec_ctrl in symbols file"
pr_debug "ibrs: found '*spec_ctrl*' symbol in $opt_map" pr_debug "ibrs: found '*spec_ctrl*' symbol in $opt_map"
elif grep -q -e spectre_v2_select_mitigation -e spectre_v2_apply_mitigation "$opt_map"; then
# spectre_v2_select_mitigation exists since v4.15; split into
# spectre_v2_select_mitigation + spectre_v2_apply_mitigation in v6.16
g_ibrs_supported="found spectre_v2 mitigation function in symbols file"
pr_debug "ibrs: found spectre_v2_*_mitigation symbol in $opt_map"
fi
fi
# CONFIG_CPU_IBRS_ENTRY (v5.19) / CONFIG_MITIGATION_IBRS_ENTRY (v6.9): kernel IBRS on entry
if [ -z "$g_ibrs_supported" ] && [ -n "$opt_config" ] && [ -r "$opt_config" ]; then
g_ibrs_can_tell=1
if grep -q '^CONFIG_\(CPU_\|MITIGATION_\)IBRS_ENTRY=y' "$opt_config"; then
g_ibrs_supported="CONFIG_CPU_IBRS_ENTRY/CONFIG_MITIGATION_IBRS_ENTRY found in kernel config"
pr_debug "ibrs: found IBRS entry config option in $opt_config"
fi fi
fi fi
# recent (4.15) vanilla kernels have IBPB but not IBRS, and without the debugfs tunables of Red Hat # recent (4.15) vanilla kernels have IBPB but not IBRS, and without the debugfs tunables of Red Hat
@@ -579,7 +627,7 @@ check_CVE_2017_5715_linux() {
rsb_filling=0 rsb_filling=0
if [ "$opt_live" = 1 ] && [ "$opt_no_sysfs" != 1 ]; then if [ "$opt_live" = 1 ] && [ "$opt_no_sysfs" != 1 ]; then
# if we're live and we aren't denied looking into /sys, let's do it # if we're live and we aren't denied looking into /sys, let's do it
if echo "$msg" | grep -qw RSB; then if echo "$ret_sys_interface_check_fullmsg" | grep -qw RSB; then
rsb_filling=1 rsb_filling=1
pstatus green YES pstatus green YES
fi fi
@@ -679,6 +727,11 @@ check_CVE_2017_5715_linux() {
*) pstatus yellow UNKNOWN ;; *) pstatus yellow UNKNOWN ;;
esac esac
# --- SMT state (used in STIBP inference and verdict) ---
is_cpu_smt_enabled
smt_enabled=$?
# smt_enabled: 0=enabled, 1=disabled, 2=unknown
# --- v2_stibp_status --- # --- v2_stibp_status ---
pr_info_nol " * STIBP status: " pr_info_nol " * STIBP status: "
if [ -n "$ret_sys_interface_check_fullmsg" ]; then if [ -n "$ret_sys_interface_check_fullmsg" ]; then
@@ -821,11 +874,6 @@ check_CVE_2017_5715_linux() {
fi fi
fi fi
# --- SMT state (used in verdict) ---
is_cpu_smt_enabled
smt_enabled=$?
# smt_enabled: 0=enabled, 1=disabled, 2=unknown
elif [ "$sys_interface_available" = 0 ]; then elif [ "$sys_interface_available" = 0 ]; then
# we have no sysfs but were asked to use it only! # we have no sysfs but were asked to use it only!
msg="/sys vulnerability interface use forced, but it's not available!" msg="/sys vulnerability interface use forced, but it's not available!"
@@ -840,6 +888,8 @@ check_CVE_2017_5715_linux() {
# --- own logic using Phase 2 variables --- # --- own logic using Phase 2 variables ---
# Helper: collect caveats for the verdict message # Helper: collect caveats for the verdict message
_v2_caveats='' _v2_caveats=''
# Append a caveat string to the _v2_caveats list
# Callers: check_CVE_2017_5715_linux (eIBRS, IBRS, retpoline verdict paths)
_v2_add_caveat() { _v2_caveats="${_v2_caveats:+$_v2_caveats; }$1"; } _v2_add_caveat() { _v2_caveats="${_v2_caveats:+$_v2_caveats; }$1"; }
# ARM branch predictor hardening (unchanged) # ARM branch predictor hardening (unchanged)
@@ -1107,6 +1157,9 @@ check_CVE_2017_5715_linux() {
pvulnstatus "$cve" OK "offline mode: kernel supports IBRS + IBPB to mitigate the vulnerability" pvulnstatus "$cve" OK "offline mode: kernel supports IBRS + IBPB to mitigate the vulnerability"
elif [ "$cap_ibrs_all" = 1 ] || [ "$cap_autoibrs" = 1 ]; then elif [ "$cap_ibrs_all" = 1 ] || [ "$cap_autoibrs" = 1 ]; then
pvulnstatus "$cve" OK "offline mode: CPU supports Enhanced / Automatic IBRS" pvulnstatus "$cve" OK "offline mode: CPU supports Enhanced / Automatic IBRS"
# CONFIG_MITIGATION_SPECTRE_V2 (v6.12+): top-level on/off for all Spectre V2 mitigations
elif [ -n "$opt_config" ] && [ -r "$opt_config" ] && grep -q '^CONFIG_MITIGATION_SPECTRE_V2=y' "$opt_config"; then
pvulnstatus "$cve" OK "offline mode: kernel has Spectre V2 mitigation framework enabled (CONFIG_MITIGATION_SPECTRE_V2)"
elif [ "$g_ibrs_can_tell" != 1 ]; then elif [ "$g_ibrs_can_tell" != 1 ]; then
pvulnstatus "$cve" UNK "offline mode: not enough information" pvulnstatus "$cve" UNK "offline mode: not enough information"
explain "Re-run this script with root privileges, and give it the kernel image (--kernel), the kernel configuration (--config) and the System.map file (--map) corresponding to the kernel you would like to inspect." explain "Re-run this script with root privileges, and give it the kernel image (--kernel), the kernel configuration (--config) and the System.map file (--map) corresponding to the kernel you would like to inspect."
@@ -1137,7 +1190,6 @@ check_CVE_2017_5715_linux() {
fi fi
} }
# CVE-2017-5715 Spectre Variant 2 (branch target injection) - BSD mitigation check
# Sets: vulnstatus # Sets: vulnstatus
check_CVE_2017_5715_bsd() { check_CVE_2017_5715_bsd() {
local ibrs_disabled ibrs_active retpoline nb_thunks local ibrs_disabled ibrs_active retpoline nb_thunks

View File

@@ -17,22 +17,132 @@ 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
# Override: when the kernel says "Unknown: Dependent on hypervisor status", it
# gave up because it's running as a VM guest and can't read MCU_OPT_CTRL.
# We can often do better: the hypervisor may have exposed GDS_NO or GDS_CTRL
# to us via ARCH_CAPABILITIES, so let our own Phase 2 checks take over.
if echo "$ret_sys_interface_check_fullmsg" | grep -qi 'Dependent on hypervisor'; then
status=UNK
fi
fi fi
if [ "$opt_sysfs_only" != 1 ]; then if [ "$opt_sysfs_only" != 1 ]; then
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
@@ -44,6 +154,7 @@ 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: "
if [ "$opt_live" = 1 ]; then
# Check dmesg message to see whether AVX has been disabled # Check dmesg message to see whether AVX has been disabled
dmesg_grep 'Microcode update needed! Disabling AVX as mitigation' dmesg_grep 'Microcode update needed! Disabling AVX as mitigation'
dmesgret=$? dmesgret=$?
@@ -69,6 +180,9 @@ check_CVE_2022_40982_linux() {
else else
pstatus yellow NO "AVX support is enabled" pstatus yellow NO "AVX support is enabled"
fi fi
else
pstatus blue N/A "not testable in offline mode"
fi
fi fi
elif [ "$sys_interface_available" = 0 ]; then elif [ "$sys_interface_available" = 0 ]; then
@@ -82,17 +196,41 @@ 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 [ "$opt_sysfs_only" != 1 ]; then
if [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then if [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then
if [ "$opt_paranoid" = 1 ] && [ "$cap_gds_mitg_lock" != 1 ]; then
pvulnstatus "$cve" VULN "Microcode mitigation is enabled but not locked"
explain "In paranoid mode, the GDS mitigation must be locked to prevent a privileged attacker\n " \
"(e.g. in a guest VM) from disabling it. Check your firmware/BIOS for an option to lock the\n " \
"GDS mitigation, or update your microcode."
else
pvulnstatus "$cve" OK "Your microcode is up to date and mitigation is enabled" 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 elif [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 1 ]; then
pvulnstatus "$cve" VULN "Your microcode is up to date but mitigation is disabled" 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 [ "$sys_interface_available" = 1 ] &&
echo "$ret_sys_interface_check_fullmsg" | grep -qi 'Dependent on hypervisor'; then
# We're in a VM guest, the kernel gave up, and we couldn't read the
# GDS MSR bits either (cap_gds_ctrl != 1). We genuinely can't tell.
pvulnstatus "$cve" UNK "Running in a VM, mitigation depends on the hypervisor"
explain "This system is running as a virtual machine guest. GDS mitigation must be handled by\n " \
"the host hypervisor. Contact your VM/cloud provider to verify that GDS is mitigated on the host."
elif [ -z "$kernel_gds" ]; then elif [ -z "$kernel_gds" ]; then
pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, and your kernel doesn't support mitigation" 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 elif [ -z "$kernel_avx_disabled" ]; then
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" 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 else
pvulnstatus "$cve" OK "Your microcode doesn't mitigate the vulnerability, but your kernel has disabled AVX support" pvulnstatus "$cve" OK "Your microcode doesn't mitigate the vulnerability, but your kernel has disabled AVX support"
fi fi
else
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else else
pvulnstatus "$cve" "$status" "$msg" pvulnstatus "$cve" "$status" "$msg"
fi fi