mirror of
https://github.com/speed47/spectre-meltdown-checker.git
synced 2026-04-23 09:03:19 +02:00
Compare commits
8 Commits
3f60773ec4
...
c0a389b086
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0a389b086 | ||
|
|
726f9e54f5 | ||
|
|
11210ab772 | ||
|
|
624aef4a46 | ||
|
|
b6a7ee2345 | ||
|
|
5698711b3d | ||
|
|
e0f9aeab81 | ||
|
|
2f550ba8cd |
2
.github/workflows/expected_cve_count
vendored
2
.github/workflows/expected_cve_count
vendored
@@ -1 +1 @@
|
||||
27
|
||||
28
|
||||
|
||||
@@ -26,6 +26,7 @@ CVE | Name | Aliases
|
||||
[CVE-2022-29901](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-29901) | Arbitrary Speculative Code Execution with Return Instructions | Retbleed (Intel), RSBA
|
||||
[CVE-2022-40982](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-40982) | Gather Data Sampling | Downfall, GDS
|
||||
[CVE-2023-20569](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-20569) | Return Address Security | Inception, SRSO
|
||||
[CVE-2023-20588](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-20588) | AMD Division by Zero Speculative Data Leak | DIV0
|
||||
[CVE-2023-20593](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-20593) | Cross-Process Information Leak | Zenbleed
|
||||
[CVE-2023-23583](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-23583) | Redundant Prefix Issue | Reptar
|
||||
[CVE-2023-28746](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-28746) | Register File Data Sampling | RFDS
|
||||
@@ -61,6 +62,7 @@ CVE-2022-29900 (Retbleed AMD) | 💥 | ✅ | 💥 | ✅ | Kernel update (+ micro
|
||||
CVE-2022-29901 (Retbleed Intel, RSBA) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update (eIBRS or IBRS)
|
||||
CVE-2022-40982 (Downfall, GDS) | 💥 | 💥 | 💥 | 💥 | Microcode update (or disable AVX)
|
||||
CVE-2023-20569 (Inception, SRSO) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update
|
||||
CVE-2023-20588 (DIV0) | 💥 | 💥 (1) | 💥 | 💥 (1) | Kernel update (+ disable SMT)
|
||||
CVE-2023-20593 (Zenbleed) | 💥 | 💥 | 💥 | 💥 | Microcode update (or kernel workaround)
|
||||
CVE-2023-23583 (Reptar) | ☠️ | ☠️ | ☠️ | ☠️ | Microcode update
|
||||
CVE-2023-28746 (RFDS) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update
|
||||
@@ -159,6 +161,10 @@ The AVX GATHER instructions can leak data from previously used vector registers
|
||||
|
||||
On AMD Zen 1 through Zen 4 processors, an attacker can manipulate the return address predictor to redirect speculative execution on return instructions, leaking kernel memory. Mitigation requires both a kernel update (providing SRSO safe-return sequences or IBPB-on-entry) and a microcode update (providing SBPB on Zen 3/4, or IBPB support on Zen 1/2 — which additionally requires SMT to be disabled). Performance impact ranges from low to significant depending on the chosen mitigation and CPU generation.
|
||||
|
||||
**CVE-2023-20588 — AMD Division by Zero Speculative Data Leak (DIV0)**
|
||||
|
||||
On AMD Zen 1 processors, a #DE (divide-by-zero) exception can leave stale quotient data from a previous division in the divider unit, observable by a subsequent division via speculative side channels. This can leak data across any privilege boundary, including between SMT sibling threads sharing the same physical core. Mitigation requires a kernel update (Linux 6.5+) that adds a dummy division (`amd_clear_divider()`) on every exit to userspace and before VMRUN, preventing stale data from persisting. No microcode update is needed. Disabling SMT provides additional protection because the kernel mitigation does not cover cross-SMT-thread leaks. Performance impact is negligible.
|
||||
|
||||
**CVE-2023-20593 — Cross-Process Information Leak (Zenbleed)**
|
||||
|
||||
A bug in AMD Zen 2 processors causes the VZEROUPPER instruction to incorrectly zero register files during speculative execution, leaving stale data from other processes observable in vector registers. This can leak data across any privilege boundary, including from the kernel and other processes, at rates up to 30 KB/s per core. Mitigation is available either through a microcode update that fixes the bug, or through a kernel workaround that sets the FP_BACKUP_FIX bit (bit 9) in the DE_CFG MSR, disabling the faulty optimization. Either approach alone is sufficient. Performance impact is negligible.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#
|
||||
# Stephane Lesimple
|
||||
#
|
||||
VERSION='26.28.0405929'
|
||||
VERSION='26.29.0406065'
|
||||
|
||||
# --- Common paths and basedirs ---
|
||||
readonly VULN_SYSFS_BASE="/sys/devices/system/cpu/vulnerabilities"
|
||||
@@ -211,6 +211,7 @@ CVE-2019-11091|MDSUM|mdsum|RIDL, microarchitectural data sampling uncacheable me
|
||||
CVE-2019-11135|TAA|taa|ZombieLoad V2, TSX Asynchronous Abort (TAA)
|
||||
CVE-2018-12207|ITLBMH|itlbmh|No eXcuses, iTLB Multihit, machine check exception on page size changes (MCEPSC)
|
||||
CVE-2020-0543|SRBDS|srbds|Special Register Buffer Data Sampling (SRBDS)
|
||||
CVE-2023-20588|DIV0|div0|Division by Zero, AMD Zen1 speculative data leak
|
||||
CVE-2023-20593|ZENBLEED|zenbleed|Zenbleed, cross-process information leak
|
||||
CVE-2022-40982|DOWNFALL|downfall|Downfall, gather data sampling (GDS)
|
||||
CVE-2022-29900|RETBLEED AMD|retbleed|Retbleed, arbitrary speculative code execution with return instructions (AMD)
|
||||
@@ -585,7 +586,8 @@ is_cpu_affected() {
|
||||
affected_itlbmh=''
|
||||
affected_srbds=''
|
||||
affected_sls=''
|
||||
# Zenbleed and Inception are both AMD specific, look for "is_amd" below:
|
||||
# DIV0, Zenbleed and Inception are all AMD specific, look for "is_amd" below:
|
||||
_set_immune div0
|
||||
_set_immune zenbleed
|
||||
_set_immune inception
|
||||
# TSA is AMD specific (Zen 3/4), look for "is_amd" below:
|
||||
@@ -1072,6 +1074,13 @@ is_cpu_affected() {
|
||||
fi
|
||||
_set_immune variantl1tf
|
||||
|
||||
# DIV0 (Zen1 only)
|
||||
# 77245f1c3c64 (v6.5, initial model list): family 0x17 models 0x00-0x2f, 0x50-0x5f
|
||||
# bfff3c6692ce (v6.8): moved to init_amd_zen1(), unconditional for all Zen1
|
||||
# All Zen1 CPUs are family 0x17, models 0x00-0x2f and 0x50-0x5f
|
||||
amd_legacy_erratum "$(amd_model_range 0x17 0x00 0x0 0x2f 0xf)" && _set_vuln div0
|
||||
amd_legacy_erratum "$(amd_model_range 0x17 0x50 0x0 0x5f 0xf)" && _set_vuln div0
|
||||
|
||||
# Zenbleed
|
||||
amd_legacy_erratum "$(amd_model_range 0x17 0x30 0x0 0x4f 0xf)" && _set_vuln zenbleed
|
||||
amd_legacy_erratum "$(amd_model_range 0x17 0x60 0x0 0x7f 0xf)" && _set_vuln zenbleed
|
||||
@@ -1281,7 +1290,7 @@ is_cpu_affected() {
|
||||
pr_debug "is_cpu_affected: final results: variant1=$affected_variant1 variant2=$affected_variant2 variant3=$affected_variant3 variant3a=$affected_variant3a"
|
||||
pr_debug "is_cpu_affected: final results: variant4=$affected_variant4 variantl1tf=$affected_variantl1tf msbds=$affected_msbds mfbds=$affected_mfbds"
|
||||
pr_debug "is_cpu_affected: final results: mlpds=$affected_mlpds mdsum=$affected_mdsum taa=$affected_taa itlbmh=$affected_itlbmh srbds=$affected_srbds"
|
||||
pr_debug "is_cpu_affected: final results: zenbleed=$affected_zenbleed inception=$affected_inception retbleed=$affected_retbleed tsa=$affected_tsa downfall=$affected_downfall reptar=$affected_reptar rfds=$affected_rfds its=$affected_its"
|
||||
pr_debug "is_cpu_affected: final results: div0=$affected_div0 zenbleed=$affected_zenbleed inception=$affected_inception retbleed=$affected_retbleed tsa=$affected_tsa downfall=$affected_downfall reptar=$affected_reptar rfds=$affected_rfds its=$affected_its"
|
||||
pr_debug "is_cpu_affected: final results: vmscape=$affected_vmscape bpi=$affected_bpi sls=$affected_sls"
|
||||
}
|
||||
affected_variantl1tf_sgx="$affected_variantl1tf"
|
||||
@@ -1440,7 +1449,7 @@ is_cpu_srbds_free() {
|
||||
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
|
||||
if [ "$cap_mds_no" -eq 1 ] && { [ "$cap_rtm" -eq 0 ] || [ "$cap_tsx_ctrl_rtm_disable" -eq 1 ] || [ "$cap_tsx_force_abort_rtm_disable" -eq 1 ]; }; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
@@ -1890,7 +1899,7 @@ while [ -n "${1:-}" ]; do
|
||||
case "$2" in
|
||||
help)
|
||||
echo "The following parameters are supported for --variant (can be used multiple times):"
|
||||
echo "1, 2, 3, 3a, 4, msbds, mfbds, mlpds, mdsum, l1tf, taa, mcepsc, srbds, zenbleed, downfall, retbleed, inception, reptar, rfds, tsa, tsa-sq, tsa-l1, its, vmscape, bpi, sls"
|
||||
echo "1, 2, 3, 3a, 4, msbds, mfbds, mlpds, mdsum, l1tf, taa, mcepsc, srbds, div0, zenbleed, downfall, retbleed, inception, reptar, rfds, tsa, tsa-sq, tsa-l1, its, vmscape, bpi, sls"
|
||||
exit 0
|
||||
;;
|
||||
1)
|
||||
@@ -1945,6 +1954,10 @@ while [ -n "${1:-}" ]; do
|
||||
opt_cve_list="$opt_cve_list CVE-2020-0543"
|
||||
opt_cve_all=0
|
||||
;;
|
||||
div0)
|
||||
opt_cve_list="$opt_cve_list CVE-2023-20588"
|
||||
opt_cve_all=0
|
||||
;;
|
||||
zenbleed)
|
||||
opt_cve_list="$opt_cve_list CVE-2023-20593"
|
||||
opt_cve_all=0
|
||||
@@ -2758,6 +2771,7 @@ write_msr_one_core() {
|
||||
readonly MSR_IA32_PLATFORM_ID=0x17
|
||||
readonly MSR_IA32_SPEC_CTRL=0x48
|
||||
readonly MSR_IA32_ARCH_CAPABILITIES=0x10a
|
||||
readonly MSR_IA32_TSX_FORCE_ABORT=0x10f
|
||||
readonly MSR_IA32_TSX_CTRL=0x122
|
||||
readonly MSR_IA32_MCU_OPT_CTRL=0x123
|
||||
readonly READ_MSR_RET_OK=0
|
||||
@@ -3029,21 +3043,25 @@ parse_cpu_details() {
|
||||
if [ -z "$cpu_ucode" ] && [ "$g_os" != Linux ]; then
|
||||
load_cpuid
|
||||
if [ -e ${BSD_CPUCTL_DEV_BASE}0 ]; then
|
||||
# init MSR with NULLs
|
||||
cpucontrol -m 0x8b=0 ${BSD_CPUCTL_DEV_BASE}0
|
||||
# call CPUID
|
||||
cpucontrol -i 1 ${BSD_CPUCTL_DEV_BASE}0 >/dev/null
|
||||
# read MSR
|
||||
cpu_ucode=$(cpucontrol -m 0x8b ${BSD_CPUCTL_DEV_BASE}0 | awk '{print $3}')
|
||||
# convert to decimal
|
||||
cpu_ucode=$((cpu_ucode))
|
||||
# convert back to hex
|
||||
cpu_ucode=$(printf "0x%x" "$cpu_ucode")
|
||||
if [ "$cpu_vendor" = AuthenticAMD ]; then
|
||||
# AMD: read MSR_PATCHLEVEL (0xC0010058) directly
|
||||
cpu_ucode=$(cpucontrol -m 0xC0010058 ${BSD_CPUCTL_DEV_BASE}0 2>/dev/null | awk '{print $3}')
|
||||
elif [ "$cpu_vendor" = GenuineIntel ]; then
|
||||
# Intel: write 0 to IA32_BIOS_SIGN_ID, execute CPUID, then read back
|
||||
cpucontrol -m 0x8b=0 ${BSD_CPUCTL_DEV_BASE}0 2>/dev/null
|
||||
cpucontrol -i 1 ${BSD_CPUCTL_DEV_BASE}0 >/dev/null 2>&1
|
||||
cpu_ucode=$(cpucontrol -m 0x8b ${BSD_CPUCTL_DEV_BASE}0 2>/dev/null | awk '{print $3}')
|
||||
fi
|
||||
if [ -n "$cpu_ucode" ]; then
|
||||
# convert to decimal then back to hex
|
||||
cpu_ucode=$((cpu_ucode))
|
||||
cpu_ucode=$(printf "0x%x" "$cpu_ucode")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# if we got no cpu_ucode (e.g. we're in a vm), fall back to 0x0
|
||||
: "${cpu_ucode:=0x0}"
|
||||
# if we got no cpu_ucode (e.g. we're in a vm), leave it empty
|
||||
# so that we can detect this case and avoid false positives
|
||||
|
||||
# on non-x86 systems (e.g. ARM), these fields may not exist in cpuinfo, fall back to 0
|
||||
: "${cpu_family:=0}"
|
||||
@@ -3058,9 +3076,11 @@ parse_cpu_details() {
|
||||
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_CPU_UCODE='$cpu_ucode'")
|
||||
fi
|
||||
|
||||
echo "$cpu_ucode" | grep -q ^0x && cpu_ucode=$((cpu_ucode))
|
||||
g_ucode_found=$(printf "family 0x%x model 0x%x stepping 0x%x ucode 0x%x cpuid 0x%x pfid 0x%x" \
|
||||
"$cpu_family" "$cpu_model" "$cpu_stepping" "$cpu_ucode" "$cpu_cpuid" "$cpu_platformid")
|
||||
if [ -n "$cpu_ucode" ]; then
|
||||
echo "$cpu_ucode" | grep -q ^0x && cpu_ucode=$((cpu_ucode))
|
||||
fi
|
||||
g_ucode_found=$(printf "family 0x%x model 0x%x stepping 0x%x ucode 0x%s cpuid 0x%x pfid 0x%x" \
|
||||
"$cpu_family" "$cpu_model" "$cpu_stepping" "${cpu_ucode:-unknown}" "$cpu_cpuid" "$cpu_platformid")
|
||||
|
||||
g_parse_cpu_details_done=1
|
||||
}
|
||||
@@ -3281,7 +3301,7 @@ has_zenbleed_fixed_firmware() {
|
||||
model_high=$(echo "$tuple" | cut -d, -f2)
|
||||
fwver=$(echo "$tuple" | cut -d, -f3)
|
||||
if [ $((cpu_model)) -ge $((model_low)) ] && [ $((cpu_model)) -le $((model_high)) ]; then
|
||||
if [ $((cpu_ucode)) -ge $((fwver)) ]; then
|
||||
if [ -n "$cpu_ucode" ] && [ $((cpu_ucode)) -ge $((fwver)) ]; then
|
||||
g_zenbleed_fw=0 # true
|
||||
break
|
||||
else
|
||||
@@ -3400,6 +3420,10 @@ is_latest_known_ucode() {
|
||||
ret_is_latest_known_ucode_latest="couldn't get your cpuid"
|
||||
return 2
|
||||
fi
|
||||
if [ -z "$cpu_ucode" ]; then
|
||||
ret_is_latest_known_ucode_latest="couldn't get your microcode version"
|
||||
return 2
|
||||
fi
|
||||
ret_is_latest_known_ucode_latest="latest microcode version for your CPU model is unknown"
|
||||
if is_intel; then
|
||||
brand_prefix=I
|
||||
@@ -3921,6 +3945,26 @@ check_cpu() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# IBPB_RET: CPUID EAX=0x80000008, ECX=0x00 return EBX[30] indicates IBPB also flushes
|
||||
# return predictions (Zen4+). Without this bit, IBPB alone does not clear the return
|
||||
# predictor, requiring an additional RSB fill (kernel X86_BUG_IBPB_NO_RET fix).
|
||||
cap_ibpb_ret=''
|
||||
if is_amd || is_hygon; then
|
||||
pr_info_nol " * CPU indicates IBPB flushes return predictions: "
|
||||
read_cpuid 0x80000008 0x0 $EBX 30 1 1
|
||||
ret=$?
|
||||
if [ $ret = $READ_CPUID_RET_OK ]; then
|
||||
cap_ibpb_ret=1
|
||||
pstatus green YES "IBPB_RET feature bit"
|
||||
elif [ $ret = $READ_CPUID_RET_KO ]; then
|
||||
cap_ibpb_ret=0
|
||||
pstatus yellow NO
|
||||
else
|
||||
cap_ibpb_ret=-1
|
||||
pstatus yellow UNKNOWN "$ret_read_cpuid_msg"
|
||||
fi
|
||||
fi
|
||||
|
||||
# STIBP
|
||||
pr_info " * Single Thread Indirect Branch Predictors (STIBP)"
|
||||
pr_info_nol " * SPEC_CTRL MSR is available: "
|
||||
@@ -4329,6 +4373,8 @@ check_cpu() {
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
# IA32_TSX_CTRL (MSR 0x122): architectural way to disable TSX, available on
|
||||
# Cascade Lake and newer, and some Coffee Lake steppings via microcode update
|
||||
if [ "$cap_tsx_ctrl_msr" = 1 ]; then
|
||||
read_msr $MSR_IA32_TSX_CTRL
|
||||
ret=$?
|
||||
@@ -4523,6 +4569,52 @@ check_cpu() {
|
||||
pstatus yellow UNKNOWN "$ret_read_cpuid_msg"
|
||||
fi
|
||||
|
||||
pr_info_nol " * CPU supports TSX Force Abort (TSX_FORCE_ABORT): "
|
||||
ret=$READ_CPUID_RET_KO
|
||||
cap_tsx_force_abort=0
|
||||
if is_intel; then
|
||||
read_cpuid 0x7 0x0 $EDX 13 1 1
|
||||
ret=$?
|
||||
fi
|
||||
if [ $ret = $READ_CPUID_RET_OK ]; then
|
||||
cap_tsx_force_abort=1
|
||||
pstatus blue YES
|
||||
elif [ $ret = $READ_CPUID_RET_KO ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
cap_tsx_force_abort=-1
|
||||
pstatus yellow UNKNOWN "$ret_read_cpuid_msg"
|
||||
fi
|
||||
|
||||
# IA32_TSX_FORCE_ABORT (MSR 0x10F): stopgap for older Skylake/Kaby Lake CPUs that
|
||||
# don't support IA32_TSX_CTRL, forces all RTM transactions to abort via microcode update
|
||||
if [ "$cap_tsx_force_abort" = 1 ]; then
|
||||
read_msr $MSR_IA32_TSX_FORCE_ABORT
|
||||
ret=$?
|
||||
if [ "$ret" = $READ_MSR_RET_OK ]; then
|
||||
cap_tsx_force_abort_rtm_disable=$((ret_read_msr_value_lo >> 0 & 1))
|
||||
cap_tsx_force_abort_cpuid_clear=$((ret_read_msr_value_lo >> 1 & 1))
|
||||
fi
|
||||
|
||||
pr_info_nol " * TSX_FORCE_ABORT MSR indicates all TSX transactions are aborted: "
|
||||
if [ "$cap_tsx_force_abort_rtm_disable" = 1 ]; then
|
||||
pstatus blue YES
|
||||
elif [ "$cap_tsx_force_abort_rtm_disable" = 0 ]; then
|
||||
pstatus blue NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read MSR"
|
||||
fi
|
||||
|
||||
pr_info_nol " * TSX_FORCE_ABORT MSR indicates TSX CPUID bit is cleared: "
|
||||
if [ "$cap_tsx_force_abort_cpuid_clear" = 1 ]; then
|
||||
pstatus blue YES
|
||||
elif [ "$cap_tsx_force_abort_cpuid_clear" = 0 ]; then
|
||||
pstatus blue NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read MSR"
|
||||
fi
|
||||
fi
|
||||
|
||||
pr_info_nol " * CPU supports Software Guard Extensions (SGX): "
|
||||
ret=$READ_CPUID_RET_KO
|
||||
cap_sgx=0
|
||||
@@ -4556,11 +4648,11 @@ check_cpu() {
|
||||
read_msr $MSR_IA32_MCU_OPT_CTRL
|
||||
ret=$?
|
||||
if [ $ret = $READ_MSR_RET_OK ]; then
|
||||
if [ "$ret_read_msr_value" = "0000000000000000" ]; then
|
||||
#SRBDS mitigation control exists and is enabled via microcode
|
||||
if [ "$((ret_read_msr_value_lo >> 0 & 1))" = 0 ]; then
|
||||
#SRBDS mitigation control exists and is enabled via microcode (RNGDS_MITG_DIS bit is 0)
|
||||
cap_srbds_on=1
|
||||
else
|
||||
#SRBDS mitigation control exists but is disabled via microcode
|
||||
#SRBDS mitigation control exists but is disabled via microcode (RNGDS_MITG_DIS bit is 1)
|
||||
cap_srbds_on=0
|
||||
fi
|
||||
else
|
||||
@@ -8034,7 +8126,19 @@ check_CVE_2019_11135_linux() {
|
||||
else
|
||||
if [ "$opt_paranoid" = 1 ]; then
|
||||
# in paranoid mode, TSX or SMT enabled are not OK, even if TAA is mitigated
|
||||
if ! echo "$ret_sys_interface_check_fullmsg" | grep -qF 'TSX disabled'; then
|
||||
# first check sysfs, then fall back to MSR-based detection for older kernels
|
||||
# that may not report TSX as disabled even when microcode has done so
|
||||
tsx_disabled=0
|
||||
if echo "$ret_sys_interface_check_fullmsg" | grep -qF 'TSX disabled'; then
|
||||
tsx_disabled=1
|
||||
elif [ "$cap_tsx_ctrl_rtm_disable" = 1 ] && [ "$cap_tsx_ctrl_cpuid_clear" = 1 ]; then
|
||||
# TSX disabled via IA32_TSX_CTRL MSR (0x122)
|
||||
tsx_disabled=1
|
||||
elif [ "$cap_tsx_force_abort_rtm_disable" = 1 ] && [ "$cap_tsx_force_abort_cpuid_clear" = 1 ]; then
|
||||
# TSX disabled via IA32_TSX_FORCE_ABORT MSR (0x10F), for older Skylake-era CPUs
|
||||
tsx_disabled=1
|
||||
fi
|
||||
if [ "$tsx_disabled" = 0 ]; then
|
||||
pvulnstatus "$cve" VULN "TSX must be disabled for full mitigation"
|
||||
elif echo "$ret_sys_interface_check_fullmsg" | grep -qF 'SMT vulnerable'; then
|
||||
pvulnstatus "$cve" VULN "SMT (HyperThreading) must be disabled for full mitigation"
|
||||
@@ -8911,7 +9015,7 @@ check_CVE_2023_20569() {
|
||||
}
|
||||
|
||||
check_CVE_2023_20569_linux() {
|
||||
local status sys_interface_available msg kernel_sro kernel_sro_err kernel_srso kernel_ibpb_entry smt_enabled
|
||||
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=''
|
||||
@@ -8929,6 +9033,15 @@ check_CVE_2023_20569_linux() {
|
||||
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
|
||||
@@ -9021,6 +9134,19 @@ check_CVE_2023_20569_linux() {
|
||||
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: "
|
||||
@@ -9070,7 +9196,11 @@ check_CVE_2023_20569_linux() {
|
||||
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
|
||||
pvulnstatus "$cve" OK "SMT is disabled and both your kernel and microcode support mitigation"
|
||||
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
|
||||
@@ -9085,7 +9215,11 @@ check_CVE_2023_20569_linux() {
|
||||
elif [ "$cap_sbpb" = 2 ]; then
|
||||
pvulnstatus "$cve" VULN "Your microcode doesn't support SBPB"
|
||||
else
|
||||
pvulnstatus "$cve" OK "Your kernel and microcode both support mitigation"
|
||||
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
|
||||
@@ -9116,6 +9250,178 @@ check_CVE_2023_20569_bsd() {
|
||||
fi
|
||||
}
|
||||
|
||||
# >>>>>> vulns/CVE-2023-20588.sh <<<<<<
|
||||
|
||||
# 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
|
||||
}
|
||||
|
||||
# >>>>>> vulns/CVE-2023-20593.sh <<<<<<
|
||||
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
@@ -9318,7 +9624,10 @@ check_CVE_2023_23583_linux() {
|
||||
pvulnstatus "$cve" VULN "your CPU is affected and no microcode update is available for your CPU stepping"
|
||||
else
|
||||
pr_info_nol "* Reptar is mitigated by microcode: "
|
||||
if [ "$cpu_ucode" -lt "$g_reptar_fixed_ucode_version" ]; then
|
||||
if [ -z "$cpu_ucode" ]; then
|
||||
pstatus yellow UNKNOWN "couldn't get your microcode version"
|
||||
pvulnstatus "$cve" UNK "couldn't detect microcode version to verify mitigation"
|
||||
elif [ "$cpu_ucode" -lt "$g_reptar_fixed_ucode_version" ]; then
|
||||
pstatus yellow NO "You have ucode $(printf "0x%x" "$cpu_ucode") and version $(printf "0x%x" "$g_reptar_fixed_ucode_version") minimum is required"
|
||||
pvulnstatus "$cve" VULN "Your microcode is too old to mitigate the vulnerability"
|
||||
else
|
||||
@@ -9775,22 +10084,24 @@ check_CVE_2024_36350_linux() {
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
pr_info_nol "* CPU explicitly indicates not vulnerable to TSA-SQ (TSA_SQ_NO): "
|
||||
if [ "$cap_tsa_sq_no" = 1 ]; then
|
||||
pstatus green YES
|
||||
elif [ "$cap_tsa_sq_no" = 0 ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read CPUID leaf 0x80000021"
|
||||
fi
|
||||
if is_amd || is_hygon; then
|
||||
pr_info_nol "* CPU explicitly indicates not vulnerable to TSA-SQ (TSA_SQ_NO): "
|
||||
if [ "$cap_tsa_sq_no" = 1 ]; then
|
||||
pstatus green YES
|
||||
elif [ "$cap_tsa_sq_no" = 0 ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read CPUID leaf 0x80000021"
|
||||
fi
|
||||
|
||||
pr_info_nol "* Microcode supports VERW buffer clearing: "
|
||||
if [ "$cap_verw_clear" = 1 ]; then
|
||||
pstatus green YES
|
||||
elif [ "$cap_verw_clear" = 0 ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read CPUID leaf 0x80000021"
|
||||
pr_info_nol "* Microcode supports VERW buffer clearing: "
|
||||
if [ "$cap_verw_clear" = 1 ]; then
|
||||
pstatus green YES
|
||||
elif [ "$cap_verw_clear" = 0 ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read CPUID leaf 0x80000021"
|
||||
fi
|
||||
fi
|
||||
|
||||
pr_info_nol "* Hyper-Threading (SMT) is enabled: "
|
||||
@@ -9952,22 +10263,24 @@ check_CVE_2024_36357_linux() {
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
pr_info_nol "* CPU explicitly indicates not vulnerable to TSA-L1 (TSA_L1_NO): "
|
||||
if [ "$cap_tsa_l1_no" = 1 ]; then
|
||||
pstatus green YES
|
||||
elif [ "$cap_tsa_l1_no" = 0 ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read CPUID leaf 0x80000021"
|
||||
fi
|
||||
if is_amd || is_hygon; then
|
||||
pr_info_nol "* CPU explicitly indicates not vulnerable to TSA-L1 (TSA_L1_NO): "
|
||||
if [ "$cap_tsa_l1_no" = 1 ]; then
|
||||
pstatus green YES
|
||||
elif [ "$cap_tsa_l1_no" = 0 ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read CPUID leaf 0x80000021"
|
||||
fi
|
||||
|
||||
pr_info_nol "* Microcode supports VERW buffer clearing: "
|
||||
if [ "$cap_verw_clear" = 1 ]; then
|
||||
pstatus green YES
|
||||
elif [ "$cap_verw_clear" = 0 ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read CPUID leaf 0x80000021"
|
||||
pr_info_nol "* Microcode supports VERW buffer clearing: "
|
||||
if [ "$cap_verw_clear" = 1 ]; then
|
||||
pstatus green YES
|
||||
elif [ "$cap_verw_clear" = 0 ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read CPUID leaf 0x80000021"
|
||||
fi
|
||||
fi
|
||||
|
||||
elif [ "$sys_interface_available" = 0 ]; then
|
||||
@@ -10060,7 +10373,10 @@ check_CVE_2024_45332_linux() {
|
||||
"update is available for your specific CPU stepping."
|
||||
else
|
||||
pr_info_nol "* BPI is mitigated by microcode: "
|
||||
if [ "$cpu_ucode" -lt "$g_bpi_fixed_ucode_version" ]; then
|
||||
if [ -z "$cpu_ucode" ]; then
|
||||
pstatus yellow UNKNOWN "couldn't get your microcode version"
|
||||
pvulnstatus "$cve" UNK "couldn't detect microcode version to verify mitigation"
|
||||
elif [ "$cpu_ucode" -lt "$g_bpi_fixed_ucode_version" ]; then
|
||||
pstatus yellow NO "You have ucode $(printf "0x%x" "$cpu_ucode") and version $(printf "0x%x" "$g_bpi_fixed_ucode_version") minimum is required"
|
||||
pvulnstatus "$cve" VULN "Your microcode is too old to mitigate the vulnerability"
|
||||
explain "CVE-2024-45332 (Branch Privilege Injection) is a race condition in the branch predictor\n" \
|
||||
|
||||
Reference in New Issue
Block a user