mirror of
https://github.com/speed47/spectre-meltdown-checker.git
synced 2025-07-15 07:11:22 +02:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
fcc4ff4de2 | |||
0bd38ddda0 | |||
e83dc818cd | |||
d69ea67101 | |||
dfe0d10f2a | |||
58a5acfdbb | |||
ccb4dbef7c | |||
afbb26277f | |||
77b34d48c6 | |||
497efe6a82 | |||
62b46df4e7 | |||
7d1f269bed | |||
4f9ca803c8 | |||
5788cec18b |
@ -143,7 +143,7 @@ docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/m
|
||||
- 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
|
||||
|
||||
|
@ -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 @@ show_usage()
|
||||
|
||||
--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_no_hw=0
|
||||
opt_vmm=-1
|
||||
opt_explain=0
|
||||
opt_paranoid=0
|
||||
opt_mock=0
|
||||
|
||||
global_critical=0
|
||||
global_unknown=0
|
||||
@ -325,6 +327,14 @@ is_cpu_vulnerable()
|
||||
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 @@ is_cpu_vulnerable()
|
||||
[ -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 @@ is_cpu_vulnerable()
|
||||
[ -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 @@ is_cpu_vulnerable()
|
||||
[ -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 @@ is_cpu_mds_free()
|
||||
#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 @@ while [ -n "$1" ]; do
|
||||
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 @@ while [ -n "$1" ]; do
|
||||
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 @@ while [ -n "$1" ]; do
|
||||
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 @@ read_cpuid()
|
||||
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 @@ parse_cpu_details()
|
||||
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 @@ parse_cpu_details()
|
||||
# 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 @@ sys_interface_check()
|
||||
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 @@ number_of_cpus()
|
||||
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 @@ check_cpu()
|
||||
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 @@ check_cpu()
|
||||
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 @@ check_CVE_2017_5715_linux()
|
||||
# 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 @@ check_CVE_2017_5715_linux()
|
||||
#
|
||||
# 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 @@ check_CVE_2018_3620_linux()
|
||||
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 @@ check_CVE_2018_3620_linux()
|
||||
|
||||
_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 @@ check_CVE_2018_3646_linux()
|
||||
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 @@ check_CVE_2018_3646_linux()
|
||||
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 @@ check_CVE_2018_3646_linux()
|
||||
|
||||
_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 @@ check_CVE_2018_3646_linux()
|
||||
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 @@ check_mds()
|
||||
{
|
||||
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 @@ check_mds()
|
||||
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 @@ check_mds()
|
||||
|
||||
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 @@ check_mds()
|
||||
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 @@ check_mds()
|
||||
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 @@ if [ "$bad_accuracy" = 1 ]; then
|
||||
_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 @@ exit 0 # ok
|
||||
# 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 @@ exit 0 # ok
|
||||
# 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 @@ exit 0 # ok
|
||||
# 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 @@ exit 0 # ok
|
||||
# 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 @@ exit 0 # ok
|
||||
# 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 @@ exit 0 # ok
|
||||
# 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 @@ exit 0 # ok
|
||||
# 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
|
||||
|
Reference in New Issue
Block a user