Improved hypervisor detection (#259)

* Code consistency

``` opt_batch_format="text" ``` replaced by ``` opt_batch_format='text' ```
```nrpe_vuln='"" ``` replaced by ``` nrpe_vuln='' ``` , as used by other parse options

Redundant ``` ! -z ``` replaced by ``` -n ```, as used elsewhere

Signed-off-by: Rob Gill <rrobgill@protonmail.com>

* Improved hypervisor detection

Tests for presence of hypervisor flag in /proc/cpuino
Tests for evidence of hypervisor in dmesg

Signed-off-by: Rob Gill <rrobgill@protonmail.com>

* formatting fix

Signed-off-by: Rob Gill <rrobgill@protonmail.com>

* Set $l1d_mode to -1 in cases where cpu/vulnerabilities/l1tf is not available

(prevents invalid number error when evaluating [ "$l1d_mode" -ge 1 ])

Signed-off-by: Rob Gill <rrobgill@protonmail.com>

* Update Intel Atom 6 cpu names to align with kernel

Update processor names of atom 6 family processors to align with those from kernel as of October 2018.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/arch/x86/include/asm/intel-family.h?id=f2c4db1bd80720cd8cb2a5aa220d9bc9f374f04e
Update list of known immune processors from
https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/commit/arch/x86/kernel/cpu/common.c?id=f2c4db1bd80720cd8cb2a5aa220d9bc9f374f04e

* Fix unset $l1d_mode

Another instance of unset l1d_mode causing error "./spectre-meltdown-checker.sh: 3867: [: Illegal number:"

* chore: update readme with brief summary of L1tfs

L1tf mitigation and impact details from

https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html and https://blogs.oracle.com/oraclesecurity/intel-l1tf

* typo
This commit is contained in:
Rob Gill 2018-12-11 04:33:07 +10:00 committed by Stéphane Lesimple
parent c45a06f414
commit 906f54cf9d
2 changed files with 96 additions and 53 deletions

View File

@ -110,17 +110,24 @@ docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/m
- 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)
**CVE-2018-3615** l1 terminal fault (Foreshadow-NG SGX)
- TBC
- Impact: Kernel & all software (any physical memory address in the system)
- Mitigation: microcode update
- Performance impact of the mitigation: negligible
**CVE-2018-3620** l1 terminal fault (Foreshadow-NG)
**CVE-2018-3620** l1 terminal fault (Foreshadow-NG SMM)
- TBC
- Impact: Kernel & System management mode
- Mitigation: updated kernel (with PTE inversion)
- Performance impact of the mitigation: negligible
**CVE-2018-3646** l1 terminal fault (Foreshadow-NG VMM)
**CVE-2018-3646** l1 terminal fault (Foreshadow-NG)
- TBC
- Impact: Virtualization software and Virtual Machine Monitors
- Mitigation: disable ept (extended page tables), disable hyper-threading (SMT), or
updated kernel (with L1d flush)
- Performance impact of the mitigation: low to significant
## Understanding what this script does and doesn't

View File

