mirror of
https://github.com/speed47/spectre-meltdown-checker
synced 2024-12-22 12:23:36 +01:00
feat: initial support for L1TF
This commit is contained in:
parent
360be7b35f
commit
e942616189
25
README.md
25
README.md
@ -2,11 +2,14 @@ Spectre & Meltdown Checker
|
||||
==========================
|
||||
|
||||
A shell script to tell if your system is vulnerable against the several "speculative execution" CVEs that were made public in 2018.
|
||||
- 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
|
||||
- CVE-2017-5753 [bounds check bypass] aka 'Spectre Variant 1'
|
||||
- CVE-2017-5715 [branch target injection] aka 'Spectre Variant 2'
|
||||
- CVE-2017-5754 [rogue data cache load] aka 'Meltdown' aka 'Variant 3'
|
||||
- CVE-2018-3640 [rogue system register read] aka 'Variant 3a'
|
||||
- CVE-2018-3639 [speculative store bypass] aka 'Variant 4'
|
||||
- CVE-2018-3615, CVE-2018-3620, CVE-2018-3646 [L1 terminal fault] aka 'Foreshadow & Foreshadow-NG'
|
||||
|
||||
**2018-08-15: Foreshadow support is being worked on, vulnerable/immune CPUs are already detected, and kernel-reported vulnerability status is checked, but manual mitigation detection is currently being implemented, will be available in the next few days**
|
||||
|
||||
Supported operating systems:
|
||||
- Linux (all versions, flavors and distros)
|
||||
@ -98,6 +101,18 @@ docker run --rm --privileged -v /boot:/boot:ro -v /lib/modules:/lib/modules:ro -
|
||||
- Mitigation: microcode update + kernel update making possible for affected software to protect itself
|
||||
- Performance impact of the mitigation: low to medium
|
||||
|
||||
**CVE-2018-3615** l1 terminal fault (Foreshadow)
|
||||
|
||||
- TBC
|
||||
|
||||
**CVE-2018-3620** l1 terminal fault (Foreshadow-NG)
|
||||
|
||||
- TBC
|
||||
|
||||
**CVE-2018-3646** l1 terminal fault (Foreshadow-NG)
|
||||
|
||||
- TBC
|
||||
|
||||
## 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.
|
||||
|
@ -9,7 +9,7 @@
|
||||
#
|
||||
# Stephane Lesimple
|
||||
#
|
||||
VERSION='0.39'
|
||||
VERSION='0.39+'
|
||||
|
||||
trap 'exit_cleanup' EXIT
|
||||
trap '_warn "interrupted, cleaning up..."; exit_cleanup; exit 1' INT
|
||||
@ -64,7 +64,7 @@ show_usage()
|
||||
--batch nrpe produce machine readable output formatted for NRPE
|
||||
--batch prometheus produce output for consumption by prometheus-node-exporter
|
||||
|
||||
--variant [1,2,3,3a,4] specify which variant you'd like to check, by default all variants are checked,
|
||||
--variant [1,2,3,3a,4,l1tf] specify which variant you'd like to check, by default all variants are checked,
|
||||
can be specified multiple times (e.g. --variant 2 --variant 3)
|
||||
--hw-only only check for CPU information, don't check for any variant
|
||||
--no-hw skip CPU information and checks, if you're inspecting a kernel not to be run on this host
|
||||
@ -126,6 +126,7 @@ opt_variant2=0
|
||||
opt_variant3=0
|
||||
opt_variant3a=0
|
||||
opt_variant4=0
|
||||
opt_variantl1tf=0
|
||||
opt_allvariants=1
|
||||
opt_no_sysfs=0
|
||||
opt_sysfs_only=0
|
||||
@ -246,11 +247,12 @@ _is_cpu_vulnerable_cached()
|
||||
{
|
||||
# shellcheck disable=SC2086
|
||||
{
|
||||
[ "$1" = 1 ] && return $variant1
|
||||
[ "$1" = 2 ] && return $variant2
|
||||
[ "$1" = 3 ] && return $variant3
|
||||
[ "$1" = 3a ] && return $variant3a
|
||||
[ "$1" = 4 ] && return $variant4
|
||||
[ "$1" = 1 ] && return $variant1
|
||||
[ "$1" = 2 ] && return $variant2
|
||||
[ "$1" = 3 ] && return $variant3
|
||||
[ "$1" = 3a ] && return $variant3a
|
||||
[ "$1" = 4 ] && return $variant4
|
||||
[ "$1" = l1tf ] && return $variantl1tf
|
||||
}
|
||||
echo "$0: error: invalid variant '$1' passed to is_cpu_vulnerable()" >&2
|
||||
exit 255
|
||||
@ -273,6 +275,7 @@ is_cpu_vulnerable()
|
||||
variant3=''
|
||||
variant3a=''
|
||||
variant4=''
|
||||
variantl1tf=''
|
||||
|
||||
if is_cpu_specex_free; then
|
||||
variant1=immune
|
||||
@ -280,6 +283,7 @@ is_cpu_vulnerable()
|
||||
variant3=immune
|
||||
variant3a=immune
|
||||
variant4=immune
|
||||
variantl1tf=immune
|
||||
elif is_intel; then
|
||||
# Intel
|
||||
# https://github.com/crozone/SpectrePoC/issues/1 ^F E5200 => spectre 2 not vulnerable
|
||||
@ -294,20 +298,52 @@ is_cpu_vulnerable()
|
||||
# capability bit for future Intel processor that will explicitly state
|
||||
# that they're not vulnerable to Meltdown
|
||||
# this var is set in check_cpu()
|
||||
variant3=immune
|
||||
_debug "is_cpu_vulnerable: RDCL_NO is set so not vuln to meltdown"
|
||||
[ -z "$variant3" ] && variant3=immune
|
||||
[ -z "$variantl1tf" ] && variantl1tf=immune
|
||||
_debug "is_cpu_vulnerable: RDCL_NO is set so not vuln to meltdown nor l1tf"
|
||||
fi
|
||||
if [ "$capabilities_ssb_no" = 1 ]; then
|
||||
# capability bit for future Intel processor that will explicitly state
|
||||
# that they're not vulnerable to Variant 4
|
||||
# this var is set in check_cpu()
|
||||
variant4=immune
|
||||
[ -z "$variant4" ] && variant4=immune
|
||||
_debug "is_cpu_vulnerable: SSB_NO is set so not vuln to variant4"
|
||||
fi
|
||||
if is_cpu_ssb_free; then
|
||||
[ -z "$variant4" ] && variant4=immune
|
||||
_debug "is_cpu_vulnerable: cpu not affected by speculative store bypass so not vuln to variant4"
|
||||
fi
|
||||
# variant 4a for xeon phi
|
||||
if [ "$cpu_family" = 6 ]; then
|
||||
if [ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] || [ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ]; then
|
||||
_debug "is_cpu_vulnerable: xeon phi immune to variant 3a"
|
||||
[ -z "$variant3a" ] && variant3a=immune
|
||||
fi
|
||||
fi
|
||||
# L1TF (RDCL_NO already checked above)
|
||||
if [ "$cpu_family" = 6 ]; then
|
||||
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_CEDARVIEW" ] || \
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_CLOVERVIEW" ] || \
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_LINCROFT" ] || \
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_PENWELL" ] || \
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_PINEVIEW" ] || \
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT1" ] || \
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT2" ] || \
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] || \
|
||||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_MERRIFIELD" ] || \
|
||||
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] || \
|
||||
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ]; then
|
||||
|
||||
_debug "is_cpu_vulnerable: intel family 6 but model known to be immune"
|
||||
[ -z "$variantl1tf" ] && variantl1tf=immune
|
||||
else
|
||||
_debug "is_cpu_vulnerable: intel family 6 is vuln"
|
||||
variantl1tf=vuln
|
||||
fi
|
||||
elif [ "$cpu_family" -lt 6 ]; then
|
||||
_debug "is_cpu_vulnerable: intel family < 6 is immune"
|
||||
[ -z "$variantl1tf" ] && variantl1tf=immune
|
||||
fi
|
||||
elif is_amd; then
|
||||
# AMD revised their statement about variant2 => vulnerable
|
||||
# https://www.amd.com/en/corporate/speculative-execution
|
||||
@ -321,9 +357,11 @@ is_cpu_vulnerable()
|
||||
[ -z "$variant4" ] && variant4=immune
|
||||
_debug "is_cpu_vulnerable: cpu not affected by speculative store bypass so not vuln to variant4"
|
||||
fi
|
||||
variantl1tf=immune
|
||||
elif [ "$cpu_vendor" = CAVIUM ]; then
|
||||
variant3=immune
|
||||
variant3a=immune
|
||||
variantl1tf=immune
|
||||
elif [ "$cpu_vendor" = ARM ]; then
|
||||
# ARM
|
||||
# reference: https://developer.arm.com/support/security-update
|
||||
@ -411,14 +449,16 @@ is_cpu_vulnerable()
|
||||
fi
|
||||
_debug "is_cpu_vulnerable: for cpu$i and so far, we have <$variant1> <$variant2> <$variant3> <$variant3a> <$variant4>"
|
||||
done
|
||||
variantl1tf=immune
|
||||
fi
|
||||
_debug "is_cpu_vulnerable: temp results are <$variant1> <$variant2> <$variant3> <$variant3a> <$variant4>"
|
||||
[ "$variant1" = "immune" ] && variant1=1 || variant1=0
|
||||
[ "$variant2" = "immune" ] && variant2=1 || variant2=0
|
||||
[ "$variant3" = "immune" ] && variant3=1 || variant3=0
|
||||
[ "$variant3a" = "immune" ] && variant3a=1 || variant3a=0
|
||||
[ "$variant4" = "immune" ] && variant4=1 || variant4=0
|
||||
_debug "is_cpu_vulnerable: final results are <$variant1> <$variant2> <$variant3> <$variant3a> <$variant4>"
|
||||
_debug "is_cpu_vulnerable: temp results are <$variant1> <$variant2> <$variant3> <$variant3a> <$variant4> <$variantl1tf>"
|
||||
[ "$variant1" = "immune" ] && variant1=1 || variant1=0
|
||||
[ "$variant2" = "immune" ] && variant2=1 || variant2=0
|
||||
[ "$variant3" = "immune" ] && variant3=1 || variant3=0
|
||||
[ "$variant3a" = "immune" ] && variant3a=1 || variant3a=0
|
||||
[ "$variant4" = "immune" ] && variant4=1 || variant4=0
|
||||
[ "$variantl1tf" = "immune" ] && variantl1tf=1 || variantl1tf=0
|
||||
_debug "is_cpu_vulnerable: final results are <$variant1> <$variant2> <$variant3> <$variant3a> <$variant4> <$variantl1tf>"
|
||||
is_cpu_vulnerable_cached=1
|
||||
_is_cpu_vulnerable_cached "$1"
|
||||
return $?
|
||||
@ -607,17 +647,18 @@ while [ -n "$1" ]; do
|
||||
shift
|
||||
elif [ "$1" = "--variant" ]; then
|
||||
if [ -z "$2" ]; then
|
||||
echo "$0: error: option --variant expects a parameter (1, 2, 3, 3a or 4)" >&2
|
||||
echo "$0: error: option --variant expects a parameter (1, 2, 3, 3a, 4 or l1tf)" >&2
|
||||
exit 255
|
||||
fi
|
||||
case "$2" in
|
||||
1) opt_variant1=1; opt_allvariants=0;;
|
||||
2) opt_variant2=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;;
|
||||
1) opt_variant1=1; opt_allvariants=0;;
|
||||
2) opt_variant2=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;;
|
||||
l1tf) opt_variantl1tf=1; opt_allvariants=0;;
|
||||
*)
|
||||
echo "$0: error: invalid parameter '$2' for --variant, expected either 1, 2, 3, 3a or 4" >&2;
|
||||
echo "$0: error: invalid parameter '$2' for --variant, expected either 1, 2, 3, 3a, 4 or l1tf" >&2;
|
||||
exit 255
|
||||
;;
|
||||
esac
|
||||
@ -686,6 +727,7 @@ pvulnstatus()
|
||||
CVE-2017-5754) aka="MELTDOWN";;
|
||||
CVE-2018-3640) aka="VARIANT 3A";;
|
||||
CVE-2018-3639) aka="VARIANT 4";;
|
||||
CVE-2018-3615/3620/3646) aka="L1TF";;
|
||||
esac
|
||||
|
||||
case "$opt_batch_format" in
|
||||
@ -3180,6 +3222,36 @@ check_variant4()
|
||||
fi
|
||||
}
|
||||
|
||||
check_variantl1tf()
|
||||
{
|
||||
_info "\033[1;34mCVE-2018-3615/3620/3646 [L1 terminal fault] aka 'Foreshadow & Foreshadow-NG'\033[0m"
|
||||
|
||||
status=UNK
|
||||
sys_interface_available=0
|
||||
msg=''
|
||||
if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/l1tf"; then
|
||||
# this kernel has the /sys interface, trust it over everything
|
||||
sys_interface_available=1
|
||||
fi
|
||||
if [ "$opt_sysfs_only" != 1 ]; then
|
||||
:
|
||||
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
|
||||
|
||||
cve='CVE-2018-3615/3620/3646'
|
||||
if ! is_cpu_vulnerable l1tf; 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"
|
||||
elif [ -z "$msg" ]; then
|
||||
pvulnstatus $cve VULN "your CPU is known to be vulnerable, and your kernel doesn't report that it mitigates the issue, but more thorough mitigation checking by this script is being worked on (check often for new versions!)"
|
||||
else
|
||||
pvulnstatus $cve "$status" "$msg"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then
|
||||
check_cpu
|
||||
check_cpu_vulnerabilities
|
||||
@ -3207,6 +3279,10 @@ if [ "$opt_variant4" = 1 ] || [ "$opt_allvariants" = 1 ]; then
|
||||
check_variant4
|
||||
_info
|
||||
fi
|
||||
if [ "$opt_variantl1tf" = 1 ] || [ "$opt_allvariants" = 1 ]; then
|
||||
check_variantl1tf
|
||||
_info
|
||||
fi
|
||||
|
||||
_vars=$(set | grep -Ev '^[A-Z_[:space:]]' | sort | tr "\n" '|')
|
||||
_debug "variables at end of script: $_vars"
|
||||
|
Loading…
Reference in New Issue
Block a user