mirror of
https://github.com/speed47/spectre-meltdown-checker
synced 2024-12-22 20:33:56 +01:00
feat(variant3a/4): initial support for 2 new CVEs
This commit is contained in:
parent
7e4899bcb8
commit
6a4318addf
25
README.md
25
README.md
@ -1,7 +1,16 @@
|
|||||||
Spectre & Meltdown Checker
|
Spectre & Meltdown Checker
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
A shell script to tell if your system is vulnerable against the 3 "speculative execution" CVEs that were made public early 2018.
|
A shell script to tell if your system is vulnerable against the several "speculative execution" CVEs that were made public in 2018.
|
||||||
|
|
||||||
|
This includes:
|
||||||
|
- CVE-2017-5753 aka Spectre Variant 1
|
||||||
|
- CVE-2017-5715 aka Spectre Variant 2
|
||||||
|
- CVE-2017-5754 aka Meltdown or Variant 3
|
||||||
|
- CVE-2018-3640 aka Variant 3a
|
||||||
|
- CVE-2018-3639 aka Variant 4
|
||||||
|
|
||||||
|
**Note: as CVE-2018-3639 and CVE-2018-3640 are extremely recent (published on May 21th 2018), expect frequent changes of the script in the next days to adjust detection.**
|
||||||
|
|
||||||
Supported operating systems:
|
Supported operating systems:
|
||||||
- Linux (all versions, flavors and distros)
|
- Linux (all versions, flavors and distros)
|
||||||
@ -74,7 +83,19 @@ sudo ./spectre-meltdown-checker.sh
|
|||||||
- Mitigation: updated kernel (with PTI/KPTI patches), updating the kernel is enough
|
- Mitigation: updated kernel (with PTI/KPTI patches), updating the kernel is enough
|
||||||
- Performance impact of the mitigation: low to medium
|
- Performance impact of the mitigation: low to medium
|
||||||
|
|
||||||
## Disclaimer
|
**CVE-2018-3640** rogue system register read (Variant 3a)
|
||||||
|
|
||||||
|
- Impact: TBC
|
||||||
|
- Mitigation: TBC
|
||||||
|
- Performance impact of the mitigation: negligible
|
||||||
|
|
||||||
|
**CVE-2018-3639** speculative store bypass (Variant 4)
|
||||||
|
|
||||||
|
- Impact: software using JIT (no known exploitation against kernel)
|
||||||
|
- Mitigation: TBC
|
||||||
|
- Performance impact of the mitigation: low to medium
|
||||||
|
|
||||||
|
## Understanding what this script does and doesn't
|
||||||
|
|
||||||
This tool does its best to determine whether your system is immune (or has proper mitigations in place) for the collectively named "speculative execution" vulnerabilities. It doesn't attempt to run any kind of exploit, and can't guarantee that your system is secure, but rather helps you verifying whether your system has the known correct mitigations in place.
|
This tool does its best to determine whether your system is immune (or has proper mitigations in place) for the collectively named "speculative execution" vulnerabilities. It doesn't attempt to run any kind of exploit, and can't guarantee that your system is secure, but rather helps you verifying whether your system has the known correct mitigations in place.
|
||||||
However, some mitigations could also exist in your kernel that this script doesn't know (yet) how to detect, or it might falsely detect mitigations that in the end don't work as expected (for example, on backported or modified kernels).
|
However, some mitigations could also exist in your kernel that this script doesn't know (yet) how to detect, or it might falsely detect mitigations that in the end don't work as expected (for example, on backported or modified kernels).
|
||||||
|
@ -248,13 +248,17 @@ _is_cpu_vulnerable_cached()
|
|||||||
[ "$1" = 2 ] && return $variant2
|
[ "$1" = 2 ] && return $variant2
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
[ "$1" = 3 ] && return $variant3
|
[ "$1" = 3 ] && return $variant3
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
[ "$1" = 3a ] && return $variant3a
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
[ "$1" = 4 ] && return $variant4
|
||||||
echo "$0: error: invalid variant '$1' passed to is_cpu_vulnerable()" >&2
|
echo "$0: error: invalid variant '$1' passed to is_cpu_vulnerable()" >&2
|
||||||
exit 255
|
exit 255
|
||||||
}
|
}
|
||||||
|
|
||||||
is_cpu_vulnerable()
|
is_cpu_vulnerable()
|
||||||
{
|
{
|
||||||
# param: 1, 2 or 3 (variant)
|
# param: 1, 2, 3, 3a or 4 (variant)
|
||||||
# returns 0 if vulnerable, 1 if not vulnerable
|
# returns 0 if vulnerable, 1 if not vulnerable
|
||||||
# (note that in shell, a return of 0 is success)
|
# (note that in shell, a return of 0 is success)
|
||||||
# by default, everything is vulnerable, we work in a "whitelist" logic here.
|
# by default, everything is vulnerable, we work in a "whitelist" logic here.
|
||||||
@ -267,11 +271,15 @@ is_cpu_vulnerable()
|
|||||||
variant1=''
|
variant1=''
|
||||||
variant2=''
|
variant2=''
|
||||||
variant3=''
|
variant3=''
|
||||||
|
variant3a=''
|
||||||
|
variant4=''
|
||||||
|
|
||||||
if is_cpu_specex_free; then
|
if is_cpu_specex_free; then
|
||||||
variant1=immune
|
variant1=immune
|
||||||
variant2=immune
|
variant2=immune
|
||||||
variant3=immune
|
variant3=immune
|
||||||
|
variant3a=immune
|
||||||
|
variant4=immune
|
||||||
elif is_intel; then
|
elif is_intel; then
|
||||||
# Intel
|
# Intel
|
||||||
# https://github.com/crozone/SpectrePoC/issues/1 ^F E5200 => spectre 2 not vulnerable
|
# https://github.com/crozone/SpectrePoC/issues/1 ^F E5200 => spectre 2 not vulnerable
|
||||||
@ -343,16 +351,29 @@ is_cpu_vulnerable()
|
|||||||
_debug "checking cpu$i: this arm non vulnerable to meltdown"
|
_debug "checking cpu$i: this arm non vulnerable to meltdown"
|
||||||
[ -z "$variant3" ] && variant3=immune
|
[ -z "$variant3" ] && variant3=immune
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# for variant3a, only A15/A57/A72 are vulnerable
|
||||||
|
if [ "$cpuarch" = 8 ] && echo "$cpupart" | grep -Eq '^0x(c0f|d07|d0a)$'; then
|
||||||
|
_debug "checking cpu$i: arm A15-A57-A72 vulnerable to variant3a"
|
||||||
|
variant3a=vuln
|
||||||
|
else
|
||||||
|
_debug "checking cpu$i: this arm non vulnerable to variant3a"
|
||||||
|
[ -z "$variant3" ] && variant3a=immune
|
||||||
fi
|
fi
|
||||||
_debug "is_cpu_vulnerable: for cpu$i and so far, we have <$variant1> <$variant2> <$variant3>"
|
fi
|
||||||
|
_debug "is_cpu_vulnerable: for cpu$i and so far, we have <$variant1> <$variant2> <$variant3> <$variant3a> <$variant4>"
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
_debug "is_cpu_vulnerable: temp results are <$variant1> <$variant2> <$variant3>"
|
# from the information we have for now, it seems that CPUs that are vulnerable to variant1 are also vulnerable to variant4
|
||||||
|
variant4=$variant1
|
||||||
|
_debug "is_cpu_vulnerable: temp results are <$variant1> <$variant2> <$variant3> <$variant3a> <$variant4>"
|
||||||
# if at least one of the cpu is vulnerable, then the system is vulnerable
|
# if at least one of the cpu is vulnerable, then the system is vulnerable
|
||||||
[ "$variant1" = "immune" ] && variant1=1 || variant1=0
|
[ "$variant1" = "immune" ] && variant1=1 || variant1=0
|
||||||
[ "$variant2" = "immune" ] && variant2=1 || variant2=0
|
[ "$variant2" = "immune" ] && variant2=1 || variant2=0
|
||||||
[ "$variant3" = "immune" ] && variant3=1 || variant3=0
|
[ "$variant3" = "immune" ] && variant3=1 || variant3=0
|
||||||
_debug "is_cpu_vulnerable: final results are <$variant1> <$variant2> <$variant3>"
|
[ "$variant3a" = "immune" ] && variant3a=1 || variant3a=0
|
||||||
|
[ "$variant4" = "immune" ] && variant4=1 || variant4=0
|
||||||
|
_debug "is_cpu_vulnerable: final results are <$variant1> <$variant2> <$variant3> <$variant3a> <$variant4>"
|
||||||
is_cpu_vulnerable_cached=1
|
is_cpu_vulnerable_cached=1
|
||||||
_is_cpu_vulnerable_cached "$1"
|
_is_cpu_vulnerable_cached "$1"
|
||||||
return $?
|
return $?
|
||||||
@ -499,8 +520,10 @@ while [ -n "$1" ]; do
|
|||||||
1) opt_variant1=1; opt_allvariants=0;;
|
1) opt_variant1=1; opt_allvariants=0;;
|
||||||
2) opt_variant2=1; opt_allvariants=0;;
|
2) opt_variant2=1; opt_allvariants=0;;
|
||||||
3) opt_variant3=1; opt_allvariants=0;;
|
3) opt_variant3=1; opt_allvariants=0;;
|
||||||
|
3a) opt_variant3a=1; opt_allvariants=0;;
|
||||||
|
4) opt_variant4=1; opt_allvariants=0;;
|
||||||
*)
|
*)
|
||||||
echo "$0: error: invalid parameter '$2' for --variant, expected either 1, 2 or 3" >&2;
|
echo "$0: error: invalid parameter '$2' for --variant, expected either 1, 2, 3, 3a or 4" >&2;
|
||||||
exit 255
|
exit 255
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@ -567,6 +590,8 @@ pvulnstatus()
|
|||||||
CVE-2017-5753) aka="SPECTRE VARIANT 1";;
|
CVE-2017-5753) aka="SPECTRE VARIANT 1";;
|
||||||
CVE-2017-5715) aka="SPECTRE VARIANT 2";;
|
CVE-2017-5715) aka="SPECTRE VARIANT 2";;
|
||||||
CVE-2017-5754) aka="MELTDOWN";;
|
CVE-2017-5754) aka="MELTDOWN";;
|
||||||
|
CVE-2018-3640) aka="VARIANT 3A";;
|
||||||
|
CVE-2018-3639) aka="VARIANT 4";;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
case "$opt_batch_format" in
|
case "$opt_batch_format" in
|
||||||
@ -888,6 +913,7 @@ parse_cpu_details()
|
|||||||
# get raw cpuid, it's always useful (referenced in the Intel doc for firmware updates for example)
|
# get raw cpuid, it's always useful (referenced in the Intel doc for firmware updates for example)
|
||||||
if read_cpuid 0x1 $EAX 0 0xFFFFFFFF; then
|
if read_cpuid 0x1 $EAX 0 0xFFFFFFFF; then
|
||||||
cpuid="$read_cpuid_value"
|
cpuid="$read_cpuid_value"
|
||||||
|
#cpuid_hex=$(printf "%X" "$cpuid")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# under BSD, linprocfs often doesn't export ucode information, so fetch it ourselves the good old way
|
# under BSD, linprocfs often doesn't export ucode information, so fetch it ourselves the good old way
|
||||||
@ -1411,7 +1437,6 @@ read_msr()
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
check_cpu()
|
check_cpu()
|
||||||
{
|
{
|
||||||
_info "\033[1;34mHardware check\033[0m"
|
_info "\033[1;34mHardware check\033[0m"
|
||||||
@ -1627,6 +1652,19 @@ check_cpu()
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# variant 4
|
||||||
|
_info " * Speculative Store Bypass Disable (SSBD)"
|
||||||
|
_info_nol " * CPU indicates SSBD capability: "
|
||||||
|
read_cpuid 0x7 $EDX 31 1 1; ret=$?
|
||||||
|
if [ $ret -eq 0 ]; then
|
||||||
|
#cpuid_ng1=1
|
||||||
|
pstatus green YES "SSBD feature bit"
|
||||||
|
elif [ $ret -eq 1 ]; then
|
||||||
|
pstatus yellow NO
|
||||||
|
else
|
||||||
|
pstatus yellow UNKNOWN "is cpuid kernel module available?"
|
||||||
|
fi
|
||||||
|
|
||||||
if is_intel; then
|
if is_intel; then
|
||||||
_info " * Enhanced IBRS (IBRS_ALL)"
|
_info " * Enhanced IBRS (IBRS_ALL)"
|
||||||
_info_nol " * CPU indicates ARCH_CAPABILITIES MSR availability: "
|
_info_nol " * CPU indicates ARCH_CAPABILITIES MSR availability: "
|
||||||
@ -1680,11 +1718,13 @@ check_cpu()
|
|||||||
capabilities=$val_cap_msr
|
capabilities=$val_cap_msr
|
||||||
capabilities_rdcl_no=0
|
capabilities_rdcl_no=0
|
||||||
capabilities_ibrs_all=0
|
capabilities_ibrs_all=0
|
||||||
|
capabilities_ssbd_no=0
|
||||||
if [ $val -eq 0 ]; then
|
if [ $val -eq 0 ]; then
|
||||||
_debug "capabilities MSR lower byte is $capabilities (decimal)"
|
_debug "capabilities MSR lower byte is $capabilities (decimal)"
|
||||||
[ $(( capabilities & 1 )) -eq 1 ] && capabilities_rdcl_no=1
|
[ $(( capabilities & 1 )) -eq 1 ] && capabilities_rdcl_no=1
|
||||||
[ $(( capabilities & 2 )) -eq 2 ] && capabilities_ibrs_all=1
|
[ $(( capabilities & 2 )) -eq 2 ] && capabilities_ibrs_all=1
|
||||||
_debug "capabilities says rdcl_no=$capabilities_rdcl_no ibrs_all=$capabilities_ibrs_all"
|
[ $(( capabilities & 4 )) -eq 4 ] && capabilities_ssbd_no=1
|
||||||
|
_debug "capabilities says rdcl_no=$capabilities_rdcl_no ibrs_all=$capabilities_ibrs_all ssbd_no=$capabilities_ssbd_no"
|
||||||
if [ "$capabilities_ibrs_all" = 1 ]; then
|
if [ "$capabilities_ibrs_all" = 1 ]; then
|
||||||
if [ $cpu_mismatch -eq 0 ]; then
|
if [ $cpu_mismatch -eq 0 ]; then
|
||||||
pstatus green YES
|
pstatus green YES
|
||||||
@ -1709,6 +1749,15 @@ check_cpu()
|
|||||||
else
|
else
|
||||||
pstatus yellow NO
|
pstatus yellow NO
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_info_nol " * CPU explicitly indicates not being vulnerable to Variant 4 (SSBD_NO): "
|
||||||
|
if [ "$capabilities_ssbd_no" = -1 ]; then
|
||||||
|
pstatus yellow UNKNOWN
|
||||||
|
elif [ "$capabilities_ssbd_no" = 1 ]; then
|
||||||
|
pstatus green YES
|
||||||
|
else
|
||||||
|
pstatus yellow NO
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_info_nol " * CPU microcode is known to cause stability problems: "
|
_info_nol " * CPU microcode is known to cause stability problems: "
|
||||||
@ -1727,8 +1776,8 @@ check_cpu()
|
|||||||
|
|
||||||
check_cpu_vulnerabilities()
|
check_cpu_vulnerabilities()
|
||||||
{
|
{
|
||||||
_info "* CPU vulnerability to the three speculative execution attack variants"
|
_info "* CPU vulnerability to the speculative execution attack variants"
|
||||||
for v in 1 2 3; do
|
for v in 1 2 3 3a 4; do
|
||||||
_info_nol " * Vulnerable to Variant $v: "
|
_info_nol " * Vulnerable to Variant $v: "
|
||||||
if is_cpu_vulnerable $v; then
|
if is_cpu_vulnerable $v; then
|
||||||
pstatus yellow YES
|
pstatus yellow YES
|
||||||
@ -2137,7 +2186,7 @@ check_variant2_linux()
|
|||||||
1) if [ "$ibrs_fw_enabled" = 1 ]; then pstatus green YES "for kernel space and firmware code"; else pstatus green YES "for kernel space"; fi;;
|
1) if [ "$ibrs_fw_enabled" = 1 ]; then pstatus green YES "for kernel space and firmware code"; else pstatus green YES "for kernel space"; fi;;
|
||||||
2) if [ "$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;;
|
2) if [ "$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 [ "$ibrs_fw_enabled" = 1 ]; then pstatus green YES "for kernel and firmware code"; else pstatus green YES; fi;;
|
3) if [ "$ibrs_fw_enabled" = 1 ]; then pstatus green YES "for kernel and firmware code"; else pstatus green YES; fi;;
|
||||||
*) if [ ! "$cpuid_ibrs" = 'SPEC_CTRL' ] && [ ! "cpuid_ibrs" = 'IBRS_SUPPORT' ] && [ ! "cpuid_spec_ctrl" = -1 ];
|
*) if [ "$cpuid_ibrs" != 'SPEC_CTRL' ] && [ "$cpuid_ibrs" != 'IBRS_SUPPORT' ] && [ "$cpuid_spec_ctrl" != -1 ];
|
||||||
then pstatus yellow NO; _debug "ibrs: known cpu not supporting SPEC-CTRL or IBRS";
|
then pstatus yellow NO; _debug "ibrs: known cpu not supporting SPEC-CTRL or IBRS";
|
||||||
else
|
else
|
||||||
pstatus yellow UNKNOWN; fi;;
|
pstatus yellow UNKNOWN; fi;;
|
||||||
@ -2817,6 +2866,32 @@ check_variant3_bsd()
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_variant3a()
|
||||||
|
{
|
||||||
|
_info "\033[1;34mCVE-2018-3640 [rogue system register read] aka 'Variant 3a'\033[0m"
|
||||||
|
|
||||||
|
cve='CVE-2018-3640'
|
||||||
|
if ! is_cpu_vulnerable 3a; then
|
||||||
|
# override status & msg in case CPU is not vulnerable after all
|
||||||
|
pvulnstatus $cve OK "your CPU vendor reported your CPU model as not vulnerable"
|
||||||
|
else
|
||||||
|
pvulnstatus $cve UNK "new vulnerability, script will when more technical information is available in the next hours/days"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_variant4()
|
||||||
|
{
|
||||||
|
_info "\033[1;34mCVE-2018-3639 [speculative store bypass] aka 'Variant 4'\033[0m"
|
||||||
|
|
||||||
|
cve='CVE-2018-3639'
|
||||||
|
if ! is_cpu_vulnerable 4; then
|
||||||
|
# override status & msg in case CPU is not vulnerable after all
|
||||||
|
pvulnstatus $cve OK "your CPU vendor reported your CPU model as not vulnerable"
|
||||||
|
else
|
||||||
|
pvulnstatus $cve UNK "new vulnerability, script will when more technical information is available in the next hours/days"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then
|
if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then
|
||||||
check_cpu
|
check_cpu
|
||||||
check_cpu_vulnerabilities
|
check_cpu_vulnerabilities
|
||||||
@ -2836,6 +2911,14 @@ if [ "$opt_variant3" = 1 ] || [ "$opt_allvariants" = 1 ]; then
|
|||||||
check_variant3
|
check_variant3
|
||||||
_info
|
_info
|
||||||
fi
|
fi
|
||||||
|
if [ "$opt_variant3a" = 1 ] || [ "$opt_allvariants" = 1 ]; then
|
||||||
|
check_variant3a
|
||||||
|
_info
|
||||||
|
fi
|
||||||
|
if [ "$opt_variant4" = 1 ] || [ "$opt_allvariants" = 1 ]; then
|
||||||
|
check_variant4
|
||||||
|
_info
|
||||||
|
fi
|
||||||
|
|
||||||
_vars=$(set | grep -Ev '^[A-Z_[:space:]]' | sort | tr "\n" '|')
|
_vars=$(set | grep -Ev '^[A-Z_[:space:]]' | sort | tr "\n" '|')
|
||||||
_debug "variables at end of script: $_vars"
|
_debug "variables at end of script: $_vars"
|
||||||
|
Loading…
Reference in New Issue
Block a user