1
0
mirror of https://github.com/speed47/spectre-meltdown-checker synced 2024-12-23 04:43:37 +01:00

feat(mds): more verbose info about kernel support and microcode support for mitigation

This commit is contained in:
Stéphane Lesimple 2019-05-15 00:21:08 +02:00
parent 11790027d3
commit de793a7204

View File

@ -63,6 +63,7 @@ show_usage()
--explain produce an additional human-readable explanation of actions to take to mitigate a vulnerability --explain produce an additional human-readable explanation of actions to take to mitigate a vulnerability
--paranoid require IBPB to deem Variant 2 as mitigated --paranoid require IBPB to deem Variant 2 as mitigated
also require SMT disabled + unconditional L1D flush to deem Foreshadow-NG VMM as mitigated also require SMT disabled + unconditional L1D flush to deem Foreshadow-NG VMM as mitigated
also require SMT disabled to deem MDS vulnerabilities mitigated
--no-sysfs don't use the /sys interface even if present [Linux] --no-sysfs don't use the /sys interface even if present [Linux]
--sysfs-only only use the /sys interface, don't run our own checks [Linux] --sysfs-only only use the /sys interface, don't run our own checks [Linux]
@ -76,7 +77,8 @@ show_usage()
--batch nrpe produce machine readable output formatted for NRPE --batch nrpe produce machine readable output formatted for NRPE
--batch prometheus produce output for consumption by prometheus-node-exporter --batch prometheus produce output for consumption by prometheus-node-exporter
--variant [1,2,3,3a,4,l1tf,msbds,mfbds,mlpds,mdsum] specify which variant you'd like to check, by default all variants are checked --variant VARIANT specify which variant you'd like to check, by default all variants are checked
VARIANT can be one of 1, 2, 3, 3a, 4, l1tf, msbds, mfbds, mlpds, mdsum
--cve [cve1,cve2,...] specify which CVE you'd like to check, by default all supported CVEs are checked --cve [cve1,cve2,...] specify which CVE you'd like to check, by default all supported CVEs are checked
can be specified multiple times (e.g. --variant 2 --variant 3) can be specified multiple times (e.g. --variant 2 --variant 3)
--hw-only only check for CPU information, don't check for any variant --hw-only only check for CPU information, don't check for any variant
@ -271,10 +273,10 @@ cve2name()
CVE-2018-3615) echo "Foreshadow (SGX), L1 terminal fault";; CVE-2018-3615) echo "Foreshadow (SGX), L1 terminal fault";;
CVE-2018-3620) echo "Foreshadow-NG (OS), L1 terminal fault";; CVE-2018-3620) echo "Foreshadow-NG (OS), L1 terminal fault";;
CVE-2018-3646) echo "Foreshadow-NG (VMM), L1 terminal fault";; CVE-2018-3646) echo "Foreshadow-NG (VMM), L1 terminal fault";;
CVE-2018-12126) echo "Microarchitectural Store Buffer Data Sampling (MSBDS)";; CVE-2018-12126) echo "Fallout, microarchitectural store buffer data sampling (MSBDS)";;
CVE-2018-12130) echo "Microarchitectural Fill Buffer Data Sampling (MFBDS)";; CVE-2018-12130) echo "ZombieLoad, microarchitectural fill buffer data sampling (MFBDS)";;
CVE-2018-12127) echo "Microarchitectural Load Port Data Sampling (MLPDS)";; CVE-2018-12127) echo "RIDL, microarchitectural load port data sampling (MLPDS)";;
CVE-2019-11091) echo "Microarchitectural Data Sampling Uncacheable Memory (MDSUM)";; CVE-2019-11091) echo "RIDL, microarchitectural data sampling uncacheable memory (MDSUM)";;
*) echo "$0: error: invalid CVE '$1' passed to cve2name()" >&2; exit 255;; *) echo "$0: error: invalid CVE '$1' passed to cve2name()" >&2; exit 255;;
esac esac
} }
@ -1877,6 +1879,7 @@ sys_interface_check()
mode="$3" mode="$3"
[ "$opt_live" = 1 ] && [ "$opt_no_sysfs" = 0 ] && [ -r "$file" ] || return 1 [ "$opt_live" = 1 ] && [ "$opt_no_sysfs" = 0 ] && [ -r "$file" ] || return 1
[ -n "$regex" ] || regex='.*' [ -n "$regex" ] || regex='.*'
fullmsg=$(cat "$file")
msg=$(grep -Eo "$regex" "$file") msg=$(grep -Eo "$regex" "$file")
if [ "$mode" = silent ]; then if [ "$mode" = silent ]; then
_info "* Information from the /sys interface: $msg" _info "* Information from the /sys interface: $msg"
@ -1886,18 +1889,18 @@ sys_interface_check()
if echo "$msg" | grep -qi '^not affected'; then if echo "$msg" | grep -qi '^not affected'; then
# Not affected # Not affected
status=OK status=OK
pstatus green YES "$msg" pstatus green YES "$fullmsg"
elif echo "$msg" | grep -qi '^mitigation'; then elif echo "$msg" | grep -qi '^mitigation'; then
# Mitigation: PTI # Mitigation: PTI
status=OK status=OK
pstatus green YES "$msg" pstatus green YES "$fullmsg"
elif echo "$msg" | grep -qi '^vulnerable'; then elif echo "$msg" | grep -qi '^vulnerable'; then
# Vulnerable # Vulnerable
status=VULN status=VULN
pstatus yellow NO "$msg" pstatus yellow NO "$fullmsg"
else else
status=UNK status=UNK
pstatus yellow UNKNOWN "$msg" pstatus yellow UNKNOWN "$fullmsg"
fi fi
_debug "sys_interface_check: $file=$msg (re=$regex)" _debug "sys_interface_check: $file=$msg (re=$regex)"
return 0 return 0
@ -2339,14 +2342,16 @@ check_cpu()
if is_intel; then if is_intel; then
_info " * Microarchitecture Data Sampling" _info " * Microarchitecture Data Sampling"
_info_nol " * MD_CLEAR instruction is available: " _info_nol " * VERW instruction is available: "
read_cpuid 0x7 $EDX 10 1 1; ret=$? read_cpuid 0x7 $EDX 10 1 1; ret=$?
if [ $ret -eq 0 ]; then if [ $ret -eq 0 ]; then
#cpuid_md_clear=1 cpuid_md_clear=1
pstatus green YES pstatus green YES "MD_CLEAR feature bit"
elif [ $ret -eq 2 ]; then elif [ $ret -eq 2 ]; then
cpuid_md_clear=-1
pstatus yellow UNKNOWN "is cpuid kernel module available?" pstatus yellow UNKNOWN "is cpuid kernel module available?"
else else
cpuid_md_clear=0
pstatus yellow NO pstatus yellow NO
fi fi
fi fi
@ -3998,6 +4003,7 @@ check_CVE_2018_3646_linux()
# 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
fi fi
l1d_mode=-1
if [ "$opt_sysfs_only" != 1 ]; then if [ "$opt_sysfs_only" != 1 ]; then
_info_nol "* This system is a host running a hypervisor: " _info_nol "* This system is a host running a hypervisor: "
has_vmm=$opt_vmm has_vmm=$opt_vmm
@ -4167,7 +4173,7 @@ check_CVE_2018_3646_linux()
if [ "$l1d_mode" -ge 1 ]; then if [ "$l1d_mode" -ge 1 ]; then
pvulnstatus $cve OK "L1D flushing is enabled and mitigates the vulnerability" pvulnstatus $cve OK "L1D flushing is enabled and mitigates the vulnerability"
else else
pvulnstatus $cve VULN "disable EPT or enabled L1D flushing to mitigate the vulnerability" pvulnstatus $cve VULN "disable EPT or enable L1D flushing to mitigate the vulnerability"
fi fi
else else
if [ "$l1d_mode" -ge 2 ]; then if [ "$l1d_mode" -ge 2 ]; then
@ -4235,7 +4241,6 @@ check_CVE_2018_3646_bsd()
check_CVE_2018_12126() check_CVE_2018_12126()
{ {
cve='CVE-2018-12126' cve='CVE-2018-12126'
check_mds $cve check_mds $cve
} }
@ -4246,7 +4251,6 @@ check_CVE_2018_12126()
check_CVE_2018_12130() check_CVE_2018_12130()
{ {
cve='CVE-2018-12130' cve='CVE-2018-12130'
check_mds $cve check_mds $cve
} }
@ -4257,7 +4261,6 @@ check_CVE_2018_12130()
check_CVE_2018_12127() check_CVE_2018_12127()
{ {
cve='CVE-2018-12127' cve='CVE-2018-12127'
check_mds $cve check_mds $cve
} }
@ -4268,68 +4271,124 @@ check_CVE_2018_12127()
check_CVE_2019_11091() check_CVE_2019_11091()
{ {
cve='CVE-2019-11091' cve='CVE-2019-11091'
check_mds $cve check_mds $cve
} }
# Microarchitectural Data Sampling # Microarchitectural Data Sampling
check_mds() check_mds()
{ {
sys_interface_available=0
cve=$1 cve=$1
_info "\033[1;34m$cve aka '$(cve2name "$cve")'\033[0m" _info "\033[1;34m$cve aka '$(cve2name "$cve")'\033[0m"
if [ "$opt_live" != 1 ]; then status=UNK
pstatus blue N/A "not testable in offline mode" sys_interface_available=0
pvulnstatus "$cve" UNK msg=''
return if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/mds" '^[^;]+'; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
fi
if [ "$opt_sysfs_only" != 1 ]; then
_info_nol "* CPU supports the MD_CLEAR functionality: "
if [ "$cpuid_md_clear" = 1 ]; then
pstatus green YES
elif [ "$cpuid_md_clear" = 0 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN "is cpuid module loaded?"
fi
_info_nol "* Kernel supports using MD_CLEAR mitigation: "
kernel_md_clear=''
kernel_md_clear_can_tell=1
if [ "$opt_live" = 1 ] && grep ^flags $procfs/cpuinfo | grep -qw md_clear; then
kernel_md_clear="md_clear found in $procfs/cpuinfo"
pstatus green YES "$kernel_md_clear"
fi
if [ -z "$kernel_md_clear" ]; then
if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
kernel_md_clear_can_tell=0
elif [ -n "$kernel_err" ]; then
kernel_md_clear_can_tell=0
elif "${opt_arch_prefix}strings" "$kernel" | grep -q 'Clear CPU buffers'; then
_debug "md_clear: found 'Clear CPU buffers' string in kernel image"
kernel_md_clear='found md_clear implementation evidence in kernel image'
pstatus green YES "$kernel_md_clear"
fi
fi
if [ -z "$kernel_md_clear" ]; then
if [ "$kernel_md_clear_can_tell" = 1 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN
fi
fi
if [ "$opt_live" = 1 ] && [ "$sys_interface_available" = 1 ]; then
_info_nol "* Kernel mitigation is enabled and active: "
if grep -qi ^mitigation /sys/devices/system/cpu/vulnerabilities/mds; then
mds_mitigated=1
pstatus green YES
else
mds_mitigated=0
pstatus yellow NO
fi
_info_nol "* SMT is either mitigated or disabled: "
if grep -Eq 'SMT (disabled|mitigated)' /sys/devices/system/cpu/vulnerabilities/mds; then
mds_smt_mitigated=1
pstatus green YES
else
mds_smt_mitigated=0
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 fi
if ! is_cpu_vulnerable "$cve"; then if ! is_cpu_vulnerable "$cve"; then
# override status & msg in case CPU is not vulnerable after all # override status & msg in case CPU is not vulnerable after all
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not vulnerable" pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not vulnerable"
return elif [ -z "$msg" ]; then
fi # if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$cpuid_md_clear" = 1 ]; then
if sys_interface_check '/sys/devices/system/cpu/vulnerabilities/mds'; then if [ -n "$kernel_md_clear" ]; then
# this kernel has the /sys interface, trust it over everything if [ "$opt_live" = 1 ]; then
sys_interface_available=1 # mitigation must also be enabled
fi if [ "$mds_mitigated" = 1 ]; then
if [ "$opt_paranoid" != 1 ] || [ "$mds_smt_mitigated" = 1 ]; then
if [ "$sys_interface_available" = 1 ]; then pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled"
if grep -Eq 'Not affected' "/sys/devices/system/cpu/vulnerabilities/mds"; then
mds_mitigated=1
elif grep -Eq '(Mitigation: Clear CPU buffers)' "/sys/devices/system/cpu/vulnerabilities/mds"; then
if grep -Eq '(SMT mitigated|disabled)' "/sys/devices/system/cpu/vulnerabilities/mds"; then
mds_mitigated=1
else else
#Simultaneous multi-threading (aka SMT or HyperThreading) is enabled. System may be vulnerable in some environments. pvulnstatus "$cve" VULN "Your microcode and kernel are both up to date for this mitigation, but your must disable SMT (Hyper-Threading) for a complete mitigation"
mds_mitigated=0
_info_nol "* Disable SMT to have complete mitigation\n"
fi
elif grep -Eq 'Vulnerable' "/sys/devices/system/cpu/vulnerabilities/mds"; then
mds_mitigated=0
_info_nol "* For more info check Linux kernel Documentation/admin-guide/hw-vuln/mds.rst\n"
else
mds_mitigated=-1
fi
if grep -Eq 'no microcode' "/sys/devices/system/cpu/vulnerabilities/mds"; then
mds_mitigated=0
_info_nol "* CPU microcode is needed to mitigate the vulnerability\n"
fi fi
else else
pstatus yellow UNKNOWN "can't find or interpret /sys/devices/system/cpu/vulnerabilities/mds" pvulnstatus "$cve" VULN "Your microcode and kernel are both up to date for this mitigation, but the mitigation is not active"
mds_mitigated=-1
fi fi
if [ $mds_mitigated = 0 ];then
pvulnstatus "$cve" VULN
elif [ $mds_mitigated = 1 ]; then
pvulnstatus "$cve" OK
else else
pvulnstatus "$cve" UNK "further action may be needed to mitigate this vulnerability. For more info check Linux kernel Documentation/admin-guide/hw-vuln/mds.rst" pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for this mitigation"
fi
else
pvulnstatus "$cve" VULN "Your microcode supports mitigation, but your kernel doesn't, upgrade it to mitigate the vulnerability"
fi
else
if [ -n "$kernel_md_clear" ]; then
pvulnstatus "$cve" VULN "Your kernel supports mitigation, but your CPU microcode also needs to be updated to mitigate the vulnerability"
else
pvulnstatus "$cve" VULN "Neither your kernel or your microcode support mitigation, upgrade both to mitigate the vulnerability"
fi
fi
else
if [ "$opt_paranoid" = 1 ]; then
# in paranoid mode, we don't only need microcode + kernel update, we also want SMT mitigation
if grep -qF -e 'SMT mitigated' -e 'SMT disabled' /sys/devices/system/cpu/vulnerabilities/mds; then
pvulnstatus "$cve" OK "$fullmsg"
else
pvulnstatus "$cve" VULN "Your kernel and microcode partially mitigate the vulnerability, but you must disable SMT (Hyper-Threading) for a complete mitigation"
fi
else
pvulnstatus "$cve" "$status" "$fullmsg"
fi
fi fi
} }