From 05e09bb7f4869a9ab238d5c1b0979f3ba9c1344d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lesimple?= Date: Mon, 30 Mar 2026 21:13:21 +0200 Subject: [PATCH] feat: implement CVE-2024-36350 CVE-2024-36357 (Transient Scheduler Attack) --- .github/workflows/expected_cve_count | 2 +- src/libs/002_core_globals.sh | 2 + src/libs/200_cpu_affected.sh | 13 +++ src/libs/230_util_optparse.sh | 14 +++- src/libs/400_hw_check.sh | 45 +++++++++++ src/vulns/CVE-2024-36350.sh | 116 +++++++++++++++++++++++++++ src/vulns/CVE-2024-36357.sh | 102 +++++++++++++++++++++++ 7 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 src/vulns/CVE-2024-36350.sh create mode 100644 src/vulns/CVE-2024-36357.sh diff --git a/.github/workflows/expected_cve_count b/.github/workflows/expected_cve_count index d6b2404..aabe6ec 100644 --- a/.github/workflows/expected_cve_count +++ b/.github/workflows/expected_cve_count @@ -1 +1 @@ -19 +21 diff --git a/src/libs/002_core_globals.sh b/src/libs/002_core_globals.sh index 83fb056..4328db9 100644 --- a/src/libs/002_core_globals.sh +++ b/src/libs/002_core_globals.sh @@ -157,6 +157,8 @@ CVE-2023-20593|ZENBLEED|zenbleed|Zenbleed, cross-process information leak CVE-2022-40982|DOWNFALL|downfall|Downfall, gather data sampling (GDS) 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) ' # Derive the supported CVE list from the registry diff --git a/src/libs/200_cpu_affected.sh b/src/libs/200_cpu_affected.sh index a004918..947edb5 100644 --- a/src/libs/200_cpu_affected.sh +++ b/src/libs/200_cpu_affected.sh @@ -74,6 +74,8 @@ is_cpu_affected() { # Zenbleed and Inception are both AMD specific, look for "is_amd" below: affected_zenbleed=immune affected_inception=immune + # TSA is AMD specific (Zen 3/4), look for "is_amd" below: + affected_tsa=immune # Downfall & Reptar are Intel specific, look for "is_intel" below: affected_downfall=immune affected_reptar=immune @@ -295,6 +297,16 @@ is_cpu_affected() { affected_inception=vuln fi + # TSA (Zen 3/4 are affected, unless CPUID says otherwise) + if [ "$cap_tsa_sq_no" = 1 ] && [ "$cap_tsa_l1_no" = 1 ]; then + # capability bits for AMD processors that explicitly state + # they're not affected to TSA-SQ and TSA-L1 + # these vars are set in check_cpu() + pr_debug "is_cpu_affected: TSA_SQ_NO and TSA_L1_NO are set so not vuln to TSA" + elif [ "$cpu_family" = $((0x19)) ]; then + affected_tsa=vuln + fi + elif [ "$cpu_vendor" = CAVIUM ]; then affected_variant3=immune affected_variant3a=immune @@ -455,6 +467,7 @@ is_cpu_affected() { [ "$affected_downfall" = "immune" ] && affected_downfall=1 || affected_downfall=0 [ "$affected_inception" = "immune" ] && affected_inception=1 || affected_inception=0 [ "$affected_reptar" = "immune" ] && affected_reptar=1 || affected_reptar=0 + [ "$affected_tsa" = "immune" ] && affected_tsa=1 || affected_tsa=0 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 [ "$cap_sgx" = 0 ] && affected_variantl1tf_sgx=1 diff --git a/src/libs/230_util_optparse.sh b/src/libs/230_util_optparse.sh index a0401d7..8987343 100644 --- a/src/libs/230_util_optparse.sh +++ b/src/libs/230_util_optparse.sh @@ -166,7 +166,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, inception" + echo "1, 2, 3, 3a, 4, msbds, mfbds, mlpds, mdsum, l1tf, taa, mcepsc, srbds, zenbleed, downfall, inception, reptar, tsa, tsa-sq, tsa-l1" exit 0 ;; 1) @@ -237,6 +237,18 @@ while [ -n "${1:-}" ]; do opt_cve_list="$opt_cve_list CVE-2023-23583" opt_cve_all=0 ;; + tsa) + opt_cve_list="$opt_cve_list CVE-2024-36350 CVE-2024-36357" + opt_cve_all=0 + ;; + tsa-sq) + opt_cve_list="$opt_cve_list CVE-2024-36350" + opt_cve_all=0 + ;; + tsa-l1) + opt_cve_list="$opt_cve_list CVE-2024-36357" + opt_cve_all=0 + ;; *) echo "$0: error: invalid parameter '$2' for --variant, see --variant help for a list" >&2 exit 255 diff --git a/src/libs/400_hw_check.sh b/src/libs/400_hw_check.sh index 37e4f09..cd1d1b4 100644 --- a/src/libs/400_hw_check.sh +++ b/src/libs/400_hw_check.sh @@ -963,6 +963,51 @@ check_cpu() { fi fi + if is_amd || is_hygon; then + pr_info " * Transient Scheduler Attacks" + pr_info_nol " * CPU indicates TSA_SQ_NO: " + cap_tsa_sq_no='' + read_cpuid 0x80000021 0x0 $ECX 1 1 1 + ret=$? + if [ $ret = $READ_CPUID_RET_OK ]; then + pstatus green YES + cap_tsa_sq_no=1 + elif [ $ret = $READ_CPUID_RET_KO ]; then + pstatus yellow NO + cap_tsa_sq_no=0 + else + pstatus yellow UNKNOWN "$ret_read_cpuid_msg" + fi + + pr_info_nol " * CPU indicates TSA_L1_NO: " + cap_tsa_l1_no='' + read_cpuid 0x80000021 0x0 $ECX 2 1 1 + ret=$? + if [ $ret = $READ_CPUID_RET_OK ]; then + pstatus green YES + cap_tsa_l1_no=1 + elif [ $ret = $READ_CPUID_RET_KO ]; then + pstatus yellow NO + cap_tsa_l1_no=0 + else + pstatus yellow UNKNOWN "$ret_read_cpuid_msg" + fi + + pr_info_nol " * CPU indicates VERW clears CPU buffers: " + cap_verw_clear='' + read_cpuid 0x80000021 0x0 $EAX 5 1 1 + ret=$? + if [ $ret = $READ_CPUID_RET_OK ]; then + pstatus green YES + cap_verw_clear=1 + elif [ $ret = $READ_CPUID_RET_KO ]; then + pstatus yellow NO + cap_verw_clear=0 + else + pstatus yellow UNKNOWN "$ret_read_cpuid_msg" + fi + fi + pr_info_nol " * CPU supports Transactional Synchronization Extensions (TSX): " ret=$READ_CPUID_RET_KO cap_rtm=0 diff --git a/src/vulns/CVE-2024-36350.sh b/src/vulns/CVE-2024-36350.sh new file mode 100644 index 0000000..31bd357 --- /dev/null +++ b/src/vulns/CVE-2024-36350.sh @@ -0,0 +1,116 @@ +# vim: set ts=4 sw=4 sts=4 et: +#################### +# TSA-SQ section + +# CVE-2024-36350 TSA-SQ (transient scheduler attack - store queue) - entry point +check_CVE_2024_36350() { + check_cve 'CVE-2024-36350' +} + +# CVE-2024-36350 TSA-SQ (transient scheduler attack - store queue) - Linux mitigation check +check_CVE_2024_36350_linux() { + local status sys_interface_available msg kernel_tsa kernel_tsa_err smt_enabled ret + status=UNK + sys_interface_available=0 + msg='' + + if sys_interface_check "$VULN_SYSFS_BASE/tsa"; then + # this kernel has the /sys interface, trust it over everything + sys_interface_available=1 + status=$ret_sys_interface_check_status + fi + + if [ "$opt_sysfs_only" != 1 ]; then + pr_info_nol "* Kernel supports TSA mitigation: " + kernel_tsa='' + kernel_tsa_err='' + if [ -n "$g_kernel_err" ]; then + kernel_tsa_err="$g_kernel_err" + # commit d8010d4ba43e: "Transient Scheduler Attacks:" is printed by tsa_select_mitigation() + elif grep -q 'Transient Scheduler Attacks' "$g_kernel"; then + kernel_tsa="found TSA mitigation message in kernel image" + fi + if [ -z "$kernel_tsa" ] && [ -r "$opt_config" ]; then + if grep -q '^CONFIG_MITIGATION_TSA=y' "$opt_config"; then + kernel_tsa="CONFIG_MITIGATION_TSA=y found in kernel config" + fi + fi + if [ -z "$kernel_tsa" ] && [ -n "$g_kernel_map" ]; then + if grep -q 'tsa_select_mitigation' "$g_kernel_map"; then + kernel_tsa="found tsa_select_mitigation in System.map" + fi + fi + if [ -n "$kernel_tsa" ]; then + pstatus green YES "$kernel_tsa" + elif [ -n "$kernel_tsa_err" ]; then + pstatus yellow UNKNOWN "$kernel_tsa_err" + else + 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 + + 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 + + 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 + + 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_verw_clear" = 1 ] && [ -n "$kernel_tsa" ]; then + if [ "$opt_paranoid" = 1 ] && [ "$smt_enabled" = 0 ]; then + pvulnstatus "$cve" VULN "Mitigation active but SMT must be disabled for full TSA-SQ protection" + explain "Disable SMT by adding \`nosmt\` to your kernel command line for complete protection against cross-thread TSA-SQ leakage." + else + pvulnstatus "$cve" OK "Both kernel and microcode mitigate the vulnerability" + fi + elif [ "$cap_verw_clear" = 1 ]; then + pvulnstatus "$cve" VULN "Microcode supports mitigation but kernel is too old" + explain "Update your kernel to a version that supports CONFIG_MITIGATION_TSA (Linux 6.16+),\n " \ + "or check if your distribution has backported the TSA mitigation." + elif [ -n "$kernel_tsa" ]; then + pvulnstatus "$cve" VULN "Kernel supports mitigation but microcode is too old" + explain "Update your CPU microcode via a BIOS/firmware update from your OEM.\n " \ + "The microcode must expose the VERW_CLEAR capability (CPUID 0x80000021 EAX bit 5)." + else + pvulnstatus "$cve" VULN "Neither kernel nor microcode mitigate the vulnerability" + explain "Both a kernel update (CONFIG_MITIGATION_TSA, Linux 6.16+) and a microcode/firmware update\n " \ + "from your OEM are needed to mitigate this vulnerability." + fi + else + pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg" + fi + else + pvulnstatus "$cve" "$status" "$msg" + fi +} diff --git a/src/vulns/CVE-2024-36357.sh b/src/vulns/CVE-2024-36357.sh new file mode 100644 index 0000000..5cbad32 --- /dev/null +++ b/src/vulns/CVE-2024-36357.sh @@ -0,0 +1,102 @@ +# vim: set ts=4 sw=4 sts=4 et: +#################### +# TSA-L1 section + +# CVE-2024-36357 TSA-L1 (transient scheduler attack - L1 cache) - entry point +check_CVE_2024_36357() { + check_cve 'CVE-2024-36357' +} + +# CVE-2024-36357 TSA-L1 (transient scheduler attack - L1 cache) - Linux mitigation check +check_CVE_2024_36357_linux() { + local status sys_interface_available msg kernel_tsa kernel_tsa_err ret + status=UNK + sys_interface_available=0 + msg='' + + if sys_interface_check "$VULN_SYSFS_BASE/tsa"; then + # this kernel has the /sys interface, trust it over everything + sys_interface_available=1 + status=$ret_sys_interface_check_status + fi + + if [ "$opt_sysfs_only" != 1 ]; then + pr_info_nol "* Kernel supports TSA mitigation: " + kernel_tsa='' + kernel_tsa_err='' + if [ -n "$g_kernel_err" ]; then + kernel_tsa_err="$g_kernel_err" + # commit d8010d4ba43e: "Transient Scheduler Attacks:" is printed by tsa_select_mitigation() + elif grep -q 'Transient Scheduler Attacks' "$g_kernel"; then + kernel_tsa="found TSA mitigation message in kernel image" + fi + if [ -z "$kernel_tsa" ] && [ -r "$opt_config" ]; then + if grep -q '^CONFIG_MITIGATION_TSA=y' "$opt_config"; then + kernel_tsa="CONFIG_MITIGATION_TSA=y found in kernel config" + fi + fi + if [ -z "$kernel_tsa" ] && [ -n "$g_kernel_map" ]; then + if grep -q 'tsa_select_mitigation' "$g_kernel_map"; then + kernel_tsa="found tsa_select_mitigation in System.map" + fi + fi + if [ -n "$kernel_tsa" ]; then + pstatus green YES "$kernel_tsa" + elif [ -n "$kernel_tsa_err" ]; then + pstatus yellow UNKNOWN "$kernel_tsa_err" + else + 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 + + 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 + + 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_verw_clear" = 1 ] && [ -n "$kernel_tsa" ]; then + pvulnstatus "$cve" OK "Both kernel and microcode mitigate the vulnerability" + elif [ "$cap_verw_clear" = 1 ]; then + pvulnstatus "$cve" VULN "Microcode supports mitigation but kernel is too old" + explain "Update your kernel to a version that supports CONFIG_MITIGATION_TSA (Linux 6.16+),\n " \ + "or check if your distribution has backported the TSA mitigation." + elif [ -n "$kernel_tsa" ]; then + pvulnstatus "$cve" VULN "Kernel supports mitigation but microcode is too old" + explain "Update your CPU microcode via a BIOS/firmware update from your OEM.\n " \ + "The microcode must expose the VERW_CLEAR capability (CPUID 0x80000021 EAX bit 5)." + else + pvulnstatus "$cve" VULN "Neither kernel nor microcode mitigate the vulnerability" + explain "Both a kernel update (CONFIG_MITIGATION_TSA, Linux 6.16+) and a microcode/firmware update\n " \ + "from your OEM are needed to mitigate this vulnerability." + fi + else + pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg" + fi + else + pvulnstatus "$cve" "$status" "$msg" + fi +}