mirror of
https://github.com/speed47/spectre-meltdown-checker.git
synced 2026-04-07 09:13:20 +02:00
split script in multiple files, reassembled through build.sh
This commit is contained in:
603
src/vulns/CVE-2017-5715.sh
Normal file
603
src/vulns/CVE-2017-5715.sh
Normal 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
|
||||
}
|
||||
235
src/vulns/CVE-2017-5753.sh
Normal file
235
src/vulns/CVE-2017-5753.sh
Normal file
@@ -0,0 +1,235 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
###################
|
||||
# SPECTRE 1 SECTION
|
||||
|
||||
# CVE-2017-5753 Spectre Variant 1 (bounds check bypass) - entry point
|
||||
check_CVE_2017_5753() {
|
||||
check_cve 'CVE-2017-5753'
|
||||
}
|
||||
|
||||
# CVE-2017-5753 Spectre Variant 1 (bounds check bypass) - Linux mitigation check
|
||||
check_CVE_2017_5753_linux() {
|
||||
local status sys_interface_available msg v1_mask_nospec nb_lfence v1_lfence ret explain_text
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
if sys_interface_check "$VULN_SYSFS_BASE/spectre_v1"; then
|
||||
# this kernel has the /sys interface, trust it over everything
|
||||
# v0.33+: don't. some kernels have backported the array_index_mask_nospec() workaround without
|
||||
# modifying the vulnerabilities/spectre_v1 file. that's bad. we can't trust it when it says Vulnerable :(
|
||||
# see "silent backport" detection at the bottom of this func
|
||||
sys_interface_available=1
|
||||
status=$ret_sys_interface_check_status
|
||||
fi
|
||||
if [ "$opt_sysfs_only" != 1 ]; then
|
||||
# no /sys interface (or offline mode), fallback to our own ways
|
||||
pr_info_nol "* Kernel has array_index_mask_nospec: "
|
||||
# vanilla: look for the Linus' mask aka array_index_mask_nospec()
|
||||
# that is inlined at least in raw_copy_from_user (__get_user_X symbols)
|
||||
#mov PER_CPU_VAR(current_task), %_ASM_DX
|
||||
#cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
|
||||
#jae bad_get_user
|
||||
# /* array_index_mask_nospec() are the 2 opcodes that follow */
|
||||
#+sbb %_ASM_DX, %_ASM_DX
|
||||
#+and %_ASM_DX, %_ASM_AX
|
||||
#ASM_STAC
|
||||
# x86 64bits: jae(0x0f 0x83 0x?? 0x?? 0x?? 0x??) sbb(0x48 0x19 0xd2) and(0x48 0x21 0xd0)
|
||||
# x86 32bits: cmp(0x3b 0x82 0x?? 0x?? 0x00 0x00) jae(0x73 0x??) sbb(0x19 0xd2) and(0x21 0xd0)
|
||||
#
|
||||
# arm32
|
||||
##ifdef CONFIG_THUMB2_KERNEL
|
||||
##define CSDB ".inst.w 0xf3af8014"
|
||||
##else
|
||||
##define CSDB ".inst 0xe320f014" e320f014
|
||||
##endif
|
||||
#asm volatile(
|
||||
# "cmp %1, %2\n" e1500003
|
||||
#" sbc %0, %1, %1\n" e0c03000
|
||||
#CSDB
|
||||
#: "=r" (mask)
|
||||
#: "r" (idx), "Ir" (sz)
|
||||
#: "cc");
|
||||
#
|
||||
# http://git.arm.linux.org.uk/cgit/linux-arm.git/commit/?h=spectre&id=a78d156587931a2c3b354534aa772febf6c9e855
|
||||
v1_mask_nospec=''
|
||||
if [ -n "$g_kernel_err" ]; then
|
||||
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
|
||||
elif ! command -v perl >/dev/null 2>&1; then
|
||||
pstatus yellow UNKNOWN "missing 'perl' binary, please install it"
|
||||
else
|
||||
perl -ne '/\x0f\x83....\x48\x19\xd2\x48\x21\xd0/ and $found++; END { exit($found) }' "$g_kernel"
|
||||
ret=$?
|
||||
if [ "$ret" -gt 0 ]; then
|
||||
pstatus green YES "$ret occurrence(s) found of x86 64 bits array_index_mask_nospec()"
|
||||
v1_mask_nospec="x86 64 bits array_index_mask_nospec"
|
||||
else
|
||||
perl -ne '/\x3b\x82..\x00\x00\x73.\x19\xd2\x21\xd0/ and $found++; END { exit($found) }' "$g_kernel"
|
||||
ret=$?
|
||||
if [ "$ret" -gt 0 ]; then
|
||||
pstatus green YES "$ret occurrence(s) found of x86 32 bits array_index_mask_nospec()"
|
||||
v1_mask_nospec="x86 32 bits array_index_mask_nospec"
|
||||
else
|
||||
ret=$("${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | grep -w -e f3af8014 -e e320f014 -B2 | grep -B1 -w sbc | grep -w -c cmp)
|
||||
if [ "$ret" -gt 0 ]; then
|
||||
pstatus green YES "$ret occurrence(s) found of arm 32 bits array_index_mask_nospec()"
|
||||
v1_mask_nospec="arm 32 bits array_index_mask_nospec"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
pr_info_nol "* Kernel has the Red Hat/Ubuntu patch: "
|
||||
check_redhat_canonical_spectre
|
||||
if [ "$g_redhat_canonical_spectre" = -1 ]; then
|
||||
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}strings' tool, please install it, usually it's in the binutils package"
|
||||
elif [ "$g_redhat_canonical_spectre" = -2 ]; then
|
||||
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
|
||||
elif [ "$g_redhat_canonical_spectre" = 1 ]; then
|
||||
pstatus green YES
|
||||
elif [ "$g_redhat_canonical_spectre" = 2 ]; then
|
||||
pstatus green YES "but without IBRS"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
pr_info_nol "* Kernel has mask_nospec64 (arm64): "
|
||||
#.macro mask_nospec64, idx, limit, tmp
|
||||
#sub \tmp, \idx, \limit
|
||||
#bic \tmp, \tmp, \idx
|
||||
#and \idx, \idx, \tmp, asr #63
|
||||
#csdb
|
||||
#.endm
|
||||
#$ aarch64-linux-gnu-objdump -d vmlinux | grep -w bic -A1 -B1 | grep -w sub -A2 | grep -w and -B2
|
||||
#ffffff8008082e44: cb190353 sub x19, x26, x25
|
||||
#ffffff8008082e48: 8a3a0273 bic x19, x19, x26
|
||||
#ffffff8008082e4c: 8a93ff5a and x26, x26, x19, asr #63
|
||||
#ffffff8008082e50: d503229f hint #0x14
|
||||
# /!\ can also just be "csdb" instead of "hint #0x14" for native objdump
|
||||
#
|
||||
# if we have v1_mask_nospec or g_redhat_canonical_spectre>0, don't bother disassembling the kernel, the answer is no.
|
||||
if [ -n "$v1_mask_nospec" ] || [ "$g_redhat_canonical_spectre" -gt 0 ]; then
|
||||
pstatus yellow NO
|
||||
elif [ -n "$g_kernel_err" ]; then
|
||||
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
|
||||
elif ! command -v perl >/dev/null 2>&1; then
|
||||
pstatus yellow UNKNOWN "missing 'perl' binary, please install it"
|
||||
elif ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then
|
||||
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package"
|
||||
else
|
||||
"${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | perl -ne 'push @r, $_; /\s(hint|csdb)\s/ && $r[0]=~/\ssub\s+(x\d+)/ && $r[1]=~/\sbic\s+$1,\s+$1,/ && $r[2]=~/\sand\s/ && exit(9); shift @r if @r>3'
|
||||
ret=$?
|
||||
if [ "$ret" -eq 9 ]; then
|
||||
pstatus green YES "mask_nospec64 macro is present and used"
|
||||
v1_mask_nospec="arm64 mask_nospec64"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
fi
|
||||
|
||||
pr_info_nol "* Kernel has array_index_nospec (arm64): "
|
||||
# in 4.19+ kernels, the mask_nospec64 asm64 macro is replaced by array_index_nospec, defined in nospec.h, and used in invoke_syscall()
|
||||
# ffffff8008090a4c: 2a0203e2 mov w2, w2
|
||||
# ffffff8008090a50: eb0200bf cmp x5, x2
|
||||
# ffffff8008090a54: da1f03e2 ngc x2, xzr
|
||||
# ffffff8008090a58: d503229f hint #0x14
|
||||
# /!\ can also just be "csdb" instead of "hint #0x14" for native objdump
|
||||
#
|
||||
# if we have v1_mask_nospec or g_redhat_canonical_spectre>0, don't bother disassembling the kernel, the answer is no.
|
||||
if [ -n "$v1_mask_nospec" ] || [ "$g_redhat_canonical_spectre" -gt 0 ]; then
|
||||
pstatus yellow NO
|
||||
elif [ -n "$g_kernel_err" ]; then
|
||||
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
|
||||
elif ! command -v perl >/dev/null 2>&1; then
|
||||
pstatus yellow UNKNOWN "missing 'perl' binary, please install it"
|
||||
elif ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then
|
||||
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package"
|
||||
else
|
||||
"${opt_arch_prefix}objdump" -d "$g_kernel" | perl -ne 'push @r, $_; /\s(hint|csdb)\s/ && $r[0]=~/\smov\s+(w\d+),\s+(w\d+)/ && $r[1]=~/\scmp\s+(x\d+),\s+(x\d+)/ && $r[2]=~/\sngc\s+$2,/ && exit(9); shift @r if @r>3'
|
||||
ret=$?
|
||||
if [ "$ret" -eq 9 ]; then
|
||||
pstatus green YES "array_index_nospec macro is present and used"
|
||||
v1_mask_nospec="arm64 array_index_nospec"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$opt_verbose" -ge 2 ] || { [ -z "$v1_mask_nospec" ] && [ "$g_redhat_canonical_spectre" != 1 ] && [ "$g_redhat_canonical_spectre" != 2 ]; }; then
|
||||
# this is a slow heuristic and we don't need it if we already know the kernel is patched
|
||||
# but still show it in verbose mode
|
||||
pr_info_nol "* Checking count of LFENCE instructions following a jump in kernel... "
|
||||
if [ -n "$g_kernel_err" ]; then
|
||||
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
|
||||
else
|
||||
if ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then
|
||||
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package"
|
||||
else
|
||||
# here we disassemble the kernel and count the number of occurrences of the LFENCE opcode
|
||||
# in non-patched kernels, this has been empirically determined as being around 40-50
|
||||
# in patched kernels, this is more around 70-80, sometimes way higher (100+)
|
||||
# v0.13: 68 found in a 3.10.23-xxxx-std-ipv6-64 (with lots of modules compiled-in directly), which doesn't have the LFENCE patches,
|
||||
# so let's push the threshold to 70.
|
||||
# v0.33+: now only count lfence opcodes after a jump, way less error-prone
|
||||
# non patched kernel have between 0 and 20 matches, patched ones have at least 40-45
|
||||
nb_lfence=$("${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" 2>/dev/null | grep -w -B1 lfence | grep -Ewc 'jmp|jne|je')
|
||||
if [ "$nb_lfence" -lt 30 ]; then
|
||||
pstatus yellow NO "only $nb_lfence jump-then-lfence instructions found, should be >= 30 (heuristic)"
|
||||
else
|
||||
v1_lfence=1
|
||||
pstatus green YES "$nb_lfence jump-then-lfence instructions found, which is >= 30 (heuristic)"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
# 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
|
||||
|
||||
# report status
|
||||
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 [ -n "$v1_mask_nospec" ]; then
|
||||
pvulnstatus "$cve" OK "Kernel source has been patched to mitigate the vulnerability ($v1_mask_nospec)"
|
||||
elif [ "$g_redhat_canonical_spectre" = 1 ] || [ "$g_redhat_canonical_spectre" = 2 ]; then
|
||||
pvulnstatus "$cve" OK "Kernel source has been patched to mitigate the vulnerability (Red Hat/Ubuntu patch)"
|
||||
elif [ "$v1_lfence" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "Kernel source has PROBABLY been patched to mitigate the vulnerability (jump-then-lfence instructions heuristic)"
|
||||
elif [ -n "$g_kernel_err" ]; then
|
||||
pvulnstatus "$cve" UNK "Couldn't find kernel image or tools missing to execute the checks"
|
||||
explain "Re-run this script with root privileges, after installing the missing tools indicated above"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Kernel source needs to be patched to mitigate the vulnerability"
|
||||
explain "Your kernel is too old to have the mitigation for Variant 1, you should upgrade to a newer kernel. If you're using a Linux distro and didn't compile the kernel yourself, you should upgrade your distro to get a newer kernel."
|
||||
fi
|
||||
else
|
||||
if [ "$msg" = "Vulnerable" ] && [ -n "$v1_mask_nospec" ]; then
|
||||
pvulnstatus "$cve" OK "Kernel source has been patched to mitigate the vulnerability (silent backport of array_index_mask_nospec)"
|
||||
else
|
||||
if [ "$msg" = "Vulnerable" ]; then
|
||||
msg="Kernel source needs to be patched to mitigate the vulnerability"
|
||||
explain_text="Your kernel is too old to have the mitigation for Variant 1, you should upgrade to a newer kernel. If you're using a Linux distro and didn't compile the kernel yourself, you should upgrade your distro to get a newer kernel."
|
||||
fi
|
||||
pvulnstatus "$cve" "$status" "$msg"
|
||||
[ -n "${explain_text:-}" ] && explain "$explain_text"
|
||||
unset explain_text
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# CVE-2017-5753 Spectre Variant 1 (bounds check bypass) - BSD mitigation check
|
||||
check_CVE_2017_5753_bsd() {
|
||||
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
|
||||
pvulnstatus "$cve" VULN "no mitigation for BSD yet"
|
||||
fi
|
||||
}
|
||||
281
src/vulns/CVE-2017-5754.sh
Normal file
281
src/vulns/CVE-2017-5754.sh
Normal file
@@ -0,0 +1,281 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
##################
|
||||
# MELTDOWN SECTION
|
||||
|
||||
# no security impact but give a hint to the user in verbose mode
|
||||
# about PCID/INVPCID cpuid features that must be present to avoid
|
||||
# Check whether PCID/INVPCID are available to reduce PTI performance impact
|
||||
# refs:
|
||||
# https://marc.info/?t=151532047900001&r=1&w=2
|
||||
# https://groups.google.com/forum/m/#!topic/mechanical-sympathy/L9mHTbeQLNU
|
||||
pti_performance_check() {
|
||||
local ret pcid invpcid
|
||||
pr_info_nol " * Reduced performance impact of PTI: "
|
||||
if [ -e "$g_procfs/cpuinfo" ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw pcid; then
|
||||
pcid=1
|
||||
else
|
||||
read_cpuid 0x1 0x0 "$ECX" 17 1 1
|
||||
ret=$?
|
||||
if [ "$ret" = "$READ_CPUID_RET_OK" ]; then
|
||||
pcid=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -e "$g_procfs/cpuinfo" ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw invpcid; then
|
||||
invpcid=1
|
||||
else
|
||||
read_cpuid 0x7 0x0 "$EBX" 10 1 1
|
||||
ret=$?
|
||||
if [ "$ret" = "$READ_CPUID_RET_OK" ]; then
|
||||
invpcid=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$invpcid" = 1 ]; then
|
||||
pstatus green YES 'CPU supports INVPCID, performance impact of PTI will be greatly reduced'
|
||||
elif [ "$pcid" = 1 ]; then
|
||||
pstatus green YES 'CPU supports PCID, performance impact of PTI will be reduced'
|
||||
else
|
||||
pstatus blue NO 'PCID/INVPCID not supported, performance impact of PTI will be significant'
|
||||
fi
|
||||
}
|
||||
|
||||
# CVE-2017-5754 Meltdown (rogue data cache load) - entry point
|
||||
check_CVE_2017_5754() {
|
||||
check_cve 'CVE-2017-5754'
|
||||
}
|
||||
|
||||
# CVE-2017-5754 Meltdown (rogue data cache load) - Linux mitigation check
|
||||
check_CVE_2017_5754_linux() {
|
||||
local status sys_interface_available msg kpti_support kpti_can_tell kpti_enabled dmesg_grep pti_xen_pv_domU xen_pv_domo xen_pv_domu explain_text
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
if sys_interface_check "$VULN_SYSFS_BASE/meltdown"; 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 Page Table Isolation (PTI): "
|
||||
kpti_support=''
|
||||
kpti_can_tell=0
|
||||
if [ -n "$opt_config" ]; then
|
||||
kpti_can_tell=1
|
||||
kpti_support=$(grep -E -w -e 'CONFIG_(MITIGATION_)?PAGE_TABLE_ISOLATION=y' -e CONFIG_KAISER=y -e CONFIG_UNMAP_KERNEL_AT_EL0=y "$opt_config")
|
||||
if [ -n "$kpti_support" ]; then
|
||||
pr_debug "kpti_support: found option '$kpti_support' in $opt_config"
|
||||
fi
|
||||
fi
|
||||
if [ -z "$kpti_support" ] && [ -n "$opt_map" ]; then
|
||||
# it's not an elif: some backports don't have the PTI config but still include the patch
|
||||
# so we try to find an exported symbol that is part of the PTI patch in System.map
|
||||
# parse_kpti: arm
|
||||
kpti_can_tell=1
|
||||
kpti_support=$(grep -w -e kpti_force_enabled -e parse_kpti "$opt_map")
|
||||
if [ -n "$kpti_support" ]; then
|
||||
pr_debug "kpti_support: found '$kpti_support' in $opt_map"
|
||||
fi
|
||||
fi
|
||||
if [ -z "$kpti_support" ] && [ -n "$g_kernel" ]; then
|
||||
# same as above but in case we don't have System.map and only kernel, look for the
|
||||
# nopti option that is part of the patch (kernel command line option)
|
||||
# 'kpti=': arm
|
||||
kpti_can_tell=1
|
||||
if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
|
||||
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}strings' tool, please install it, usually it's in the binutils package"
|
||||
else
|
||||
kpti_support=$("${opt_arch_prefix}strings" "$g_kernel" | grep -w -e nopti -e kpti=)
|
||||
if [ -n "$kpti_support" ]; then
|
||||
pr_debug "kpti_support: found '$kpti_support' in $g_kernel"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$kpti_support" ]; then
|
||||
if [ "$opt_verbose" -ge 2 ]; then
|
||||
pstatus green YES "found '$kpti_support'"
|
||||
else
|
||||
pstatus green YES
|
||||
fi
|
||||
elif [ "$kpti_can_tell" = 1 ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read your kernel configuration nor System.map file"
|
||||
fi
|
||||
|
||||
mount_debugfs
|
||||
pr_info_nol " * PTI enabled and active: "
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
dmesg_grep="Kernel/User page tables isolation: enabled"
|
||||
dmesg_grep="$dmesg_grep|Kernel page table isolation enabled"
|
||||
dmesg_grep="$dmesg_grep|x86/pti: Unmapping kernel while in userspace"
|
||||
# aarch64
|
||||
dmesg_grep="$dmesg_grep|CPU features: detected( feature)?: Kernel page table isolation \(KPTI\)"
|
||||
if grep ^flags "$g_procfs/cpuinfo" | grep -qw pti; then
|
||||
# vanilla PTI patch sets the 'pti' flag in cpuinfo
|
||||
pr_debug "kpti_enabled: found 'pti' flag in $g_procfs/cpuinfo"
|
||||
kpti_enabled=1
|
||||
elif grep ^flags "$g_procfs/cpuinfo" | grep -qw kaiser; then
|
||||
# kernel line 4.9 sets the 'kaiser' flag in cpuinfo
|
||||
pr_debug "kpti_enabled: found 'kaiser' flag in $g_procfs/cpuinfo"
|
||||
kpti_enabled=1
|
||||
elif [ -e "$DEBUGFS_BASE/x86/pti_enabled" ]; then
|
||||
# Red Hat Backport creates a dedicated file, see https://access.redhat.com/articles/3311301
|
||||
kpti_enabled=$(cat "$DEBUGFS_BASE/x86/pti_enabled" 2>/dev/null)
|
||||
pr_debug "kpti_enabled: file $DEBUGFS_BASE/x86/pti_enabled exists and says: $kpti_enabled"
|
||||
elif is_xen_dom0; then
|
||||
pti_xen_pv_domU=$(xl dmesg 2>/dev/null | grep 'XPTI' | grep 'DomU enabled' | head -n1)
|
||||
|
||||
[ -n "$pti_xen_pv_domU" ] && kpti_enabled=1
|
||||
fi
|
||||
if [ -z "$kpti_enabled" ]; then
|
||||
dmesg_grep "$dmesg_grep"
|
||||
ret=$?
|
||||
if [ "$ret" -eq 0 ]; then
|
||||
pr_debug "kpti_enabled: found hint in dmesg: $ret_dmesg_grep_grepped"
|
||||
kpti_enabled=1
|
||||
elif [ "$ret" -eq 2 ]; then
|
||||
pr_debug "kpti_enabled: dmesg truncated"
|
||||
kpti_enabled=-1
|
||||
fi
|
||||
fi
|
||||
if [ -z "$kpti_enabled" ]; then
|
||||
pr_debug "kpti_enabled: couldn't find any hint that PTI is enabled"
|
||||
kpti_enabled=0
|
||||
fi
|
||||
if [ "$kpti_enabled" = 1 ]; then
|
||||
pstatus green YES
|
||||
elif [ "$kpti_enabled" = -1 ]; then
|
||||
pstatus yellow UNKNOWN "dmesg truncated, please reboot and relaunch this script"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
else
|
||||
pstatus blue N/A "not testable in offline mode"
|
||||
fi
|
||||
|
||||
pti_performance_check
|
||||
|
||||
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
|
||||
|
||||
# Test if the current host is a Xen PV Dom0 / DomU
|
||||
xen_pv_domo=0
|
||||
xen_pv_domu=0
|
||||
is_xen_dom0 && xen_pv_domo=1
|
||||
is_xen_domU && xen_pv_domu=1
|
||||
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
# checking whether we're running under Xen PV 64 bits. If yes, we are affected by affected_variant3
|
||||
# (unless we are a Dom0)
|
||||
pr_info_nol "* Running as a Xen PV DomU: "
|
||||
if [ "$xen_pv_domu" = 1 ]; then
|
||||
pstatus yellow YES
|
||||
else
|
||||
pstatus blue NO
|
||||
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 [ -z "$msg" ]; then
|
||||
# if msg is empty, sysfs check didn't fill it, rely on our own test
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if [ "$kpti_enabled" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "PTI mitigates the vulnerability"
|
||||
elif [ "$xen_pv_domo" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "Xen Dom0s are safe and do not require PTI"
|
||||
elif [ "$xen_pv_domu" = 1 ]; then
|
||||
pvulnstatus "$cve" VULN "Xen PV DomUs are vulnerable and need to be run in HVM, PVHVM, PVH mode, or the Xen hypervisor must have the Xen's own PTI patch"
|
||||
explain "Go to https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ for more information"
|
||||
elif [ "$kpti_enabled" = -1 ]; then
|
||||
pvulnstatus "$cve" UNK "couldn't find any clue of PTI activation due to a truncated dmesg, please reboot and relaunch this script"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "PTI is needed to mitigate the vulnerability"
|
||||
if [ -n "$kpti_support" ]; then
|
||||
if [ -e "$DEBUGFS_BASE/x86/pti_enabled" ]; then
|
||||
explain "Your kernel supports PTI but it's disabled, you can enable it with \`echo 1 > $DEBUGFS_BASE/x86/pti_enabled\`"
|
||||
elif echo "$g_kernel_cmdline" | grep -q -w -e nopti -e pti=off; then
|
||||
explain "Your kernel supports PTI but it has been disabled on command-line, remove the nopti or pti=off option from your bootloader configuration"
|
||||
else
|
||||
explain "Your kernel supports PTI but it has been disabled, check \`dmesg\` right after boot to find clues why the system disabled it"
|
||||
fi
|
||||
else
|
||||
explain "If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel with the CONFIG_(MITIGATION_)PAGE_TABLE_ISOLATION option (named CONFIG_KAISER for some kernels), or the CONFIG_UNMAP_KERNEL_AT_EL0 option (for ARM64)"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if [ -n "$kpti_support" ]; then
|
||||
pvulnstatus "$cve" OK "offline mode: PTI will mitigate the vulnerability if enabled at runtime"
|
||||
elif [ "$kpti_can_tell" = 1 ]; then
|
||||
pvulnstatus "$cve" VULN "PTI is needed to mitigate the vulnerability"
|
||||
explain "If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel with the CONFIG_(MITIGATION_)PAGE_TABLE_ISOLATION option (named CONFIG_KAISER for some kernels), or the CONFIG_UNMAP_KERNEL_AT_EL0 option (for ARM64)"
|
||||
else
|
||||
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
|
||||
else
|
||||
if [ "$xen_pv_domo" = 1 ]; then
|
||||
msg="Xen Dom0s are safe and do not require PTI"
|
||||
status="OK"
|
||||
elif [ "$xen_pv_domu" = 1 ]; then
|
||||
msg="Xen PV DomUs are vulnerable and need to be run in HVM, PVHVM, PVH mode, or the Xen hypervisor must have the Xen's own PTI patch"
|
||||
status="VULN"
|
||||
explain_text="Go to https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ for more information"
|
||||
elif [ "$msg" = "Vulnerable" ]; then
|
||||
msg="PTI is needed to mitigate the vulnerability"
|
||||
explain_text="If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel with the CONFIG_(MITIGATION_)PAGE_TABLE_ISOLATION option (named CONFIG_KAISER for some kernels), or the CONFIG_UNMAP_KERNEL_AT_EL0 option (for ARM64)"
|
||||
fi
|
||||
pvulnstatus "$cve" "$status" "$msg"
|
||||
[ -z "${explain_text:-}" ] && [ "$msg" = "Vulnerable" ] && explain_text="If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel with the CONFIG_(MITIGATION_)PAGE_TABLE_ISOLATION option (named CONFIG_KAISER for some kernels), or the CONFIG_UNMAP_KERNEL_AT_EL0 option (for ARM64)"
|
||||
[ -n "${explain_text:-}" ] && explain "$explain_text"
|
||||
unset explain_text
|
||||
fi
|
||||
|
||||
# Warn the user about XSA-254 recommended mitigations
|
||||
if [ "$xen_pv_domo" = 1 ]; then
|
||||
pr_warn
|
||||
pr_warn "This host is a Xen Dom0. Please make sure that you are running your DomUs"
|
||||
pr_warn "in HVM, PVHVM or PVH mode to prevent any guest-to-host / host-to-guest attacks."
|
||||
pr_warn
|
||||
pr_warn "See https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ and XSA-254 for details."
|
||||
fi
|
||||
}
|
||||
|
||||
# CVE-2017-5754 Meltdown (rogue data cache load) - BSD mitigation check
|
||||
check_CVE_2017_5754_bsd() {
|
||||
local kpti_enabled
|
||||
pr_info_nol "* Kernel supports Page Table Isolation (PTI): "
|
||||
kpti_enabled=$(sysctl -n vm.pmap.pti 2>/dev/null)
|
||||
if [ -z "$kpti_enabled" ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus green YES
|
||||
fi
|
||||
|
||||
pr_info_nol " * PTI enabled and active: "
|
||||
if [ "$kpti_enabled" = 1 ]; then
|
||||
pstatus green YES
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
pti_performance_check
|
||||
|
||||
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 [ "$kpti_enabled" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "PTI mitigates the vulnerability"
|
||||
elif [ -n "$kpti_enabled" ]; then
|
||||
pvulnstatus "$cve" VULN "PTI is supported but disabled on your system"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "PTI is needed to mitigate the vulnerability"
|
||||
fi
|
||||
}
|
||||
8
src/vulns/CVE-2018-12126.sh
Normal file
8
src/vulns/CVE-2018-12126.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
###################
|
||||
# MSBDS SECTION
|
||||
|
||||
# CVE-2018-12126 MSBDS (microarchitectural store buffer data sampling) - entry point
|
||||
check_CVE_2018_12126() {
|
||||
check_cve 'CVE-2018-12126' check_mds
|
||||
}
|
||||
8
src/vulns/CVE-2018-12127.sh
Normal file
8
src/vulns/CVE-2018-12127.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
###################
|
||||
# MLPDS SECTION
|
||||
|
||||
# CVE-2018-12127 MLPDS (microarchitectural load port data sampling) - entry point
|
||||
check_CVE_2018_12127() {
|
||||
check_cve 'CVE-2018-12127' check_mds
|
||||
}
|
||||
8
src/vulns/CVE-2018-12130.sh
Normal file
8
src/vulns/CVE-2018-12130.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
###################
|
||||
# MFBDS SECTION
|
||||
|
||||
# CVE-2018-12130 MFBDS (microarchitectural fill buffer data sampling) - entry point
|
||||
check_CVE_2018_12130() {
|
||||
check_cve 'CVE-2018-12130' check_mds
|
||||
}
|
||||
111
src/vulns/CVE-2018-12207.sh
Normal file
111
src/vulns/CVE-2018-12207.sh
Normal file
@@ -0,0 +1,111 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
#######################
|
||||
# iTLB Multihit section
|
||||
|
||||
# CVE-2018-12207 iTLB multihit (machine check exception on page size changes) - entry point
|
||||
check_CVE_2018_12207() {
|
||||
check_cve 'CVE-2018-12207'
|
||||
}
|
||||
|
||||
# CVE-2018-12207 iTLB multihit (machine check exception on page size changes) - Linux mitigation check
|
||||
check_CVE_2018_12207_linux() {
|
||||
local status sys_interface_available msg kernel_itlbmh kernel_itlbmh_err
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
if sys_interface_check "$VULN_SYSFS_BASE/itlb_multihit"; 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
|
||||
check_has_vmm
|
||||
|
||||
pr_info_nol "* iTLB Multihit mitigation is supported by kernel: "
|
||||
kernel_itlbmh=''
|
||||
if [ -n "$g_kernel_err" ]; then
|
||||
kernel_itlbmh_err="$g_kernel_err"
|
||||
# commit 5219505fcbb640e273a0d51c19c38de0100ec5a9
|
||||
elif grep -q 'itlb_multihit' "$g_kernel"; then
|
||||
kernel_itlbmh="found itlb_multihit in kernel image"
|
||||
fi
|
||||
if [ -n "$kernel_itlbmh" ]; then
|
||||
pstatus green YES "$kernel_itlbmh"
|
||||
elif [ -n "$kernel_itlbmh_err" ]; then
|
||||
pstatus yellow UNKNOWN "$kernel_itlbmh_err"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
pr_info_nol "* iTLB Multihit mitigation enabled and active: "
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if [ -n "$ret_sys_interface_check_fullmsg" ]; then
|
||||
if echo "$ret_sys_interface_check_fullmsg" | grep -qF 'Mitigation'; then
|
||||
pstatus green YES "$ret_sys_interface_check_fullmsg"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
else
|
||||
pstatus yellow NO "itlb_multihit not found in sysfs hierarchy"
|
||||
fi
|
||||
else
|
||||
pstatus blue N/A "not testable in offline 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 [ "$g_has_vmm" = 0 ]; then
|
||||
pvulnstatus "$cve" OK "this system is not running a hypervisor"
|
||||
elif [ -z "$msg" ]; then
|
||||
# if msg is empty, sysfs check didn't fill it, rely on our own test
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
|
||||
pvulnstatus "$cve" VULN "Your kernel doesn't support iTLB Multihit mitigation, update it"
|
||||
else
|
||||
if [ -n "$kernel_itlbmh" ]; then
|
||||
pvulnstatus "$cve" OK "Your kernel supports iTLB Multihit mitigation"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Your kernel doesn't support iTLB Multihit mitigation, update it"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" "$status" "$msg"
|
||||
fi
|
||||
}
|
||||
|
||||
# CVE-2018-12207 iTLB multihit (machine check exception on page size changes) - BSD mitigation check
|
||||
check_CVE_2018_12207_bsd() {
|
||||
local kernel_2m_x_ept
|
||||
pr_info_nol "* Kernel supports disabling superpages for executable mappings under EPT: "
|
||||
kernel_2m_x_ept=$(sysctl -n vm.pmap.allow_2m_x_ept 2>/dev/null)
|
||||
if [ -z "$kernel_2m_x_ept" ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus green YES
|
||||
fi
|
||||
|
||||
pr_info_nol "* Superpages are disabled for executable mappings under EPT: "
|
||||
if [ "$kernel_2m_x_ept" = 0 ]; then
|
||||
pstatus green YES
|
||||
else
|
||||
pstatus yellow NO
|
||||
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 "$kernel_2m_x_ept" ]; then
|
||||
pvulnstatus "$cve" VULN "Your kernel doesn't support mitigating this CVE, you should update it"
|
||||
elif [ "$kernel_2m_x_ept" != 0 ]; then
|
||||
pvulnstatus "$cve" VULN "Your kernel supports mitigating this CVE, but the mitigation is disabled"
|
||||
explain "To enable the mitigation, use \`sysctl vm.pmap.allow_2m_x_ept=0\`"
|
||||
else
|
||||
pvulnstatus "$cve" OK "Your kernel has support for mitigation and the mitigation is enabled"
|
||||
fi
|
||||
}
|
||||
36
src/vulns/CVE-2018-3615.sh
Normal file
36
src/vulns/CVE-2018-3615.sh
Normal file
@@ -0,0 +1,36 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
###########################
|
||||
# L1TF / FORESHADOW SECTION
|
||||
|
||||
# CVE-2018-3615 Foreshadow (L1 terminal fault SGX) - entry point
|
||||
check_CVE_2018_3615() {
|
||||
local cve
|
||||
cve='CVE-2018-3615'
|
||||
pr_info "\033[1;34m$cve aka '$(cve2name "$cve")'\033[0m"
|
||||
|
||||
pr_info_nol "* CPU microcode mitigates the vulnerability: "
|
||||
if { [ "$cap_flush_cmd" = 1 ] || { [ "$g_msr_locked_down" = 1 ] && [ "$cap_l1df" = 1 ]; }; } && [ "$cap_sgx" = 1 ]; then
|
||||
# no easy way to detect a fixed SGX but we know that
|
||||
# microcodes that have the FLUSH_CMD MSR also have the
|
||||
# fixed SGX (for CPUs that support it), because Intel
|
||||
# delivered fixed microcodes for both issues at the same time
|
||||
#
|
||||
# if the system we're running on is locked down (no way to write MSRs),
|
||||
# make the assumption that if the L1D flush CPUID bit is set, probably
|
||||
# that FLUSH_CMD MSR is here too
|
||||
pstatus green YES
|
||||
elif [ "$cap_sgx" = 1 ]; then
|
||||
pstatus red NO
|
||||
else
|
||||
pstatus blue N/A
|
||||
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 [ "$cap_flush_cmd" = 1 ] || { [ "$g_msr_locked_down" = 1 ] && [ "$cap_l1df" = 1 ]; }; then
|
||||
pvulnstatus "$cve" OK "your CPU microcode mitigates the vulnerability"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "your CPU supports SGX and the microcode is not up to date"
|
||||
fi
|
||||
}
|
||||
110
src/vulns/CVE-2018-3620.sh
Normal file
110
src/vulns/CVE-2018-3620.sh
Normal file
@@ -0,0 +1,110 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
# CVE-2018-3620 Foreshadow-NG OS (L1 terminal fault OS) - entry point
|
||||
check_CVE_2018_3620() {
|
||||
check_cve 'CVE-2018-3620'
|
||||
}
|
||||
|
||||
# CVE-2018-3620 Foreshadow-NG OS (L1 terminal fault OS) - Linux mitigation check
|
||||
check_CVE_2018_3620_linux() {
|
||||
local status sys_interface_available msg pteinv_supported pteinv_active
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
if sys_interface_check "$VULN_SYSFS_BASE/l1tf"; 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 PTE inversion: "
|
||||
if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
|
||||
pstatus yellow UNKNOWN "missing 'strings' tool, please install it"
|
||||
pteinv_supported=-1
|
||||
elif [ -n "$g_kernel_err" ]; then
|
||||
pstatus yellow UNKNOWN "$g_kernel_err"
|
||||
pteinv_supported=-1
|
||||
else
|
||||
if "${opt_arch_prefix}strings" "$g_kernel" | grep -Fq 'PTE Inversion'; then
|
||||
pstatus green YES "found in kernel image"
|
||||
pr_debug "pteinv: found pte inversion evidence in kernel image"
|
||||
pteinv_supported=1
|
||||
else
|
||||
pstatus yellow NO
|
||||
pteinv_supported=0
|
||||
fi
|
||||
fi
|
||||
|
||||
pr_info_nol "* PTE inversion enabled and active: "
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if [ -n "$ret_sys_interface_check_fullmsg" ]; then
|
||||
if echo "$ret_sys_interface_check_fullmsg" | grep -q 'Mitigation: PTE Inversion'; then
|
||||
pstatus green YES
|
||||
pteinv_active=1
|
||||
else
|
||||
pstatus yellow NO
|
||||
pteinv_active=0
|
||||
fi
|
||||
else
|
||||
pstatus yellow UNKNOWN "sysfs interface not available"
|
||||
pteinv_active=-1
|
||||
fi
|
||||
else
|
||||
pstatus blue N/A "not testable in offline 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 [ "$pteinv_supported" = 1 ]; then
|
||||
if [ "$pteinv_active" = 1 ] || [ "$opt_live" != 1 ]; then
|
||||
pvulnstatus "$cve" OK "PTE inversion mitigates the vulnerability"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Your kernel supports PTE inversion but it doesn't seem to be enabled"
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Your kernel doesn't support PTE inversion, update it"
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" "$status" "$msg"
|
||||
fi
|
||||
}
|
||||
|
||||
# CVE-2018-3620 Foreshadow-NG OS (L1 terminal fault OS) - BSD mitigation check
|
||||
check_CVE_2018_3620_bsd() {
|
||||
local bsd_zero_reserved
|
||||
pr_info_nol "* Kernel reserved the memory page at physical address 0x0: "
|
||||
if ! kldstat -q -m vmm; then
|
||||
kldload vmm 2>/dev/null && g_kldload_vmm=1
|
||||
pr_debug "attempted to load module vmm, g_kldload_vmm=$g_kldload_vmm"
|
||||
else
|
||||
pr_debug "vmm module already loaded"
|
||||
fi
|
||||
if sysctl hw.vmm.vmx.l1d_flush >/dev/null 2>&1; then
|
||||
# https://security.FreeBSD.org/patches/SA-18:09/l1tf-11.2.patch
|
||||
# this is very difficult to detect that the kernel reserved the 0 page, but this fix
|
||||
# is part of the exact same patch than the other L1TF CVE, so we detect it
|
||||
# and deem it as OK if the other patch is there
|
||||
pstatus green YES
|
||||
bsd_zero_reserved=1
|
||||
else
|
||||
pstatus yellow NO
|
||||
bsd_zero_reserved=0
|
||||
fi
|
||||
|
||||
if ! is_cpu_affected "$cve"; then
|
||||
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
|
||||
else
|
||||
if [ "$bsd_zero_reserved" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "kernel mitigates the vulnerability"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "your kernel needs to be updated"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
188
src/vulns/CVE-2018-3639.sh
Normal file
188
src/vulns/CVE-2018-3639.sh
Normal file
@@ -0,0 +1,188 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
###################
|
||||
# VARIANT 4 SECTION
|
||||
|
||||
# CVE-2018-3639 Variant 4 (speculative store bypass) - entry point
|
||||
check_CVE_2018_3639() {
|
||||
check_cve 'CVE-2018-3639'
|
||||
}
|
||||
|
||||
# CVE-2018-3639 Variant 4 (speculative store bypass) - Linux mitigation check
|
||||
check_CVE_2018_3639_linux() {
|
||||
local status sys_interface_available msg kernel_ssb kernel_ssbd_enabled mitigated_processes
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
if sys_interface_check "$VULN_SYSFS_BASE/spec_store_bypass"; 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 disabling speculative store bypass (SSB): "
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if grep -Eq 'Speculation.?Store.?Bypass:' "$g_procfs/self/status" 2>/dev/null; then
|
||||
kernel_ssb="found in $g_procfs/self/status"
|
||||
pr_debug "found Speculation.Store.Bypass: in $g_procfs/self/status"
|
||||
fi
|
||||
fi
|
||||
# arm64 kernels can have cpu_show_spec_store_bypass with ARM64_SSBD, so exclude them
|
||||
if [ -z "$kernel_ssb" ] && [ -n "$g_kernel" ] && ! grep -q 'arm64_sys_' "$g_kernel"; then
|
||||
kernel_ssb=$("${opt_arch_prefix}strings" "$g_kernel" | grep spec_store_bypass | head -n1)
|
||||
[ -n "$kernel_ssb" ] && kernel_ssb="found $kernel_ssb in kernel"
|
||||
fi
|
||||
# arm64 kernels can have cpu_show_spec_store_bypass with ARM64_SSBD, so exclude them
|
||||
if [ -z "$kernel_ssb" ] && [ -n "$opt_map" ] && ! grep -q 'arm64_sys_' "$opt_map"; then
|
||||
kernel_ssb=$(grep spec_store_bypass "$opt_map" | awk '{print $3}' | head -n1)
|
||||
[ -n "$kernel_ssb" ] && kernel_ssb="found $kernel_ssb in System.map"
|
||||
fi
|
||||
# arm64 only:
|
||||
if [ -z "$kernel_ssb" ] && [ -n "$opt_map" ]; then
|
||||
kernel_ssb=$(grep -w cpu_enable_ssbs "$opt_map" | awk '{print $3}' | head -n1)
|
||||
[ -n "$kernel_ssb" ] && kernel_ssb="found $kernel_ssb in System.map"
|
||||
fi
|
||||
if [ -z "$kernel_ssb" ] && [ -n "$opt_config" ]; then
|
||||
kernel_ssb=$(grep -w 'CONFIG_ARM64_SSBD=y' "$opt_config")
|
||||
[ -n "$kernel_ssb" ] && kernel_ssb="CONFIG_ARM64_SSBD enabled in kconfig"
|
||||
fi
|
||||
if [ -z "$kernel_ssb" ] && [ -n "$g_kernel" ]; then
|
||||
# this string only appears in kernel if CONFIG_ARM64_SSBD is set
|
||||
kernel_ssb=$(grep -w "Speculative Store Bypassing Safe (SSBS)" "$g_kernel")
|
||||
[ -n "$kernel_ssb" ] && kernel_ssb="found 'Speculative Store Bypassing Safe (SSBS)' in kernel"
|
||||
fi
|
||||
# /arm64 only
|
||||
|
||||
if [ -n "$kernel_ssb" ]; then
|
||||
pstatus green YES "$kernel_ssb"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
kernel_ssbd_enabled=-1
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
# https://elixir.bootlin.com/linux/v5.0/source/fs/proc/array.c#L340
|
||||
pr_info_nol "* SSB mitigation is enabled and active: "
|
||||
if grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+thread' "$g_procfs/self/status" 2>/dev/null; then
|
||||
kernel_ssbd_enabled=1
|
||||
pstatus green YES "per-thread through prctl"
|
||||
elif grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+globally mitigated' "$g_procfs/self/status" 2>/dev/null; then
|
||||
kernel_ssbd_enabled=2
|
||||
pstatus green YES "global"
|
||||
elif grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+vulnerable' "$g_procfs/self/status" 2>/dev/null; then
|
||||
kernel_ssbd_enabled=0
|
||||
pstatus yellow NO
|
||||
elif grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+not vulnerable' "$g_procfs/self/status" 2>/dev/null; then
|
||||
kernel_ssbd_enabled=-2
|
||||
pstatus blue NO "not vulnerable"
|
||||
elif grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+unknown' "$g_procfs/self/status" 2>/dev/null; then
|
||||
kernel_ssbd_enabled=0
|
||||
pstatus blue NO
|
||||
else
|
||||
pstatus blue UNKNOWN "unknown value: $(grep -E 'Speculation.?Store.?Bypass:' "$g_procfs/self/status" 2>/dev/null | cut -d: -f2-)"
|
||||
fi
|
||||
|
||||
if [ "$kernel_ssbd_enabled" = 1 ]; then
|
||||
pr_info_nol "* SSB mitigation currently active for selected processes: "
|
||||
# silence grep's stderr here to avoid ENOENT errors from processes that have exited since the shell's expansion of the *
|
||||
mitigated_processes=$(find /proc -mindepth 2 -maxdepth 2 -type f -name status -print0 2>/dev/null |
|
||||
xargs -r0 grep -El 'Speculation.?Store.?Bypass:[[:space:]]+thread (force )?mitigated' 2>/dev/null |
|
||||
sed s/status/exe/ | xargs -r -n1 readlink -f 2>/dev/null | xargs -r -n1 basename | sort -u | tr "\n" " " | sed 's/ $//')
|
||||
if [ -n "$mitigated_processes" ]; then
|
||||
pstatus green YES "$mitigated_processes"
|
||||
else
|
||||
pstatus yellow NO "no process found using SSB mitigation through prctl"
|
||||
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"
|
||||
elif [ -z "$msg" ] || [ "$msg" = "Vulnerable" ]; then
|
||||
# if msg is empty, sysfs check didn't fill it, rely on our own test
|
||||
if [ -n "$cap_ssbd" ]; then
|
||||
if [ -n "$kernel_ssb" ]; then
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if [ "$kernel_ssbd_enabled" -gt 0 ]; then
|
||||
pvulnstatus "$cve" OK "your CPU and kernel both support SSBD and mitigation is enabled"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "your CPU and kernel both support SSBD but the mitigation is not active"
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" OK "your system provides the necessary tools for software mitigation"
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" VULN "your kernel needs to be updated"
|
||||
explain "You have a recent-enough CPU microcode but your kernel is too old to use the new features exported by your CPU's microcode. If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel from recent-enough sources."
|
||||
fi
|
||||
else
|
||||
if [ -n "$kernel_ssb" ]; then
|
||||
pvulnstatus "$cve" VULN "Your CPU doesn't support SSBD"
|
||||
explain "Your kernel is recent enough to use the CPU microcode features for mitigation, but your CPU microcode doesn't actually provide the necessary features for the kernel to use. The microcode of your CPU hence needs to be upgraded. 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)."
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Neither your CPU nor your kernel support SSBD"
|
||||
explain "Both your CPU microcode and your kernel are lacking support for mitigation. If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel from recent-enough sources. The microcode of your CPU also needs to be upgraded. 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)."
|
||||
fi
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" "$status" "$msg"
|
||||
fi
|
||||
}
|
||||
|
||||
# CVE-2018-3639 Variant 4 (speculative store bypass) - BSD mitigation check
|
||||
check_CVE_2018_3639_bsd() {
|
||||
local kernel_ssb ssb_enabled ssb_active
|
||||
pr_info_nol "* Kernel supports speculation store bypass: "
|
||||
if sysctl hw.spec_store_bypass_disable >/dev/null 2>&1; then
|
||||
kernel_ssb=1
|
||||
pstatus green YES
|
||||
else
|
||||
kernel_ssb=0
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
pr_info_nol "* Speculation store bypass is administratively enabled: "
|
||||
ssb_enabled=$(sysctl -n hw.spec_store_bypass_disable 2>/dev/null)
|
||||
pr_debug "hw.spec_store_bypass_disable=$ssb_enabled"
|
||||
case "$ssb_enabled" in
|
||||
0) pstatus yellow NO "disabled" ;;
|
||||
1) pstatus green YES "enabled" ;;
|
||||
2) pstatus green YES "auto mode" ;;
|
||||
*) pstatus yellow NO "unavailable" ;;
|
||||
esac
|
||||
|
||||
pr_info_nol "* Speculation store bypass is currently active: "
|
||||
ssb_active=$(sysctl -n hw.spec_store_bypass_disable_active 2>/dev/null)
|
||||
pr_debug "hw.spec_store_bypass_disable_active=$ssb_active"
|
||||
case "$ssb_active" in
|
||||
1) pstatus green YES ;;
|
||||
*) pstatus yellow NO ;;
|
||||
esac
|
||||
|
||||
if ! is_cpu_affected "$cve"; then
|
||||
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
|
||||
else
|
||||
if [ "$ssb_active" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "SSBD mitigates the vulnerability"
|
||||
elif [ -n "$cap_ssbd" ]; then
|
||||
if [ "$kernel_ssb" = 1 ]; then
|
||||
pvulnstatus "$cve" VULN "you need to enable SSBD through sysctl to mitigate the vulnerability"
|
||||
explain "To enable SSBD right now, you can run \`sysctl hw.spec_store_bypass_disable=2'. To make this change persistent across reboots, you can add 'sysctl hw.spec_store_bypass_disable=2' to /etc/sysctl.conf."
|
||||
else
|
||||
pvulnstatus "$cve" VULN "your kernel needs to be updated"
|
||||
fi
|
||||
else
|
||||
if [ "$kernel_ssb" = 1 ]; then
|
||||
pvulnstatus "$cve" VULN "Your CPU doesn't support SSBD"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Neither your CPU nor your kernel support SSBD"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
33
src/vulns/CVE-2018-3640.sh
Normal file
33
src/vulns/CVE-2018-3640.sh
Normal file
@@ -0,0 +1,33 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
####################
|
||||
# VARIANT 3A SECTION
|
||||
|
||||
# CVE-2018-3640 Variant 3a (rogue system register read) - entry point
|
||||
check_CVE_2018_3640() {
|
||||
local status sys_interface_available msg cve
|
||||
cve='CVE-2018-3640'
|
||||
pr_info "\033[1;34m$cve aka '$(cve2name "$cve")'\033[0m"
|
||||
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
|
||||
pr_info_nol "* CPU microcode mitigates the vulnerability: "
|
||||
if [ -n "$cap_ssbd" ]; then
|
||||
# microcodes that ship with SSBD are known to also fix affected_variant3a
|
||||
# there is no specific cpuid bit as far as we know
|
||||
pstatus green YES
|
||||
else
|
||||
pstatus yellow NO
|
||||
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 [ -n "$cap_ssbd" ]; then
|
||||
pvulnstatus "$cve" OK "your CPU microcode mitigates the vulnerability"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "an up-to-date CPU microcode is needed to mitigate this vulnerability"
|
||||
explain "The microcode of your CPU needs to be upgraded to mitigate this vulnerability. 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). The microcode update is enough, there is no additional OS, kernel or software change needed."
|
||||
fi
|
||||
}
|
||||
214
src/vulns/CVE-2018-3646.sh
Normal file
214
src/vulns/CVE-2018-3646.sh
Normal file
@@ -0,0 +1,214 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
# CVE-2018-3646 Foreshadow-NG VMM (L1 terminal fault VMM) - entry point
|
||||
check_CVE_2018_3646() {
|
||||
check_cve 'CVE-2018-3646'
|
||||
}
|
||||
|
||||
# CVE-2018-3646 Foreshadow-NG VMM (L1 terminal fault VMM) - Linux mitigation check
|
||||
check_CVE_2018_3646_linux() {
|
||||
local status sys_interface_available msg l1d_mode ept_disabled l1d_kernel l1d_kernel_err l1d_xen_hardware l1d_xen_hypervisor l1d_xen_pv_domU smt_enabled
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
if sys_interface_check "$VULN_SYSFS_BASE/l1tf" '.*' quiet; then
|
||||
# this kernel has the /sys interface, trust it over everything
|
||||
sys_interface_available=1
|
||||
fi
|
||||
l1d_mode=-1
|
||||
if [ "$opt_sysfs_only" != 1 ]; then
|
||||
check_has_vmm
|
||||
|
||||
pr_info "* Mitigation 1 (KVM)"
|
||||
pr_info_nol " * EPT is disabled: "
|
||||
ept_disabled=-1
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if ! [ -r "$SYS_MODULE_BASE/kvm_intel/parameters/ept" ]; then
|
||||
pstatus blue N/A "the kvm_intel module is not loaded"
|
||||
elif [ "$(cat "$SYS_MODULE_BASE/kvm_intel/parameters/ept")" = N ]; then
|
||||
pstatus green YES
|
||||
ept_disabled=1
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
else
|
||||
pstatus blue N/A "not testable in offline mode"
|
||||
fi
|
||||
|
||||
pr_info "* Mitigation 2"
|
||||
pr_info_nol " * L1D flush is supported by kernel: "
|
||||
if [ "$opt_live" = 1 ] && grep -qw flush_l1d "$g_procfs/cpuinfo"; then
|
||||
l1d_kernel="found flush_l1d in $g_procfs/cpuinfo"
|
||||
fi
|
||||
if [ -z "$l1d_kernel" ]; then
|
||||
if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
|
||||
l1d_kernel_err="missing '${opt_arch_prefix}strings' tool, please install it, usually it's in the binutils package"
|
||||
elif [ -n "$g_kernel_err" ]; then
|
||||
l1d_kernel_err="$g_kernel_err"
|
||||
elif "${opt_arch_prefix}strings" "$g_kernel" | grep -qw flush_l1d; then
|
||||
l1d_kernel='found flush_l1d in kernel image'
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$l1d_kernel" ]; then
|
||||
pstatus green YES "$l1d_kernel"
|
||||
elif [ -n "$l1d_kernel_err" ]; then
|
||||
pstatus yellow UNKNOWN "$l1d_kernel_err"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
pr_info_nol " * L1D flush enabled: "
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if [ -n "$ret_sys_interface_check_fullmsg" ]; then
|
||||
# vanilla: VMX: $l1dstatus, SMT $smtstatus
|
||||
# Red Hat: VMX: SMT $smtstatus, L1D $l1dstatus
|
||||
# $l1dstatus is one of (auto|vulnerable|conditional cache flushes|cache flushes|EPT disabled|flush not necessary)
|
||||
# $smtstatus is one of (vulnerable|disabled)
|
||||
# can also just be "Not affected"
|
||||
if echo "$ret_sys_interface_check_fullmsg" | grep -Eq -e 'Not affected' -e '(VMX:|L1D) (EPT disabled|vulnerable|flush not necessary)'; then
|
||||
l1d_mode=0
|
||||
pstatus yellow NO
|
||||
elif echo "$ret_sys_interface_check_fullmsg" | grep -Eq '(VMX:|L1D) conditional cache flushes'; then
|
||||
l1d_mode=1
|
||||
pstatus green YES "conditional flushes"
|
||||
elif echo "$ret_sys_interface_check_fullmsg" | grep -Eq '(VMX:|L1D) cache flushes'; then
|
||||
l1d_mode=2
|
||||
pstatus green YES "unconditional flushes"
|
||||
else
|
||||
if is_xen_dom0; then
|
||||
l1d_xen_hardware=$(xl dmesg 2>/dev/null | grep 'Hardware features:' | grep 'L1D_FLUSH' | head -n1)
|
||||
l1d_xen_hypervisor=$(xl dmesg 2>/dev/null | grep 'Xen settings:' | grep 'L1D_FLUSH' | head -n1)
|
||||
l1d_xen_pv_domU=$(xl dmesg 2>/dev/null | grep 'PV L1TF shadowing:' | grep 'DomU enabled' | head -n1)
|
||||
|
||||
if [ -n "$l1d_xen_hardware" ] && [ -n "$l1d_xen_hypervisor" ] && [ -n "$l1d_xen_pv_domU" ]; then
|
||||
l1d_mode=5
|
||||
pstatus green YES "for XEN guests"
|
||||
elif [ -n "$l1d_xen_hardware" ] && [ -n "$l1d_xen_hypervisor" ]; then
|
||||
l1d_mode=4
|
||||
pstatus yellow YES "for XEN guests (HVM only)"
|
||||
elif [ -n "$l1d_xen_pv_domU" ]; then
|
||||
l1d_mode=3
|
||||
pstatus yellow YES "for XEN guests (PV only)"
|
||||
else
|
||||
l1d_mode=0
|
||||
pstatus yellow NO "for XEN guests"
|
||||
fi
|
||||
else
|
||||
l1d_mode=-1
|
||||
pstatus yellow UNKNOWN "unrecognized mode"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
l1d_mode=-1
|
||||
pstatus yellow UNKNOWN "can't find or read $VULN_SYSFS_BASE/l1tf"
|
||||
fi
|
||||
else
|
||||
l1d_mode=-1
|
||||
pstatus blue N/A "not testable in offline mode"
|
||||
fi
|
||||
|
||||
pr_info_nol " * Hardware-backed L1D flush supported: "
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if grep -qw flush_l1d "$g_procfs/cpuinfo" || [ -n "$l1d_xen_hardware" ]; then
|
||||
pstatus green YES "performance impact of the mitigation will be greatly reduced"
|
||||
else
|
||||
pstatus blue NO "flush will be done in software, this is slower"
|
||||
fi
|
||||
else
|
||||
pstatus blue N/A "not testable in offline mode"
|
||||
fi
|
||||
|
||||
pr_info_nol " * Hyper-Threading (SMT) is enabled: "
|
||||
is_cpu_smt_enabled
|
||||
smt_enabled=$?
|
||||
if [ "$smt_enabled" = 0 ]; then
|
||||
pstatus yellow YES
|
||||
elif [ "$smt_enabled" = 1 ]; then
|
||||
pstatus green NO
|
||||
else
|
||||
pstatus yellow UNKNOWN
|
||||
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
|
||||
l1d_mode=-1
|
||||
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 [ "$ret_sys_interface_check_fullmsg" = "Not affected" ]; then
|
||||
# just in case a very recent kernel knows better than we do
|
||||
pvulnstatus "$cve" OK "your kernel reported your CPU model as not affected"
|
||||
elif [ "$g_has_vmm" = 0 ]; then
|
||||
pvulnstatus "$cve" OK "this system is not running a hypervisor"
|
||||
else
|
||||
if [ "$ept_disabled" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "EPT is disabled which mitigates the vulnerability"
|
||||
elif [ "$opt_paranoid" = 0 ]; then
|
||||
if [ "$l1d_mode" -ge 1 ]; then
|
||||
pvulnstatus "$cve" OK "L1D flushing is enabled and mitigates the vulnerability"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "disable EPT or enable L1D flushing to mitigate the vulnerability"
|
||||
fi
|
||||
else
|
||||
if [ "$l1d_mode" -ge 2 ]; then
|
||||
if [ "$smt_enabled" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "L1D unconditional flushing and Hyper-Threading disabled are mitigating the vulnerability"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Hyper-Threading must be disabled to fully mitigate the vulnerability"
|
||||
fi
|
||||
else
|
||||
if [ "$smt_enabled" = 1 ]; then
|
||||
pvulnstatus "$cve" VULN "L1D unconditional flushing should be enabled to fully mitigate the vulnerability"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "enable L1D unconditional flushing and disable Hyper-Threading to fully mitigate the vulnerability"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$l1d_mode" -gt 3 ]; then
|
||||
pr_warn
|
||||
pr_warn "This host is a Xen Dom0. Please make sure that you are running your DomUs"
|
||||
pr_warn "with a kernel which contains CVE-2018-3646 mitigations."
|
||||
pr_warn
|
||||
pr_warn "See https://www.suse.com/support/kb/doc/?id=7023078 and XSA-273 for details."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# CVE-2018-3646 Foreshadow-NG VMM (L1 terminal fault VMM) - BSD mitigation check
|
||||
check_CVE_2018_3646_bsd() {
|
||||
local kernel_l1d_supported kernel_l1d_enabled
|
||||
pr_info_nol "* Kernel supports L1D flushing: "
|
||||
if sysctl hw.vmm.vmx.l1d_flush >/dev/null 2>&1; then
|
||||
pstatus green YES
|
||||
kernel_l1d_supported=1
|
||||
else
|
||||
pstatus yellow NO
|
||||
kernel_l1d_supported=0
|
||||
fi
|
||||
|
||||
pr_info_nol "* L1D flushing is enabled: "
|
||||
kernel_l1d_enabled=$(sysctl -n hw.vmm.vmx.l1d_flush 2>/dev/null)
|
||||
case "$kernel_l1d_enabled" in
|
||||
0) pstatus yellow NO ;;
|
||||
1) pstatus green YES ;;
|
||||
"") pstatus yellow NO ;;
|
||||
*) pstatus yellow UNKNOWN ;;
|
||||
esac
|
||||
|
||||
if ! is_cpu_affected "$cve"; then
|
||||
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
|
||||
else
|
||||
if [ "$kernel_l1d_enabled" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "L1D flushing mitigates the vulnerability"
|
||||
elif [ "$kernel_l1d_supported" = 1 ]; then
|
||||
pvulnstatus "$cve" VULN "L1D flushing is supported by your kernel but is disabled"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "your kernel needs to be updated"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
8
src/vulns/CVE-2019-11091.sh
Normal file
8
src/vulns/CVE-2019-11091.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
###################
|
||||
# MDSUM SECTION
|
||||
|
||||
# CVE-2019-11091 MDSUM (microarchitectural data sampling uncacheable memory) - entry point
|
||||
check_CVE_2019_11091() {
|
||||
check_cve 'CVE-2019-11091' check_mds
|
||||
}
|
||||
96
src/vulns/CVE-2019-11135.sh
Normal file
96
src/vulns/CVE-2019-11135.sh
Normal file
@@ -0,0 +1,96 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
###################
|
||||
# TAA SECTION
|
||||
|
||||
# CVE-2019-11135 TAA (TSX asynchronous abort) - entry point
|
||||
check_CVE_2019_11135() {
|
||||
check_cve 'CVE-2019-11135'
|
||||
}
|
||||
|
||||
# CVE-2019-11135 TAA (TSX asynchronous abort) - Linux mitigation check
|
||||
check_CVE_2019_11135_linux() {
|
||||
local status sys_interface_available msg kernel_taa kernel_taa_err
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
if sys_interface_check "$VULN_SYSFS_BASE/tsx_async_abort"; 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 "* TAA mitigation is supported by kernel: "
|
||||
kernel_taa=''
|
||||
if [ -n "$g_kernel_err" ]; then
|
||||
kernel_taa_err="$g_kernel_err"
|
||||
elif grep -q 'tsx_async_abort' "$g_kernel"; then
|
||||
kernel_taa="found tsx_async_abort in kernel image"
|
||||
fi
|
||||
if [ -n "$kernel_taa" ]; then
|
||||
pstatus green YES "$kernel_taa"
|
||||
elif [ -n "$kernel_taa_err" ]; then
|
||||
pstatus yellow UNKNOWN "$kernel_taa_err"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
pr_info_nol "* TAA mitigation enabled and active: "
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if [ -n "$ret_sys_interface_check_fullmsg" ]; then
|
||||
if echo "$ret_sys_interface_check_fullmsg" | grep -qE '^Mitigation'; then
|
||||
pstatus green YES "$ret_sys_interface_check_fullmsg"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
else
|
||||
pstatus yellow NO "tsx_async_abort not found in sysfs hierarchy"
|
||||
fi
|
||||
else
|
||||
pstatus blue N/A "not testable in offline 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_live" = 1 ]; then
|
||||
# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
|
||||
pvulnstatus "$cve" VULN "Your kernel doesn't support TAA mitigation, update it"
|
||||
else
|
||||
if [ -n "$kernel_taa" ]; then
|
||||
pvulnstatus "$cve" OK "Your kernel supports TAA mitigation"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Your kernel doesn't support TAA mitigation, update it"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if [ "$opt_paranoid" = 1 ]; then
|
||||
# in paranoid mode, TSX or SMT enabled are not OK, even if TAA is mitigated
|
||||
if ! echo "$ret_sys_interface_check_fullmsg" | grep -qF 'TSX disabled'; then
|
||||
pvulnstatus "$cve" VULN "TSX must be disabled for full mitigation"
|
||||
elif echo "$ret_sys_interface_check_fullmsg" | grep -qF 'SMT vulnerable'; then
|
||||
pvulnstatus "$cve" VULN "SMT (HyperThreading) must be disabled for full mitigation"
|
||||
else
|
||||
pvulnstatus "$cve" "$status" "$msg"
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" "$status" "$msg"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# CVE-2019-11135 TAA (TSX asynchronous abort) - BSD mitigation check
|
||||
check_CVE_2019_11135_bsd() {
|
||||
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
|
||||
pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script"
|
||||
fi
|
||||
}
|
||||
115
src/vulns/CVE-2020-0543.sh
Normal file
115
src/vulns/CVE-2020-0543.sh
Normal file
@@ -0,0 +1,115 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
###################
|
||||
# SRBDS SECTION
|
||||
|
||||
# CVE-2020-0543 SRBDS (special register buffer data sampling) - entry point
|
||||
check_CVE_2020_0543() {
|
||||
check_cve 'CVE-2020-0543'
|
||||
}
|
||||
|
||||
# CVE-2020-0543 SRBDS (special register buffer data sampling) - Linux mitigation check
|
||||
check_CVE_2020_0543_linux() {
|
||||
local status sys_interface_available msg kernel_srbds kernel_srbds_err
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
if sys_interface_check "$VULN_SYSFS_BASE/srbds"; 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 "* SRBDS mitigation control is supported by the kernel: "
|
||||
kernel_srbds=''
|
||||
if [ -n "$g_kernel_err" ]; then
|
||||
kernel_srbds_err="$g_kernel_err"
|
||||
elif grep -q 'Dependent on hypervisor' "$g_kernel"; then
|
||||
kernel_srbds="found SRBDS implementation evidence in kernel image. Your kernel is up to date for SRBDS mitigation"
|
||||
fi
|
||||
if [ -n "$kernel_srbds" ]; then
|
||||
pstatus green YES "$kernel_srbds"
|
||||
elif [ -n "$kernel_srbds_err" ]; then
|
||||
pstatus yellow UNKNOWN "$kernel_srbds_err"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
pr_info_nol "* SRBDS mitigation control is enabled and active: "
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if [ -n "$ret_sys_interface_check_fullmsg" ]; then
|
||||
if echo "$ret_sys_interface_check_fullmsg" | grep -qE '^Mitigation'; then
|
||||
pstatus green YES "$ret_sys_interface_check_fullmsg"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
else
|
||||
pstatus yellow NO "SRBDS not found in sysfs hierarchy"
|
||||
fi
|
||||
else
|
||||
pstatus blue N/A "not testable in offline 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"
|
||||
else
|
||||
if [ "$opt_sysfs_only" != 1 ]; then
|
||||
if [ "$cap_srbds" = 1 ]; then
|
||||
# SRBDS mitigation control exists
|
||||
if [ "$cap_srbds_on" = 1 ]; then
|
||||
# SRBDS mitigation control is enabled
|
||||
if [ -z "$msg" ]; then
|
||||
# if msg is empty, sysfs check didn't fill it, rely on our own test
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
|
||||
pvulnstatus "$cve" OK "Your microcode is up to date for SRBDS mitigation control. The kernel needs to be updated"
|
||||
fi
|
||||
else
|
||||
if [ -n "$kernel_srbds" ]; then
|
||||
pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for SRBDS mitigation control. Mitigation is enabled"
|
||||
else
|
||||
pvulnstatus "$cve" OK "Your microcode is up to date for SRBDS mitigation control. The kernel needs to be updated"
|
||||
fi
|
||||
fi
|
||||
elif [ "$cap_srbds_on" = 0 ]; then
|
||||
# SRBDS mitigation control is disabled
|
||||
if [ -z "$msg" ]; then
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
|
||||
pvulnstatus "$cve" VULN "Your microcode is up to date for SRBDS mitigation control. The kernel needs to be updated. Mitigation is disabled"
|
||||
fi
|
||||
else
|
||||
if [ -n "$kernel_srbds" ]; then
|
||||
pvulnstatus "$cve" VULN "Your microcode and kernel are both up to date for SRBDS mitigation control. Mitigation is disabled"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Your microcode is up to date for SRBDS mitigation control. The kernel needs to be updated. Mitigation is disabled"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# rdmsr: CPU 0 cannot read MSR 0x00000123
|
||||
pvulnstatus "$cve" UNK "Not able to enumerate MSR for SRBDS mitigation control"
|
||||
fi
|
||||
else
|
||||
# [ $cap_srbds != 1 ]
|
||||
pvulnstatus "$cve" VULN "Your CPU microcode may need to be updated to mitigate the vulnerability"
|
||||
fi
|
||||
else
|
||||
# sysfs only: return the status/msg we got
|
||||
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# CVE-2020-0543 SRBDS (special register buffer data sampling) - BSD mitigation check
|
||||
check_CVE_2020_0543_bsd() {
|
||||
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
|
||||
pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script"
|
||||
fi
|
||||
}
|
||||
99
src/vulns/CVE-2022-40982.sh
Normal file
99
src/vulns/CVE-2022-40982.sh
Normal file
@@ -0,0 +1,99 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
#########################
|
||||
# Downfall section
|
||||
|
||||
# CVE-2022-40982 Downfall (gather data sampling) - entry point
|
||||
check_CVE_2022_40982() {
|
||||
check_cve 'CVE-2022-40982'
|
||||
}
|
||||
|
||||
# CVE-2022-40982 Downfall (gather data sampling) - Linux mitigation check
|
||||
check_CVE_2022_40982_linux() {
|
||||
local status sys_interface_available msg kernel_gds kernel_gds_err kernel_avx_disabled dmesgret ret
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
|
||||
if sys_interface_check "$VULN_SYSFS_BASE/gather_data_sampling"; 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 "* GDS is mitigated by microcode: "
|
||||
if [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then
|
||||
pstatus green OK "microcode mitigation is supported and enabled"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
pr_info_nol "* Kernel supports software mitigation by disabling AVX: "
|
||||
if [ -n "$g_kernel_err" ]; then
|
||||
kernel_gds_err="$g_kernel_err"
|
||||
elif grep -q 'gather_data_sampling' "$g_kernel"; then
|
||||
kernel_gds="found gather_data_sampling in kernel image"
|
||||
fi
|
||||
if [ -n "$kernel_gds" ]; then
|
||||
pstatus green YES "$kernel_gds"
|
||||
elif [ -n "$kernel_gds_err" ]; then
|
||||
pstatus yellow UNKNOWN "$kernel_gds_err"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
if [ -n "$kernel_gds" ]; then
|
||||
pr_info_nol "* Kernel has disabled AVX as a mitigation: "
|
||||
|
||||
# Check dmesg message to see whether AVX has been disabled
|
||||
dmesg_grep 'Microcode update needed! Disabling AVX as mitigation'
|
||||
dmesgret=$?
|
||||
if [ "$dmesgret" -eq 0 ]; then
|
||||
kernel_avx_disabled="AVX disabled by the kernel (dmesg)"
|
||||
pstatus green YES "$kernel_avx_disabled"
|
||||
elif [ "$cap_avx2" = 0 ]; then
|
||||
# Find out by ourselves
|
||||
# cpuinfo says we don't have AVX2, query
|
||||
# the CPU directly about AVX2 support
|
||||
read_cpuid 0x7 0x0 "$EBX" 5 1 1
|
||||
ret=$?
|
||||
if [ "$ret" -eq "$READ_CPUID_RET_OK" ]; then
|
||||
kernel_avx_disabled="AVX disabled by the kernel (cpuid)"
|
||||
pstatus green YES "$kernel_avx_disabled"
|
||||
elif [ "$ret" -eq "$READ_CPUID_RET_KO" ]; then
|
||||
pstatus yellow NO "CPU doesn't support AVX"
|
||||
elif [ "$dmesgret" -eq 2 ]; then
|
||||
pstatus yellow UNKNOWN "dmesg truncated, can't tell whether mitigation is active, please reboot and relaunch this script"
|
||||
else
|
||||
pstatus yellow UNKNOWN "No sign of mitigation in dmesg and couldn't read cpuid info"
|
||||
fi
|
||||
else
|
||||
pstatus yellow NO "AVX support is enabled"
|
||||
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"
|
||||
elif [ -z "$msg" ]; then
|
||||
# if msg is empty, sysfs check didn't fill it, rely on our own test
|
||||
if [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then
|
||||
pvulnstatus "$cve" OK "Your microcode is up to date and mitigation is enabled"
|
||||
elif [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 1 ]; then
|
||||
pvulnstatus "$cve" VULN "Your microcode is up to date but mitigation is disabled"
|
||||
elif [ -z "$kernel_gds" ]; then
|
||||
pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, and your kernel doesn't support mitigation"
|
||||
elif [ -z "$kernel_avx_disabled" ]; then
|
||||
pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, your kernel support the mitigation but the script did not detect AVX as disabled by the kernel"
|
||||
else
|
||||
pvulnstatus "$cve" OK "Your microcode doesn't mitigate the vulnerability, but your kernel has disabled AVX support"
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" "$status" "$msg"
|
||||
fi
|
||||
}
|
||||
170
src/vulns/CVE-2023-20569.sh
Normal file
170
src/vulns/CVE-2023-20569.sh
Normal file
@@ -0,0 +1,170 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
#######################
|
||||
# Inception section
|
||||
|
||||
# CVE-2023-20569 Inception (SRSO, speculative return stack overflow) - entry point
|
||||
check_CVE_2023_20569() {
|
||||
check_cve 'CVE-2023-20569'
|
||||
}
|
||||
|
||||
# CVE-2023-20569 Inception (SRSO, speculative return stack overflow) - Linux mitigation check
|
||||
check_CVE_2023_20569_linux() {
|
||||
local status sys_interface_available msg kernel_sro kernel_sro_err kernel_srso kernel_ibpb_entry smt_enabled
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
|
||||
if sys_interface_check "$VULN_SYSFS_BASE/spec_rstack_overflow"; 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_sro_err="$g_kernel_err"
|
||||
elif grep -q 'spec_rstack_overflow' "$g_kernel"; then
|
||||
kernel_sro="found spec_rstack_overflow in kernel image"
|
||||
fi
|
||||
if [ -n "$kernel_sro" ]; then
|
||||
pstatus green YES "$kernel_sro"
|
||||
elif [ -n "$kernel_sro_err" ]; then
|
||||
pstatus yellow UNKNOWN "$kernel_sro_err"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
|
||||
pr_info_nol "* Kernel compiled with SRSO support: "
|
||||
if [ -r "$opt_config" ]; then
|
||||
# CONFIG_CPU_SRSO: Linux < 6.9
|
||||
# CONFIG_MITIGATION_SRSO: Linux >= 6.9
|
||||
if grep -Eq '^CONFIG_(CPU|MITIGATION)_SRSO=y' "$opt_config"; then
|
||||
pstatus green YES
|
||||
kernel_srso="CONFIG_(CPU|MITIGATION)_SRSO=y found in kernel config"
|
||||
else
|
||||
pstatus yellow NO "required for safe RET and ibpb_on_vmexit mitigations"
|
||||
fi
|
||||
else
|
||||
# https://github.com/torvalds/linux/commit/138bcddb86d8a4f842e4ed6f0585abc9b1a764ff#diff-17bd24a7a7850613cced545790ac30646097e8d6207348c2bd1845f397acb390R2313
|
||||
if [ -n "$g_kernel_err" ]; then
|
||||
pstatus yellow UNKNOWN "$g_kernel_err"
|
||||
elif grep -Eq 'WARNING: kernel not compiled with (CPU|MITIGATION)_SRSO' "$g_kernel"; then
|
||||
# this msg is optimized out at compile time if the option is not enabled, see commit referenced above
|
||||
# if it's present, then SRSO is NOT compiled in
|
||||
pstatus yellow NO "kernel not compiled with (CPU|MITIGATION)_SRSO"
|
||||
else
|
||||
# if it's not present, then SRSO is compiled in IF kernel_sro==1, otherwise we're just
|
||||
# in front of an old kernel that doesn't have the mitigation logic at all
|
||||
if [ "$kernel_sro" = 1 ]; then
|
||||
kernel_srso="SRSO mitigation logic is compiled in the kernel"
|
||||
pstatus green OK "$kernel_srso"
|
||||
else
|
||||
pstatus yellow NO "your kernel is too old and doesn't have the mitigation logic"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
pr_info_nol "* Kernel compiled with IBPB_ENTRY support: "
|
||||
if [ -r "$opt_config" ]; then
|
||||
# CONFIG_CPU_IBPB_ENTRY: Linux < 6.9
|
||||
# CONFIG_MITIGATION_IBPB_ENTRY: Linux >= 6.9
|
||||
if grep -Eq '^CONFIG_(CPU|MITIGATION)_IBPB_ENTRY=y' "$opt_config"; then
|
||||
pstatus green YES
|
||||
kernel_ibpb_entry="CONFIG_(CPU|MITIGATION)_IBPB_ENTRY=y found in kernel config"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
else
|
||||
# https://github.com/torvalds/linux/commit/138bcddb86d8a4f842e4ed6f0585abc9b1a764ff#diff-17bd24a7a7850613cced545790ac30646097e8d6207348c2bd1845f397acb390R2325
|
||||
if [ -n "$g_kernel_err" ]; then
|
||||
pstatus yellow UNKNOWN "$g_kernel_err"
|
||||
elif grep -Eq 'WARNING: kernel not compiled with (CPU|MITIGATION)_IBPB_ENTRY' "$g_kernel"; then
|
||||
# this msg is optimized out at compile time if the option is not enabled, see commit referenced above
|
||||
# if it's present, then IBPB_ENTRY is NOT compiled in
|
||||
pstatus yellow NO "kernel not compiled with (CPU|MITIGATION)_IBPB_ENTRY"
|
||||
else
|
||||
# if it's not present, then IBPB_ENTRY is compiled in IF kernel_sro==1, otherwise we're just
|
||||
# in front of an old kernel that doesn't have the mitigation logic at all
|
||||
if [ "$kernel_sro" = 1 ]; then
|
||||
kernel_ibpb_entry="IBPB_ENTRY mitigation logic is compiled in the kernel"
|
||||
pstatus green OK "$kernel_ibpb_entry"
|
||||
else
|
||||
pstatus yellow NO "your kernel is too old and doesn't have the mitigation logic"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Zen & Zen2 : if the right IBPB microcode applied + SMT off --> not vuln
|
||||
if [ "$cpu_family" = $((0x17)) ]; then
|
||||
pr_info_nol "* CPU supports IBPB: "
|
||||
if [ -n "$cap_ibpb" ]; then
|
||||
pstatus green YES "$cap_ibpb"
|
||||
else
|
||||
pstatus yellow NO
|
||||
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
|
||||
# Zen 3/4 microcode brings SBPB mitigation
|
||||
elif [ "$cpu_family" = $((0x19)) ]; then
|
||||
pr_info_nol "* CPU supports SBPB: "
|
||||
if [ "$cap_sbpb" = 1 ]; then
|
||||
pstatus green YES
|
||||
elif [ "$cap_sbpb" = 3 ]; then
|
||||
pstatus yellow UNKNOWN "cannot write MSR, rerun with --allow-msr-write"
|
||||
else
|
||||
pstatus yellow NO
|
||||
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"
|
||||
elif [ -z "$msg" ]; then
|
||||
# if msg is empty, sysfs check didn't fill it, so we rely on our own logic
|
||||
# Zen/Zen2
|
||||
if [ "$cpu_family" = $((0x17)) ]; then
|
||||
if [ "$smt_enabled" = 0 ]; then
|
||||
pvulnstatus "$cve" VULN "SMT is enabled on your Zen/Zen2 CPU, which makes mitigation ineffective"
|
||||
explain "For Zen/Zen2 CPUs, proper mitigation needs an up to date microcode, and SMT needs to be disabled (this can be done by adding \`nosmt\` to your kernel command line)"
|
||||
elif [ -z "$kernel_sro" ]; then
|
||||
pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the SRSO mitigation logic"
|
||||
elif [ -n "$cap_ibpb" ]; then
|
||||
pvulnstatus "$cve" OK "SMT is disabled and both your kernel and microcode support mitigation"
|
||||
else
|
||||
pvulnstatus "$cve" VULN "Your microcode is too old"
|
||||
fi
|
||||
# Zen3/Zen4
|
||||
elif [ "$cpu_family" = $((0x19)) ]; then
|
||||
if [ -z "$kernel_sro" ]; then
|
||||
pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the SRSO mitigation logic"
|
||||
elif [ -z "$kernel_srso" ] && [ -z "$kernel_ibpb_entry" ]; then
|
||||
pvulnstatus "$cve" VULN "Your kernel doesn't have either SRSO or IBPB_ENTRY compiled-in"
|
||||
elif [ "$cap_sbpb" = 3 ]; then
|
||||
pvulnstatus "$cve" UNK "Couldn't verify if your microcode supports IBPB (rerun with --allow-msr-write)"
|
||||
elif [ "$cap_sbpb" = 2 ]; then
|
||||
pvulnstatus "$cve" VULN "Your microcode doesn't support SBPB"
|
||||
else
|
||||
pvulnstatus "$cve" OK "Your kernel and microcode both support mitigation"
|
||||
fi
|
||||
else
|
||||
# not supposed to happen, as normally this CPU should not be affected and not run this code
|
||||
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
|
||||
fi
|
||||
else
|
||||
pvulnstatus "$cve" "$status" "$msg"
|
||||
fi
|
||||
}
|
||||
120
src/vulns/CVE-2023-20593.sh
Normal file
120
src/vulns/CVE-2023-20593.sh
Normal file
@@ -0,0 +1,120 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
####################
|
||||
# Zenbleed section
|
||||
|
||||
# CVE-2023-20593 Zenbleed (cross-process information leak via AVX2) - entry point
|
||||
check_CVE_2023_20593() {
|
||||
check_cve 'CVE-2023-20593'
|
||||
}
|
||||
|
||||
# CVE-2023-20593 Zenbleed (cross-process information leak via AVX2) - Linux mitigation check
|
||||
check_CVE_2023_20593_linux() {
|
||||
local status sys_interface_available msg kernel_zenbleed kernel_zenbleed_err fp_backup_fix ucode_zenbleed zenbleed_print_vuln ret
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
if [ "$opt_sysfs_only" != 1 ]; then
|
||||
pr_info_nol "* Zenbleed mitigation is supported by kernel: "
|
||||
kernel_zenbleed=''
|
||||
if [ -n "$g_kernel_err" ]; then
|
||||
kernel_zenbleed_err="$g_kernel_err"
|
||||
# commit 522b1d69219d8f083173819fde04f994aa051a98
|
||||
elif grep -q 'Zenbleed:' "$g_kernel"; then
|
||||
kernel_zenbleed="found zenbleed message in kernel image"
|
||||
fi
|
||||
if [ -n "$kernel_zenbleed" ]; then
|
||||
pstatus green YES "$kernel_zenbleed"
|
||||
elif [ -n "$kernel_zenbleed_err" ]; then
|
||||
pstatus yellow UNKNOWN "$kernel_zenbleed_err"
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
pr_info_nol "* Zenbleed kernel mitigation enabled and active: "
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
# read the DE_CFG MSR, we want to check the 9th bit
|
||||
# don't do it on non-Zen2 AMD CPUs or later, aka Family 17h,
|
||||
# as the behavior could be unknown on others
|
||||
if is_amd && [ "$cpu_family" -ge $((0x17)) ]; then
|
||||
read_msr 0xc0011029
|
||||
ret=$?
|
||||
if [ "$ret" = "$READ_MSR_RET_OK" ]; then
|
||||
if [ $((ret_read_msr_value >> 9 & 1)) -eq 1 ]; then
|
||||
pstatus green YES "FP_BACKUP_FIX bit set in DE_CFG"
|
||||
fp_backup_fix=1
|
||||
else
|
||||
pstatus yellow NO "FP_BACKUP_FIX is cleared in DE_CFG"
|
||||
fp_backup_fix=0
|
||||
fi
|
||||
elif [ "$ret" = "$READ_MSR_RET_KO" ]; then
|
||||
pstatus yellow UNKNOWN "Couldn't read the DE_CFG MSR"
|
||||
else
|
||||
pstatus yellow UNKNOWN "$ret_read_msr_msg"
|
||||
fi
|
||||
else
|
||||
fp_backup_fix=0
|
||||
pstatus blue N/A "CPU is incompatible"
|
||||
fi
|
||||
else
|
||||
pstatus blue N/A "not testable in offline mode"
|
||||
fi
|
||||
|
||||
pr_info_nol "* Zenbleed mitigation is supported by CPU microcode: "
|
||||
has_zenbleed_fixed_firmware
|
||||
ret=$?
|
||||
if [ "$ret" -eq 0 ]; then
|
||||
pstatus green YES
|
||||
ucode_zenbleed=1
|
||||
elif [ "$ret" -eq 1 ]; then
|
||||
pstatus yellow NO
|
||||
ucode_zenbleed=2
|
||||
else
|
||||
pstatus yellow UNKNOWN
|
||||
ucode_zenbleed=3
|
||||
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
|
||||
zenbleed_print_vuln=0
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if [ "$fp_backup_fix" = 1 ] && [ "$ucode_zenbleed" = 1 ]; then
|
||||
# this should never happen, but if it does, it's interesting to know
|
||||
pvulnstatus "$cve" OK "Both your CPU microcode and kernel are mitigating Zenbleed"
|
||||
elif [ "$ucode_zenbleed" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "Your CPU microcode mitigates Zenbleed"
|
||||
elif [ "$fp_backup_fix" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "Your kernel mitigates Zenbleed"
|
||||
else
|
||||
zenbleed_print_vuln=1
|
||||
fi
|
||||
else
|
||||
if [ "$ucode_zenbleed" = 1 ]; then
|
||||
pvulnstatus "$cve" OK "Your CPU microcode mitigates Zenbleed"
|
||||
elif [ -n "$kernel_zenbleed" ]; then
|
||||
pvulnstatus "$cve" OK "Your kernel mitigates Zenbleed"
|
||||
else
|
||||
zenbleed_print_vuln=1
|
||||
fi
|
||||
fi
|
||||
if [ "$zenbleed_print_vuln" = 1 ]; then
|
||||
pvulnstatus "$cve" VULN "Your kernel is too old to mitigate Zenbleed and your CPU microcode doesn't mitigate it either"
|
||||
explain "Your CPU vendor may have a new microcode for your CPU model that mitigates this issue (refer to the hardware section above).\n " \
|
||||
"Otherwise, the Linux kernel is able to mitigate this issue regardless of the microcode version you have, but in this case\n " \
|
||||
"your kernel is too old to support this, your Linux distribution vendor might have a more recent version you should upgrade to.\n " \
|
||||
"Note that either having an up to date microcode OR an up to date kernel is enough to mitigate this issue.\n " \
|
||||
"To manually mitigate the issue right now, you may use the following command: \`wrmsr -a 0xc0011029 \$((\$(rdmsr -c 0xc0011029) | (1<<9)))\`,\n " \
|
||||
"however note that this manual mitigation will only be active until the next reboot."
|
||||
fi
|
||||
unset zenbleed_print_vuln
|
||||
else
|
||||
pvulnstatus "$cve" "$status" "$msg"
|
||||
fi
|
||||
}
|
||||
32
src/vulns/CVE-2023-23583.sh
Normal file
32
src/vulns/CVE-2023-23583.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
# vim: set ts=4 sw=4 sts=4 et:
|
||||
#######################
|
||||
# Reptar section
|
||||
|
||||
# CVE-2023-23583 Reptar (redundant prefix issue) - entry point
|
||||
check_CVE_2023_23583() {
|
||||
check_cve 'CVE-2023-23583'
|
||||
}
|
||||
|
||||
# CVE-2023-23583 Reptar (redundant prefix issue) - Linux mitigation check
|
||||
check_CVE_2023_23583_linux() {
|
||||
local status sys_interface_available msg
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
|
||||
# there is no sysfs file for this vuln, and no kernel patch,
|
||||
# the mitigation is only ucode-based and there's no flag exposed,
|
||||
# so most of the work has already been done by is_cpu_affected()
|
||||
if ! is_cpu_affected "$cve"; then
|
||||
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
|
||||
else
|
||||
pr_info_nol "* Reptar is mitigated by microcode: "
|
||||
if [ "$cpu_ucode" -lt "$g_reptar_fixed_ucode_version" ]; then
|
||||
pstatus yellow NO "You have ucode $(printf "0x%x" "$cpu_ucode") and version $(printf "0x%x" "$g_reptar_fixed_ucode_version") minimum is required"
|
||||
pvulnstatus "$cve" VULN "Your microcode is too old to mitigate the vulnerability"
|
||||
else
|
||||
pstatus green YES "You have ucode $(printf "0x%x" "$cpu_ucode") which is recent enough (>= $(printf "0x%x" "$g_reptar_fixed_ucode_version"))"
|
||||
pvulnstatus "$cve" OK "Your microcode mitigates the vulnerability"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
Reference in New Issue
Block a user