split script in multiple files, reassembled through build.sh

This commit is contained in:
Stéphane Lesimple
2026-03-30 20:04:16 +02:00
parent 7e660812e9
commit cebda01d05
47 changed files with 7712 additions and 7617 deletions

603
src/vulns/CVE-2017-5715.sh Normal file
View File

@@ -0,0 +1,603 @@
# vim: set ts=4 sw=4 sts=4 et:
###################
# SPECTRE 2 SECTION
# CVE-2017-5715 Spectre Variant 2 (branch target injection) - entry point
check_CVE_2017_5715() {
check_cve 'CVE-2017-5715'
}
# CVE-2017-5715 Spectre Variant 2 (branch target injection) - Linux mitigation check
check_CVE_2017_5715_linux() {
local status sys_interface_available msg dir bp_harden_can_tell bp_harden retpoline retpoline_compiler retpoline_compiler_reason retp_enabled rsb_filling explain_hypervisor
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/spectre_v2"; 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 "* Mitigation 1"
g_ibrs_can_tell=0
g_ibrs_supported=''
g_ibrs_enabled=''
g_ibpb_can_tell=0
g_ibpb_supported=''
g_ibpb_enabled=''
if [ "$opt_live" = 1 ]; then
# in live mode, we can check for the ibrs_enabled file in debugfs
# all versions of the patches have it (NOT the case of IBPB or KPTI)
g_ibrs_can_tell=1
mount_debugfs
for dir in \
$DEBUGFS_BASE \
$DEBUGFS_BASE/x86 \
"$g_procfs/sys/kernel"; do
if [ -e "$dir/ibrs_enabled" ]; then
# if the file is there, we have IBRS compiled-in
# $DEBUGFS_BASE/ibrs_enabled: vanilla
# $DEBUGFS_BASE/x86/ibrs_enabled: Red Hat (see https://access.redhat.com/articles/3311301)
# /proc/sys/kernel/ibrs_enabled: OpenSUSE tumbleweed
g_specex_knob_dir=$dir
g_ibrs_supported="$dir/ibrs_enabled exists"
g_ibrs_enabled=$(cat "$dir/ibrs_enabled" 2>/dev/null)
pr_debug "ibrs: found $dir/ibrs_enabled=$g_ibrs_enabled"
# if ibrs_enabled is there, ibpb_enabled will be in the same dir
if [ -e "$dir/ibpb_enabled" ]; then
# if the file is there, we have IBPB compiled-in (see note above for IBRS)
g_ibpb_supported="$dir/ibpb_enabled exists"
g_ibpb_enabled=$(cat "$dir/ibpb_enabled" 2>/dev/null)
pr_debug "ibpb: found $dir/ibpb_enabled=$g_ibpb_enabled"
else
pr_debug "ibpb: $dir/ibpb_enabled file doesn't exist"
fi
break
else
pr_debug "ibrs: $dir/ibrs_enabled file doesn't exist"
fi
done
# on some newer kernels, the spec_ctrl_ibrs flag in "$g_procfs/cpuinfo"
# is set when ibrs has been administratively enabled (usually from cmdline)
# which in that case means ibrs is supported *and* enabled for kernel & user
# as per the ibrs patch series v3
if [ -z "$g_ibrs_supported" ]; then
if grep ^flags "$g_procfs/cpuinfo" | grep -qw spec_ctrl_ibrs; then
pr_debug "ibrs: found spec_ctrl_ibrs flag in $g_procfs/cpuinfo"
g_ibrs_supported="spec_ctrl_ibrs flag in $g_procfs/cpuinfo"
# enabled=2 -> kernel & user
g_ibrs_enabled=2
# XXX and what about ibpb ?
fi
fi
if [ -n "$ret_sys_interface_check_fullmsg" ]; then
# when IBPB is enabled on 4.15+, we can see it in sysfs
if echo "$ret_sys_interface_check_fullmsg" | grep -q 'IBPB'; then
pr_debug "ibpb: found enabled in sysfs"
[ -z "$g_ibpb_supported" ] && g_ibpb_supported='IBPB found enabled in sysfs'
[ -z "$g_ibpb_enabled" ] && g_ibpb_enabled=1
fi
# when IBRS_FW is enabled on 4.15+, we can see it in sysfs
if echo "$ret_sys_interface_check_fullmsg" | grep -q '[,;] IBRS_FW'; then
pr_debug "ibrs: found IBRS_FW in sysfs"
[ -z "$g_ibrs_supported" ] && g_ibrs_supported='found IBRS_FW in sysfs'
g_ibrs_fw_enabled=1
fi
# when IBRS is enabled on 4.15+, we can see it in sysfs
# on a more recent kernel, classic "IBRS" is not even longer an option, because of the performance impact.
# only "Enhanced IBRS" is available (on CPUs with the IBRS_ALL flag)
if echo "$ret_sys_interface_check_fullmsg" | grep -q -e '\<IBRS\>' -e 'Indirect Branch Restricted Speculation'; then
pr_debug "ibrs: found IBRS in sysfs"
[ -z "$g_ibrs_supported" ] && g_ibrs_supported='found IBRS in sysfs'
[ -z "$g_ibrs_enabled" ] && g_ibrs_enabled=3
fi
# checking for 'Enhanced IBRS' in sysfs, enabled on CPUs with IBRS_ALL
if echo "$ret_sys_interface_check_fullmsg" | grep -q -e 'Enhanced IBRS'; then
[ -z "$g_ibrs_supported" ] && g_ibrs_supported='found Enhanced IBRS in sysfs'
# 4 isn't actually a valid value of the now extinct "g_ibrs_enabled" flag file,
# that only went from 0 to 3, so we use 4 as "enhanced ibrs is enabled"
g_ibrs_enabled=4
fi
fi
# in live mode, if ibrs or ibpb is supported and we didn't find these are enabled, then they are not
[ -n "$g_ibrs_supported" ] && [ -z "$g_ibrs_enabled" ] && g_ibrs_enabled=0
[ -n "$g_ibpb_supported" ] && [ -z "$g_ibpb_enabled" ] && g_ibpb_enabled=0
fi
if [ -z "$g_ibrs_supported" ]; then
check_redhat_canonical_spectre
if [ "$g_redhat_canonical_spectre" = 1 ]; then
g_ibrs_supported="Red Hat/Ubuntu variant"
g_ibpb_supported="Red Hat/Ubuntu variant"
fi
fi
if [ -z "$g_ibrs_supported" ] && [ -n "$g_kernel" ]; then
if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
:
else
g_ibrs_can_tell=1
g_ibrs_supported=$("${opt_arch_prefix}strings" "$g_kernel" | grep -Fw -e '[,;] IBRS_FW' | head -n1)
if [ -n "$g_ibrs_supported" ]; then
pr_debug "ibrs: found ibrs evidence in kernel image ($g_ibrs_supported)"
g_ibrs_supported="found '$g_ibrs_supported' in kernel image"
fi
fi
fi
if [ -z "$g_ibrs_supported" ] && [ -n "$opt_map" ]; then
g_ibrs_can_tell=1
if grep -q spec_ctrl "$opt_map"; then
g_ibrs_supported="found spec_ctrl in symbols file"
pr_debug "ibrs: found '*spec_ctrl*' symbol in $opt_map"
fi
fi
# recent (4.15) vanilla kernels have IBPB but not IBRS, and without the debugfs tunables of Red Hat
# we can detect it directly in the image
if [ -z "$g_ibpb_supported" ] && [ -n "$g_kernel" ]; then
if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
:
else
g_ibpb_can_tell=1
g_ibpb_supported=$("${opt_arch_prefix}strings" "$g_kernel" | grep -Fw -e 'ibpb' -e ', IBPB' | head -n1)
if [ -n "$g_ibpb_supported" ]; then
pr_debug "ibpb: found ibpb evidence in kernel image ($g_ibpb_supported)"
g_ibpb_supported="found '$g_ibpb_supported' in kernel image"
fi
fi
fi
pr_info_nol " * Kernel is compiled with IBRS support: "
if [ -z "$g_ibrs_supported" ]; then
if [ "$g_ibrs_can_tell" = 1 ]; then
pstatus yellow NO
else
# problem obtaining/inspecting kernel or strings not installed, but if the later is true,
# then readelf is not installed either (both in binutils) which makes the former true, so
# either way g_kernel_err should be set
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
fi
else
if [ "$opt_verbose" -ge 2 ]; then
pstatus green YES "$g_ibrs_supported"
else
pstatus green YES
fi
fi
pr_info_nol " * IBRS enabled and active: "
if [ "$opt_live" = 1 ]; then
if [ "$g_ibpb_enabled" = 2 ]; then
# if ibpb=2, ibrs is forcefully=0
pstatus blue NO "IBPB used instead of IBRS in all kernel entrypoints"
else
# 0 means disabled
# 1 is enabled only for kernel space
# 2 is enabled for kernel and user space
# 3 is enabled
# 4 is enhanced ibrs enabled
case "$g_ibrs_enabled" in
0)
if [ "$g_ibrs_fw_enabled" = 1 ]; then
pstatus blue YES "for firmware code only"
else
pstatus yellow NO
fi
;;
1) if [ "$g_ibrs_fw_enabled" = 1 ]; then pstatus green YES "for kernel space and firmware code"; else pstatus green YES "for kernel space"; fi ;;
2) if [ "$g_ibrs_fw_enabled" = 1 ]; then pstatus green YES "for kernel, user space, and firmware code"; else pstatus green YES "for both kernel and user space"; fi ;;
3) if [ "$g_ibrs_fw_enabled" = 1 ]; then pstatus green YES "for kernel and firmware code"; else pstatus green YES; fi ;;
4) pstatus green YES "Enhanced flavor, performance impact will be greatly reduced" ;;
*) if [ "$cap_ibrs" != 'SPEC_CTRL' ] && [ "$cap_ibrs" != 'IBRS_SUPPORT' ] && [ "$cap_spec_ctrl" != -1 ]; then
pstatus yellow NO
pr_debug "ibrs: known cpu not supporting SPEC-CTRL or IBRS"
else
pstatus yellow UNKNOWN
fi ;;
esac
fi
else
pstatus blue N/A "not testable in offline mode"
fi
pr_info_nol " * Kernel is compiled with IBPB support: "
if [ -z "$g_ibpb_supported" ]; then
if [ "$g_ibpb_can_tell" = 1 ]; then
pstatus yellow NO
else
# if we're in offline mode without System.map, we can't really know
pstatus yellow UNKNOWN "in offline mode, we need the kernel image to be able to tell"
fi
else
if [ "$opt_verbose" -ge 2 ]; then
pstatus green YES "$g_ibpb_supported"
else
pstatus green YES
fi
fi
pr_info_nol " * IBPB enabled and active: "
if [ "$opt_live" = 1 ]; then
case "$g_ibpb_enabled" in
"")
if [ "$g_ibrs_supported" = 1 ]; then
pstatus yellow UNKNOWN
else
pstatus yellow NO
fi
;;
0)
pstatus yellow NO
;;
1) pstatus green YES ;;
2) pstatus green YES "IBPB used instead of IBRS in all kernel entrypoints" ;;
*) pstatus yellow UNKNOWN ;;
esac
else
pstatus blue N/A "not testable in offline mode"
fi
pr_info "* Mitigation 2"
pr_info_nol " * Kernel has branch predictor hardening (arm): "
bp_harden_can_tell=0
bp_harden=''
if [ -r "$opt_config" ]; then
bp_harden_can_tell=1
bp_harden=$(grep -w 'CONFIG_HARDEN_BRANCH_PREDICTOR=y' "$opt_config")
if [ -n "$bp_harden" ]; then
pstatus green YES
pr_debug "bp_harden: found '$bp_harden' in $opt_config"
fi
fi
if [ -z "$bp_harden" ] && [ -n "$opt_map" ]; then
bp_harden_can_tell=1
bp_harden=$(grep -w bp_hardening_data "$opt_map")
if [ -n "$bp_harden" ]; then
pstatus green YES
pr_debug "bp_harden: found '$bp_harden' in $opt_map"
fi
fi
if [ -z "$bp_harden" ]; then
if [ "$bp_harden_can_tell" = 1 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN
fi
fi
pr_info_nol " * Kernel compiled with retpoline option: "
# We check the RETPOLINE kernel options
retpoline=0
if [ -r "$opt_config" ]; then
if grep -q '^CONFIG_\(MITIGATION_\)\?RETPOLINE=y' "$opt_config"; then
pstatus green YES
retpoline=1
# shellcheck disable=SC2046
pr_debug 'retpoline: found '$(grep '^CONFIG_\(MITIGATION_\)\?RETPOLINE' "$opt_config")" in $opt_config"
else
pstatus yellow NO
fi
else
pstatus yellow UNKNOWN "couldn't read your kernel configuration"
fi
if [ "$retpoline" = 1 ]; then
# Now check if the compiler used to compile the kernel knows how to insert retpolines in generated asm
# For gcc, this is -mindirect-branch=thunk-extern (detected by the kernel makefiles)
# See gcc commit https://github.com/hjl-tools/gcc/commit/23b517d4a67c02d3ef80b6109218f2aadad7bd79
# In latest retpoline LKML patches, the noretpoline_setup symbol exists only if CONFIG_MITIGATION_RETPOLINE is set
# *AND* if the compiler is retpoline-compliant, so look for that symbol. The name of this kernel config
# option before version 6.9-rc1 is CONFIG_RETPOLINE.
#
# if there is "retpoline" in the file and NOT "minimal", then it's full retpoline
# (works for vanilla and Red Hat variants)
#
# since 5.15.28, this is now "Retpolines" as the implementation was switched to a generic one,
# so we look for both "retpoline" and "retpolines"
if [ "$opt_live" = 1 ] && [ -n "$ret_sys_interface_check_fullmsg" ]; then
if echo "$ret_sys_interface_check_fullmsg" | grep -qwi -e retpoline -e retpolines; then
if echo "$ret_sys_interface_check_fullmsg" | grep -qwi minimal; then
retpoline_compiler=0
retpoline_compiler_reason="kernel reports minimal retpoline compilation"
else
retpoline_compiler=1
retpoline_compiler_reason="kernel reports full retpoline compilation"
fi
fi
elif [ -n "$opt_map" ]; then
# look for the symbol
if grep -qw noretpoline_setup "$opt_map"; then
retpoline_compiler=1
retpoline_compiler_reason="noretpoline_setup symbol found in System.map"
fi
elif [ -n "$g_kernel" ]; then
# look for the symbol
if command -v "${opt_arch_prefix}nm" >/dev/null 2>&1; then
# the proper way: use nm and look for the symbol
if "${opt_arch_prefix}nm" "$g_kernel" 2>/dev/null | grep -qw 'noretpoline_setup'; then
retpoline_compiler=1
retpoline_compiler_reason="noretpoline_setup found in kernel symbols"
fi
elif grep -q noretpoline_setup "$g_kernel"; then
# if we don't have nm, nevermind, the symbol name is long enough to not have
# any false positive using good old grep directly on the binary
retpoline_compiler=1
retpoline_compiler_reason="noretpoline_setup found in kernel"
fi
fi
if [ -n "$retpoline_compiler" ]; then
pr_info_nol " * Kernel compiled with a retpoline-aware compiler: "
if [ "$retpoline_compiler" = 1 ]; then
if [ -n "$retpoline_compiler_reason" ]; then
pstatus green YES "$retpoline_compiler_reason"
else
pstatus green YES
fi
else
if [ -n "$retpoline_compiler_reason" ]; then
pstatus red NO "$retpoline_compiler_reason"
else
pstatus red NO
fi
fi
fi
fi
# only Red Hat has a tunable to disable it on runtime
retp_enabled=-1
if [ "$opt_live" = 1 ]; then
if [ -e "$g_specex_knob_dir/retp_enabled" ]; then
retp_enabled=$(cat "$g_specex_knob_dir/retp_enabled" 2>/dev/null)
pr_debug "retpoline: found $g_specex_knob_dir/retp_enabled=$retp_enabled"
pr_info_nol " * Retpoline is enabled: "
if [ "$retp_enabled" = 1 ]; then
pstatus green YES
else
pstatus yellow NO
fi
fi
fi
# only for information, in verbose mode
if [ "$opt_verbose" -ge 2 ]; then
pr_info_nol " * Local gcc is retpoline-aware: "
if command -v gcc >/dev/null 2>&1; then
if [ -n "$(gcc -mindirect-branch=thunk-extern --version 2>&1 >/dev/null)" ]; then
pstatus blue NO
else
pstatus green YES
fi
else
pstatus blue NO "gcc is not installed"
fi
fi
if is_vulnerable_to_empty_rsb || [ "$opt_verbose" -ge 2 ]; then
pr_info_nol " * Kernel supports RSB filling: "
rsb_filling=0
if [ "$opt_live" = 1 ] && [ "$opt_no_sysfs" != 1 ]; then
# if we're live and we aren't denied looking into /sys, let's do it
if echo "$msg" | grep -qw RSB; then
rsb_filling=1
pstatus green YES
fi
fi
if [ "$rsb_filling" = 0 ]; then
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
else
if grep -qw -e 'Filling RSB on context switch' "$g_kernel"; then
rsb_filling=1
pstatus green YES
else
rsb_filling=0
pstatus yellow NO
fi
fi
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"
else
if [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ] && [ "$retp_enabled" != 0 ] && [ -n "$g_ibpb_enabled" ] && [ "$g_ibpb_enabled" -ge 1 ] && (! is_vulnerable_to_empty_rsb || [ "$rsb_filling" = 1 ]); then
pvulnstatus "$cve" OK "Full retpoline + IBPB are mitigating the vulnerability"
elif [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ] && [ "$retp_enabled" != 0 ] && [ "$opt_paranoid" = 0 ] && (! is_vulnerable_to_empty_rsb || [ "$rsb_filling" = 1 ]); then
pvulnstatus "$cve" OK "Full retpoline is mitigating the vulnerability"
if [ -n "$cap_ibpb" ]; then
pr_warn "You should enable IBPB to complete retpoline as a Variant 2 mitigation"
else
pr_warn "IBPB is considered as a good addition to retpoline for Variant 2 mitigation, but your CPU microcode doesn't support it"
fi
elif [ -n "$g_ibrs_enabled" ] && [ -n "$g_ibpb_enabled" ] && [ "$g_ibrs_enabled" -ge 1 ] && [ "$g_ibpb_enabled" -ge 1 ]; then
if [ "$g_ibrs_enabled" = 4 ]; then
pvulnstatus "$cve" OK "Enhanced IBRS + IBPB are mitigating the vulnerability"
else
pvulnstatus "$cve" OK "IBRS + IBPB are mitigating the vulnerability"
fi
elif [ "$g_ibpb_enabled" = 2 ] && ! is_cpu_smt_enabled; then
pvulnstatus "$cve" OK "Full IBPB is mitigating the vulnerability"
elif [ -n "$bp_harden" ]; then
pvulnstatus "$cve" OK "Branch predictor hardening mitigates the vulnerability"
elif [ -z "$bp_harden" ] && [ "$cpu_vendor" = ARM ]; then
pvulnstatus "$cve" VULN "Branch predictor hardening is needed to mitigate the vulnerability"
explain "Your kernel has not been compiled with the CONFIG_UNMAP_KERNEL_AT_EL0 option, recompile it with this option enabled."
elif [ "$opt_live" != 1 ]; then
if [ "$retpoline" = 1 ] && [ -n "$g_ibpb_supported" ]; then
pvulnstatus "$cve" OK "offline mode: kernel supports retpoline + IBPB to mitigate the vulnerability"
elif [ -n "$g_ibrs_supported" ] && [ -n "$g_ibpb_supported" ]; then
pvulnstatus "$cve" OK "offline mode: kernel supports IBRS + IBPB to mitigate the vulnerability"
elif [ "$g_ibrs_can_tell" != 1 ]; then
pvulnstatus "$cve" UNK "offline mode: not enough information"
explain "Re-run this script with root privileges, and give it the kernel image (--kernel), the kernel configuration (--config) and the System.map file (--map) corresponding to the kernel you would like to inspect."
fi
fi
# if we arrive here and didn't already call pvulnstatus, then it's VULN, let's explain why
if [ "$g_pvulnstatus_last_cve" != "$cve" ]; then
# explain what's needed for this CPU
if is_vulnerable_to_empty_rsb; then
pvulnstatus "$cve" VULN "IBRS+IBPB or retpoline+IBPB+RSB filling, is needed to mitigate the vulnerability"
explain "To mitigate this vulnerability, you need either IBRS + IBPB, both requiring hardware support from your CPU microcode in addition to kernel support, or a kernel compiled with retpoline and IBPB, with retpoline requiring a retpoline-aware compiler (re-run this script with -v to know if your version of gcc is retpoline-aware) and IBPB requiring hardware support from your CPU microcode. You also need a recent-enough kernel that supports RSB filling if you plan to use retpoline. For Skylake+ CPUs, the IBRS + IBPB approach is generally preferred as it guarantees complete protection, and the performance impact is not as high as with older CPUs in comparison with retpoline. More information about how to enable the missing bits for those two possible mitigations on your system follow. You only need to take one of the two approaches."
elif is_zen_cpu || is_moksha_cpu; then
pvulnstatus "$cve" VULN "retpoline+IBPB is needed to mitigate the vulnerability"
explain "To mitigate this vulnerability, You need a kernel compiled with retpoline + IBPB support, with retpoline requiring a retpoline-aware compiler (re-run this script with -v to know if your version of gcc is retpoline-aware) and IBPB requiring hardware support from your CPU microcode."
elif is_intel || is_amd || is_hygon; then
pvulnstatus "$cve" VULN "IBRS+IBPB or retpoline+IBPB is needed to mitigate the vulnerability"
explain "To mitigate this vulnerability, you need either IBRS + IBPB, both requiring hardware support from your CPU microcode in addition to kernel support, or a kernel compiled with retpoline and IBPB, with retpoline requiring a retpoline-aware compiler (re-run this script with -v to know if your version of gcc is retpoline-aware) and IBPB requiring hardware support from your CPU microcode. The retpoline + IBPB approach is generally preferred as the performance impact is lower. More information about how to enable the missing bits for those two possible mitigations on your system follow. You only need to take one of the two approaches."
else
# in that case, we might want to trust sysfs if it's there
if [ -n "$msg" ]; then
[ "$msg" = Vulnerable ] && msg="no known mitigation exists for your CPU vendor ($cpu_vendor)"
pvulnstatus "$cve" "$status" "$msg"
else
pvulnstatus "$cve" VULN "no known mitigation exists for your CPU vendor ($cpu_vendor)"
fi
fi
fi
# if we are in live mode, we can check for a lot more stuff and explain further
if [ "$opt_live" = 1 ] && [ "$vulnstatus" != "OK" ]; then
explain_hypervisor="An updated CPU microcode will have IBRS/IBPB capabilities indicated in the Hardware Check section above. If you're running under a hypervisor (KVM, Xen, VirtualBox, VMware, ...), the hypervisor needs to be up to date to be able to export the new host CPU flags to the guest. You can run this script on the host to check if the host CPU is IBRS/IBPB. If it is, and it doesn't show up in the guest, upgrade the hypervisor. You may need to reconfigure your VM to use a CPU model that has IBRS capability; in Libvirt, such CPUs are listed with an IBRS suffix."
# IBPB (amd & intel)
if { [ -z "$g_ibpb_enabled" ] || [ "$g_ibpb_enabled" = 0 ]; } && { is_intel || is_amd || is_hygon; }; then
if [ -z "$cap_ibpb" ]; then
explain "The microcode of your CPU needs to be upgraded to be able to use IBPB. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section). $explain_hypervisor"
fi
if [ -z "$g_ibpb_supported" ]; then
explain "Your kernel doesn't have IBPB support, so you need to either upgrade your kernel (if you're using a distro) or recompiling a more recent kernel."
fi
if [ -n "$cap_ibpb" ] && [ -n "$g_ibpb_supported" ]; then
if [ -e "$g_specex_knob_dir/g_ibpb_enabled" ]; then
# newer (April 2018) Red Hat kernels have g_ibpb_enabled as ro, and automatically enables it with retpoline
if [ ! -w "$g_specex_knob_dir/g_ibpb_enabled" ] && [ -e "$g_specex_knob_dir/retp_enabled" ]; then
explain "Both your CPU and your kernel have IBPB support, but it is currently disabled. You kernel should enable IBPB automatically if you enable retpoline. You may enable it with \`echo 1 > $g_specex_knob_dir/retp_enabled\`."
else
explain "Both your CPU and your kernel have IBPB support, but it is currently disabled. You may enable it with \`echo 1 > $g_specex_knob_dir/g_ibpb_enabled\`."
fi
else
explain "Both your CPU and your kernel have IBPB support, but it is currently disabled. You may enable it. Check in your distro's documentation on how to do this."
fi
fi
elif [ "$g_ibpb_enabled" = 2 ] && is_cpu_smt_enabled; then
explain "You have g_ibpb_enabled set to 2, but it only offers sufficient protection when simultaneous multi-threading (aka SMT or HyperThreading) is disabled. You should reboot your system with the kernel parameter \`nosmt\`."
fi
# /IBPB
# IBRS (amd & intel)
if { [ -z "$g_ibrs_enabled" ] || [ "$g_ibrs_enabled" = 0 ]; } && { is_intel || is_amd || is_hygon; }; then
if [ -z "$cap_ibrs" ]; then
explain "The microcode of your CPU needs to be upgraded to be able to use IBRS. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section). $explain_hypervisor"
fi
if [ -z "$g_ibrs_supported" ]; then
explain "Your kernel doesn't have IBRS support, so you need to either upgrade your kernel (if you're using a distro) or recompiling a more recent kernel."
fi
if [ -n "$cap_ibrs" ] && [ -n "$g_ibrs_supported" ]; then
if [ -e "$g_specex_knob_dir/g_ibrs_enabled" ]; then
explain "Both your CPU and your kernel have IBRS support, but it is currently disabled. You may enable it with \`echo 1 > $g_specex_knob_dir/g_ibrs_enabled\`."
else
explain "Both your CPU and your kernel have IBRS support, but it is currently disabled. You may enable it. Check in your distro's documentation on how to do this."
fi
fi
fi
# /IBRS
unset explain_hypervisor
# RETPOLINE (amd & intel &hygon )
if is_amd || is_intel || is_hygon; then
if [ "$retpoline" = 0 ]; then
explain "Your kernel is not compiled with retpoline support, so you need to either upgrade your kernel (if you're using a distro) or recompile your kernel with the CONFIG_MITIGATION_RETPOLINE option enabled (was named CONFIG_RETPOLINE before kernel 6.9-rc1). You also need to compile your kernel with a retpoline-aware compiler (re-run this script with -v to know if your version of gcc is retpoline-aware)."
elif [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 0 ]; then
explain "Your kernel is compiled with retpoline, but without a retpoline-aware compiler (re-run this script with -v to know if your version of gcc is retpoline-aware)."
elif [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ] && [ "$retp_enabled" = 0 ]; then
explain "Your kernel has retpoline support and has been compiled with a retpoline-aware compiler, but retpoline is disabled. You should enable it with \`echo 1 > $g_specex_knob_dir/retp_enabled\`."
fi
fi
# /RETPOLINE
fi
fi
# sysfs msgs:
#1 "Vulnerable"
#2 "Vulnerable: Minimal generic ASM retpoline"
#2 "Vulnerable: Minimal AMD ASM retpoline"
# "Mitigation: Full generic retpoline"
# "Mitigation: Full AMD retpoline"
# $MITIGATION + ", IBPB"
# $MITIGATION + ", IBRS_FW"
#5 $MITIGATION + " - vulnerable module loaded"
# Red Hat only:
#2 "Vulnerable: Minimal ASM retpoline",
#3 "Vulnerable: Retpoline without IBPB",
#4 "Vulnerable: Retpoline on Skylake+",
#5 "Vulnerable: Retpoline with unsafe module(s)",
# "Mitigation: Full retpoline",
# "Mitigation: Full retpoline and IBRS (user space)",
# "Mitigation: IBRS (kernel)",
# "Mitigation: IBRS (kernel and user space)",
# "Mitigation: IBP disabled",
}
# CVE-2017-5715 Spectre Variant 2 (branch target injection) - BSD mitigation check
check_CVE_2017_5715_bsd() {
local ibrs_disabled ibrs_active retpoline nb_thunks
pr_info "* Mitigation 1"
pr_info_nol " * Kernel supports IBRS: "
ibrs_disabled=$(sysctl -n hw.ibrs_disable 2>/dev/null)
if [ -z "$ibrs_disabled" ]; then
pstatus yellow NO
else
pstatus green YES
fi
pr_info_nol " * IBRS enabled and active: "
ibrs_active=$(sysctl -n hw.ibrs_active 2>/dev/null)
if [ "$ibrs_active" = 1 ]; then
pstatus green YES
else
pstatus yellow NO
fi
pr_info "* Mitigation 2"
pr_info_nol " * Kernel compiled with RETPOLINE: "
retpoline=0
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
else
if ! command -v "${opt_arch_prefix}readelf" >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}readelf' tool, please install it, usually it's in the binutils package"
else
nb_thunks=$("${opt_arch_prefix}readelf" -s "$g_kernel" | grep -c -e __llvm_retpoline_ -e __llvm_external_retpoline_ -e __x86_indirect_thunk_)
if [ "$nb_thunks" -gt 0 ]; then
retpoline=1
pstatus green YES "found $nb_thunks thunk(s)"
else
pstatus yellow NO
fi
fi
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 [ "$retpoline" = 1 ]; then
pvulnstatus "$cve" OK "Retpoline mitigates the vulnerability"
elif [ "$ibrs_active" = 1 ]; then
pvulnstatus "$cve" OK "IBRS mitigates the vulnerability"
elif [ "$ibrs_disabled" = 0 ]; then
pvulnstatus "$cve" VULN "IBRS is supported by your kernel but your CPU microcode lacks support"
explain "The microcode of your CPU needs to be upgraded to be able to use IBRS. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section). To do a microcode update, you can search the ports for the \`cpupdate\` tool. Microcode updates done this way are not reboot-proof, so be sure to do it every time the system boots up."
elif [ "$ibrs_disabled" = 1 ]; then
pvulnstatus "$cve" VULN "IBRS is supported but administratively disabled on your system"
explain "To enable IBRS, use \`sysctl hw.ibrs_disable=0\`"
else
pvulnstatus "$cve" VULN "IBRS is needed to mitigate the vulnerability but your kernel is missing support"
explain "You need to either upgrade your kernel or recompile yourself a more recent version having IBRS support"
fi
}