feat: add detection of iTLB Multihit vuln/mitigation (CVE-2018-12207)

This commit is contained in:
Stéphane Lesimple 2019-11-24 19:25:56 +01:00
parent 8ddf6b2d6d
commit bd47275501
3 changed files with 293 additions and 139 deletions

View File

@ -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

View File

@ -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.

View File

@ -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 '\<qemu' -e '/qemu' -e '<\kvm' -e '/kvm' -e '/xenstored' -e '/xenconsoled'; then
has_vmm=1
fi
fi
fi
if [ "$has_vmm" = 0 ]; then
if [ "$opt_vmm" != -1 ]; then
pstatus green NO "forced from command line"
else
pstatus green NO
fi
else
if [ "$opt_vmm" != -1 ]; then
pstatus blue YES "forced from command line"
elif [ "$has_vmm" = 2 ]; then
pstatus blue YES "paranoid mode"
else
pstatus blue YES
fi
fi
}
###################
# SPECTRE 1 SECTION
@ -4210,7 +4309,7 @@ check_CVE_2018_3615()
_info "\033[1;34m$cve aka '$(cve2name "$cve")'\033[0m"
_info_nol "* CPU microcode mitigates the vulnerability: "
if ( [ "$cpu_flush_cmd" = 1 ] || ( [ "$msr_locked_down" = 1 ] && [ "$cpuid_l1df" = 1 ] ) ) && [ "$cpuid_sgx" = 1 ]; then
if { [ "$cpu_flush_cmd" = 1 ] || { [ "$msr_locked_down" = 1 ] && [ "$cpuid_l1df" = 1 ]; }; } && [ "$cpuid_sgx" = 1 ]; then
# no easy way to detect a fixed SGX but we know that
# microcodes that have the FLUSH_CMD MSR also have the
# fixed SGX (for CPUs that support it), because Intel
@ -4229,7 +4328,7 @@ check_CVE_2018_3615()
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 [ "$cpu_flush_cmd" = 1 ] || ( [ "$msr_locked_down" = 1 ] && [ "$cpuid_l1df" = 1 ] ) ; then
elif [ "$cpu_flush_cmd" = 1 ] || { [ "$msr_locked_down" = 1 ] && [ "$cpuid_l1df" = 1 ]; } ; then
pvulnstatus $cve OK "your CPU microcode mitigates the vulnerability"
else
pvulnstatus $cve VULN "your CPU supports SGX and the microcode is not up to date"
@ -4377,48 +4476,7 @@ check_CVE_2018_3646_linux()
fi
l1d_mode=-1
if [ "$opt_sysfs_only" != 1 ]; then
_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 '\<qemu' -e '/qemu' -e '<\kvm' -e '/kvm' -e '/xenstored' -e '/xenconsoled'; then
has_vmm=1
fi
fi
fi
if [ "$has_vmm" = 0 ]; then
if [ "$opt_vmm" != -1 ]; then
pstatus green NO "forced from command line"
else
pstatus green NO
fi
else
if [ "$opt_vmm" != -1 ]; then
pstatus blue YES "forced from command line"
elif [ "$has_vmm" = 2 ]; then
pstatus blue YES "paranoid mode"
else
pstatus blue YES
fi
fi
check_has_vmm
_info "* Mitigation 1 (KVM)"
_info_nol " * EPT is disabled: "
@ -4978,6 +5036,95 @@ check_CVE_2019_11135_linux()
fi
}
#######################
# iTLB Multihit section
check_CVE_2018_12207()
{
cve='CVE-2018-12207'
_info "\033[1;34m$cve aka '$(cve2name "$cve")'\033[0m"
if [ "$os" = Linux ]; then
check_CVE_2018_12207_linux
#elif echo "$os" | grep -q BSD; then
# check_CVE_2018_12207_bsd
else
_warn "Unsupported OS ($os)"
fi
}
check_CVE_2018_12207_linux()
{
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/itlb_multihit"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
fi
if [ "$opt_sysfs_only" != 1 ]; then
check_has_vmm
_info_nol "* iTLB Multihit mitigation is supported by kernel: "
kernel_itlbmh=''
if [ -n "$kernel_err" ]; then
kernel_itlbmh_err="$kernel_err"
# commit 5219505fcbb640e273a0d51c19c38de0100ec5a9
elif grep -q 'itlb_multihit' "$kernel"; then
kernel_itlbmh="found itlb_multihit in kernel image"
fi
if [ -n "$kernel_itlbmh" ]; then
pstatus green YES "$kernel_itlbmh"
elif [ -n "$kernel_itlbmh_err" ]; then
pstatus yellow UNKNOWN "$kernel_itlbmh_err"
else
pstatus yellow NO
fi
_info_nol "* iTLB Multihit mitigation enabled and active: "
if [ "$opt_live" = 1 ]; then
if [ -n "$fullmsg" ]; then
if echo "$fullmsg" | grep -qF 'Mitigation'; then
pstatus green YES "$fullmsg"
else
pstatus yellow NO
fi
else
pstatus yellow NO "itlb_multihit not found in sysfs hierarchy"
fi
else
pstatus blue N/A "not testable in offline mode"
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
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 a hypervisor"
elif [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$opt_live" = 1 ]; then
# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
pvulnstatus $cve VULN "Your kernel doesn't support iTLB Multihit mitigation, update it"
else
if [ -n "$kernel_itlbmh" ]; then
pvulnstatus $cve OK "Your kernel supports iTLB Multihit mitigation"
else
pvulnstatus $cve VULN "Your kernel doesn't support iTLB Multihit mitigation, update it"
fi
fi
else
pvulnstatus $cve "$status" "$msg"
fi
}
#######################
# END OF VULNS SECTIONS
if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then
check_cpu
check_cpu_vulnerabilities