From bd47275501f275b6cfe34a8d839cdd924e9f4479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lesimple?= Date: Sun, 24 Nov 2019 19:25:56 +0100 Subject: [PATCH] feat: add detection of iTLB Multihit vuln/mitigation (CVE-2018-12207) --- .github/workflows/check.yml | 6 +- README.md | 11 +- spectre-meltdown-checker.sh | 415 ++++++++++++++++++++++++------------ 3 files changed, 293 insertions(+), 139 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index ee3abda..1665bb9 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -24,7 +24,7 @@ jobs: fi - name: check direct execution run: | - expected=13 + expected=14 nb=$(sudo ./spectre-meltdown-checker.sh --batch json | jq '.[]|.CVE' | wc -l) if [ "$nb" -ne "$expected" ]; then echo "Invalid number of CVEs reported: $nb instead of $expected" @@ -34,7 +34,7 @@ jobs: fi - name: check docker-compose run execution run: | - expected=13 + expected=14 docker-compose build nb=$(docker-compose run --rm spectre-meltdown-checker --batch json | jq '.[]|.CVE' | wc -l) if [ "$nb" -ne "$expected" ]; then @@ -45,7 +45,7 @@ jobs: fi - name: check docker run execution run: | - expected=13 + expected=14 docker build -t spectre-meltdown-checker . nb=$(docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/modules:/lib/modules:ro spectre-meltdown-checker --batch json | jq '.[]|.CVE' | wc -l) if [ "$nb" -ne "$expected" ]; then diff --git a/README.md b/README.md index 2cec98f..2fe22f5 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ A shell script to tell if your system is vulnerable against the several "specula - CVE-2018-12130 [microarchitectural fill buffer data sampling (MFBDS)] aka 'ZombieLoad' - CVE-2018-12127 [microarchitectural load port data sampling (MLPDS)] aka 'RIDL' - CVE-2019-11091 [microarchitectural data sampling uncacheable memory (MDSUM)] aka 'RIDL' -- CVE-2019-11135 [TSX asynchronous abort] aka 'TAA' +- CVE-2019-11135 [TSX asynchronous abort] aka 'TAA' aka 'ZombieLoad V2' +- CVE-2018-12207 [iTLB Multihit] aka 'No eXcuses' Supported operating systems: - Linux (all versions, flavors and distros) @@ -146,12 +147,18 @@ docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/m - Mitigation: microcode update + kernel update making possible to protect various CPU internal buffers from unprivileged speculative access to data - Performance impact of the mitigation: low to significant -**CVE-2019-11135** TSX Asynchronous Abort (TAA) +**CVE-2019-11135** TSX Asynchronous Abort (TAA, ZombieLoad V2) - Impact: Kernel - Mitigation: microcode update + kernel update making possible to protect various CPU internal buffers from unprivileged speculative access to data - Performance impact of the mitigation: low to significant +**CVE-2018-12207** iTLB Multihit (No eXcuses) + + - Impact: Virtualization software and Virtual Machine Monitors + - Mitigation: disable hugepages use in hypervisor, or update hypervisor to benefit from mitigation + - Performance impact of the mitigation: low to significant + ## 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. diff --git a/spectre-meltdown-checker.sh b/spectre-meltdown-checker.sh index a4d5ecd..eded45b 100755 --- a/spectre-meltdown-checker.sh +++ b/spectre-meltdown-checker.sh @@ -163,7 +163,7 @@ global_critical=0 global_unknown=0 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 CVE-2018-12126 CVE-2018-12130 CVE-2018-12127 CVE-2019-11091 CVE-2019-11135' +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 CVE-2018-12126 CVE-2018-12130 CVE-2018-12127 CVE-2019-11091 CVE-2019-11135 CVE-2018-12207' # find a sane command to print colored messages, we prefer `printf` over `echo` # because `printf` behavior is more standard across Linux/BSD @@ -285,7 +285,8 @@ cve2name() CVE-2018-12130) echo "ZombieLoad, microarchitectural fill buffer data sampling (MFBDS)";; CVE-2018-12127) echo "RIDL, microarchitectural load port data sampling (MLPDS)";; CVE-2019-11091) echo "RIDL, microarchitectural data sampling uncacheable memory (MDSUM)";; - CVE-2019-11135) echo "Transactional Synchronization Extensions (TSX) Asynchronous Abort (TAA)";; + CVE-2019-11135) echo "ZombieLoad V2, TSX Asynchronous Abort (TAA)";; + CVE-2018-12207) echo "No eXcuses, iTLB Multihit";; *) echo "$0: error: invalid CVE '$1' passed to cve2name()" >&2; exit 255;; esac } @@ -308,6 +309,7 @@ _is_cpu_vulnerable_cached() CVE-2018-12127) return $variant_mlpds;; CVE-2019-11091) return $variant_mdsum;; CVE-2019-11135) return $variant_taa;; + CVE-2018-12207) return $variant_itlbmh;; *) echo "$0: error: invalid variant '$1' passed to is_cpu_vulnerable()" >&2; exit 255;; esac } @@ -335,6 +337,7 @@ is_cpu_vulnerable() variant_mlpds='' variant_mdsum='' variant_taa='' + variant_itlbmh='' if is_cpu_mds_free; then [ -z "$variant_msbds" ] && variant_msbds=immune @@ -406,25 +409,55 @@ is_cpu_vulnerable() [ "$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_SILVERMONT_D" ] || \ [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] || \ [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT_MID" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT_NP" ] || \ [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || \ - [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_X" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] || \ [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_D" ] || \ [ "$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" + _debug "is_cpu_vulnerable: intel family 6 but model known to be immune to l1tf" [ -z "$variantl1tf" ] && variantl1tf=immune else - _debug "is_cpu_vulnerable: intel family 6 is vuln" - [ -z "$variantl1tf" ] && variantl1tf=vuln + _debug "is_cpu_vulnerable: intel family 6 is vuln to l1tf" + variantl1tf=vuln fi elif [ "$cpu_family" -lt 6 ]; then - _debug "is_cpu_vulnerable: intel family < 6 is immune" + _debug "is_cpu_vulnerable: intel family < 6 is immune to l1tf" [ -z "$variantl1tf" ] && variantl1tf=immune fi + # iTLB MultiHit + # commit f9aa6b73a407b714c9aac44734eb4045c893c6f7 + if [ "$cpu_model" = 6 ]; then + 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_D" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT_MID" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ]; then + _debug "is_cpu_vulnerable: intel family 6 but model known to be immune to itlbmh" + [ -z "$variantitlbmh" ] && variantitlbmh=immune + else + _debug "is_cpu_vulnerable: intel family 6 is vuln to itlbmh" + variantitlbmh=vuln + fi + elif [ "$cpu_family" -lt 6 ]; then + _debug "is_cpu_vulnerable: intel family < 6 is immune to itlbmh" + [ -z "$variantitlbmh" ] && variantitlbmh=immune + fi elif is_amd || is_hygon; then # AMD revised their statement about variant2 => vulnerable # https://www.amd.com/en/corporate/speculative-execution @@ -439,10 +472,12 @@ is_cpu_vulnerable() _debug "is_cpu_vulnerable: cpu not affected by speculative store bypass so not vuln to variant4" fi variantl1tf=immune + variantitlbmh=immune elif [ "$cpu_vendor" = CAVIUM ]; then variant3=immune variant3a=immune variantl1tf=immune + variantitlbmh=immune elif [ "$cpu_vendor" = ARM ]; then # ARM # reference: https://developer.arm.com/support/security-update @@ -531,19 +566,21 @@ is_cpu_vulnerable() _debug "is_cpu_vulnerable: for cpu$i and so far, we have <$variant1> <$variant2> <$variant3> <$variant3a> <$variant4>" done variantl1tf=immune + variantitlbmh=immune fi _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 - [ "$variant_msbds" = "immune" ] && variant_msbds=1 || variant_msbds=0 - [ "$variant_mfbds" = "immune" ] && variant_mfbds=1 || variant_mfbds=0 - [ "$variant_mlpds" = "immune" ] && variant_mlpds=1 || variant_mlpds=0 - [ "$variant_mdsum" = "immune" ] && variant_mdsum=1 || variant_mdsum=0 - [ "$variant_taa" = "immune" ] && variant_taa=1 || variant_taa=0 + [ "$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 + [ "$variant_msbds" = "immune" ] && variant_msbds=1 || variant_msbds=0 + [ "$variant_mfbds" = "immune" ] && variant_mfbds=1 || variant_mfbds=0 + [ "$variant_mlpds" = "immune" ] && variant_mlpds=1 || variant_mlpds=0 + [ "$variant_mdsum" = "immune" ] && variant_mdsum=1 || variant_mdsum=0 + [ "$variant_taa" = "immune" ] && variant_taa=1 || variant_taa=0 + [ "$variant_itlbmh" = "immune" ] && variant_itlbmh=1 || variant_itlbmh=0 variantl1tf_sgx="$variantl1tf" # even if we are vulnerable to L1TF, if there's no SGX, we're safe for the original foreshadow [ "$cpuid_sgx" = 0 ] && variantl1tf_sgx=1 @@ -608,7 +645,7 @@ is_cpu_mds_free() if is_intel; then if [ "$cpu_family" = 6 ]; then if [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || \ - [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_X" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] || \ [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ]; then return 0 fi @@ -675,7 +712,7 @@ is_cpu_ssb_free() if [ "$cpu_family" = 6 ]; then if [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] || \ [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] || \ - [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_X" ] || \ + [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_D" ] || \ [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ]; then return 0 elif [ "$cpu_model" = "$INTEL_FAM6_CORE_YONAH" ] || \ @@ -1077,6 +1114,7 @@ pvulnstatus() CVE-2018-12127) aka="MLPDS";; CVE-2019-11091) aka="MDSUM";; CVE-2019-11135) aka="TAA";; + CVE-2018-12207) aka="ITLBMH";; *) echo "$0: error: invalid CVE '$1' passed to pvulnstatus()" >&2; exit 255;; esac @@ -1513,66 +1551,68 @@ parse_cpu_details() ucode_found=$(printf "model 0x%x family 0x%x stepping 0x%x ucode 0x%x cpuid 0x%x" "$cpu_model" "$cpu_family" "$cpu_stepping" "$cpu_ucode" "$cpu_cpuid") # also define those that we will need in other funcs - # taken from ttps://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/include/asm/intel-family.h + # taken from https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/include/asm/intel-family.h + # curl -s 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/arch/x86/include/asm/intel-family.h' | awk '/#define INTEL_FAM6/ {print $2"=$(( "$3" )) # "$4,$5,$6,$7,$8,$9}' # shellcheck disable=SC2034 { + INTEL_FAM6_CORE_YONAH=$(( 0x0E )) # + INTEL_FAM6_CORE2_MEROM=$(( 0x0F )) # + INTEL_FAM6_CORE2_MEROM_L=$(( 0x16 )) # + INTEL_FAM6_CORE2_PENRYN=$(( 0x17 )) # + INTEL_FAM6_CORE2_DUNNINGTON=$(( 0x1D )) # + INTEL_FAM6_NEHALEM=$(( 0x1E )) # + INTEL_FAM6_NEHALEM_G=$(( 0x1F )) # /* Auburndale / Havendale */ + INTEL_FAM6_NEHALEM_EP=$(( 0x1A )) # + INTEL_FAM6_NEHALEM_EX=$(( 0x2E )) # + INTEL_FAM6_WESTMERE=$(( 0x25 )) # + INTEL_FAM6_WESTMERE_EP=$(( 0x2C )) # + INTEL_FAM6_WESTMERE_EX=$(( 0x2F )) # + INTEL_FAM6_SANDYBRIDGE=$(( 0x2A )) # + INTEL_FAM6_SANDYBRIDGE_X=$(( 0x2D )) # + INTEL_FAM6_IVYBRIDGE=$(( 0x3A )) # + INTEL_FAM6_IVYBRIDGE_X=$(( 0x3E )) # + INTEL_FAM6_HASWELL=$(( 0x3C )) # + INTEL_FAM6_HASWELL_X=$(( 0x3F )) # + INTEL_FAM6_HASWELL_L=$(( 0x45 )) # + INTEL_FAM6_HASWELL_G=$(( 0x46 )) # + INTEL_FAM6_BROADWELL=$(( 0x3D )) # + INTEL_FAM6_BROADWELL_G=$(( 0x47 )) # + INTEL_FAM6_BROADWELL_X=$(( 0x4F )) # + INTEL_FAM6_BROADWELL_D=$(( 0x56 )) # + INTEL_FAM6_SKYLAKE_L=$(( 0x4E )) # + INTEL_FAM6_SKYLAKE=$(( 0x5E )) # + INTEL_FAM6_SKYLAKE_X=$(( 0x55 )) # + INTEL_FAM6_KABYLAKE_L=$(( 0x8E )) # + INTEL_FAM6_KABYLAKE=$(( 0x9E )) # + INTEL_FAM6_CANNONLAKE_L=$(( 0x66 )) # + INTEL_FAM6_ICELAKE_X=$(( 0x6A )) # + INTEL_FAM6_ICELAKE_D=$(( 0x6C )) # + INTEL_FAM6_ICELAKE=$(( 0x7D )) # + INTEL_FAM6_ICELAKE_L=$(( 0x7E )) # + INTEL_FAM6_ICELAKE_NNPI=$(( 0x9D )) # + INTEL_FAM6_TIGERLAKE_L=$(( 0x8C )) # + INTEL_FAM6_TIGERLAKE=$(( 0x8D )) # + INTEL_FAM6_COMETLAKE=$(( 0xA5 )) # + INTEL_FAM6_COMETLAKE_L=$(( 0xA6 )) # + INTEL_FAM6_ATOM_BONNELL=$(( 0x1C )) # /* Diamondville, Pineview */ + INTEL_FAM6_ATOM_BONNELL_MID=$(( 0x26 )) # /* Silverthorne, Lincroft */ + INTEL_FAM6_ATOM_SALTWELL=$(( 0x36 )) # /* Cedarview */ + INTEL_FAM6_ATOM_SALTWELL_MID=$(( 0x27 )) # /* Penwell */ + INTEL_FAM6_ATOM_SALTWELL_TABLET=$(( 0x35 )) # /* Cloverview */ + INTEL_FAM6_ATOM_SILVERMONT=$(( 0x37 )) # /* Bay Trail, Valleyview */ + INTEL_FAM6_ATOM_SILVERMONT_D=$(( 0x4D )) # /* Avaton, Rangely */ + INTEL_FAM6_ATOM_SILVERMONT_MID=$(( 0x4A )) # /* Merriefield */ + INTEL_FAM6_ATOM_AIRMONT=$(( 0x4C )) # /* Cherry Trail, Braswell */ + INTEL_FAM6_ATOM_AIRMONT_MID=$(( 0x5A )) # /* Moorefield */ + INTEL_FAM6_ATOM_AIRMONT_NP=$(( 0x75 )) # /* Lightning Mountain */ + INTEL_FAM6_ATOM_GOLDMONT=$(( 0x5C )) # /* Apollo Lake */ + INTEL_FAM6_ATOM_GOLDMONT_D=$(( 0x5F )) # /* Denverton */ + INTEL_FAM6_ATOM_GOLDMONT_PLUS=$(( 0x7A )) # /* Gemini Lake */ + INTEL_FAM6_ATOM_TREMONT_D=$(( 0x86 )) # /* Jacobsville */ + INTEL_FAM6_ATOM_TREMONT=$(( 0x96 )) # /* Elkhart Lake */ + INTEL_FAM6_XEON_PHI_KNL=$(( 0x57 )) # /* Knights Landing */ + INTEL_FAM6_XEON_PHI_KNM=$(( 0x85 )) # /* Knights Mill */ INTEL_FAM6_CORE_YONAH=$(( 0x0E )) - - INTEL_FAM6_CORE2_MEROM=$(( 0x0F )) - INTEL_FAM6_CORE2_MEROM_L=$(( 0x16 )) - INTEL_FAM6_CORE2_PENRYN=$(( 0x17 )) - INTEL_FAM6_CORE2_DUNNINGTON=$(( 0x1D )) - - INTEL_FAM6_NEHALEM=$(( 0x1E )) - INTEL_FAM6_NEHALEM_G=$(( 0x1F )) - INTEL_FAM6_NEHALEM_EP=$(( 0x1A )) - INTEL_FAM6_NEHALEM_EX=$(( 0x2E )) - - INTEL_FAM6_WESTMERE=$(( 0x25 )) - INTEL_FAM6_WESTMERE_EP=$(( 0x2C )) - INTEL_FAM6_WESTMERE_EX=$(( 0x2F )) - - INTEL_FAM6_SANDYBRIDGE=$(( 0x2A )) - INTEL_FAM6_SANDYBRIDGE_X=$(( 0x2D )) - INTEL_FAM6_IVYBRIDGE=$(( 0x3A )) - INTEL_FAM6_IVYBRIDGE_X=$(( 0x3E )) - - INTEL_FAM6_HASWELL_CORE=$(( 0x3C )) - INTEL_FAM6_HASWELL_X=$(( 0x3F )) - INTEL_FAM6_HASWELL_ULT=$(( 0x45 )) - INTEL_FAM6_HASWELL_GT3E=$(( 0x46 )) - - INTEL_FAM6_BROADWELL_CORE=$(( 0x3D )) - INTEL_FAM6_BROADWELL_GT3E=$(( 0x47 )) - INTEL_FAM6_BROADWELL_X=$(( 0x4F )) - INTEL_FAM6_BROADWELL_XEON_D=$(( 0x56 )) - - INTEL_FAM6_SKYLAKE_MOBILE=$(( 0x4E )) - INTEL_FAM6_SKYLAKE_DESKTOP=$(( 0x5E )) - INTEL_FAM6_SKYLAKE_X=$(( 0x55 )) - INTEL_FAM6_KABYLAKE_MOBILE=$(( 0x8E )) - INTEL_FAM6_KABYLAKE_DESKTOP=$(( 0x9E )) - - # /* "Small Core" Processors (Atom) */ - - 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_AIRMONT_MID=$(( 0x5A )) - INTEL_FAM6_ATOM_GOLDMONT=$(( 0x5C )) - INTEL_FAM6_ATOM_GOLDMONT_X=$(( 0x5F )) - INTEL_FAM6_ATOM_GOLDMONT_PLUS=$(( 0x7A )) - - # /* Xeon Phi */ - - INTEL_FAM6_XEON_PHI_KNL=$(( 0x57 )) - INTEL_FAM6_XEON_PHI_KNM=$(( 0x85 )) } parse_cpu_details_done=1 } @@ -1639,7 +1679,7 @@ is_ucode_blacklisted() $INTEL_FAM6_BROADWELL_XEON_D,0x03,0x07000011 \ $INTEL_FAM6_BROADWELL_X,0x01,0x0b000023 \ $INTEL_FAM6_BROADWELL_X,0x01,0x0b000025 \ - $INTEL_FAM6_HASWELL_ULT,0x01,0x21 \ + $INTEL_FAM6_HASWELL_L,0x01,0x21 \ $INTEL_FAM6_HASWELL_GT3E,0x01,0x18 \ $INTEL_FAM6_HASWELL_CORE,0x03,0x23 \ $INTEL_FAM6_HASWELL_X,0x02,0x3b \ @@ -1648,10 +1688,10 @@ is_ucode_blacklisted() $INTEL_FAM6_SANDYBRIDGE_X,0x06,0x61b \ $INTEL_FAM6_SANDYBRIDGE_X,0x07,0x712 do - model=$(echo $tuple | cut -d, -f1) - stepping=$(( $(echo $tuple | cut -d, -f2) )) + model=$(echo "$tuple" | cut -d, -f1) + stepping=$(( $(echo "$tuple" | cut -d, -f2) )) if [ "$cpu_model" = "$model" ] && [ "$cpu_stepping" = "$stepping" ]; then - ucode=$(( $(echo $tuple | cut -d, -f3) )) + ucode=$(( $(echo "$tuple" | cut -d, -f3) )) if [ "$cpu_ucode" = "$ucode" ]; then _debug "is_ucode_blacklisted: we have a match! ($cpu_model/$cpu_stepping/$cpu_ucode)" return 0 @@ -1678,11 +1718,11 @@ is_skylake_cpu() parse_cpu_details is_intel || return 1 [ "$cpu_family" = 6 ] || return 1 - if [ "$cpu_model" = $INTEL_FAM6_SKYLAKE_MOBILE ] || \ - [ "$cpu_model" = $INTEL_FAM6_SKYLAKE_DESKTOP ] || \ - [ "$cpu_model" = $INTEL_FAM6_SKYLAKE_X ] || \ - [ "$cpu_model" = $INTEL_FAM6_KABYLAKE_MOBILE ] || \ - [ "$cpu_model" = $INTEL_FAM6_KABYLAKE_DESKTOP ]; then + if [ "$cpu_model" = $INTEL_FAM6_SKYLAKE_L ] || \ + [ "$cpu_model" = $INTEL_FAM6_SKYLAKE ] || \ + [ "$cpu_model" = $INTEL_FAM6_SKYLAKE_X ] || \ + [ "$cpu_model" = $INTEL_FAM6_KABYLAKE_L ] || \ + [ "$cpu_model" = $INTEL_FAM6_KABYLAKE ]; then return 0 fi return 1 @@ -2138,7 +2178,7 @@ sys_interface_check() # Not affected status=OK pstatus green YES "$fullmsg" - elif echo "$msg" | grep -qi '^mitigation'; then + elif echo "$msg" | grep -qEi '^(kvm: )?mitigation'; then # Mitigation: PTI status=OK pstatus green YES "$fullmsg" @@ -2709,6 +2749,7 @@ check_cpu() capabilities_rsba=-1 capabilities_l1dflush_no=-1 capabilities_ssb_no=-1 + capabilities_pschange_msc_no=-1 if [ "$cpuid_arch_capabilities" = -1 ]; then pstatus yellow UNKNOWN elif [ "$cpuid_arch_capabilities" != 1 ]; then @@ -2719,6 +2760,7 @@ check_cpu() capabilities_rsba=0 capabilities_l1dflush_no=0 capabilities_ssb_no=0 + capabilities_pschange_msc_no=0 pstatus yellow NO elif [ ! -e /dev/cpu/0/msr ] && [ ! -e /dev/cpuctl0 ]; then spec_ctrl_msr=-1 @@ -2752,6 +2794,7 @@ check_cpu() capabilities_rsba=0 capabilities_l1dflush_no=0 capabilities_ssb_no=0 + capabilities_pschange_msc_no=0 if [ $val -eq 0 ]; then _debug "capabilities MSR is $capabilities (decimal)" [ $(( capabilities >> 0 & 1 )) -eq 1 ] && capabilities_rdcl_no=1 @@ -2760,8 +2803,9 @@ check_cpu() [ $(( capabilities >> 3 & 1 )) -eq 1 ] && capabilities_l1dflush_no=1 [ $(( capabilities >> 4 & 1 )) -eq 1 ] && capabilities_ssb_no=1 [ $(( capabilities >> 5 & 1 )) -eq 1 ] && capabilities_mds_no=1 + [ $(( capabilities >> 6 & 1 )) -eq 1 ] && capabilities_pschange_msc_no=1 [ $(( capabilities >> 8 & 1 )) -eq 1 ] && capabilities_taa_no=1 - _debug "capabilities says rdcl_no=$capabilities_rdcl_no ibrs_all=$capabilities_ibrs_all rsba=$capabilities_rsba l1dflush_no=$capabilities_l1dflush_no ssb_no=$capabilities_ssb_no mds_no=$capabilities_mds_no taa_no=$capabilities_taa_no" + _debug "capabilities says rdcl_no=$capabilities_rdcl_no ibrs_all=$capabilities_ibrs_all rsba=$capabilities_rsba l1dflush_no=$capabilities_l1dflush_no ssb_no=$capabilities_ssb_no mds_no=$capabilities_mds_no taa_no=$capabilities_taa_no pschange_msc_no=$capabilities_pschange_msc_no" if [ "$capabilities_ibrs_all" = 1 ]; then if [ $cpu_mismatch -eq 0 ]; then pstatus green YES @@ -2827,7 +2871,7 @@ check_cpu() pstatus yellow NO fi - _info_nol " * CPU explicitly indicates not being vulnerable to TSX Asynchrnonous Abort (TAA_NO): " + _info_nol " * CPU explicitly indicates not being vulnerable to TSX Asynchronous Abort (TAA_NO): " if [ "$capabilities_taa_no" = -1 ]; then pstatus yellow UNKNOWN elif [ "$capabilities_taa_no" = 1 ]; then @@ -2835,6 +2879,15 @@ check_cpu() else pstatus yellow NO fi + + _info_nol " * CPU explicitly indicates not being vulnerable to iTLB Multihit (PSCHANGE_MSC_NO): " + if [ "$capabilities_pschange_msc_no" = -1 ]; then + pstatus yellow UNKNOWN + elif [ "$capabilities_pschange_msc_no" = 1 ]; then + pstatus green YES + else + pstatus yellow NO + fi fi _info_nol " * CPU supports Software Guard Extensions (SGX): " @@ -2918,6 +2971,52 @@ check_redhat_canonical_spectre() fi } +check_has_vmm() +{ + _info_nol "* This system is a host running a hypervisor: " + has_vmm=$opt_vmm + if [ "$has_vmm" = -1 ] && [ "$opt_paranoid" = 1 ]; then + # In paranoid mode, if --vmm was not specified on the command-line, + # we want to be secure before everything else, so assume we're running + # a hypervisor, as this requires more mitigations + has_vmm=2 + elif [ "$has_vmm" = -1 ]; then + # Here, we want to know if we are hosting a hypervisor, and running some VMs on it. + # If we find no evidence that this is the case, assume we're not (to avoid scaring users), + # this can always be overridden with --vmm in any case. + has_vmm=0 + if command -v pgrep >/dev/null 2>&1; then + # remove xenbus and xenwatch, also present inside domU + # remove libvirtd as it can also be used to manage containers and not VMs + if pgrep qemu >/dev/null || pgrep kvm >/dev/null || \ + pgrep xenstored >/dev/null || pgrep xenconsoled >/dev/null; then + has_vmm=1 + fi + else + # ignore SC2009 as `ps ax` is actually used as a fallback if `pgrep` isn't installed + # shellcheck disable=SC2009 + if ps ax | grep -vw grep | grep -q -e '\/dev/null 2>&1; then - # remove xenbus and xenwatch, also present inside domU - # remove libvirtd as it can also be used to manage containers and not VMs - if pgrep qemu >/dev/null || pgrep kvm >/dev/null || \ - pgrep xenstored >/dev/null || pgrep xenconsoled >/dev/null; then - has_vmm=1 - fi - else - # ignore SC2009 as `ps ax` is actually used as a fallback if `pgrep` isn't installed - # shellcheck disable=SC2009 - if ps ax | grep -vw grep | grep -q -e '\