@ -80,7 +80,7 @@ show_usage()
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
--vmm [auto,yes,no] override the detection of the presence of an hypervisor (for CVE-2018-3646), default: auto
--vmm [auto,yes,no] override the detection of the presence of a hypervisor (for CVE-2018-3646), default: auto
--update-mcedb update our local copy of the CPU microcodes versions database (from the awesome MCExtractor project)
--update-builtin-mcedb same as --update-mcedb but update builtin DB inside the script itself
@ -134,7 +134,7 @@ opt_live_explicit=0
opt_live=1
opt_no_color=0
opt_batch=0
opt_batch_format="text"
opt_batch_format='text'
opt_verbose=1
opt_cve_list=''
opt_cve_all=1
@ -150,7 +150,7 @@ opt_paranoid=0
global_critical=0
global_unknown=0
nrpe_vuln=""
nrpe_vuln=''
supported_cve_list='CVE-2017-5753 CVE-2017-5715 CVE-2017-5754 CVE-2018-3640 CVE-2018-3639 CVE-2018-3615 CVE-2018-3620 CVE-2018-3646'
@ -351,17 +351,21 @@ is_cpu_vulnerable()
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" ] || \
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_TABLET" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_MID" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL_MID" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_X" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_MERRIFIELD" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT_MID" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_X" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ] || \
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] || \
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ]; then
[ "$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
@ -501,23 +505,24 @@ is_cpu_specex_free()
# return true (0) if the CPU doesn't do speculative execution, false (1) if it does.
# if it's not in the list we know, return false (1).
# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c#n882
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CEDARVIEW, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CLOVERVIEW, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_LINCROFT, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PENWELL, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PINEVIEW, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL_TABLET, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_BONNELL_MID, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL_MID, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_BONNELL, X86_FEATURE_ANY },
# { X86_VENDOR_CENTAUR, 5 },
# { X86_VENDOR_INTEL, 5 },
# { X86_VENDOR_NSC, 5 },
# { X86_VENDOR_ANY, 4 },
parse_cpu_details
if is_intel; then
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" ]; then
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_TABLET" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL_MID" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_MID" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL" ]; then
return 0
fi
elif [ "$cpu_family" = 5 ]; then
@ -535,10 +540,10 @@ is_cpu_ssb_free()
# source1: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c#n945
# source2: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/tree/arch/x86/kernel/cpu/common.c
# Only list CPUs that speculate but are immune, to avoid duplication of cpus listed in is_cpu_specex_free()
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT2 },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MERRIFIELD },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_X },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_MID },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_CORE_YONAH },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM },
@ -550,9 +555,9 @@ is_cpu_ssb_free()
if is_intel; then
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT1" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT2" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_MERRIFIELD" ]; then
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_X" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ]; then
return 0
elif [ "$cpu_model" = "$INTEL_FAM6_CORE_YONAH" ] || \
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] || \
@ -1261,19 +1266,19 @@ parse_cpu_details()
# /* "Small Core" Processors (Atom) */
INTEL_FAM6_ATOM_PINEVIEW=$(( 0x1C ))
INTEL_FAM6_ATOM_LINCROFT=$(( 0x26 ))
INTEL_FAM6_ATOM_PENWELL=$(( 0x27 ))
INTEL_FAM6_ATOM_CLOVERVIEW=$(( 0x35 ))
INTEL_FAM6_ATOM_CEDARVIEW=$(( 0x36 ))
INTEL_FAM6_ATOM_SILVERMONT1=$(( 0x37 ))
INTEL_FAM6_ATOM_SILVERMONT2=$(( 0x4D ))
INTEL_FAM6_ATOM_BONNELL=$(( 0x1C ))
INTEL_FAM6_ATOM_BONNELL_MID=$(( 0x26 ))
INTEL_FAM6_ATOM_SALTWELL_MID=$(( 0x27 ))
INTEL_FAM6_ATOM_SALTWELL_TABLET=$(( 0x35 ))
INTEL_FAM6_ATOM_SALTWELL=$(( 0x36 ))
INTEL_FAM6_ATOM_SILVERMONT=$(( 0x37 ))
INTEL_FAM6_ATOM_SILVERMONT_MID=$(( 0x4A ))
INTEL_FAM6_ATOM_SILVERMONT_X=$(( 0x4D ))
INTEL_FAM6_ATOM_AIRMONT=$(( 0x4C ))
INTEL_FAM6_ATOM_MERRIFIELD=$(( 0x4A ))
INTEL_FAM6_ATOM_MOOREFIELD=$(( 0x5A ))
INTEL_FAM6_ATOM_AIRMONT_MID=$(( 0x5A ))
INTEL_FAM6_ATOM_GOLDMONT=$(( 0x5C ))
INTEL_FAM6_ATOM_DENVERTON=$(( 0x5F ))
INTEL_FAM6_ATOM_GEMINI_LAKE=$(( 0x7A ))
INTEL_FAM6_ATOM_GOLDMONT_X=$(( 0x5F ))
INTEL_FAM6_ATOM_GOLDMONT_PLUS=$(( 0x7A ))
# /* Xeon Phi */
@ -2992,7 +2997,7 @@ check_CVE_2017_5715_linux()
# if we are in live mode, we can check for a lot more stuff and explain further
if [ "$opt_live" = 1 ] && [ "$vulnstatus" != "OK" ]; then
_explain_hypervisor="An updated CPU microcode will have IBRS/IBPB capabilities indicated in the Hardware Check section above. If you're running under an hypervisor (KVM, Xen, VirtualBox, VMware, ...), the hypervisor needs to be up to date to be able to export the new host CPU flags to the guest. You can run this script on the host to check if the host CPU is IBRS/IBPB. If it is, and it doesn't show up in the guest, upgrade the hypervisor. You may need to reconfigure your VM to use a CPU model that has IBRS capability; in Libvirt, such CPUs are listed with an IBRS suffix."
_explain_hypervisor="An updated CPU microcode will have IBRS/IBPB capabilities indicated in the Hardware Check section above. If you're running under a hypervisor (KVM, Xen, VirtualBox, VMware, ...), the hypervisor needs to be up to date to be able to export the new host CPU flags to the guest. You can run this script on the host to check if the host CPU is IBRS/IBPB. If it is, and it doesn't show up in the guest, upgrade the hypervisor. You may need to reconfigure your VM to use a CPU model that has IBRS capability; in Libvirt, such CPUs are listed with an IBRS suffix."
# IBPB (amd & intel)
if ( [ -z "$ibpb_enabled" ] || [ "$ibpb_enabled" = 0 ] ) && ( is_intel || is_amd ); then
if [ -z "$cpuid_ibpb" ]; then
@ -3743,13 +3748,41 @@ check_CVE_2018_3646_linux()
sys_interface_available=1
fi
if [ "$opt_sysfs_only" != 1 ]; then
_info_nol "* This system is a host running an hypervisor: "
_info_nol "* This system is a host running a hypervisor: "
has_vmm=$opt_vmm
if [ "$has_vmm" = -1 ]; then
# FIXME enhance detection, this one is pretty basic/stupid
# Assumed to be running on bare metal unless evidence of vm is found.
has_vmm=0
# shellcheck disable=SC2009
ps ax | grep -v -e grep -e '\[kvm' | grep -q -e qemu -e kvm && has_vmm=1
# test for presence of hypervisor flag - definitive if set
if [ -e "$procfs/cpuinfo" ] && grep ^flags "$procfs/cpuinfo" | grep -qw hypervisor; then
has_vmm=1
_debug "hypervisor: present - hypervisor flag set in $procfs/cpuinfo"
else
_debug "hypervisor: unknown - hypervisor flag not set in $procfs/cpuinfo"
fi
# test for kernel detected hypervisor
dmesg_grep "Hypervisor detected:" ; ret=$?
if [ $ret -eq 0 ]; then
_debug "hypervisor: present - found in dmesg: $dmesg_grepped"
has_vmm=1
elif [ $ret -eq 2 ]; then
_debug "hypervisor: dmesg truncated"
fi
# test for kernel detected paravirtualization
dmesg_grep "Booting paravirtualized kernel on bare metal" ; ret=$?
if [ $ret -eq 0 ]; then
_debug "hypervisor: not present (bare metal)- found in dmesg: $dmesg_grepped"
elif [ $ret -eq 2 ]; then
_debug "hypervisor: dmesg truncated"
else
dmesg_grep "Booting paravirtualized kernel on" ; ret=$?
if [ $ret -eq 0 ]; then
_debug "hypervisor: present - found in dmesg: $dmesg_grepped"
has_vmm=1
elif [ $ret -eq 2 ]; then
_debug "hypervisor: dmesg truncated"
fi
fi
fi
if [ "$has_vmm" = 0 ]; then
if [ "$opt_vmm" != -1 ]; then
@ -3824,9 +3857,11 @@ check_CVE_2018_3646_linux()
pstatus yellow UNKNOWN "unrecognized mode"
fi
else
l1d_mode=-1
pstatus yellow UNKNOWN "can't find or read /sys/devices/system/cpu/vulnerabilities/l1tf"
fi
else
l1d_mode=-1
pstatus blue N/A "not testable in offline mode"
fi
@ -3855,13 +3890,14 @@ check_CVE_2018_3646_linux()
# we have no sysfs but were asked to use it only!
msg="/sys vulnerability interface use forced, but it's not available!"
status=UNK
l1d_mode=-1
fi
if ! is_cpu_vulnerable "$cve"; 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 [ "$has_vmm" = 0 ]; then
pvulnstatus $cve OK "this system is not running an hypervisor"
pvulnstatus $cve OK "this system is not running a hypervisor"
else
if [ "$ept_disabled" = 1 ]; then
pvulnstatus $cve OK "EPT is disabled which mitigates the vulnerability"
@ -3956,7 +3992,7 @@ fi
_info "A false sense of security is worse than no security at all, see --disclaimer"
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "nrpe" ]; then
if [ ! -z "$nrpe_vuln" ]; then
if [ -n "$nrpe_vuln" ]; then
echo "Vulnerable:$nrpe_vuln"
else
echo "OK"