feat: implement CVE-2023-28746 (RFDS, Register File Data Sampling)

This commit is contained in:
Stéphane Lesimple
2026-04-05 23:57:28 +02:00
parent 548d504e88
commit 34807b0d11
6 changed files with 241 additions and 4 deletions

View File

@@ -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)
'

View File

@@ -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"

View File

@@ -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

View File

@@ -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
View 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
}