mirror of
https://github.com/speed47/spectre-meltdown-checker.git
synced 2026-04-05 16:23:19 +02:00
feat: implement CVE-2024-28956 (ITS, Indirect Target Selection) vulnerability and mitigation detection
This commit is contained in:
2
.github/workflows/expected_cve_count
vendored
2
.github/workflows/expected_cve_count
vendored
@@ -1 +1 @@
|
||||
23
|
||||
24
|
||||
|
||||
@@ -710,7 +710,7 @@ CVEs that need VMM context should call `check_has_vmm` early in their `_linux()`
|
||||
- **Always handle both live and offline modes** - use `$opt_live` to branch, and print `N/A "not testable in offline mode"` for runtime-only checks when offline.
|
||||
- **Use `explain()`** when reporting VULN to give actionable remediation advice (see "Cross-Cutting Features" above).
|
||||
- **Handle `--paranoid` and `--vmm`** when the CVE has stricter mitigation tiers or VMM-specific aspects (see "Cross-Cutting Features" above).
|
||||
- **All indentation must use tabs** (CI enforces this).
|
||||
- **All indentation must use 4 spaces** (CI enforces this via `fmt-check`; the vim modeline `et` enables expandtab).
|
||||
- **Stay POSIX-compatible** - no bashisms, no GNU-only flags in portable code paths.
|
||||
|
||||
## Function documentation headers
|
||||
|
||||
8
dist/README.md
vendored
8
dist/README.md
vendored
@@ -30,6 +30,7 @@ CVE | Name | Aliases
|
||||
[CVE-2023-23583](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-23583) | Redundant Prefix Issue | Reptar
|
||||
[CVE-2024-36350](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-36350) | Transient Scheduler Attack, Store Queue | TSA-SQ
|
||||
[CVE-2024-36357](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-36357) | Transient Scheduler Attack, L1 | TSA-L1
|
||||
[CVE-2024-28956](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-28956) | Indirect Target Selection | ITS
|
||||
|
||||
## Am I at risk?
|
||||
|
||||
@@ -61,6 +62,7 @@ CVE-2023-20593 (Zenbleed) | 💥 | 💥 | 💥 | 💥 | Microcode update (or ker
|
||||
CVE-2023-23583 (Reptar) | ☠️ | ☠️ | ☠️ | ☠️ | Microcode update
|
||||
CVE-2024-36350 (TSA-SQ) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
|
||||
CVE-2024-36357 (TSA-L1) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
|
||||
CVE-2024-28956 (ITS) | 💥 | ✅ | 💥 (4) | ✅ | Microcode + kernel update
|
||||
|
||||
> 💥 Data can be leaked across this boundary.
|
||||
|
||||
@@ -74,6 +76,8 @@ CVE-2024-36357 (TSA-L1) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel
|
||||
|
||||
> (3) CVE-2018-3615 (Foreshadow SGX) inverts the normal trust model: the OS reads SGX enclave data. It is irrelevant unless the system runs SGX enclaves, and the attacker must already have OS-level access.
|
||||
|
||||
> (4) VM→Host leakage applies only to certain affected CPU models (Skylake-X, Kaby Lake, Comet Lake). Ice Lake, Tiger Lake, and Rocket Lake are only affected for native (user-to-kernel) attacks, not guest-to-host.
|
||||
|
||||
## Detailed CVE descriptions
|
||||
|
||||
<details>
|
||||
@@ -165,6 +169,10 @@ On AMD Zen 3 and Zen 4 processors, the CPU's transient scheduler may speculative
|
||||
|
||||
On AMD Zen 3 and Zen 4 processors, the CPU's transient scheduler may speculatively retrieve stale data from the L1 data cache during certain timing windows, allowing an attacker to infer data in the L1D cache across privilege boundaries. Mitigation requires the same microcode and kernel updates as TSA-SQ: a microcode update exposing VERW_CLEAR and a kernel update (CONFIG_MITIGATION_TSA, Linux 6.16+) that clears CPU buffers via VERW on privilege transitions. Performance impact is low to medium.
|
||||
|
||||
**CVE-2024-28956 — Indirect Target Selection (ITS)**
|
||||
|
||||
On certain Intel processors (Skylake-X stepping 6+, Kaby Lake, Comet Lake, Ice Lake, Tiger Lake, Rocket Lake), an attacker can train the indirect branch predictor to speculatively execute a targeted gadget in the kernel, bypassing eIBRS protections. The Branch Target Buffer (BTB) uses only partial address bits to index indirect branch targets, allowing user-space code to influence kernel-space speculative execution. Some affected CPUs (Ice Lake, Tiger Lake, Rocket Lake) are only vulnerable to native user-to-kernel attacks, not guest-to-host (VMX) attacks. Mitigation requires both a microcode update (IPU 2025.1 / microcode-20250512+, which fixes IBPB to fully flush indirect branch predictions) and a kernel update (CONFIG_MITIGATION_ITS, Linux 6.15+) that aligns branch/return thunks or uses RSB stuffing. Performance impact is low.
|
||||
|
||||
</details>
|
||||
|
||||
## Unsupported CVEs
|
||||
|
||||
@@ -161,6 +161,7 @@ CVE-2023-20569|INCEPTION|inception|Inception, return address security (RAS)
|
||||
CVE-2023-23583|REPTAR|reptar|Reptar, redundant prefix issue
|
||||
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)
|
||||
'
|
||||
|
||||
# Derive the supported CVE list from the registry
|
||||
|
||||
@@ -106,9 +106,10 @@ is_cpu_affected() {
|
||||
_set_immune tsa
|
||||
# Retbleed: AMD (CVE-2022-29900) and Intel (CVE-2022-29901) specific:
|
||||
_set_immune retbleed
|
||||
# Downfall & Reptar are Intel specific, look for "is_intel" below:
|
||||
# Downfall, Reptar & ITS are Intel specific, look for "is_intel" below:
|
||||
_set_immune downfall
|
||||
_set_immune reptar
|
||||
_set_immune its
|
||||
|
||||
if is_cpu_mds_free; then
|
||||
_infer_immune msbds
|
||||
@@ -261,6 +262,32 @@ is_cpu_affected() {
|
||||
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)
|
||||
# immunity: X86_FEATURE_BHI_CTRL (none of the affected CPUs have this)
|
||||
# vendor scope: Intel only (family 6), with stepping constraints on some models
|
||||
if [ "$cap_its_no" = 1 ]; then
|
||||
pr_debug "is_cpu_affected: its: not affected (ITS_NO)"
|
||||
_set_immune its
|
||||
elif [ "$cpu_family" = 6 ]; then
|
||||
set -u
|
||||
if { [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] && [ "$cpu_stepping" -gt 5 ]; } ||
|
||||
{ [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] && [ "$cpu_stepping" -gt 11 ]; } ||
|
||||
{ [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] && [ "$cpu_stepping" -gt 12 ]; } ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_D" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_X" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE_L" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE_L" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE" ] ||
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ]; then
|
||||
pr_debug "is_cpu_affected: its: affected"
|
||||
_set_vuln its
|
||||
fi
|
||||
set +u
|
||||
fi
|
||||
# Reptar
|
||||
# the only way to know whether a CPU is vuln, is to check whether there is a known ucode update for it,
|
||||
# as the mitigation is only ucode-based and there's no flag exposed by the kernel or by an updated ucode.
|
||||
@@ -520,12 +547,12 @@ is_cpu_affected() {
|
||||
_infer_immune itlbmh
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2154 # affected_zenbleed/inception/retbleed/tsa/downfall/reptar set via eval (_set_immune)
|
||||
# shellcheck disable=SC2154 # affected_zenbleed/inception/retbleed/tsa/downfall/reptar/its set via eval (_set_immune)
|
||||
{
|
||||
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"
|
||||
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"
|
||||
}
|
||||
affected_variantl1tf_sgx="$affected_variantl1tf"
|
||||
# even if we are affected to L1TF, if there's no SGX, we're not affected to the original foreshadow
|
||||
|
||||
@@ -734,6 +734,7 @@ check_cpu() {
|
||||
cap_tsx_ctrl_msr=-1
|
||||
cap_gds_ctrl=-1
|
||||
cap_gds_no=-1
|
||||
cap_its_no=-1
|
||||
if [ "$cap_arch_capabilities" = -1 ]; then
|
||||
pstatus yellow UNKNOWN
|
||||
elif [ "$cap_arch_capabilities" != 1 ]; then
|
||||
@@ -748,6 +749,7 @@ check_cpu() {
|
||||
cap_tsx_ctrl_msr=0
|
||||
cap_gds_ctrl=0
|
||||
cap_gds_no=0
|
||||
cap_its_no=0
|
||||
pstatus yellow NO
|
||||
else
|
||||
read_msr $MSR_IA32_ARCH_CAPABILITIES
|
||||
@@ -763,6 +765,7 @@ check_cpu() {
|
||||
cap_tsx_ctrl_msr=0
|
||||
cap_gds_ctrl=0
|
||||
cap_gds_no=0
|
||||
cap_its_no=0
|
||||
if [ $ret = $READ_MSR_RET_OK ]; then
|
||||
capabilities=$ret_read_msr_value
|
||||
# https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/include/asm/msr-index.h#n82
|
||||
@@ -778,7 +781,8 @@ 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
|
||||
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"
|
||||
[ $((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"
|
||||
if [ "$cap_ibrs_all" = 1 ]; then
|
||||
pstatus green YES
|
||||
else
|
||||
|
||||
163
src/vulns/CVE-2024-28956.sh
Normal file
163
src/vulns/CVE-2024-28956.sh
Normal file
@@ -0,0 +1,163 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
###############################
|
||||
# CVE-2024-28956, ITS, Indirect Target Selection
|
||||
|
||||
check_CVE_2024_28956() {
|
||||
check_cve 'CVE-2024-28956'
|
||||
}
|
||||
|
||||
check_CVE_2024_28956_linux() {
|
||||
local status sys_interface_available msg kernel_its kernel_its_err ret
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
|
||||
if sys_interface_check "$VULN_SYSFS_BASE/indirect_target_selection"; then
|
||||
# this kernel has the /sys interface, trust it over everything
|
||||
sys_interface_available=1
|
||||
#
|
||||
# Kernel source inventory for indirect_target_selection (ITS)
|
||||
#
|
||||
# --- sysfs messages ---
|
||||
# all versions:
|
||||
# "Not affected" (cpu_show_common, pre-existing)
|
||||
#
|
||||
# --- mainline ---
|
||||
# f4818881c47f (v6.15-rc2, initial ITS sysfs):
|
||||
# "Vulnerable" (ITS_MITIGATION_OFF)
|
||||
# "Mitigation: Aligned branch/return thunks" (ITS_MITIGATION_ALIGNED_THUNKS)
|
||||
# "Mitigation: Retpolines, Stuffing RSB" (ITS_MITIGATION_RETPOLINE_STUFF)
|
||||
# 2665281a07e1 (v6.15-rc2, added vmexit option):
|
||||
# "Mitigation: Vulnerable, KVM: Not affected" (ITS_MITIGATION_VMEXIT_ONLY)
|
||||
# facd226f7e0c (v6.15-rc2, added stuff cmdline option):
|
||||
# no string changes; added "stuff" boot param value
|
||||
# 61ab72c2c6bf (v6.16-rc1, restructured select/update/apply):
|
||||
# no string changes; added ITS_MITIGATION_AUTO (internal, resolved before display)
|
||||
# split into its_select_mitigation() + its_update_mitigation() + its_apply_mitigation()
|
||||
# 0cdd2c4f35cf (v6.18-rc1, attack vector controls):
|
||||
# no string changes; added per-vector on/off control
|
||||
#
|
||||
# --- stable backports ---
|
||||
# 5.10.y, 5.15.y, 6.1.y: 3 strings only (no VMEXIT_ONLY, no RETPOLINE_STUFF
|
||||
# in 5.10/5.15/6.1). Uses CONFIG_RETPOLINE/CONFIG_RETHUNK (not CONFIG_MITIGATION_*).
|
||||
# 6.6.y, 6.12.y, 6.14.y, 6.15.y: all 4 strings, full vmexit+stuff support.
|
||||
# 6.16.y+: restructured 3-phase select/update/apply.
|
||||
# Not backported to: 5.4.y, 6.11.y, 6.13.y.
|
||||
#
|
||||
# --- RHEL/CentOS ---
|
||||
# rocky9 (5.14): all 4 strings, restructured 3-phase version.
|
||||
# rocky10 (6.12): all 4 strings, restructured 3-phase version.
|
||||
# Not backported to: centos7, rocky8.
|
||||
#
|
||||
# --- Kconfig symbols ---
|
||||
# f4818881c47f (v6.15-rc2): CONFIG_MITIGATION_ITS (default y)
|
||||
# depends on CPU_SUP_INTEL && X86_64 && MITIGATION_RETPOLINE && MITIGATION_RETHUNK
|
||||
# stable 5.10.y, 5.15.y, 6.1.y: CONFIG_MITIGATION_ITS
|
||||
# depends on CONFIG_RETPOLINE && CONFIG_RETHUNK (pre-rename names)
|
||||
#
|
||||
# --- kernel functions (for $opt_map / System.map) ---
|
||||
# f4818881c47f (v6.15-rc2): its_select_mitigation(), its_parse_cmdline(),
|
||||
# its_show_state()
|
||||
# 61ab72c2c6bf (v6.16-rc1): split into its_select_mitigation() +
|
||||
# its_update_mitigation() + its_apply_mitigation()
|
||||
# stable 5.10.y-6.15.y: its_select_mitigation() (no split)
|
||||
# rocky9, rocky10: its_select_mitigation() + its_update_mitigation() +
|
||||
# its_apply_mitigation()
|
||||
#
|
||||
# --- CPU affection logic (for is_cpu_affected) ---
|
||||
# X86_BUG_ITS is set when ALL conditions are true:
|
||||
# 1. Intel vendor, family 6
|
||||
# 2. CPU matches model blacklist (with stepping constraints)
|
||||
# 3. ARCH_CAP_ITS_NO (bit 62 of IA32_ARCH_CAPABILITIES) is NOT set
|
||||
# 4. X86_FEATURE_BHI_CTRL is NOT present
|
||||
# 159013a7ca18 (v6.15-rc2, initial model list):
|
||||
# Intel: SKYLAKE_X (stepping > 5), KABYLAKE_L (stepping > 0xb),
|
||||
# KABYLAKE (stepping > 0xc), ICELAKE_L, ICELAKE_D, ICELAKE_X,
|
||||
# COMETLAKE, COMETLAKE_L, TIGERLAKE_L, TIGERLAKE, ROCKETLAKE
|
||||
# (all steppings unless noted)
|
||||
# ITS_NATIVE_ONLY flag (X86_BUG_ITS_NATIVE_ONLY): set for
|
||||
# ICELAKE_L, ICELAKE_D, ICELAKE_X, TIGERLAKE_L, TIGERLAKE, ROCKETLAKE
|
||||
# These CPUs are affected for user-to-kernel but NOT guest-to-host (VMX)
|
||||
# immunity: ARCH_CAP_ITS_NO (bit 62 of IA32_ARCH_CAPABILITIES)
|
||||
# immunity: X86_FEATURE_BHI_CTRL (none of the affected CPUs have this)
|
||||
# vendor scope: Intel only
|
||||
#
|
||||
# all messages start with either "Not affected", "Vulnerable", or "Mitigation"
|
||||
status=$ret_sys_interface_check_status
|
||||
fi
|
||||
|
||||
if [ "$opt_sysfs_only" != 1 ]; then
|
||||
pr_info_nol "* Kernel supports ITS mitigation: "
|
||||
kernel_its=''
|
||||
kernel_its_err=''
|
||||
if [ -n "$g_kernel_err" ]; then
|
||||
kernel_its_err="$g_kernel_err"
|
||||
elif grep -q 'indirect_target_selection' "$g_kernel"; then
|
||||
kernel_its="found indirect_target_selection in kernel image"
|
||||
fi
|
||||
if [ -z "$kernel_its" ] && [ -r "$opt_config" ]; then
|
||||
if grep -q '^CONFIG_MITIGATION_ITS=y' "$opt_config"; then
|
||||
kernel_its="ITS mitigation config option found enabled in kernel config"
|
||||
fi
|
||||
fi
|
||||
if [ -z "$kernel_its" ] && [ -n "$opt_map" ]; then
|
||||
if grep -q 'its_select_mitigation' "$opt_map"; then
|
||||
kernel_its="found its_select_mitigation in System.map"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$kernel_its" ]; then
|
||||
pstatus green YES "$kernel_its"
|
||||
elif [ -n "$kernel_its_err" ]; then
|
||||
pstatus yellow UNKNOWN "$kernel_its_err"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
pr_info_nol "* CPU explicitly indicates not being affected by ITS (ITS_NO): "
|
||||
if [ "$cap_its_no" = -1 ]; then
|
||||
pstatus yellow UNKNOWN
|
||||
elif [ "$cap_its_no" = 1 ]; then
|
||||
pstatus green YES
|
||||
else
|
||||
pstatus yellow NO
|
||||
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
|
||||
if [ "$cap_its_no" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "CPU is not affected (ITS_NO)"
|
||||
elif [ -n "$kernel_its" ]; then
|
||||
pvulnstatus "$cve" OK "Kernel mitigates the vulnerability"
|
||||
elif [ -z "$kernel_its" ] && [ -z "$kernel_its_err" ]; then
|
||||
pvulnstatus "$cve" VULN "Your kernel doesn't support ITS mitigation"
|
||||
explain "Update your kernel to a version that includes ITS mitigation (Linux 6.15+, or check\n" \
|
||||
"if your distro has a backport). Also update your CPU microcode to ensure IBPB fully\n" \
|
||||
"flushes indirect branch predictions (microcode-20250512+)."
|
||||
else
|
||||
pvulnstatus "$cve" UNK "couldn't determine mitigation status: $kernel_its_err"
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" "$status" "$msg"
|
||||
fi
|
||||
}
|
||||
|
||||
check_CVE_2024_28956_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