# 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 is_x86_kernel && grep -q 'indirect_target_selection' "$g_kernel"; then
            kernel_its="found indirect_target_selection in kernel image"
        fi
        if [ -z "$kernel_its" ] && is_x86_kernel && [ -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" ] && is_x86_kernel && [ -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
}
