# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2022-29901, Retbleed (Intel), RSB Alternate Behavior (RSBA)

check_CVE_2022_29901() {
    check_cve 'CVE-2022-29901'
}

check_CVE_2022_29901_linux() {
    local status sys_interface_available msg kernel_retbleed kernel_retbleed_err kernel_ibrs_entry
    status=UNK
    sys_interface_available=0
    msg=''

    #
    # Kernel source inventory for retbleed (CVE-2022-29900 / CVE-2022-29901)
    #
    # See CVE-2022-29900.sh for the full sysfs/Kconfig/function/stable/vendor inventory.
    #
    # Intel-specific notes:
    # - eIBRS (IBRS_ALL) mitigates the vulnerability on Intel
    # - plain retpoline does NOT mitigate on RSBA-capable CPUs (Retbleed bypasses retpoline)
    # - IBRS entry also mitigates
    # - call depth tracking / stuffing mitigates (v6.2+)
    #
    # --- Kconfig symbols (Intel-relevant) ---
    # CONFIG_CPU_IBRS_ENTRY (< 6.9) / CONFIG_MITIGATION_IBRS_ENTRY (>= 6.9): Intel IBRS
    # CONFIG_CALL_DEPTH_TRACKING (< 6.9) / CONFIG_MITIGATION_CALL_DEPTH_TRACKING (>= 6.9): stuffing
    #
    # --- CPU affection logic (Intel) ---
    # 6ad0ad2bf8a6 (v5.19-rc7, initial Intel list):
    #   SKYLAKE_L, SKYLAKE, SKYLAKE_X, KABYLAKE_L, KABYLAKE,
    #   ICELAKE_L, COMETLAKE, COMETLAKE_L, LAKEFIELD, ROCKETLAKE
    # f54d45372c6a (post-v5.19): + CANNONLAKE_L
    # + any Intel with ARCH_CAP_RSBA set in IA32_ARCH_CAPABILITIES MSR (bit 2)
    # immunity: none (no _NO bit for RETBLEED on Intel; eIBRS is a mitigation, not immunity)
    #

    if sys_interface_check "$VULN_SYSFS_BASE/retbleed"; 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 mitigation: "
        if [ -n "$g_kernel_err" ]; then
            kernel_retbleed_err="$g_kernel_err"
        elif grep -q 'retbleed' "$g_kernel"; then
            kernel_retbleed="found retbleed mitigation logic in kernel image"
        fi
        if [ -z "$kernel_retbleed" ] && [ -n "$opt_map" ]; then
            if grep -q 'retbleed_select_mitigation' "$opt_map"; then
                kernel_retbleed="found retbleed_select_mitigation in System.map"
            fi
        fi
        if [ -n "$kernel_retbleed" ]; then
            pstatus green YES "$kernel_retbleed"
        elif [ -n "$kernel_retbleed_err" ]; then
            pstatus yellow UNKNOWN "$kernel_retbleed_err"
        else
            pstatus yellow NO
        fi

        pr_info_nol "* Kernel compiled with IBRS_ENTRY support: "
        if [ -r "$opt_config" ]; then
            # CONFIG_CPU_IBRS_ENTRY: Linux < 6.9
            # CONFIG_MITIGATION_IBRS_ENTRY: Linux >= 6.9
            if grep -Eq '^CONFIG_(CPU|MITIGATION)_IBRS_ENTRY=y' "$opt_config"; then
                pstatus green YES
                kernel_ibrs_entry="CONFIG_(CPU|MITIGATION)_IBRS_ENTRY=y found in kernel config"
            else
                pstatus yellow NO
            fi
        else
            if [ -n "$g_kernel_err" ]; then
                pstatus yellow UNKNOWN "$g_kernel_err"
            elif [ -n "$kernel_retbleed" ]; then
                kernel_ibrs_entry="retbleed mitigation logic present in kernel (IBRS_ENTRY status unknown)"
                pstatus yellow UNKNOWN "kernel has retbleed mitigation but config not available to verify"
            else
                pstatus yellow NO "your kernel is too old and doesn't have the retbleed mitigation logic"
            fi
        fi

        pr_info_nol "* CPU supports Enhanced IBRS (IBRS_ALL): "
        if [ "$g_mode" = live ] || [ "$cap_ibrs_all" != -1 ]; then
            if [ "$cap_ibrs_all" = 1 ]; then
                pstatus green YES
            elif [ "$cap_ibrs_all" = 0 ]; then
                pstatus yellow NO
            else
                pstatus yellow UNKNOWN
            fi
        else
            pstatus blue N/A "not testable in no-runtime mode"
        fi

        pr_info_nol "* CPU has RSB Alternate Behavior (RSBA): "
        if [ "$g_mode" = live ] || [ "$cap_rsba" != -1 ]; then
            if [ "$cap_rsba" = 1 ]; then
                pstatus yellow YES "this CPU is affected by RSB underflow"
            elif [ "$cap_rsba" = 0 ]; then
                pstatus green NO
            else
                pstatus yellow UNKNOWN
            fi
        else
            pstatus blue N/A "not testable in no-runtime mode"
        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 [ -z "$kernel_retbleed" ]; then
                pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the retbleed mitigation logic"
            elif [ "$cap_ibrs_all" = 1 ]; then
                if [ "$opt_paranoid" = 1 ] && [ "$cap_rrsba" = 1 ]; then
                    pvulnstatus "$cve" VULN "eIBRS is enabled but RRSBA is present, which may weaken the mitigation"
                    explain "In paranoid mode, the combination of eIBRS and RRSBA (Restricted RSB Alternate Behavior)\n" \
                        "is flagged because RRSBA means the RSB can still be influenced in some scenarios.\n" \
                        "Check if your firmware/kernel supports disabling RRSBA via RRSBA_CTRL."
                else
                    pvulnstatus "$cve" OK "Enhanced IBRS (IBRS_ALL) mitigates the vulnerability"
                fi
            elif [ -n "$kernel_ibrs_entry" ]; then
                pvulnstatus "$cve" OK "Your kernel has IBRS_ENTRY mitigation compiled-in"
            else
                pvulnstatus "$cve" VULN "Your kernel has retbleed mitigation but IBRS_ENTRY is not compiled-in and eIBRS is not available"
                explain "Retpoline alone does NOT mitigate Retbleed on RSBA-capable Intel CPUs.\n" \
                    "You need either Enhanced IBRS (eIBRS, via firmware/microcode update) or a kernel\n" \
                    "compiled with IBRS_ENTRY support (Linux 5.19+, CONFIG_(CPU|MITIGATION)_IBRS_ENTRY)."
            fi
        else
            pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
        fi
    else
        pvulnstatus "$cve" "$status" "$msg"
    fi
}

check_CVE_2022_29901_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
}
