Hello community,
here is the log from the commit of package spectre-meltdown-checker for
openSUSE:Factory checked in at 2019-06-26 16:04:55
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/spectre-meltdown-checker (Old)
and /work/SRC/openSUSE:Factory/.spectre-meltdown-checker.new.4615 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "spectre-meltdown-checker"
Wed Jun 26 16:04:55 2019 rev:7 rq:712091 version:0.42
Changes:
--------
---
/work/SRC/openSUSE:Factory/spectre-meltdown-checker/spectre-meltdown-checker.changes
2019-05-25 13:20:47.572324113 +0200
+++
/work/SRC/openSUSE:Factory/.spectre-meltdown-checker.new.4615/spectre-meltdown-checker.changes
2019-06-26 16:05:28.607751881 +0200
@@ -1,0 +2,13 @@
+Wed Jun 26 06:54:42 UTC 2019 - Pavol Cupka <[email protected]>
+
+- version 0.42
+ * add FreeBSD MDS mitigation detection
+ * add mocking functionality to help debugging, dump data to mock the
behavior of your CPU with --dump-mock-data
+ * AMD, ARM and CAVIUM are not vulnerable to MDS
+ * RDCL_NO bit wasn't taking precedence for L1TF check on some newer Intel
CPUs
+ * The MDS_NO bit on newer Intel CPUs is now recognized and used
+ * remove libvirtd from hypervisor detection to avoid false positives (#278)
+ * under BSD, the data returned when reading MSR was incorrectly formatted
+ * update builtin MCEdb from v110 to v111
+
+-------------------------------------------------------------------
Old:
----
v0.41.tar.gz
New:
----
v0.42.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ spectre-meltdown-checker.spec ++++++
--- /var/tmp/diff_new_pack.dwX4dR/_old 2019-06-26 16:05:29.423753036 +0200
+++ /var/tmp/diff_new_pack.dwX4dR/_new 2019-06-26 16:05:29.423753036 +0200
@@ -17,7 +17,7 @@
Name: spectre-meltdown-checker
-Version: 0.41
+Version: 0.42
Release: 0
Summary: Spectre & Meltdown Vulnerability Checker
License: GPL-3.0-only
++++++ v0.41.tar.gz -> v0.42.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/spectre-meltdown-checker-0.41/README.md
new/spectre-meltdown-checker-0.42/README.md
--- old/spectre-meltdown-checker-0.41/README.md 2019-05-15 09:57:28.000000000
+0200
+++ new/spectre-meltdown-checker-0.42/README.md 2019-05-24 22:49:45.000000000
+0200
@@ -143,7 +143,7 @@
- Note: These 4 CVEs are similar and collectively named "MDS"
vulnerabilities, the mitigation is identical for all
- 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: TBC
+ - Performance impact of the mitigation: low to significant
## Understanding what this script does and doesn't
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spectre-meltdown-checker-0.41/spectre-meltdown-checker.sh
new/spectre-meltdown-checker-0.42/spectre-meltdown-checker.sh
--- old/spectre-meltdown-checker-0.41/spectre-meltdown-checker.sh
2019-05-15 09:57:28.000000000 +0200
+++ new/spectre-meltdown-checker-0.42/spectre-meltdown-checker.sh
2019-05-24 22:49:45.000000000 +0200
@@ -11,7 +11,7 @@
#
# Stephane Lesimple
#
-VERSION='0.41'
+VERSION='0.42'
trap 'exit_cleanup' EXIT
trap '_warn "interrupted, cleaning up..."; exit_cleanup; exit 1' INT
@@ -79,13 +79,14 @@
--variant VARIANT specify which variant you'd like to
check, by default all variants are checked
VARIANT can be one of 1, 2, 3, 3a, 4,
l1tf, msbds, mfbds, mlpds, mdsum
- --cve [cve1,cve2,...] specify which CVE you'd like to check,
by default all supported CVEs are checked
can be specified multiple times (e.g.
--variant 2 --variant 3)
+ --cve [cve1,cve2,...] specify which CVE you'd like to check,
by default all supported CVEs are checked
--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 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
+ --dump-mock-data used to mimick a CPU on an other
system, mainly used to help debugging this script
Return codes:
0 (not vulnerable), 2 (vulnerable), 3 (unknown), 255 (error)
@@ -150,6 +151,7 @@
opt_vmm=-1
opt_explain=0
opt_paranoid=0
+opt_mock=0
global_critical=0
global_unknown=0
@@ -325,6 +327,14 @@
variant_mlpds=''
variant_mdsum=''
+ if is_cpu_mds_free; then
+ [ -z "$variant_msbds" ] && variant_msbds=immune
+ [ -z "$variant_mfbds" ] && variant_mfbds=immune
+ [ -z "$variant_mlpds" ] && variant_mlpds=immune
+ [ -z "$variant_mdsum" ] && variant_mdsum=immune
+ _debug "is_cpu_vulnerable: cpu not affected by
Microarchitectural Data Sampling"
+ fi
+
if is_cpu_specex_free; then
variant1=immune
variant2=immune
@@ -365,13 +375,6 @@
[ -z "$variant4" ] && variant4=immune
_debug "is_cpu_vulnerable: cpu not affected by
speculative store bypass so not vuln to variant4"
fi
- if is_cpu_mds_free; then
- [ -z "$variant_msbds" ] && variant_msbds=immune
- [ -z "$variant_mfbds" ] && variant_mfbds=immune
- [ -z "$variant_mlpds" ] && variant_mlpds=immune
- [ -z "$variant_mdsum" ] && variant_mdsum=immune
- _debug "is_cpu_vulnerable: cpu not affected by
Microarchitectural Data Sampling"
- 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
@@ -401,7 +404,7 @@
[ -z "$variantl1tf" ] && variantl1tf=immune
else
_debug "is_cpu_vulnerable: intel family 6 is
vuln"
- variantl1tf=vuln
+ [ -z "$variantl1tf" ] && variantl1tf=vuln
fi
elif [ "$cpu_family" -lt 6 ]; then
_debug "is_cpu_vulnerable: intel family < 6 is immune"
@@ -420,13 +423,6 @@
[ -z "$variant4" ] && variant4=immune
_debug "is_cpu_vulnerable: cpu not affected by
speculative store bypass so not vuln to variant4"
fi
- if is_cpu_mds_free; then
- [ -z "$variant_msbds" ] && variant_msbds=immune
- [ -z "$variant_mfbds" ] && variant_mfbds=immune
- [ -z "$variant_mlpds" ] && variant_mlpds=immune
- [ -z "$variant_mdsum" ] && variant_mdsum=immune
- _debug "is_cpu_vulnerable: cpu not affected by
Microarchitectural Data Sampling"
- fi
variantl1tf=immune
elif [ "$cpu_vendor" = CAVIUM ]; then
variant3=immune
@@ -593,30 +589,31 @@
#VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS),
#VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS),
parse_cpu_details
- if is_intel; then
+ if is_intel; then
if [ "$cpu_family" = 6 ]; then
- if [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || \
+ if [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || \
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_X"
] || \
[ "$cpu_model" =
"$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ]; then
- return 0
- fi
- fi
- fi
-
- if is_amd; then
- if [ "$cpu_family" = "18" ] || \
- [ "$cpu_family" = "17" ] || \
- [ "$cpu_family" = "16" ] || \
- [ "$cpu_family" = "15" ]; then
- return 0
+ return 0
+ fi
fi
+ [ "$capabilities_mds_no" = 1 ] && return 0
fi
- if is_hygon; then
+
+ # official statement from AMD says none of their CPUs are vulnerable
+ # https://www.amd.com/en/corporate/product-security
+ # https://www.amd.com/system/files/documents/security-whitepaper.pdf
+ if is_amd; then
+ return 0
+ elif is_hygon; then
+ return 0
+ elif [ "$cpu_vendor" = CAVIUM ]; then
+ return 0
+ elif [ "$cpu_vendor" = ARM ]; then
return 0
fi
-
- return 1
-
+
+ return 1
}
is_cpu_ssb_free()
@@ -821,6 +818,9 @@
elif [ "$1" = "--update-builtin-mcedb" ]; then
update_mcedb builtin
exit $?
+ elif [ "$1" = "--dump-mock-data" ]; then
+ opt_mock=1
+ shift
elif [ "$1" = "--explain" ]; then
opt_explain=1
shift
@@ -841,6 +841,7 @@
esac
elif [ "$1" = "-v" ] || [ "$1" = "--verbose" ]; then
opt_verbose=$(( opt_verbose + 1 ))
+ [ "$opt_verbose" -ge 2 ] && opt_mock=1
shift
elif [ "$1" = "--cve" ]; then
if [ -z "$2" ]; then
@@ -885,7 +886,7 @@
mdsum) opt_cve_list="$opt_cve_list CVE-2019-11091";
opt_cve_all=0;;
l1tf) opt_cve_list="$opt_cve_list CVE-2018-3615
CVE-2018-3620 CVE-2018-3646"; opt_cve_all=0;;
*)
- echo "$0: error: invalid parameter '$2' for
--variant, expected either 1, 2, 3, 3a, 4 or l1tf" >&2;
+ echo "$0: error: invalid parameter '$2' for
--variant, expected either 1, 2, 3, 3a, 4, msbds, mfbds, mlpds, mdsum, or l1tf"
>&2;
exit 255
;;
esac
@@ -1216,6 +1217,14 @@
fi
_debug "cpuid: leaf$_leaf on cpu0, eax-ebx-ecx-edx: $_cpuid"
+ _mockvarname="SMC_MOCK_CPUID_${_leaf}"
+ if [ -n "$(eval echo \$$_mockvarname)" ]; then
+ _cpuid="$(eval echo \$$_mockvarname)"
+ _debug "read_cpuid: MOCKING enabled for leaf $_leaf, will
return $_cpuid"
+ mocked=1
+ else
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_CPUID_${_leaf}='$_cpuid'")
+ fi
[ -z "$_cpuid" ] && return 2
# get the value of the register we want
_reg=$(echo "$_cpuid" | awk '{print $'"$_register"'}')
@@ -1299,6 +1308,42 @@
cpu_friendly_name=$(sysctl -n hw.model)
fi
+ if [ -n "$SMC_MOCK_CPU_FRIENDLY_NAME" ]; then
+ cpu_friendly_name="$SMC_MOCK_CPU_FRIENDLY_NAME"
+ _debug "parse_cpu_details: MOCKING cpu friendly name to
$cpu_friendly_name"
+ mocked=1
+ else
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_CPU_FRIENDLY_NAME='$cpu_friendly_name'")
+ fi
+ if [ -n "$SMC_MOCK_CPU_VENDOR" ]; then
+ cpu_vendor="$SMC_MOCK_CPU_VENDOR"
+ _debug "parse_cpu_details: MOCKING cpu vendor to $cpu_vendor"
+ mocked=1
+ else
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_CPU_VENDOR='$cpu_vendor'")
+ fi
+ if [ -n "$SMC_MOCK_CPU_FAMILY" ]; then
+ cpu_family="$SMC_MOCK_CPU_FAMILY"
+ _debug "parse_cpu_details: MOCKING cpu family to $cpu_family"
+ mocked=1
+ else
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_CPU_FAMILY='$cpu_family'")
+ fi
+ if [ -n "$SMC_MOCK_CPU_MODEL" ]; then
+ cpu_model="$SMC_MOCK_CPU_MODEL"
+ _debug "parse_cpu_details: MOCKING cpu model to $cpu_model"
+ mocked=1
+ else
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_CPU_MODEL='$cpu_model'")
+ fi
+ if [ -n "$SMC_MOCK_CPU_STEPPING" ]; then
+ cpu_stepping="$SMC_MOCK_CPU_STEPPING"
+ _debug "parse_cpu_details: MOCKING cpu stepping to
$cpu_stepping"
+ mocked=1
+ else
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_CPU_STEPPING='$cpu_stepping'")
+ fi
+
# 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
cpu_cpuid="$read_cpuid_value"
@@ -1326,6 +1371,14 @@
# if we got no cpu_ucode (e.g. we're in a vm), fall back to 0x0
[ -z "$cpu_ucode" ] && cpu_ucode=0x0
+ if [ -n "$SMC_MOCK_CPU_UCODE" ]; then
+ cpu_ucode="$SMC_MOCK_CPU_UCODE"
+ _debug "parse_cpu_details: MOCKING cpu ucode to $cpu_ucode"
+ mocked=1
+ else
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_CPU_UCODE='$cpu_ucode'")
+ fi
+
echo "$cpu_ucode" | grep -q ^0x && cpu_ucode=$(( cpu_ucode ))
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")
@@ -1877,12 +1930,41 @@
file="$1"
regex="$2"
mode="$3"
- [ "$opt_live" = 1 ] && [ "$opt_no_sysfs" = 0 ] && [ -r "$file" ] ||
return 1
+ msg=''
+ fullmsg=''
+
+ if [ "$opt_live" = 1 ] && [ "$opt_no_sysfs" = 0 ] && [ -r "$file" ];
then
+ :
+ else
+ mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_SYSFS_$(basename
"$file")_RET=1")
+ return 1
+ fi
+
+ _mockvarname="SMC_MOCK_SYSFS_$(basename "$file")_RET"
+ # shellcheck disable=SC2086
+ if [ -n "$(eval echo \$$_mockvarname)" ]; then
+ _debug "sysfs: MOCKING enabled for $file func returns $(eval
echo \$$_mockvarname)"
+ mocked=1
+ return "$(eval echo \$$_mockvarname)"
+ fi
+
[ -n "$regex" ] || regex='.*'
- fullmsg=$(cat "$file")
- msg=$(grep -Eo "$regex" "$file")
+ _mockvarname="SMC_MOCK_SYSFS_$(basename "$file")"
+ # shellcheck disable=SC2086
+ if [ -n "$(eval echo \$$_mockvarname)" ]; then
+ fullmsg="$(eval echo \$$_mockvarname)"
+ msg=$(echo "$fullmsg" | grep -Eo "$regex")
+ _debug "sysfs: MOCKING enabled for $file, will return $fullmsg"
+ mocked=1
+ else
+ fullmsg=$(cat "$file")
+ msg=$(grep -Eo "$regex" "$file")
+ mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_SYSFS_$(basename
"$file")='$fullmsg'")
+ fi
if [ "$mode" = silent ]; then
- _info "* Information from the /sys interface: $msg"
+ return 0
+ elif [ "$mode" = quiet ]; then
+ _info "* Information from the /sys interface: $fullmsg"
return 0
fi
_info_nol "* Mitigated according to the /sys interface: "
@@ -1919,90 +2001,128 @@
return "$n"
}
-# $1 - msr number
-# $2 - cpu index
+# write_msr
+# param1 (mandatory): MSR, can be in hex or decimal.
+# param2 (optional): CPU index, starting from 0. Default 0.
write_msr()
{
- # _msr must be in hex, in the form 0x1234:
- _msr="$1"
- # cpu index, starting from 0:
+ _msr_dec=$(( $1 ))
+ _msr=$(printf "0x%x" "$_msr_dec")
_cpu="$2"
+ [ -z "$_cpu" ] && _cpu=0
+
+ _mockvarname="SMC_MOCK_WRMSR_${_msr}_RET"
+ # shellcheck disable=SC2086
+ if [ -n "$(eval echo \$$_mockvarname)" ]; then
+ _debug "write_msr: MOCKING enabled for msr $_msr func returns
$(eval echo \$$_mockvarname)"
+ mocked=1
+ return "$(eval echo \$$_mockvarname)"
+ fi
+
if [ "$os" != Linux ]; then
cpucontrol -m "$_msr=0" "/dev/cpuctl$_cpu" >/dev/null 2>&1;
ret=$?
else
# for Linux
# convert to decimal
- _msr=$(( _msr ))
if [ ! -w /dev/cpu/"$_cpu"/msr ]; then
ret=200 # permission error
# if wrmsr is available, use it
elif command -v wrmsr >/dev/null 2>&1 && [ "$SMC_NO_WRMSR" != 1
]; then
_debug "write_msr: using wrmsr"
- wrmsr $_msr 0 2>/dev/null; ret=$?
+ wrmsr $_msr_dec 0 2>/dev/null; ret=$?
# or if we have perl, use it, any 5.x version will work
elif command -v perl >/dev/null 2>&1 && [ "$SMC_NO_PERL" != 1
]; then
_debug "write_msr: using perl"
ret=1
- perl -e "open(M,'>','/dev/cpu/$_cpu/msr') and
seek(M,$_msr,0) and exit(syswrite(M,pack('H16',0)))"; [ $? -eq 8 ] && ret=0
+ perl -e "open(M,'>','/dev/cpu/$_cpu/msr') and
seek(M,$_msr_dec,0) and exit(syswrite(M,pack('H16',0)))"; [ $? -eq 8 ] && ret=0
# fallback to dd if it supports seek_bytes
- elif dd if=/dev/null of=/dev/null bs=8 count=1 seek="$_msr"
oflag=seek_bytes 2>/dev/null; then
+ elif dd if=/dev/null of=/dev/null bs=8 count=1 seek="$_msr_dec"
oflag=seek_bytes 2>/dev/null; then
_debug "write_msr: using dd"
- dd if=/dev/zero of=/dev/cpu/"$_cpu"/msr bs=8 count=1
seek="$_msr" oflag=seek_bytes 2>/dev/null; ret=$?
+ dd if=/dev/zero of=/dev/cpu/"$_cpu"/msr bs=8 count=1
seek="$_msr_dec" oflag=seek_bytes 2>/dev/null; ret=$?
else
_debug "write_msr: got no wrmsr, perl or recent enough
dd!"
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_WRMSR_${_msr}_RET=201")
return 201 # missing tool error
fi
fi
# normalize ret
[ "$ret" != 0 ] && ret=1
_debug "write_msr: for cpu $_cpu on msr $_msr, ret=$ret"
+ mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_WRMSR_${_msr}_RET=$ret")
return $ret
}
+# read_msr
+# param1 (mandatory): MSR, can be in hex or decimal.
+# param2 (optional): CPU index, starting from 0. Default 0.
read_msr()
{
- # _msr must be in hex, in the form 0x1234:
- _msr="$1"
- # cpu index, starting from 0:
+ _msr_dec=$(( $1 ))
+ _msr=$(printf "0x%x" "$_msr_dec")
_cpu="$2"
+ [ -z "$_cpu" ] && _cpu=0
+
read_msr_value=''
+
+ _mockvarname="SMC_MOCK_RDMSR_${_msr}"
+ # shellcheck disable=SC2086
+ if [ -n "$(eval echo \$$_mockvarname)" ]; then
+ read_msr_value="$(eval echo \$$_mockvarname)"
+ _debug "read_msr: MOCKING enabled for msr $_msr, returning
$read_msr_value"
+ mocked=1
+ return 0
+ else
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_RDMSR_${_msr}='$read_msr_value'")
+ fi
+
+ _mockvarname="SMC_MOCK_RDMSR_${_msr}_RET"
+ # shellcheck disable=SC2086
+ if [ -n "$(eval echo \$$_mockvarname)" ] && [ "$(eval echo
\$$_mockvarname)" -ne 0 ]; then
+ _debug "read_msr: MOCKING enabled for msr $_msr func returns
$(eval echo \$$_mockvarname)"
+ mocked=1
+ return "$(eval echo \$$_mockvarname)"
+ fi
+
if [ "$os" != Linux ]; then
+ # for BSD
_msr=$(cpucontrol -m "$_msr" "/dev/cpuctl$_cpu" 2>/dev/null);
ret=$?
- [ $ret -ne 0 ] && return 1
+ if [ $ret -ne 0 ]; then
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_RDMSR_${_msr}_RET=1")
+ return 1
+ fi
# MSR 0x10: 0x000003e1 0xb106dded
_msr_h=$(echo "$_msr" | awk '{print $3}');
- _msr_h="$(( _msr_h >> 24 & 0xFF )) $(( _msr_h >> 16 & 0xFF ))
$(( _msr_h >> 8 & 0xFF )) $(( _msr_h & 0xFF ))"
_msr_l=$(echo "$_msr" | awk '{print $4}');
- _msr_l="$(( _msr_l >> 24 & 0xFF )) $(( _msr_l >> 16 & 0xFF ))
$(( _msr_l >> 8 & 0xFF )) $(( _msr_l & 0xFF ))"
- read_msr_value="$_msr_h $_msr_l"
+ read_msr_value=$(( _msr_h << 32 | _msr_l ))
else
# for Linux
- # convert to decimal
- _msr=$(( _msr ))
if [ ! -r /dev/cpu/"$_cpu"/msr ]; then
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_RDMSR_${_msr}_RET=200")
return 200 # permission error
# if rdmsr is available, use it
elif command -v rdmsr >/dev/null 2>&1 && [ "$SMC_NO_RDMSR" != 1
]; then
_debug "read_msr: using rdmsr"
- read_msr_value=$(rdmsr -r $_msr 2>/dev/null | od -t u8
-A n)
+ read_msr_value=$(rdmsr -r $_msr_dec 2>/dev/null | od -t
u8 -A n)
# or if we have perl, use it, any 5.x version will work
elif command -v perl >/dev/null 2>&1 && [ "$SMC_NO_PERL" != 1
]; then
_debug "read_msr: using perl"
- read_msr_value=$(perl -e
"open(M,'<','/dev/cpu/$_cpu/msr') and seek(M,$_msr,0) and read(M,\$_,8) and
print" | od -t u8 -A n)
+ read_msr_value=$(perl -e
"open(M,'<','/dev/cpu/$_cpu/msr') and seek(M,$_msr_dec,0) and read(M,\$_,8) and
print" | od -t u8 -A n)
# fallback to dd if it supports skip_bytes
- elif dd if=/dev/null of=/dev/null bs=8 count=1 skip="$_msr"
iflag=skip_bytes 2>/dev/null; then
+ elif dd if=/dev/null of=/dev/null bs=8 count=1 skip="$_msr_dec"
iflag=skip_bytes 2>/dev/null; then
_debug "read_msr: using dd"
- read_msr_value=$(dd if=/dev/cpu/"$_cpu"/msr bs=8
count=1 skip="$_msr" iflag=skip_bytes 2>/dev/null | od -t u8 -A n)
+ read_msr_value=$(dd if=/dev/cpu/"$_cpu"/msr bs=8
count=1 skip="$_msr_dec" iflag=skip_bytes 2>/dev/null | od -t u8 -A n)
else
_debug "read_msr: got no rdmsr, perl or recent enough
dd!"
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_RDMSR_${_msr}_RET=201")
return 201 # missing tool error
fi
if [ -z "$read_msr_value" ]; then
# MSR doesn't exist, don't check for $? because some
versions of dd still return 0!
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_RDMSR_${_msr}_RET=1")
return 1
fi
fi
- _debug "read_msr: MSR=$1 value is $read_msr_value"
+ _debug "read_msr: MSR=$_msr value is $read_msr_value"
return 0
}
@@ -2447,7 +2567,7 @@
fi
fi
- _info_nol " * CPU explicitly indicates not being vulnerable to
Meltdown (RDCL_NO): "
+ _info_nol " * CPU explicitly indicates not being vulnerable to
Meltdown/L1TF (RDCL_NO): "
if [ "$capabilities_rdcl_no" = -1 ]; then
pstatus yellow UNKNOWN
elif [ "$capabilities_rdcl_no" = 1 ]; then
@@ -2483,14 +2603,14 @@
pstatus blue NO
fi
- _info_nol " * CPU explicitly indicates not being vulnerable to
Microarchitectural Data Sampling (MDC_NO): "
+ _info_nol " * CPU explicitly indicates not being vulnerable to
Microarchitectural Data Sampling (MDS_NO): "
if [ "$capabilities_mds_no" = -1 ]; then
pstatus yellow UNKNOWN
elif [ "$capabilities_mds_no" = 1 ]; then
pstatus green YES
else
pstatus yellow NO
- fi
+ fi
fi
_info_nol " * CPU supports Software Guard Extensions (SGX): "
@@ -2865,21 +2985,21 @@
# XXX and what about ibpb ?
fi
fi
- if [ -e
"/sys/devices/system/cpu/vulnerabilities/spectre_v2" ]; then
+ if [ -n "$fullmsg" ]; then
# when IBPB is enabled on 4.15+, we can see it
in sysfs
- if grep -q 'IBPB'
"/sys/devices/system/cpu/vulnerabilities/spectre_v2"; then
+ if echo "$fullmsg" | grep -q 'IBPB'; then
_debug "ibpb: found enabled in sysfs"
[ -z "$ibpb_supported" ] &&
ibpb_supported='IBPB found enabled in sysfs'
[ -z "$ibpb_enabled" ] &&
ibpb_enabled=1
fi
# when IBRS_FW is enabled on 4.15+, we can see
it in sysfs
- if grep -q ', IBRS_FW'
"/sys/devices/system/cpu/vulnerabilities/spectre_v2"; then
+ if echo "$fullmsg" | grep -q ', IBRS_FW'; then
_debug "ibrs: found IBRS_FW in sysfs"
[ -z "$ibrs_supported" ] &&
ibrs_supported='found IBRS_FW in sysfs'
ibrs_fw_enabled=1
fi
# when IBRS is enabled on 4.15+, we can see it
in sysfs
- if grep -q -e '\<IBRS\>' -e 'Indirect Branch
Restricted Speculation' "/sys/devices/system/cpu/vulnerabilities/spectre_v2";
then
+ if echo "$fullmsg" | grep -q -e '\<IBRS\>' -e
'Indirect Branch Restricted Speculation'; then
_debug "ibrs: found IBRS in sysfs"
[ -z "$ibrs_supported" ] &&
ibrs_supported='found IBRS in sysfs'
[ -z "$ibrs_enabled" ] &&
ibrs_enabled=3
@@ -3064,9 +3184,9 @@
#
# if there is "retpoline" in the file and NOT
"minimal", then it's full retpoline
# (works for vanilla and Red Hat variants)
- if [ "$opt_live" = 1 ] && [ -e
"/sys/devices/system/cpu/vulnerabilities/spectre_v2" ]; then
- if grep -qwi retpoline
/sys/devices/system/cpu/vulnerabilities/spectre_v2; then
- if grep -qwi minimal
/sys/devices/system/cpu/vulnerabilities/spectre_v2; then
+ if [ "$opt_live" = 1 ] && [ -n "$fullmsg" ]; then
+ if echo "$fullmsg" | grep -qwi retpoline; then
+ if echo "$fullmsg" | grep -qwi minimal;
then
retpoline_compiler=0
retpoline_compiler_reason="kernel reports minimal retpoline compilation"
else
@@ -3887,7 +4007,7 @@
status=UNK
sys_interface_available=0
msg=''
- if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/l1tf"
'^[^;]+'; then
+ 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
@@ -3908,8 +4028,8 @@
_info_nol "* PTE inversion enabled and active: "
if [ "$opt_live" = 1 ]; then
- if [ "$sys_interface_available" = 1 ]; then
- if grep -q 'Mitigation: PTE Inversion'
/sys/devices/system/cpu/vulnerabilities/l1tf; then
+ if [ -n "$fullmsg" ]; then
+ if echo "$fullmsg" | grep -q 'Mitigation: PTE
Inversion'; then
pstatus green YES
pteinv_active=1
else
@@ -3999,7 +4119,7 @@
status=UNK
sys_interface_available=0
msg=''
- if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/l1tf"
'VMX:.*' silent; then
+ if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/l1tf"
'.*' quiet; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
fi
@@ -4019,14 +4139,15 @@
has_vmm=0
if command -v pgrep >/dev/null 2>&1; then
# remove xenbus and xenwatch, also present
inside domU
- if pgrep qemu >/dev/null || pgrep kvm
>/dev/null || pgrep libvirtd >/dev/null || \
+ # 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 '/libvirtd' -e '/xenstored' -e
'/xenconsoled'; then
+ 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
@@ -4087,18 +4208,19 @@
_info_nol " * L1D flush enabled: "
if [ "$opt_live" = 1 ]; then
- if [ -r "/sys/devices/system/cpu/vulnerabilities/l1tf"
]; then
+ if [ -n "$fullmsg" ]; then
# vanilla: VMX: $l1dstatus, SMT $smtstatus
# Red Hat: VMX: SMT $smtstatus, L1D $l1dstatus
# $l1dstatus is one of
(auto|vulnerable|conditional cache flushes|cache flushes|EPT disabled|flush not
necessary)
# $smtstatus is one of (vulnerable|disabled)
- if grep -Eq '(VMX:|L1D) (EPT
disabled|vulnerable|flush not necessary)'
"/sys/devices/system/cpu/vulnerabilities/l1tf"; then
+ # can also just be "Not affected"
+ if echo "$fullmsg" | grep -Eq -e 'Not affected'
-e '(VMX:|L1D) (EPT disabled|vulnerable|flush not necessary)'; then
l1d_mode=0
pstatus yellow NO
- elif grep -Eq '(VMX:|L1D) conditional cache
flushes' "/sys/devices/system/cpu/vulnerabilities/l1tf"; then
+ elif echo "$fullmsg" | grep -Eq '(VMX:|L1D)
conditional cache flushes'; then
l1d_mode=1
pstatus green YES "conditional flushes"
- elif grep -Eq '(VMX:|L1D) cache flushes'
"/sys/devices/system/cpu/vulnerabilities/l1tf"; then
+ elif echo "$fullmsg" | grep -Eq '(VMX:|L1D)
cache flushes'; then
l1d_mode=2
pstatus green YES "unconditional
flushes"
else
@@ -4165,6 +4287,9 @@
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 [ "$fullmsg" = "Not affected" ]; then
+ # just in case a very recent kernel knows better than we do
+ pvulnstatus $cve OK "your kernel reported your CPU model as not
vulnerable"
elif [ "$has_vmm" = 0 ]; then
pvulnstatus $cve OK "this system is not running a hypervisor"
else
@@ -4280,7 +4405,114 @@
{
cve=$1
_info "\033[1;34m$cve aka '$(cve2name "$cve")'\033[0m"
+ if [ "$os" = Linux ]; then
+ check_mds_linux "$cve"
+ elif echo "$os" | grep -q BSD; then
+ check_mds_bsd "$cve"
+ else
+ _warn "Unsupported OS ($os)"
+ fi
+}
+
+check_mds_bsd()
+{
+ _info_nol "* Kernel supports using MD_CLEAR mitigation: "
+ if [ "$opt_live" = 1 ]; then
+ if sysctl hw.mds_disable >/dev/null 2>&1; then
+ pstatus green YES
+ kernel_md_clear=1
+ else
+ pstatus yellow NO
+ kernel_md_clear=0
+ fi
+ else
+ if command -v "strings" >/dev/null 2>&1; then
+ if strings /boot/kernel/kernel | grep -Fq
hw.mds_disable; then
+ pstatus green YES
+ kernel_md_clear=1
+ else
+ kernel_md_clear=0
+ pstatus yellow NO
+ fi
+ else
+ pstatus yellow UNKNOWN
+ fi
+ fi
+ _info_nol "* CPU Hyper-Threading (SMT) is disabled: "
+ if sysctl machdep.hyperthreading_allowed >/dev/null 2>&1; then
+ kernel_smt_allowed=$(sysctl -n machdep.hyperthreading_allowed
2>/dev/null)
+ if [ "$kernel_smt_allowed" = 1 ]; then
+ pstatus yellow NO
+ else
+ pstatus green YES
+ fi
+ else
+ pstatus yellow UNKNOWN "sysctl machdep.hyperthreading_allowed
doesn't exist"
+ fi
+
+ _info_nol "* Kernel mitigation is enabled: "
+ if [ "$kernel_md_clear" = 1 ]; then
+ kernel_mds_enabled=$(sysctl -n hw.mds_disable 2>/dev/null)
+ else
+ kernel_mds_enabled=0
+ fi
+ case "$kernel_mds_enabled" in
+ 0) pstatus yellow NO;;
+ 1) pstatus green YES "with microcode support";;
+ 2) pstatus green YES "software-only support (SLOW)";;
+ 3) pstatus green YES;;
+ *) pstatus yellow UNKNOWN "unknown value $kernel_mds_enabled"
+ esac
+
+ _info_nol "* Kernel mitigation is active: "
+ if [ "$kernel_md_clear" = 1 ]; then
+ kernel_mds_state=$(sysctl -n hw.mds_disable_state 2>/dev/null)
+ else
+ kernel_mds_state=inactive
+ fi
+ #
https://github.com/freebsd/freebsd/blob/master/sys/x86/x86/cpu_machdep.c#L953
+ case "$kernel_mds_state" in
+ inactive) pstatus yellow NO;;
+ VERW) pstatus green YES "with microcode support";;
+ software*) pstatus green YES "software-only support (SLOW)";;
+ *) pstatus yellow UNKNOWN
+ esac
+
+ if ! is_cpu_vulnerable "$cve"; then
+ pvulnstatus "$cve" OK "your CPU vendor reported your CPU model
as not vulnerable"
+ else
+ if [ "$cpuid_md_clear" = 1 ]; then
+ if [ "$kernel_md_clear" = 1 ]; then
+ if [ "$opt_live" = 1 ]; then
+ # mitigation must also be enabled
+ if [ "$kernel_mds_enabled" -ge 1 ]; then
+ if [ "$opt_paranoid" != 1 ] ||
[ "$kernel_smt_allowed" = 0 ]; then
+ pvulnstatus "$cve" OK
"Your microcode and kernel are both up to date for this mitigation, and
mitigation is enabled"
+ else
+ pvulnstatus "$cve" VULN
"Your microcode and kernel are both up to date for this mitigation, but your
must disable SMT (Hyper-Threading) for a complete mitigation"
+ fi
+ else
+ pvulnstatus "$cve" VULN "Your
microcode and kernel are both up to date for this mitigation, but the
mitigation is not active"
+ fi
+ else
+ pvulnstatus "$cve" OK "Your microcode
and kernel are both up to date for this mitigation"
+ fi
+ else
+ pvulnstatus "$cve" VULN "Your microcode
supports mitigation, but your kernel doesn't, upgrade it to mitigate the
vulnerability"
+ fi
+ else
+ if [ "$kernel_md_clear" = 1 ]; then
+ pvulnstatus "$cve" VULN "Your kernel supports
mitigation, but your CPU microcode also needs to be updated to mitigate the
vulnerability"
+ else
+ pvulnstatus "$cve" VULN "Neither your kernel or
your microcode support mitigation, upgrade both to mitigate the vulnerability"
+ fi
+ fi
+ fi
+}
+
+check_mds_linux()
+{
status=UNK
sys_interface_available=0
msg=''
@@ -4289,15 +4521,6 @@
sys_interface_available=1
fi
if [ "$opt_sysfs_only" != 1 ]; then
- _info_nol "* CPU supports the MD_CLEAR functionality: "
- if [ "$cpuid_md_clear" = 1 ]; then
- pstatus green YES
- elif [ "$cpuid_md_clear" = 0 ]; then
- pstatus yellow NO
- else
- pstatus yellow UNKNOWN "is cpuid module loaded?"
- fi
-
_info_nol "* Kernel supports using MD_CLEAR mitigation: "
kernel_md_clear=''
kernel_md_clear_can_tell=1
@@ -4326,7 +4549,7 @@
if [ "$opt_live" = 1 ] && [ "$sys_interface_available" = 1 ];
then
_info_nol "* Kernel mitigation is enabled and active: "
- if grep -qi ^mitigation
/sys/devices/system/cpu/vulnerabilities/mds; then
+ if echo "$fullmsg" | grep -qi ^mitigation; then
mds_mitigated=1
pstatus green YES
else
@@ -4334,7 +4557,7 @@
pstatus yellow NO
fi
_info_nol "* SMT is either mitigated or disabled: "
- if grep -Eq 'SMT (disabled|mitigated)'
/sys/devices/system/cpu/vulnerabilities/mds; then
+ if echo "$fullmsg" | grep -Eq 'SMT
(disabled|mitigated)'; then
mds_smt_mitigated=1
pstatus green YES
else
@@ -4382,7 +4605,7 @@
else
if [ "$opt_paranoid" = 1 ]; then
# in paranoid mode, we don't only need microcode +
kernel update, we also want SMT mitigation
- if grep -qF -e 'SMT mitigated' -e 'SMT disabled'
/sys/devices/system/cpu/vulnerabilities/mds; then
+ if echo "$fullmsg" | grep -qF -e 'SMT mitigated' -e
'SMT disabled'; then
pvulnstatus "$cve" OK "$fullmsg"
else
pvulnstatus "$cve" VULN "Your kernel and
microcode partially mitigate the vulnerability, but you must disable SMT
(Hyper-Threading) for a complete mitigation"
@@ -4417,15 +4640,40 @@
_warn "We're missing some kernel info (see -v), accuracy might be
reduced"
fi
-_vars=$(set | grep -Ev '^[A-Z_[:space:]]' | sort | tr "\n" '|')
+_vars=$(set | grep -Ev '^[A-Z_[:space:]]' | grep -v -F 'mockme=' | sort | tr
"\n" '|')
_debug "variables at end of script: $_vars"
+if [ -n "$mockme" ] && [ "$opt_mock" = 1 ]; then
+ if command -v "gzip" >/dev/null 2>&1; then
+ # not a useless use of cat: gzipping cpuinfo directly doesn't
work well
+ # shellcheck disable=SC2002
+ if command -v "base64" >/dev/null 2>&1; then
+ mock_cpuinfo="$(cat /proc/cpuinfo | gzip -c | base64
-w0)"
+ elif command -v "uuencode" >/dev/null 2>&1; then
+ mock_cpuinfo="$(cat /proc/cpuinfo | gzip -c | uuencode
-m - | grep -Fv 'begin-base64' | grep -Fxv -- '====' | tr -d "\n")"
+ fi
+ fi
+ if [ -n "$mock_cpuinfo" ]; then
+ mockme=$(printf "%b\n%b" "$mockme"
"SMC_MOCK_CPUINFO='$mock_cpuinfo'")
+ unset mock_cpuinfo
+ fi
+ _info ""
+ # shellcheck disable=SC2046
+ _warn "To mock this CPU, set those vars: "$(echo "$mockme" | sort -u)
+fi
+
if [ "$opt_explain" = 0 ]; then
_info "Need more detailed information about mitigation options? Use
--explain"
fi
_info "A false sense of security is worse than no security at all, see
--disclaimer"
+if [ "$mocked" = 1 ]; then
+ _info ""
+ _warn "One or several values have been mocked. This should only be done
when debugging/testing this script."
+ _warn "The results do NOT reflect the actual status of the system we're
running on."
+fi
+
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "nrpe" ]; then
if [ -n "$nrpe_vuln" ]; then
echo "Vulnerable:$nrpe_vuln"
@@ -4460,7 +4708,7 @@
# wget https://github.com/platomav/MCExtractor/raw/master/MCE.db
# sqlite3 MCE.db "select '%%% MCEDB v'||revision||' - '||strftime('%Y/%m/%d',
date, 'unixepoch') from MCE; select '#
I,0x'||cpuid||',0x'||version||','||max(yyyymmdd) from Intel group by cpuid
order by cpuid asc; select '# A,0x'||cpuid||',0x'||version||','||max(yyyymmdd)
from AMD group by cpuid order by cpuid asc"
-# %%% MCEDB v110 - 2019/05/11
+# %%% MCEDB v111 - 2019/05/18
# I,0x00000611,0x00000B27,19961218
# I,0x00000612,0x000000C6,19961210
# I,0x00000616,0x000000C6,19961210
@@ -4639,8 +4887,8 @@
# I,0x00030671,0x00000117,20130410
# I,0x00030672,0x0000022E,20140401
# I,0x00030673,0x00000326,20180110
-# I,0x00030678,0x00000837,20180125
-# I,0x00030679,0x0000090A,20180110
+# I,0x00030678,0x00000838,20190422
+# I,0x00030679,0x0000090C,20190423
# I,0x000306A0,0x00000007,20110407
# I,0x000306A2,0x0000000C,20110725
# I,0x000306A4,0x00000007,20110908
@@ -4678,8 +4926,8 @@
# I,0x000406A9,0x0000081F,20140812
# I,0x000406C1,0x0000010B,20140814
# I,0x000406C2,0x00000221,20150218
-# I,0x000406C3,0x00000367,20171225
-# I,0x000406C4,0x00000410,20180104
+# I,0x000406C3,0x00000368,20190423
+# I,0x000406C4,0x00000411,20190423
# I,0x000406D0,0x0000000E,20130612
# I,0x000406D8,0x0000012A,20180104
# I,0x000406E1,0x00000020,20141111
@@ -4694,8 +4942,8 @@
# I,0x00050653,0x01000146,20180824
# I,0x00050654,0x0200005E,20190402
# I,0x00050655,0x03000010,20181116
-# I,0x00050656,0x04000021,20190227
-# I,0x00050657,0x05000021,20190227
+# I,0x00050656,0x04000024,20190407
+# I,0x00050657,0x05000024,20190407
# I,0x00050661,0xF1000008,20150130
# I,0x00050662,0x0000001A,20190323
# I,0x00050663,0x07000017,20190323
@@ -4715,7 +4963,7 @@
# I,0x000506E3,0x000000CC,20190401
# I,0x000506E8,0x00000034,20160710
# I,0x000506F0,0x00000010,20160607
-# I,0x000506F1,0x0000002A,20190211
+# I,0x000506F1,0x0000002E,20190321
# I,0x00060660,0x0000000C,20160821
# I,0x00060661,0x0000000E,20170128
# I,0x00060662,0x00000022,20171129
@@ -4730,8 +4978,8 @@
# I,0x00080650,0x00000018,20180108
# I,0x000806E9,0x000000B4,20190401
# I,0x000806EA,0x000000B4,20190401
-# I,0x000806EB,0x000000AE,20190214
-# I,0x000806EC,0x000000B4,20190228
+# I,0x000806EB,0x000000B8,20190330
+# I,0x000806EC,0x000000B8,20190330
# I,0x000906E9,0x000000B4,20190401
# I,0x000906EA,0x000000B4,20190401
# I,0x000906EB,0x000000B4,20190401
@@ -4808,10 +5056,10 @@
# A,0x00800F12,0x08001230,20180804
# A,0x00800F82,0x0800820C,20190204
# A,0x00810F00,0x08100004,20161120
-# A,0x00810F10,0x08101013,20181129
+# A,0x00810F10,0x08101014,20190307
# A,0x00810F11,0x08101102,20181106
# A,0x00810F80,0x08108002,20180605
# A,0x00810F81,0x08108102,20180813
# A,0x00820F00,0x08200002,20180214
# A,0x00870F00,0x08700004,20181206
-# A,0x00870F10,0x0870100A,20190322
+# A,0x00870F10,0x08701011,20190415