feat: add CVE-2023-20588 (AMD DIV0 bug) (#473)

This commit is contained in:
Stéphane Lesimple
2026-04-06 02:40:09 +02:00
parent 53c45e3363
commit 3d01978cd4
6 changed files with 192 additions and 4 deletions

169
src/vulns/CVE-2023-20588.sh Normal file
View File

@@ -0,0 +1,169 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2023-20588, DIV0, AMD Division by Zero Speculative Data Leak
check_CVE_2023_20588() {
check_cve 'CVE-2023-20588'
}
# shellcheck disable=SC2034
_cve_2023_20588_pvulnstatus_smt() {
# common logic for both live (cpuinfo) and live (kernel image fallback) paths:
# if --paranoid and SMT is on, report VULN; otherwise OK.
# $1 = mitigation detail message
if [ "$opt_paranoid" != 1 ] || ! is_cpu_smt_enabled; then
pvulnstatus "$cve" OK "Mitigation: amd_clear_divider on exit to user/guest"
else
pvulnstatus "$cve" VULN "DIV0 mitigation is active but SMT is enabled, data leak possible between sibling threads"
explain "Disable SMT (Simultaneous Multi-Threading) for full protection against DIV0.\n " \
"The kernel mitigation only covers kernel-to-user and host-to-guest leak paths, not cross-SMT-thread leaks.\n " \
"You can disable SMT by booting with the \`nosmt\` kernel parameter, or at runtime:\n " \
"\`echo off > /sys/devices/system/cpu/smt/control\`"
fi
}
# shellcheck disable=SC2034
_cve_2023_20588_pvulnstatus_no_kernel() {
pvulnstatus "$cve" VULN "your kernel doesn't support DIV0 mitigation"
explain "Update your kernel to a version that includes the amd_clear_divider mitigation (Linux >= 6.5 or a backported stable/vendor kernel).\n " \
"The kernel fix adds a dummy division on every exit to userspace and before VMRUN, preventing stale quotient data from leaking.\n " \
"Also disable SMT for full protection, as the mitigation doesn't cover cross-SMT-thread leaks."
}
check_CVE_2023_20588_linux() {
local status sys_interface_available msg kernel_mitigated cpuinfo_div0 dmesg_div0 ret
status=UNK
sys_interface_available=0
msg=''
# No sysfs interface exists for this CVE (no /sys/devices/system/cpu/vulnerabilities/div0).
# sys_interface_available stays 0.
#
# Kernel source inventory for CVE-2023-20588 (DIV0), traced via git blame:
#
# --- sysfs messages ---
# none: this vulnerability has no sysfs entry
#
# --- Kconfig symbols ---
# none: the mitigation is unconditional, not configurable (no CONFIG_* knob)
#
# --- kernel functions (for $opt_map / System.map) ---
# 77245f1c3c64 (v6.5, initial fix): amd_clear_divider()
# initially called from exc_divide_error() (#DE handler)
# f58d6fbcb7c8 (v6.5, follow-up fix): moved amd_clear_divider() call to
# exit-to-userspace path and before VMRUN (SVM)
# bfff3c6692ce (v6.8): moved DIV0 detection from model range check to
# unconditional in init_amd_zen1()
# 501bd734f933 (v6.11): amd_clear_divider() made __always_inline
# (may no longer appear in System.map on newer kernels)
#
# --- dmesg ---
# 77245f1c3c64 (v6.5): "AMD Zen1 DIV0 bug detected. Disable SMT for full protection."
# (present since the initial fix, printed via pr_notice_once)
#
# --- /proc/cpuinfo bugs field ---
# 77245f1c3c64 (v6.5): X86_BUG_DIV0 mapped to "div0" in bugs field
#
# --- CPU affection logic (for is_cpu_affected) ---
# 77245f1c3c64 (v6.5, initial model list):
# AMD: family 0x17 models 0x00-0x2f, 0x50-0x5f
# bfff3c6692ce (v6.8): moved to init_amd_zen1(), unconditional for all Zen1
# (same model ranges, just different detection path)
# vendor scope: AMD only (Zen1 microarchitecture)
#
# --- stable backports ---
# 5.10.y, 5.15.y, 6.1.y, 6.4.y: backported via cpu_has_amd_erratum() path
# (same as mainline v6.5 initial implementation)
# 6.5.y, 6.7.y: same erratum-table detection as mainline v6.5
# 6.6.y: stable-specific commit 824549816609 backported the init_amd_zen1()
# move (equivalent to mainline bfff3c6692ce but adapted to 6.6 context)
# 6.8.y, 6.9.y, 6.10.y: carry mainline bfff3c6692ce directly
# 6.7.y missed the init_amd_zen1() move (EOL before backport landed)
# 501bd734f933 (__always_inline) was NOT backported to any stable branch
# 4.14.y, 4.19.y, 5.4.y: do NOT have the fix (EOL or not backported)
# no stable-specific string or behavior differences; all branches use the
# same dmesg message and /proc/cpuinfo bugs field as mainline
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports DIV0 mitigation: "
kernel_mitigated=''
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif grep -q 'amd_clear_divider' "$g_kernel"; then
kernel_mitigated="found amd_clear_divider in kernel image"
pstatus green YES "$kernel_mitigated"
elif [ -n "$opt_map" ] && grep -q 'amd_clear_divider' "$opt_map"; then
kernel_mitigated="found amd_clear_divider in System.map"
pstatus green YES "$kernel_mitigated"
else
pstatus yellow NO
fi
pr_info_nol "* DIV0 mitigation enabled and active: "
cpuinfo_div0=''
dmesg_div0=''
if [ "$opt_live" = 1 ]; then
if [ -e "$g_procfs/cpuinfo" ] && grep -qw 'div0' "$g_procfs/cpuinfo" 2>/dev/null; then
cpuinfo_div0=1
pstatus green YES "div0 found in $g_procfs/cpuinfo bug flags"
else
# cpuinfo flag not found, fall back to dmesg
dmesg_grep 'AMD Zen1 DIV0 bug detected'
ret=$?
if [ "$ret" -eq 0 ]; then
dmesg_div0=1
pstatus green YES "DIV0 bug detected message found in dmesg"
elif [ "$ret" -eq 2 ]; then
pstatus yellow UNKNOWN "dmesg truncated, cannot check for DIV0 message"
else
pstatus yellow NO "div0 not found in $g_procfs/cpuinfo bug flags or dmesg"
fi
fi
else
pstatus blue N/A "not testable in offline mode"
fi
pr_info_nol "* SMT (Simultaneous Multi-Threading) status: "
is_cpu_smt_enabled
elif [ "$sys_interface_available" = 0 ]; then
msg="/sys vulnerability interface use forced, but it's not available!"
status=UNK
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -z "$msg" ]; then
if [ "$opt_sysfs_only" != 1 ]; then
if [ "$opt_live" = 1 ]; then
# live mode: cpuinfo div0 flag is the strongest proof the mitigation is active
if [ "$cpuinfo_div0" = 1 ] || [ "$dmesg_div0" = 1 ]; then
_cve_2023_20588_pvulnstatus_smt
elif [ -n "$kernel_mitigated" ]; then
# kernel has the code but the bug flag is not set, it shouldn't happen on affected CPUs,
# but if it does, trust the kernel image evidence
_cve_2023_20588_pvulnstatus_smt
else
_cve_2023_20588_pvulnstatus_no_kernel
fi
else
# offline mode: only kernel image / System.map evidence is available
if [ -n "$kernel_mitigated" ]; then
pvulnstatus "$cve" OK "Mitigation: amd_clear_divider found in kernel image"
else
_cve_2023_20588_pvulnstatus_no_kernel
fi
fi
else
pvulnstatus "$cve" "$status" "no sysfs interface available for this CVE, use --no-sysfs to check"
fi
else
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2023_20588_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
}