mirror of
https://github.com/speed47/spectre-meltdown-checker.git
synced 2026-04-07 17:23:18 +02:00
feat: implement CVE-2023-28746 (RFDS, Register File Data Sampling)
This commit is contained in:
@@ -166,6 +166,7 @@ CVE-2024-36350|TSA_SQ|tsa|Transient Scheduler Attack - Store Queue (TSA-SQ)
|
||||
CVE-2024-36357|TSA_L1|tsa|Transient Scheduler Attack - L1 (TSA-L1)
|
||||
CVE-2024-28956|ITS|its|Indirect Target Selection (ITS)
|
||||
CVE-2025-40300|VMSCAPE|vmscape|VMScape, VM-exit stale branch prediction
|
||||
CVE-2023-28746|RFDS|rfds|Register File Data Sampling (RFDS)
|
||||
CVE-2024-45332|BPI|bpi|Branch Privilege Injection (BPI)
|
||||
CVE-0000-0001|SLS|sls|Straight-Line Speculation (SLS)
|
||||
'
|
||||
|
||||
@@ -107,9 +107,10 @@ is_cpu_affected() {
|
||||
_set_immune tsa
|
||||
# Retbleed: AMD (CVE-2022-29900) and Intel (CVE-2022-29901) specific:
|
||||
_set_immune retbleed
|
||||
# Downfall, Reptar, ITS & BPI are Intel specific, look for "is_intel" below:
|
||||
# Downfall, Reptar, RFDS, ITS & BPI are Intel specific, look for "is_intel" below:
|
||||
_set_immune downfall
|
||||
_set_immune reptar
|
||||
_set_immune rfds
|
||||
_set_immune its
|
||||
_set_immune bpi
|
||||
# VMScape affects Intel, AMD and Hygon — set immune, overridden below:
|
||||
@@ -266,6 +267,32 @@ is_cpu_affected() {
|
||||
fi
|
||||
set +u
|
||||
fi
|
||||
# RFDS (Register File Data Sampling, CVE-2023-28746)
|
||||
# kernel cpu_vuln_blacklist (8076fcde016c, initial model list)
|
||||
# immunity: ARCH_CAP_RFDS_NO (bit 27 of IA32_ARCH_CAPABILITIES)
|
||||
# vendor scope: Intel only (family 6), Atom/hybrid cores
|
||||
if [ "$cap_rfds_no" = 1 ]; then
|
||||
pr_debug "is_cpu_affected: rfds: not affected (RFDS_NO)"
|
||||
_set_immune rfds
|
||||
elif [ "$cpu_family" = 6 ]; then
|
||||
set -u
|
||||
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_D" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_L" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GRACEMONT" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE_L" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE_P" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE_S" ]; then
|
||||
pr_debug "is_cpu_affected: rfds: affected"
|
||||
_set_vuln rfds
|
||||
fi
|
||||
set +u
|
||||
fi
|
||||
# ITS (Indirect Target Selection, CVE-2024-28956)
|
||||
# kernel vulnerable_to_its() + cpu_vuln_blacklist (159013a7ca18)
|
||||
# immunity: ARCH_CAP_ITS_NO (bit 62 of IA32_ARCH_CAPABILITIES)
|
||||
@@ -769,7 +796,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 its=$affected_its"
|
||||
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: vmscape=$affected_vmscape bpi=$affected_bpi sls=$affected_sls"
|
||||
}
|
||||
affected_variantl1tf_sgx="$affected_variantl1tf"
|
||||
|
||||
@@ -169,7 +169,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, tsa, tsa-sq, tsa-l1, its, vmscape, bpi, sls"
|
||||
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"
|
||||
exit 0
|
||||
;;
|
||||
1)
|
||||
@@ -244,6 +244,10 @@ while [ -n "${1:-}" ]; do
|
||||
opt_cve_list="$opt_cve_list CVE-2023-23583"
|
||||
opt_cve_all=0
|
||||
;;
|
||||
rfds)
|
||||
opt_cve_list="$opt_cve_list CVE-2023-28746"
|
||||
opt_cve_all=0
|
||||
;;
|
||||
tsa)
|
||||
opt_cve_list="$opt_cve_list CVE-2024-36350 CVE-2024-36357"
|
||||
opt_cve_all=0
|
||||
|
||||
@@ -734,6 +734,8 @@ check_cpu() {
|
||||
cap_tsx_ctrl_msr=-1
|
||||
cap_gds_ctrl=-1
|
||||
cap_gds_no=-1
|
||||
cap_rfds_no=-1
|
||||
cap_rfds_clear=-1
|
||||
cap_its_no=-1
|
||||
if [ "$cap_arch_capabilities" = -1 ]; then
|
||||
pstatus yellow UNKNOWN
|
||||
@@ -749,6 +751,8 @@ check_cpu() {
|
||||
cap_tsx_ctrl_msr=0
|
||||
cap_gds_ctrl=0
|
||||
cap_gds_no=0
|
||||
cap_rfds_no=0
|
||||
cap_rfds_clear=0
|
||||
cap_its_no=0
|
||||
pstatus yellow NO
|
||||
else
|
||||
@@ -765,6 +769,8 @@ check_cpu() {
|
||||
cap_tsx_ctrl_msr=0
|
||||
cap_gds_ctrl=0
|
||||
cap_gds_no=0
|
||||
cap_rfds_no=0
|
||||
cap_rfds_clear=0
|
||||
cap_its_no=0
|
||||
if [ $ret = $READ_MSR_RET_OK ]; then
|
||||
capabilities=$ret_read_msr_value
|
||||
@@ -781,8 +787,10 @@ check_cpu() {
|
||||
[ $((ret_read_msr_value_lo >> 8 & 1)) -eq 1 ] && cap_taa_no=1
|
||||
[ $((ret_read_msr_value_lo >> 25 & 1)) -eq 1 ] && cap_gds_ctrl=1
|
||||
[ $((ret_read_msr_value_lo >> 26 & 1)) -eq 1 ] && cap_gds_no=1
|
||||
[ $((ret_read_msr_value_lo >> 27 & 1)) -eq 1 ] && cap_rfds_no=1
|
||||
[ $((ret_read_msr_value_lo >> 28 & 1)) -eq 1 ] && cap_rfds_clear=1
|
||||
[ $((ret_read_msr_value_hi >> 30 & 1)) -eq 1 ] && cap_its_no=1
|
||||
pr_debug "capabilities says rdcl_no=$cap_rdcl_no ibrs_all=$cap_ibrs_all rsba=$cap_rsba l1dflush_no=$cap_l1dflush_no ssb_no=$cap_ssb_no mds_no=$cap_mds_no taa_no=$cap_taa_no pschange_msc_no=$cap_pschange_msc_no its_no=$cap_its_no"
|
||||
pr_debug "capabilities says rdcl_no=$cap_rdcl_no ibrs_all=$cap_ibrs_all rsba=$cap_rsba l1dflush_no=$cap_l1dflush_no ssb_no=$cap_ssb_no mds_no=$cap_mds_no taa_no=$cap_taa_no pschange_msc_no=$cap_pschange_msc_no rfds_no=$cap_rfds_no rfds_clear=$cap_rfds_clear its_no=$cap_its_no"
|
||||
if [ "$cap_ibrs_all" = 1 ]; then
|
||||
pstatus green YES
|
||||
else
|
||||
@@ -941,6 +949,24 @@ check_cpu() {
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
pr_info_nol " * CPU explicitly indicates not being affected by RFDS (RFDS_NO): "
|
||||
if [ "$cap_rfds_no" = -1 ]; then
|
||||
pstatus yellow UNKNOWN "couldn't read MSR"
|
||||
elif [ "$cap_rfds_no" = 1 ]; then
|
||||
pstatus green YES
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
pr_info_nol " * CPU microcode supports clearing register files (RFDS_CLEAR): "
|
||||
if [ "$cap_rfds_clear" = -1 ]; then
|
||||
pstatus yellow UNKNOWN "couldn't read MSR"
|
||||
elif [ "$cap_rfds_clear" = 1 ]; then
|
||||
pstatus green YES
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if is_amd || is_hygon; then
|
||||
|
||||
173
src/vulns/CVE-2023-28746.sh
Normal file
173
src/vulns/CVE-2023-28746.sh
Normal file
@@ -0,0 +1,173 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
###############################
|
||||
# CVE-2023-28746, RFDS, Register File Data Sampling
|
||||
|
||||
check_CVE_2023_28746() {
|
||||
check_cve 'CVE-2023-28746'
|
||||
}
|
||||
|
||||
check_CVE_2023_28746_linux() {
|
||||
local status sys_interface_available msg kernel_rfds kernel_rfds_err rfds_mitigated
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
|
||||
if sys_interface_check "$VULN_SYSFS_BASE/reg_file_data_sampling"; then
|
||||
# this kernel has the /sys interface, trust it over everything
|
||||
sys_interface_available=1
|
||||
#
|
||||
# Kernel source inventory for reg_file_data_sampling (RFDS)
|
||||
#
|
||||
# --- sysfs messages ---
|
||||
# all versions:
|
||||
# "Not affected" (cpu_show_common, pre-existing)
|
||||
#
|
||||
# --- mainline ---
|
||||
# 8076fcde016c (v6.9-rc1, initial RFDS sysfs):
|
||||
# "Vulnerable" (RFDS_MITIGATION_OFF)
|
||||
# "Vulnerable: No microcode" (RFDS_MITIGATION_UCODE_NEEDED)
|
||||
# "Mitigation: Clear Register File" (RFDS_MITIGATION_VERW)
|
||||
# b8ce25df2999 (v6.15, added AUTO state):
|
||||
# no string changes; RFDS_MITIGATION_AUTO is internal, resolved before display
|
||||
# 203d81f8e167 (v6.17, restructured):
|
||||
# no string changes; added rfds_update_mitigation() + rfds_apply_mitigation()
|
||||
#
|
||||
# --- stable backports ---
|
||||
# 5.10.215, 5.15.154, 6.1.82, 6.6.22, 6.7.10, 6.8.1:
|
||||
# same 3 strings as mainline; no structural differences
|
||||
# macro ALDERLAKE_N (0xBE) used instead of mainline ATOM_GRACEMONT (same model)
|
||||
#
|
||||
# --- Kconfig symbols ---
|
||||
# 8076fcde016c (v6.9-rc1): CONFIG_MITIGATION_RFDS (default y)
|
||||
# no renames across any version
|
||||
#
|
||||
# --- kernel functions (for $opt_map / System.map) ---
|
||||
# 8076fcde016c (v6.9-rc1): rfds_select_mitigation(), rfds_parse_cmdline(),
|
||||
# rfds_show_state(), cpu_show_reg_file_data_sampling(), vulnerable_to_rfds()
|
||||
# 203d81f8e167 (v6.17): + rfds_update_mitigation(), rfds_apply_mitigation()
|
||||
#
|
||||
# --- CPU affection logic (for is_cpu_affected) ---
|
||||
# 8076fcde016c (v6.9-rc1, initial model list):
|
||||
# Intel: ATOM_GOLDMONT (0x5C), ATOM_GOLDMONT_D (0x5F),
|
||||
# ATOM_GOLDMONT_PLUS (0x7A), ATOM_TREMONT_D (0x86),
|
||||
# ATOM_TREMONT (0x96), ATOM_TREMONT_L (0x9C),
|
||||
# ATOM_GRACEMONT (0xBE), ALDERLAKE (0x97),
|
||||
# ALDERLAKE_L (0x9A), RAPTORLAKE (0xB7),
|
||||
# RAPTORLAKE_P (0xBA), RAPTORLAKE_S (0xBF)
|
||||
# 722fa0dba74f (v6.15, P-only hybrid exclusion):
|
||||
# ALDERLAKE (0x97) and RAPTORLAKE (0xB7) narrowed to Atom core type only
|
||||
# via X86_HYBRID_CPU_TYPE_ATOM check in vulnerable_to_rfds(); P-cores on
|
||||
# these hybrid models are not affected, only E-cores (Gracemont) are.
|
||||
# (not modeled here, we conservatively flag all steppings per whitelist principle,
|
||||
# because detecting the active core type at runtime is unreliable from userspace)
|
||||
# immunity: ARCH_CAP_RFDS_NO (bit 27 of IA32_ARCH_CAPABILITIES)
|
||||
# mitigation: ARCH_CAP_RFDS_CLEAR (bit 28 of IA32_ARCH_CAPABILITIES)
|
||||
# vendor scope: Intel only
|
||||
#
|
||||
# all messages start with either "Not affected", "Mitigation", or "Vulnerable"
|
||||
status=$ret_sys_interface_check_status
|
||||
fi
|
||||
|
||||
if [ "$opt_sysfs_only" != 1 ]; then
|
||||
pr_info_nol "* CPU microcode mitigates the vulnerability: "
|
||||
if [ "$cap_rfds_clear" = 1 ]; then
|
||||
pstatus green YES "RFDS_CLEAR capability indicated by microcode"
|
||||
elif [ "$cap_rfds_clear" = 0 ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read MSR"
|
||||
fi
|
||||
|
||||
pr_info_nol "* Kernel supports RFDS mitigation (VERW on transitions): "
|
||||
kernel_rfds=''
|
||||
kernel_rfds_err=''
|
||||
if [ -n "$g_kernel_err" ]; then
|
||||
kernel_rfds_err="$g_kernel_err"
|
||||
elif grep -q 'Clear Register File' "$g_kernel"; then
|
||||
kernel_rfds="found 'Clear Register File' string in kernel image"
|
||||
elif grep -q 'reg_file_data_sampling' "$g_kernel"; then
|
||||
kernel_rfds="found reg_file_data_sampling in kernel image"
|
||||
fi
|
||||
if [ -z "$kernel_rfds" ] && [ -r "$opt_config" ]; then
|
||||
if grep -q '^CONFIG_MITIGATION_RFDS=y' "$opt_config"; then
|
||||
kernel_rfds="RFDS mitigation config option found enabled in kernel config"
|
||||
fi
|
||||
fi
|
||||
if [ -z "$kernel_rfds" ] && [ -n "$opt_map" ]; then
|
||||
if grep -q 'rfds_select_mitigation' "$opt_map"; then
|
||||
kernel_rfds="found rfds_select_mitigation in System.map"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$kernel_rfds" ]; then
|
||||
pstatus green YES "$kernel_rfds"
|
||||
elif [ -n "$kernel_rfds_err" ]; then
|
||||
pstatus yellow UNKNOWN "$kernel_rfds_err"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
if [ "$opt_live" = 1 ] && [ "$sys_interface_available" = 1 ]; then
|
||||
pr_info_nol "* RFDS mitigation is enabled and active: "
|
||||
if echo "$ret_sys_interface_check_fullmsg" | grep -qi '^Mitigation'; then
|
||||
rfds_mitigated=1
|
||||
pstatus green YES
|
||||
else
|
||||
rfds_mitigated=0
|
||||
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 [ "$opt_sysfs_only" != 1 ]; then
|
||||
if [ "$cap_rfds_clear" = 1 ]; then
|
||||
if [ -n "$kernel_rfds" ]; then
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if [ "$rfds_mitigated" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Your microcode and kernel are both up to date for this mitigation, but the mitigation is not active"
|
||||
explain "The RFDS mitigation has been disabled. Remove 'reg_file_data_sampling=off' or 'mitigations=off'\n " \
|
||||
"from your kernel command line to re-enable it."
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for this mitigation"
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Your microcode supports mitigation, but your kernel doesn't, upgrade it to mitigate the vulnerability"
|
||||
explain "Update your kernel to a version that supports RFDS mitigation (Linux 6.9+, or check if your distro\n " \
|
||||
"has a backport). Your CPU microcode already provides the RFDS_CLEAR capability."
|
||||
fi
|
||||
else
|
||||
if [ -n "$kernel_rfds" ]; then
|
||||
pvulnstatus "$cve" VULN "Your kernel supports mitigation, but your CPU microcode also needs to be updated to mitigate the vulnerability"
|
||||
explain "Update your CPU microcode (via BIOS/firmware update or linux-firmware package) to a version that\n " \
|
||||
"provides the RFDS_CLEAR capability."
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Neither your kernel or your microcode support mitigation, upgrade both to mitigate the vulnerability"
|
||||
explain "Update both your CPU microcode (via BIOS/firmware update from your OEM) and your kernel to a version\n " \
|
||||
"that supports RFDS mitigation (Linux 6.9+, or check if your distro has a backport)."
|
||||
fi
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" "$status" "$msg"
|
||||
fi
|
||||
}
|
||||
|
||||
check_CVE_2023_28746_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
|
||||
}
|
||||
Reference in New Issue
Block a user