mirror of
https://github.com/speed47/spectre-meltdown-checker.git
synced 2024-12-22 11:08:04 +01:00
feat(ibpb): now also check for IBPB on variant 2
In addition to IBRS (and microcode support), IBPB must be used to mitigate variant 2, if retpoline support is not available. The vulnerability status of a system will be defined as "non vulnerable" if IBRS and IBPB are both enabled, or if IBPB is enabled with a value of 2 for RedHat kernels, see https://access.redhat.com/articles/3311301
This commit is contained in:
parent
3e454f1817
commit
443d9a2ae9
@ -861,9 +861,10 @@ check_variant2()
|
|||||||
# this kernel has the /sys interface, trust it over everything
|
# this kernel has the /sys interface, trust it over everything
|
||||||
sys_interface_available=1
|
sys_interface_available=1
|
||||||
else
|
else
|
||||||
_info "* Mitigation 1"
|
_info "* Mitigation 1"
|
||||||
_info "* Hardware (CPU microcode) support for mitigation"
|
_info " * Hardware support (CPU microcode)"
|
||||||
_info_nol "* The SPEC_CTRL MSR is available: "
|
_info " * Indirect Branch Restricted Speculation (IBRS)"
|
||||||
|
_info_nol " * SPEC_CTRL MSR is available: "
|
||||||
if [ ! -e /dev/cpu/0/msr ]; then
|
if [ ! -e /dev/cpu/0/msr ]; then
|
||||||
# try to load the module ourselves (and remember it so we can rmmod it afterwards)
|
# try to load the module ourselves (and remember it so we can rmmod it afterwards)
|
||||||
load_msr
|
load_msr
|
||||||
@ -873,7 +874,8 @@ check_variant2()
|
|||||||
else
|
else
|
||||||
# the new MSR 'SPEC_CTRL' is at offset 0x48
|
# the new MSR 'SPEC_CTRL' is at offset 0x48
|
||||||
# here we use dd, it's the same as using 'rdmsr 0x48' but without needing the rdmsr tool
|
# here we use dd, it's the same as using 'rdmsr 0x48' but without needing the rdmsr tool
|
||||||
# if we get a read error, the MSR is not there
|
# if we get a read error, the MSR is not there. bs has to be 8 for msr
|
||||||
|
# skip=9 because 8*9=72=0x48
|
||||||
dd if=/dev/cpu/0/msr of=/dev/null bs=8 count=1 skip=9 2>/dev/null
|
dd if=/dev/cpu/0/msr of=/dev/null bs=8 count=1 skip=9 2>/dev/null
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
pstatus green YES
|
pstatus green YES
|
||||||
@ -882,23 +884,20 @@ check_variant2()
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
unload_msr
|
_info_nol " * CPU indicates IBRS capability: "
|
||||||
|
|
||||||
# CPUID test
|
|
||||||
_info_nol "* The SPEC_CTRL CPUID feature bit is set: "
|
|
||||||
if [ ! -e /dev/cpu/0/cpuid ]; then
|
if [ ! -e /dev/cpu/0/cpuid ]; then
|
||||||
# try to load the module ourselves (and remember it so we can rmmod it afterwards)
|
# try to load the module ourselves (and remember it so we can rmmod it afterwards)
|
||||||
load_cpuid
|
load_cpuid
|
||||||
fi
|
fi
|
||||||
if [ ! -e /dev/cpu/0/cpuid ]; then
|
if [ ! -e /dev/cpu/0/cpuid ]; then
|
||||||
pstatus yellow UNKNOWN "couldn't read /dev/cpu/0/cpuidr, is cpuid support enabled in your kernel?"
|
pstatus yellow UNKNOWN "couldn't read /dev/cpu/0/cpuid, is cpuid support enabled in your kernel?"
|
||||||
else
|
else
|
||||||
# from kernel src: { X86_FEATURE_SPEC_CTRL, CPUID_EDX,26, 0x00000007, 0 },
|
# from kernel src: { X86_FEATURE_SPEC_CTRL, CPUID_EDX,26, 0x00000007, 0 },
|
||||||
if [ "$opt_verbose" -ge 3 ]; then
|
if [ "$opt_verbose" -ge 3 ]; then
|
||||||
dd if=/dev/cpu/0/cpuid bs=16 skip=7 iflag=skip_bytes count=1 >/dev/null 2>/dev/null
|
dd if=/dev/cpu/0/cpuid bs=16 skip=7 iflag=skip_bytes count=1 >/dev/null 2>/dev/null
|
||||||
_debug "cpuid: reading leaf7 of cpuid on cpu0, ret=$?"
|
_debug "cpuid: reading leaf7 of cpuid on cpu0, ret=$?"
|
||||||
_debug "cpuid: leaf7 eax-ebx-ecd-edx: "$(dd if=/dev/cpu/0/cpuid bs=16 skip=7 iflag=skip_bytes count=1 2>/dev/null | od -x -A n)
|
_debug "cpuid: leaf7 eax-ebx-ecx-edx: "$(dd if=/dev/cpu/0/cpuid bs=16 skip=7 iflag=skip_bytes count=1 2>/dev/null | od -x -A n)
|
||||||
_debug "cpuid: leaf7 edx higher-half is: "$(dd if=/dev/cpu/0/cpuid bs=16 skip=7 iflag=skip_bytes count=1 2>/dev/null | dd bs=1 skip=15 count=1 2>/dev/null | od -x -A n)
|
_debug "cpuid: leaf7 edx higher byte is: "$(dd if=/dev/cpu/0/cpuid bs=16 skip=7 iflag=skip_bytes count=1 2>/dev/null | dd bs=1 skip=15 count=1 2>/dev/null | od -x -A n)
|
||||||
fi
|
fi
|
||||||
# getting high byte of edx on leaf7 of cpuinfo in decimal
|
# getting high byte of edx on leaf7 of cpuinfo in decimal
|
||||||
edx_hb=$(dd if=/dev/cpu/0/cpuid bs=16 skip=7 iflag=skip_bytes count=1 2>/dev/null | dd bs=1 skip=15 count=1 2>/dev/null | od -t u -A n | awk '{print $1}')
|
edx_hb=$(dd if=/dev/cpu/0/cpuid bs=16 skip=7 iflag=skip_bytes count=1 2>/dev/null | dd bs=1 skip=15 count=1 2>/dev/null | od -t u -A n | awk '{print $1}')
|
||||||
@ -906,48 +905,102 @@ check_variant2()
|
|||||||
edx_bit26=$(( edx_hb & 8 ))
|
edx_bit26=$(( edx_hb & 8 ))
|
||||||
_debug "cpuid: edx_bit26=$edx_bit26"
|
_debug "cpuid: edx_bit26=$edx_bit26"
|
||||||
if [ "$edx_bit26" -eq 8 ]; then
|
if [ "$edx_bit26" -eq 8 ]; then
|
||||||
pstatus green YES
|
pstatus green YES "SPEC_CTRL feature bit"
|
||||||
|
cpuid_spec_ctrl=1
|
||||||
else
|
else
|
||||||
pstatus red NO
|
pstatus red NO
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
unload_cpuid
|
|
||||||
|
|
||||||
# hardware support according to kernel
|
# hardware support according to kernel
|
||||||
if [ "$opt_verbose" -ge 2 ]; then
|
if [ "$opt_verbose" -ge 2 ]; then
|
||||||
_verbose_nol "* The kernel has set the spec_ctrl flag in cpuinfo: "
|
# the spec_ctrl flag in cpuinfo is set if and only if the kernel sees
|
||||||
|
# that the spec_ctrl cpuinfo bit set. we already check that ourselves above
|
||||||
|
# but let's check it anyway (in verbose mode only)
|
||||||
|
_verbose_nol " * Kernel has set the spec_ctrl flag in cpuinfo: "
|
||||||
if [ "$opt_live" = 1 ]; then
|
if [ "$opt_live" = 1 ]; then
|
||||||
if grep ^flags /proc/cpuinfo | grep -qw spec_ctrl; then
|
if grep ^flags /proc/cpuinfo | grep -qw spec_ctrl; then
|
||||||
pstatus green YES
|
pstatus green YES
|
||||||
else
|
else
|
||||||
pstatus red NO
|
pstatus blue NO
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
pstatus blue N/A "not testable in offline mode"
|
pstatus blue N/A "not testable in offline mode"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_info_nol "* Kernel support for IBRS: "
|
# IBPB
|
||||||
|
_info " * Indirect Branch Prediction Barrier (IBPB)"
|
||||||
|
_info_nol " * PRED_CMD MSR is available: "
|
||||||
|
if [ ! -e /dev/cpu/0/msr ]; then
|
||||||
|
pstatus yellow UNKNOWN "couldn't read /dev/cpu/0/msr, is msr support enabled in your kernel?"
|
||||||
|
else
|
||||||
|
# the new MSR 'PRED_CTRL' is at offset 0x49, write-only
|
||||||
|
# here we use dd, it's the same as using 'wrmsr 0x49 0' but without needing the wrmsr tool
|
||||||
|
# if we get a write error, the MSR is not there
|
||||||
|
$echo_cmd -ne "\0\0\0\0\0\0\0\0" | dd of=/dev/cpu/0/msr bs=8 count=1 seek=73 oflag=seek_bytes 2>/dev/null
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
pstatus green YES
|
||||||
|
else
|
||||||
|
pstatus red NO
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info_nol " * CPU indicates IBPB capability: "
|
||||||
|
if [ ! -e /dev/cpu/0/cpuid ]; then
|
||||||
|
pstatus yellow UNKNOWN "couldn't read /dev/cpu/0/cpuidr, is cpuid support enabled in your kernel?"
|
||||||
|
else
|
||||||
|
# CPUID EAX=0x80000008, ECX=0x00 return EBX[12] indicates support for just IBPB.
|
||||||
|
if [ "$opt_verbose" -ge 3 ]; then
|
||||||
|
dd if=/dev/cpu/0/cpuid bs=16 skip=2147483656 iflag=skip_bytes count=1 >/dev/null 2>/dev/null
|
||||||
|
_debug "cpuid: reading leaf80000008 of cpuid on cpu0, ret=$?"
|
||||||
|
_debug "cpuid: leaf80000008 eax-ebx-ecx-edx: "$(dd if=/dev/cpu/0/cpuid bs=16 skip=2147483656 iflag=skip_bytes count=1 2>/dev/null | od -x -A n)
|
||||||
|
_debug "cpuid: leaf80000008 ebx 3rd byte is: "$(dd if=/dev/cpu/0/cpuid bs=16 skip=2147483656 iflag=skip_bytes count=1 2>/dev/null | dd bs=1 skip=5 count=1 2>/dev/null | od -x -A n)
|
||||||
|
fi
|
||||||
|
# getting high byte of edx on leaf7 of cpuinfo in decimal
|
||||||
|
ebx_b3=$(dd if=/dev/cpu/0/cpuid bs=16 skip=2147483656 iflag=skip_bytes count=1 2>/dev/null | dd bs=1 skip=5 count=1 2>/dev/null | od -t u -A n | awk '{print $1}')
|
||||||
|
_debug "cpuid: leaf80000008 ebx 3rd byte: $ebx_b3 (decimal)"
|
||||||
|
ebx_bit12=$(( ebx_b3 & 16 ))
|
||||||
|
_debug "cpuid: ebx_bit12=$ebx_bit12"
|
||||||
|
if [ "$ebx_bit12" -eq 16 ]; then
|
||||||
|
pstatus green YES "IBPB_SUPPORT feature bit"
|
||||||
|
cpuid_ibpb=1
|
||||||
|
elif [ "$cpuid_spec_ctrl" = 1 ]; then
|
||||||
|
pstatus green YES "SPEC_CTRL feature bit"
|
||||||
|
else
|
||||||
|
pstatus red NO
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info_nol " * Kernel is compiled with IBRS/IBPB support: "
|
||||||
ibrs_can_tell=0
|
ibrs_can_tell=0
|
||||||
|
|
||||||
if [ "$opt_live" = 1 ]; then
|
if [ "$opt_live" = 1 ]; then
|
||||||
ibrs_can_tell=1
|
ibrs_can_tell=1
|
||||||
mount_debugfs
|
mount_debugfs
|
||||||
for ibrs_file in \
|
for dir in \
|
||||||
/sys/kernel/debug/ibrs_enabled \
|
/sys/kernel/debug \
|
||||||
/sys/kernel/debug/x86/ibrs_enabled \
|
/sys/kernel/debug/x86 \
|
||||||
/proc/sys/kernel/ibrs_enabled; do
|
/proc/sys/kernel; do
|
||||||
if [ -e "$ibrs_file" ]; then
|
if [ -e "$dir/ibrs_enabled" ]; then
|
||||||
# if the file is there, we have IBRS compiled-in
|
# if the file is there, we have IBRS compiled-in
|
||||||
# /sys/kernel/debug/ibrs_enabled: vanilla
|
# /sys/kernel/debug/ibrs_enabled: vanilla
|
||||||
# /sys/kernel/debug/x86/ibrs_enabled: RedHat (see https://access.redhat.com/articles/3311301)
|
# /sys/kernel/debug/x86/ibrs_enabled: RedHat (see https://access.redhat.com/articles/3311301)
|
||||||
# /proc/sys/kernel/ibrs_enabled: OpenSUSE tumbleweed
|
# /proc/sys/kernel/ibrs_enabled: OpenSUSE tumbleweed
|
||||||
pstatus green YES
|
pstatus green YES
|
||||||
|
ibrs_knob_dir=$dir
|
||||||
ibrs_supported=1
|
ibrs_supported=1
|
||||||
ibrs_enabled=$(cat "$ibrs_file" 2>/dev/null)
|
ibrs_enabled=$(cat "$dir/ibrs_enabled" 2>/dev/null)
|
||||||
_debug "ibrs: found $ibrs_file=$ibrs_enabled"
|
_debug "ibrs: found $dir/ibrs_enabled=$ibrs_enabled"
|
||||||
|
if [ -e "$dir/ibpb_enabled" ]; then
|
||||||
|
ibpb_enabled=$(cat "$dir/ibpb_enabled" 2>/dev/null)
|
||||||
|
_debug "ibpb: found $dir/ibpb_enabled=$ibpb_enabled"
|
||||||
|
else
|
||||||
|
_debug "ibpb: no ibpb_enabled file in $dir"
|
||||||
|
fi
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
_debug "ibrs: file $ibrs_file doesn't exist"
|
_debug "ibrs: $dir/ibrs_enabled file doesn't exist"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
# on some newer kernels, the spec_ctrl_ibrs flag in /proc/cpuinfo
|
# on some newer kernels, the spec_ctrl_ibrs flag in /proc/cpuinfo
|
||||||
@ -960,6 +1013,7 @@ check_variant2()
|
|||||||
ibrs_supported=1
|
ibrs_supported=1
|
||||||
# enabled=2 -> kernel & user
|
# enabled=2 -> kernel & user
|
||||||
ibrs_enabled=2
|
ibrs_enabled=2
|
||||||
|
# XXX and what about ibpb ?
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -980,33 +1034,60 @@ check_variant2()
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_info_nol "* IBRS enabled for Kernel space: "
|
_info " * Currently enabled features"
|
||||||
|
_info_nol " * IBRS enabled for Kernel space: "
|
||||||
if [ "$opt_live" = 1 ]; then
|
if [ "$opt_live" = 1 ]; then
|
||||||
# 0 means disabled
|
if [ "$ibpb_enabled" = 2 ]; then
|
||||||
# 1 is enabled only for kernel space
|
# if ibpb=2, ibrs is forcefully=0
|
||||||
# 2 is enabled for kernel and user space
|
pstatus blue NO "IBPB used instead of IBRS in all kernel entrypoints"
|
||||||
case "$ibrs_enabled" in
|
else
|
||||||
"") [ "$ibrs_supported" = 1 ] && pstatus yellow UNKNOWN || pstatus red NO;;
|
# 0 means disabled
|
||||||
0) pstatus red NO;;
|
# 1 is enabled only for kernel space
|
||||||
1 | 2) pstatus green YES;;
|
# 2 is enabled for kernel and user space
|
||||||
*) pstatus yellow UNKNOWN;;
|
case "$ibrs_enabled" in
|
||||||
esac
|
"") [ "$ibrs_supported" = 1 ] && pstatus yellow UNKNOWN || pstatus red NO;;
|
||||||
|
0) pstatus red NO "echo 1 > $ibrs_knob_dir/ibrs_enabled";;
|
||||||
|
1 | 2) pstatus green YES;;
|
||||||
|
*) pstatus yellow UNKNOWN;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
pstatus blue N/A "not testable in offline mode"
|
pstatus blue N/A "not testable in offline mode"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_info_nol "* IBRS enabled for User space: "
|
_info_nol " * IBRS enabled for User space: "
|
||||||
if [ "$opt_live" = 1 ]; then
|
if [ "$opt_live" = 1 ]; then
|
||||||
case "$ibrs_enabled" in
|
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
|
||||||
|
"") [ "$ibrs_supported" = 1 ] && pstatus yellow UNKNOWN || pstatus red NO;;
|
||||||
|
0 | 1) pstatus red NO "echo 2 > $ibrs_knob_dir/ibrs_enabled";;
|
||||||
|
2) pstatus green YES;;
|
||||||
|
*) pstatus yellow UNKNOWN;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pstatus blue N/A "not testable in offline mode"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info_nol " * IBPB enabled: "
|
||||||
|
if [ "$opt_live" = 1 ]; then
|
||||||
|
case "$ibpb_enabled" in
|
||||||
"") [ "$ibrs_supported" = 1 ] && pstatus yellow UNKNOWN || pstatus red NO;;
|
"") [ "$ibrs_supported" = 1 ] && pstatus yellow UNKNOWN || pstatus red NO;;
|
||||||
0 | 1) pstatus red NO;;
|
0) pstatus red NO "echo 1 > $ibrs_knob_dir/ibpb_enabled";;
|
||||||
2) pstatus green YES;;
|
1) pstatus green YES;;
|
||||||
|
2) pstatus green YES "IBPB used instead of IBRS in all kernel entrypoints";;
|
||||||
*) pstatus yellow UNKNOWN;;
|
*) pstatus yellow UNKNOWN;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
pstatus blue N/A "not testable in offline mode"
|
pstatus blue N/A "not testable in offline mode"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
unload_msr
|
||||||
|
unload_cpuid
|
||||||
|
|
||||||
_info "* Mitigation 2"
|
_info "* Mitigation 2"
|
||||||
_info_nol "* Kernel compiled with retpoline option: "
|
_info_nol "* Kernel compiled with retpoline option: "
|
||||||
# We check the RETPOLINE kernel options
|
# We check the RETPOLINE kernel options
|
||||||
@ -1068,14 +1149,16 @@ check_variant2()
|
|||||||
if [ "$retpoline" = 1 -a "$retpoline_compiler" = 1 ]; then
|
if [ "$retpoline" = 1 -a "$retpoline_compiler" = 1 ]; then
|
||||||
pvulnstatus CVE-2017-5715 OK "retpoline mitigate the vulnerability"
|
pvulnstatus CVE-2017-5715 OK "retpoline mitigate the vulnerability"
|
||||||
elif [ "$opt_live" = 1 ]; then
|
elif [ "$opt_live" = 1 ]; then
|
||||||
if [ "$ibrs_enabled" = 1 -o "$ibrs_enabled" = 2 ]; then
|
if [ "$ibrs_enabled" = 1 -o "$ibrs_enabled" = 2 ] && [ "$ibpb_enabled" = 1 ]; then
|
||||||
pvulnstatus CVE-2017-5715 OK "IBRS mitigates the vulnerability"
|
pvulnstatus CVE-2017-5715 OK "IBRS/IBPB are mitigating the vulnerability"
|
||||||
|
elif [ "$ibpb_enabled" = 2 ]; then
|
||||||
|
pvulnstatus CVE-2017-5715 OK "Full IBPB is mitigating the vulnerability"
|
||||||
else
|
else
|
||||||
pvulnstatus CVE-2017-5715 VULN "IBRS hardware + kernel support OR kernel with retpoline are needed to mitigate the vulnerability"
|
pvulnstatus CVE-2017-5715 VULN "IBRS hardware + kernel support OR kernel with retpoline are needed to mitigate the vulnerability"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [ "$ibrs_supported" = 1 ]; then
|
if [ "$ibrs_supported" = 1 ]; then
|
||||||
pvulnstatus CVE-2017-5715 OK "offline mode: IBRS will mitigate the vulnerability if enabled at runtime"
|
pvulnstatus CVE-2017-5715 OK "offline mode: IBRS/IBPB will mitigate the vulnerability if enabled at runtime"
|
||||||
elif [ "$ibrs_can_tell" = 1 ]; then
|
elif [ "$ibrs_can_tell" = 1 ]; then
|
||||||
pvulnstatus CVE-2017-5715 VULN "IBRS hardware + kernel support OR kernel with retpoline are needed to mitigate the vulnerability"
|
pvulnstatus CVE-2017-5715 VULN "IBRS hardware + kernel support OR kernel with retpoline are needed to mitigate the vulnerability"
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user