Files
spectre-meltdown-checker/src/vulns/CVE-2023-20569.sh
T
Stéphane Lesimple ee618ead07 enh: detect IPBP return predictor bypass in Inception/SRSO ("PB-Inception") (#500)
AMD Zen 1-3 CPUs don't flush return predictions on IBPB, allowing
cross-process Spectre attacks even with IBPB-on-entry active. The kernel
fix (v6.12+, backported) adds RSB fill after IBPB on affected CPUs.
Detect this gap by checking CPUID IBPB_RET bit and kernel ibpb_no_ret
bug flag, and flag systems relying on IBPB without the RSB fill fix.
2026-04-08 22:35:52 +02:00

244 lines
13 KiB
Bash

# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2023-20569, Inception, SRSO, Return Address Security
check_CVE_2023_20569() {
check_cve 'CVE-2023-20569'
}
check_CVE_2023_20569_linux() {
local status sys_interface_available msg kernel_sro kernel_sro_err kernel_srso kernel_ibpb_entry kernel_ibpb_no_ret smt_enabled
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/spec_rstack_overflow"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
status=$ret_sys_interface_check_status
# kernels before the fix from dc6306ad5b0d (v6.6-rc6, backported to v6.5.6)
# incorrectly reported "Mitigation: safe RET, no microcode" as mitigated,
# when in fact userspace is still vulnerable because IBPB doesn't flush
# branch type predictions without the extending microcode.
# override the sysfs status in that case.
if echo "$ret_sys_interface_check_fullmsg" | grep -qi 'Mitigation:.*safe RET.*no microcode'; then
status=VULN
msg="Vulnerable: Safe RET, no microcode (your kernel incorrectly reports this as mitigated, it was fixed in more recent kernels)"
fi
# kernels before the IBPB_NO_RET fix (v6.12, backported to v6.11.5/v6.6.58/v6.1.114/v5.15.169/v5.10.228)
# don't fill the RSB after IBPB, so when sysfs reports an IBPB-based mitigation, the return predictor
# can still be poisoned cross-process (PB-Inception). Override sysfs in that case.
if [ "$status" = OK ] && echo "$ret_sys_interface_check_fullmsg" | grep -qi 'IBPB'; then
if [ "$cap_ibpb_ret" != 1 ] && ! grep -q 'ibpb_no_ret' "$g_kernel" 2>/dev/null; then
status=VULN
msg="Vulnerable: IBPB-based mitigation active but kernel lacks return prediction clearing after IBPB (PB-Inception, upgrade to kernel 6.12+)"
fi
fi
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports mitigation: "
if [ -n "$g_kernel_err" ]; then
kernel_sro_err="$g_kernel_err"
elif grep -q 'spec_rstack_overflow' "$g_kernel"; then
kernel_sro="found spec_rstack_overflow in kernel image"
fi
if [ -n "$kernel_sro" ]; then
pstatus green YES "$kernel_sro"
elif [ -n "$kernel_sro_err" ]; then
pstatus yellow UNKNOWN "$kernel_sro_err"
else
pstatus yellow NO
fi
pr_info_nol "* Kernel compiled with SRSO support: "
if [ -r "$opt_config" ]; then
# CONFIG_CPU_SRSO: Linux < 6.9
# CONFIG_MITIGATION_SRSO: Linux >= 6.9
if grep -Eq '^CONFIG_(CPU|MITIGATION)_SRSO=y' "$opt_config"; then
pstatus green YES
kernel_srso="CONFIG_(CPU|MITIGATION)_SRSO=y found in kernel config"
else
pstatus yellow NO "required for safe RET and ibpb_on_vmexit mitigations"
fi
else
# https://github.com/torvalds/linux/commit/138bcddb86d8a4f842e4ed6f0585abc9b1a764ff#diff-17bd24a7a7850613cced545790ac30646097e8d6207348c2bd1845f397acb390R2313
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif grep -Eq 'WARNING: kernel not compiled with (CPU|MITIGATION)_SRSO' "$g_kernel"; then
# this msg is optimized out at compile time if the option is not enabled, see commit referenced above
# if it's present, then SRSO is NOT compiled in
pstatus yellow NO "kernel not compiled with (CPU|MITIGATION)_SRSO"
else
# if it's not present, then SRSO is compiled in IF kernel_sro is set, otherwise we're just
# in front of an old kernel that doesn't have the mitigation logic at all
if [ -n "$kernel_sro" ]; then
kernel_srso="SRSO mitigation logic is compiled in the kernel"
pstatus green OK "$kernel_srso"
else
pstatus yellow NO "your kernel is too old and doesn't have the mitigation logic"
fi
fi
fi
# check whether the running kernel has the corrected SRSO reporting
# (dc6306ad5b0d, v6.6-rc6, backported to v6.5.6): kernels with the fix
# contain the string "Vulnerable: Safe RET, no microcode" in their image,
# while older kernels only have "safe RET" (and append ", no microcode" dynamically).
pr_info_nol "* Kernel has accurate SRSO reporting: "
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif grep -q 'Vulnerable: Safe RET, no microcode' "$g_kernel"; then
pstatus green YES
elif [ -n "$kernel_sro" ]; then
pstatus yellow NO "your kernel reports partial SRSO mitigations as fully mitigated, upgrade recommended"
else
pstatus yellow NO "your kernel is too old and doesn't have the SRSO mitigation logic"
fi
pr_info_nol "* Kernel compiled with IBPB_ENTRY support: "
if [ -r "$opt_config" ]; then
# CONFIG_CPU_IBPB_ENTRY: Linux < 6.9
# CONFIG_MITIGATION_IBPB_ENTRY: Linux >= 6.9
if grep -Eq '^CONFIG_(CPU|MITIGATION)_IBPB_ENTRY=y' "$opt_config"; then
pstatus green YES
kernel_ibpb_entry="CONFIG_(CPU|MITIGATION)_IBPB_ENTRY=y found in kernel config"
else
pstatus yellow NO
fi
else
# https://github.com/torvalds/linux/commit/138bcddb86d8a4f842e4ed6f0585abc9b1a764ff#diff-17bd24a7a7850613cced545790ac30646097e8d6207348c2bd1845f397acb390R2325
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif grep -Eq 'WARNING: kernel not compiled with (CPU|MITIGATION)_IBPB_ENTRY' "$g_kernel"; then
# this msg is optimized out at compile time if the option is not enabled, see commit referenced above
# if it's present, then IBPB_ENTRY is NOT compiled in
pstatus yellow NO "kernel not compiled with (CPU|MITIGATION)_IBPB_ENTRY"
else
# if it's not present, then IBPB_ENTRY is compiled in IF kernel_sro is set, otherwise we're just
# in front of an old kernel that doesn't have the mitigation logic at all
if [ -n "$kernel_sro" ]; then
kernel_ibpb_entry="IBPB_ENTRY mitigation logic is compiled in the kernel"
pstatus green OK "$kernel_ibpb_entry"
else
pstatus yellow NO "your kernel is too old and doesn't have the mitigation logic"
fi
fi
fi
# check whether the kernel is aware of the IBPB return predictor bypass (PB-Inception).
# kernels with the fix (v6.12+, backported) contain the "ibpb_no_ret" bug flag string,
# and add an RSB fill after every IBPB on affected CPUs (Zen 1-3).
pr_info_nol "* Kernel is aware of IBPB return predictor bypass: "
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif grep -q 'ibpb_no_ret' "$g_kernel"; then
kernel_ibpb_no_ret="ibpb_no_ret found in kernel image"
pstatus green YES "$kernel_ibpb_no_ret"
else
pstatus yellow NO
fi
# Zen & Zen2 : if the right IBPB microcode applied + SMT off --> not vuln
if [ "$cpu_family" = $((0x17)) ]; then
pr_info_nol "* CPU supports IBPB: "
if [ -n "$cap_ibpb" ]; then
pstatus green YES "$cap_ibpb"
else
pstatus yellow NO
fi
pr_info_nol "* Hyper-Threading (SMT) is enabled: "
is_cpu_smt_enabled
smt_enabled=$?
if [ "$smt_enabled" = 0 ]; then
pstatus yellow YES
else
pstatus green NO
fi
# Zen 3/4 microcode brings SBPB mitigation
elif [ "$cpu_family" = $((0x19)) ]; then
pr_info_nol "* CPU supports SBPB: "
if [ "$cap_sbpb" = 1 ]; then
pstatus green YES
elif [ "$cap_sbpb" = 3 ]; then
pstatus yellow UNKNOWN "cannot write MSR, rerun with --allow-msr-write"
else
pstatus yellow NO
fi
fi
elif [ "$sys_interface_available" = 0 ]; then
# we have no sysfs but were asked to use it only!
msg="/sys vulnerability interface use forced, but it's not available!"
status=UNK
fi
if ! is_cpu_affected "$cve"; then
# override status & msg in case CPU is not vulnerable after all
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$opt_sysfs_only" != 1 ]; then
# Zen/Zen2
if [ "$cpu_family" = $((0x17)) ]; then
if [ "$smt_enabled" = 0 ]; then
pvulnstatus "$cve" VULN "SMT is enabled on your Zen/Zen2 CPU, which makes mitigation ineffective"
explain "For Zen/Zen2 CPUs, proper mitigation needs an up to date microcode, and SMT needs to be disabled (this can be done by adding \`nosmt\` to your kernel command line)"
elif [ -z "$kernel_sro" ]; then
pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the SRSO mitigation logic"
elif [ -n "$cap_ibpb" ]; then
if [ "$cap_ibpb_ret" != 1 ] && [ -z "$kernel_ibpb_no_ret" ]; then
pvulnstatus "$cve" VULN "IBPB alone doesn't flush return predictions on this CPU, kernel update needed (PB-Inception, fixed in 6.12+)"
else
pvulnstatus "$cve" OK "SMT is disabled and both your kernel and microcode support mitigation"
fi
else
pvulnstatus "$cve" VULN "Your microcode is too old"
fi
# Zen3/Zen4
elif [ "$cpu_family" = $((0x19)) ]; then
if [ -z "$kernel_sro" ]; then
pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the SRSO mitigation logic"
elif [ -z "$kernel_srso" ] && [ -z "$kernel_ibpb_entry" ]; then
pvulnstatus "$cve" VULN "Your kernel doesn't have either SRSO or IBPB_ENTRY compiled-in"
elif [ "$cap_sbpb" = 3 ]; then
pvulnstatus "$cve" UNK "Couldn't verify if your microcode supports IBPB (rerun with --allow-msr-write)"
elif [ "$cap_sbpb" = 2 ]; then
pvulnstatus "$cve" VULN "Your microcode doesn't support SBPB"
else
if [ "$cap_ibpb_ret" != 1 ] && [ -z "$kernel_ibpb_no_ret" ] && [ -n "$kernel_ibpb_entry" ]; then
pvulnstatus "$cve" VULN "IBPB alone doesn't flush return predictions on this CPU, kernel update needed (PB-Inception, fixed in 6.12+)"
else
pvulnstatus "$cve" OK "Your kernel and microcode both support mitigation"
fi
fi
else
# not supposed to happen, as normally this CPU should not be affected and not run this code
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
fi
else
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
pvulnstatus "$cve" "$status" "$msg"
if echo "$msg" | grep -qi 'your kernel incorrectly reports this as mitigated'; then
explain "Your kernel's /sys interface reports 'Mitigation: safe RET, no microcode' for the SRSO vulnerability.\n" \
"This was a bug in the kernel's reporting (fixed in v6.5.6/v6.6-rc6, commit dc6306ad5b0d):\n" \
"the Safe RET mitigation alone only protects the kernel from userspace attacks, but without\n" \
"the IBPB-extending microcode, userspace itself remains vulnerable because IBPB doesn't flush\n" \
"branch type predictions. Newer kernels correctly report this as 'Vulnerable: Safe RET, no microcode'.\n" \
"To fully mitigate, you need both the Safe RET kernel support AND an updated CPU microcode.\n" \
"Updating your kernel to v6.5.6+ or v6.6+ will also give you accurate vulnerability reporting."
fi
fi
}
check_CVE_2023_20569_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
}