mirror of
https://github.com/speed47/spectre-meltdown-checker
synced 2024-12-22 20:33:56 +01:00
feat: rework Spectre V2 mitigations detection w/ latest vanilla & Red Hat 7 kernels
This commit is contained in:
parent
07484d0ea7
commit
de02dad909
@ -1831,11 +1831,18 @@ check_variant2_linux()
|
||||
sys_interface_available=1
|
||||
fi
|
||||
if [ "$opt_sysfs_only" != 1 ]; then
|
||||
_info "* Mitigation 1"
|
||||
_info_nol " * Kernel is compiled with IBRS/IBPB support: "
|
||||
_info "* Mitigation 1"
|
||||
|
||||
ibrs_can_tell=0
|
||||
ibrs_supported=''
|
||||
ibrs_enabled=''
|
||||
ibpb_can_tell=0
|
||||
ibpb_supported=''
|
||||
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)
|
||||
ibrs_can_tell=1
|
||||
mount_debugfs
|
||||
for dir in \
|
||||
@ -1847,17 +1854,18 @@ check_variant2_linux()
|
||||
# /sys/kernel/debug/ibrs_enabled: vanilla
|
||||
# /sys/kernel/debug/x86/ibrs_enabled: Red Hat (see https://access.redhat.com/articles/3311301)
|
||||
# /proc/sys/kernel/ibrs_enabled: OpenSUSE tumbleweed
|
||||
pstatus green YES
|
||||
ibrs_knob_dir=$dir
|
||||
ibrs_supported=1
|
||||
specex_knob_dir=$dir
|
||||
ibrs_supported="$dir/ibrs_enabled exists"
|
||||
ibrs_enabled=$(cat "$dir/ibrs_enabled" 2>/dev/null)
|
||||
_debug "ibrs: found $dir/ibrs_enabled=$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)
|
||||
ibpb_supported="$dir/ibpb_enabled exists"
|
||||
ibpb_enabled=$(cat "$dir/ibpb_enabled" 2>/dev/null)
|
||||
_debug "ibpb: found $dir/ibpb_enabled=$ibpb_enabled"
|
||||
else
|
||||
ibpb_enabled=-1
|
||||
_debug "ibpb: no ibpb_enabled file in $dir"
|
||||
_debug "ibpb: $dir/ibpb_enabled file doesn't exist"
|
||||
fi
|
||||
break
|
||||
else
|
||||
@ -1868,42 +1876,93 @@ check_variant2_linux()
|
||||
# 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 [ "$ibrs_supported" = 0 ]; then
|
||||
if [ -z "$ibrs_supported" ]; then
|
||||
if grep ^flags "$procfs/cpuinfo" | grep -qw spec_ctrl_ibrs; then
|
||||
_debug "ibrs: found spec_ctrl_ibrs flag in $procfs/cpuinfo"
|
||||
ibrs_supported=1
|
||||
ibrs_supported="spec_ctrl_ibrs flag in $procfs/cpuinfo"
|
||||
# enabled=2 -> kernel & user
|
||||
ibrs_enabled=2
|
||||
# XXX and what about ibpb ?
|
||||
fi
|
||||
fi
|
||||
if [ -e "/sys/devices/system/cpu/vulnerabilities/spectre_v2" ]; then
|
||||
# when IBPB is enabled on 4.15+, we can see it in sysfs
|
||||
if grep -q ', IBPB' "/sys/devices/system/cpu/vulnerabilities/spectre_v2"; then
|
||||
_debug "ibpb: found enabled in sysfs"
|
||||
ibpb_supported='IBPB found enabled in sysfs'
|
||||
ibpb_enabled=1
|
||||
fi
|
||||
# when IBRS_FW is enabled on 4.15+, we can see it in sysfs
|
||||
if grep -q ', IBRS_FW' "/sys/devices/system/cpu/vulnerabilities/spectre_v2"; then
|
||||
_debug "ibrs: found IBRS_FW in sysfs"
|
||||
ibrs_supported='found IBRS_FW in sysfs'
|
||||
ibrs_fw_enabled=1
|
||||
fi
|
||||
# when IBRS is enabled on 4.15+, we can see it in sysfs
|
||||
if grep -q 'Indirect Branch Restricted Speculation' "/sys/devices/system/cpu/vulnerabilities/spectre_v2"; then
|
||||
_debug "ibrs: found IBRS in sysfs"
|
||||
ibrs_supported='found IBRS in sysfs'
|
||||
ibrs_enabled=3
|
||||
fi
|
||||
fi
|
||||
# in live mode, if ibrs or ibpb is supported and we didn't find these are enabled, then they are not
|
||||
[ -n "$ibrs_supported" ] && [ -z "$ibrs_enabled" ] && ibrs_enabled=0
|
||||
[ -n "$ibpb_supported" ] && [ -z "$ibpb_enabled" ] && ibpb_enabled=0
|
||||
fi
|
||||
if [ "$ibrs_supported" != 1 ] && [ -n "$opt_map" ]; then
|
||||
if [ -z "$ibrs_supported" ]; then
|
||||
check_redhat_canonical_spectre
|
||||
if [ "$redhat_canonical_spectre" = 1 ]; then
|
||||
ibrs_supported="Red Hat/Ubuntu variant"
|
||||
ibpb_supported="Red Hat/Ubuntu variant"
|
||||
fi
|
||||
fi
|
||||
if [ -z "$ibrs_supported" ] && [ -n "$kernel" ]; then
|
||||
if ! which "${opt_arch_prefix}strings" >/dev/null 2>&1; then
|
||||
:
|
||||
else
|
||||
ibrs_can_tell=1
|
||||
ibrs_supported=$("${opt_arch_prefix}strings" "$kernel" | grep -Fw -e ', IBRS_FW' | head -1)
|
||||
if [ -n "$ibrs_supported" ]; then
|
||||
_debug "ibrs: found ibrs evidence in kernel image ($ibrs_supported)"
|
||||
ibrs_supported="found '$ibrs_supported' in kernel image"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ -z "$ibrs_supported" ] && [ -n "$opt_map" ]; then
|
||||
ibrs_can_tell=1
|
||||
if grep -q spec_ctrl "$opt_map"; then
|
||||
pstatus green YES
|
||||
ibrs_supported=1
|
||||
ibrs_supported="found spec_ctrl in symbols file"
|
||||
_debug "ibrs: found '*spec_ctrl*' symbol in $opt_map"
|
||||
fi
|
||||
fi
|
||||
if [ "$ibrs_supported" != 1 ]; then
|
||||
check_redhat_canonical_spectre
|
||||
if [ "$redhat_canonical_spectre" = 1 ]; then
|
||||
pstatus green YES "Red Hat/Ubuntu patch"
|
||||
ibrs_supported=1
|
||||
# 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 "$ibpb_supported" ] && [ -n "$kernel" ]; then
|
||||
if ! which "${opt_arch_prefix}strings" >/dev/null 2>&1; then
|
||||
:
|
||||
else
|
||||
ibpb_can_tell=1
|
||||
ibpb_supported=$("${opt_arch_prefix}strings" "$kernel" | grep -Fw -e 'ibpb' -e ', IBPB' | head -1)
|
||||
if [ -n "$ibpb_supported" ]; then
|
||||
_debug "ibpb: found ibpb evidence in kernel image ($ibpb_supported)"
|
||||
ibpb_supported="found '$ibpb_supported' in kernel image"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ "$ibrs_supported" != 1 ]; then
|
||||
|
||||
_info_nol " * Kernel is compiled with IBRS support: "
|
||||
if [ -z "$ibrs_supported" ]; then
|
||||
if [ "$ibrs_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 System.map to be able to tell"
|
||||
pstatus yellow UNKNOWN "in offline mode, we need the kernel image and System.map to be able to tell"
|
||||
fi
|
||||
else
|
||||
pstatus green YES "$ibrs_supported"
|
||||
fi
|
||||
|
||||
_info " * Currently enabled features"
|
||||
_info_nol " * IBRS enabled for Kernel space: "
|
||||
_info_nol " * IBRS enabled and active: "
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if [ "$ibpb_enabled" = 2 ]; then
|
||||
# if ibpb=2, ibrs is forcefully=0
|
||||
@ -1912,53 +1971,41 @@ check_variant2_linux()
|
||||
# 0 means disabled
|
||||
# 1 is enabled only for kernel space
|
||||
# 2 is enabled for kernel and user space
|
||||
# 3 is enabled
|
||||
case "$ibrs_enabled" in
|
||||
"")
|
||||
if [ "$ibrs_supported" = 1 ]; then
|
||||
pstatus yellow UNKNOWN
|
||||
else
|
||||
pstatus yellow NO
|
||||
fi
|
||||
;;
|
||||
0)
|
||||
pstatus yellow NO
|
||||
_verbose " - To enable, \`echo 1 > $ibrs_knob_dir/ibrs_enabled' as root. If you don't have hardware support, you'll get an error."
|
||||
;;
|
||||
1 | 2) pstatus green YES;;
|
||||
*) pstatus yellow UNKNOWN;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
pstatus blue N/A "not testable in offline mode"
|
||||
fi
|
||||
|
||||
_info_nol " * IBRS enabled for User space: "
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if [ "$ibpb_enabled" = 2 ]; then
|
||||
# if ibpb=2, ibrs is forcefully=0
|
||||
pstatus blue NO "IBPB used instead of IBRS in all kernel entrypoints"
|
||||
else
|
||||
case "$ibrs_enabled" in
|
||||
"")
|
||||
if [ "$ibrs_supported" = 1 ]; then
|
||||
pstatus yellow UNKNOWN
|
||||
if [ "$ibrs_fw_enabled" = 1 ]; then
|
||||
pstatus green YES "for firmware code"
|
||||
else
|
||||
pstatus yellow NO
|
||||
if [ -e "$specex_knob_dir/ibrs_enabled" ]; then
|
||||
_verbose " - To enable, \`echo 1 > $specex_knob_dir/ibrs_enabled' as root. If you don't have hardware support, you'll get an error."
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
0 | 1)
|
||||
pstatus yellow NO
|
||||
_verbose " - To enable, \`echo 2 > $ibrs_knob_dir/ibrs_enabled' as root. If you don't have hardware support, you'll get an error."
|
||||
;;
|
||||
2) pstatus green YES;;
|
||||
*) pstatus yellow UNKNOWN;;
|
||||
1) pstatus green YES "for kernel space";;
|
||||
2) pstatus green YES "for both kernel and user space";;
|
||||
3) if [ "$ibrs_fw_enabled" = 1 ]; then pstatus green YES "for kernel and firmware code"; else pstatus green YES; fi;;
|
||||
*) pstatus yellow UNKNOWN;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
pstatus blue N/A "not testable in offline mode"
|
||||
fi
|
||||
|
||||
_info_nol " * IBPB enabled: "
|
||||
_info_nol " * Kernel is compiled with IBPB support: "
|
||||
if [ -z "$ibpb_supported" ]; then
|
||||
if [ "$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
|
||||
pstatus green YES "$ibpb_supported"
|
||||
fi
|
||||
|
||||
_info_nol " * IBPB enabled and active: "
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
case "$ibpb_enabled" in
|
||||
"")
|
||||
@ -1970,7 +2017,7 @@ check_variant2_linux()
|
||||
;;
|
||||
0)
|
||||
pstatus yellow NO
|
||||
_verbose " - To enable, \`echo 1 > $ibrs_knob_dir/ibpb_enabled' as root. If you don't have hardware support, you'll get an error."
|
||||
_verbose " - To enable, \`echo 1 > $specex_knob_dir/ibpb_enabled' as root. If you don't have hardware support, you'll get an error."
|
||||
;;
|
||||
1) pstatus green YES;;
|
||||
2) pstatus green YES "IBPB used instead of IBRS in all kernel entrypoints";;
|
||||
@ -2021,18 +2068,23 @@ check_variant2_linux()
|
||||
pstatus yellow UNKNOWN "couldn't read your kernel configuration"
|
||||
fi
|
||||
|
||||
_info_nol " * Kernel compiled with a retpoline-aware compiler: "
|
||||
_info_nol " * Kernel compiled with a retpoline-aware compiler: "
|
||||
# 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_RETPOLINE is set
|
||||
# *AND* if the compiler is retpoline-compliant, so look for that symbol
|
||||
#
|
||||
# if there is "retpoline" in the file and NOT "minimal", then it's full retpoline
|
||||
# (works for vanilla and Red Hat variants)
|
||||
if [ "$opt_live" = 1 ] && [ -e "/sys/devices/system/cpu/vulnerabilities/spectre_v2" ]; then
|
||||
if grep -qw Minimal /sys/devices/system/cpu/vulnerabilities/spectre_v2; then
|
||||
pstatus yellow NO "kernel reports minimal retpoline compilation"
|
||||
elif grep -qw Full /sys/devices/system/cpu/vulnerabilities/spectre_v2; then
|
||||
retpoline_compiler=1
|
||||
pstatus green YES "kernel reports full retpoline compilation"
|
||||
if grep -qwi retpoline /sys/devices/system/cpu/vulnerabilities/spectre_v2; then
|
||||
if grep -qwi minimal /sys/devices/system/cpu/vulnerabilities/spectre_v2; then
|
||||
pstatus yellow NO "kernel reports minimal retpoline compilation"
|
||||
else
|
||||
retpoline_compiler=1
|
||||
pstatus green YES "kernel reports full retpoline compilation"
|
||||
fi
|
||||
else
|
||||
if [ "$retpoline" = 1 ]; then
|
||||
pstatus yellow UNKNOWN
|
||||
@ -2085,6 +2137,22 @@ check_variant2_linux()
|
||||
pstatus yellow NO
|
||||
fi
|
||||
fi
|
||||
|
||||
# only Red Hat has a tunable to disable it on runtime
|
||||
if [ "$opt_live" = 1 ]; then
|
||||
if [ -e "$specex_knob_dir/retp_enabled" ]; then
|
||||
retp_enabled=$(cat "$specex_knob_dir/retp_enabled" 2>/dev/null)
|
||||
_debug "retpoline: found $specex_knob_dir/retp_enabled=$retp_enabled"
|
||||
_info_nol " * Retpoline is enabled: "
|
||||
if [ "$retp_enabled" = 1 ]; then
|
||||
pstatus green YES
|
||||
else
|
||||
pstatus yellow NO
|
||||
_verbose " - To enable, \`echo 1 > $specex_knob_dir/retp_enabled' as root."
|
||||
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!"
|
||||
@ -2097,7 +2165,7 @@ check_variant2_linux()
|
||||
pvulnstatus $cve OK "your CPU vendor reported your CPU model as not vulnerable"
|
||||
elif [ -z "$msg" ]; then
|
||||
# if msg is empty, sysfs check didn't fill it, rely on our own test
|
||||
if [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ]; then
|
||||
if [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ] && [ "$retp_enabled" != 0 ]; then
|
||||
pvulnstatus $cve OK "retpoline mitigates the vulnerability"
|
||||
elif [ -n "$bp_harden" ]; then
|
||||
pvulnstatus $cve OK 'branch predictor hardening mitigates the vulnerability for ARM'
|
||||
@ -2115,8 +2183,10 @@ check_variant2_linux()
|
||||
pvulnstatus $cve VULN "IBRS hardware + kernel support OR kernel with retpoline are needed to mitigate the vulnerability"
|
||||
fi
|
||||
else
|
||||
if [ "$ibrs_supported" = 1 ]; then
|
||||
if [ -n "$ibrs_supported" ]; then
|
||||
pvulnstatus $cve OK "offline mode: IBRS/IBPB will mitigate the vulnerability if enabled at runtime"
|
||||
elif [ "$retpoline" = 1 ]; then
|
||||
pvulnstatus $cve OK "retpoline mitigates the vulnerability"
|
||||
elif [ "$ibrs_can_tell" = 1 ]; then
|
||||
pvulnstatus $cve VULN "IBRS hardware + kernel support OR kernel with retpoline are needed to mitigate the vulnerability"
|
||||
else
|
||||
@ -2251,7 +2321,7 @@ check_variant3_linux()
|
||||
fi
|
||||
|
||||
mount_debugfs
|
||||
_info_nol "* PTI enabled and active: "
|
||||
_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"
|
||||
@ -2291,7 +2361,7 @@ check_variant3_linux()
|
||||
pstatus yellow NO
|
||||
fi
|
||||
else
|
||||
pstatus blue N/A "can't verify if PTI is enabled in offline mode"
|
||||
pstatus blue N/A "not testable in offline mode"
|
||||
fi
|
||||
|
||||
# no security impact but give a hint to the user in verbose mode
|
||||
@ -2413,7 +2483,7 @@ check_variant3_bsd()
|
||||
pstatus green YES
|
||||
fi
|
||||
|
||||
_info_nol "* PTI enabled and active: "
|
||||
_info_nol " * PTI enabled and active: "
|
||||
if [ "$kpti_enabled" = 1 ]; then
|
||||
pstatus green YES
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user