mirror of
https://github.com/speed47/spectre-meltdown-checker.git
synced 2024-12-27 12:30:30 +01:00
feat: add --prefix-arch for cross-arch kernel inspection
This commit is contained in:
parent
4961f8327f
commit
2d993812ab
@ -50,6 +50,8 @@ show_usage()
|
|||||||
--no-sysfs Don't use the /sys interface even if present
|
--no-sysfs Don't use the /sys interface even if present
|
||||||
--sysfs-only Only use the /sys interface, don't run our own checks
|
--sysfs-only Only use the /sys interface, don't run our own checks
|
||||||
--coreos Special mode for CoreOS (use an ephemeral toolbox to inspect kernel)
|
--coreos Special mode for CoreOS (use an ephemeral toolbox to inspect kernel)
|
||||||
|
--arch-prefix PREFIX Specify a prefix for cross-inspecting a kernel of a different arch, for example "aarch64-linux-gnu-",
|
||||||
|
so that invoked tools such as objdump will be prefixed with this (i.e. aarch64-linux-gnu-objdump)
|
||||||
--batch text Produce machine readable output, this is the default if --batch is specified alone
|
--batch text Produce machine readable output, this is the default if --batch is specified alone
|
||||||
--batch json Produce JSON output formatted for Puppet, Ansible, Chef...
|
--batch json Produce JSON output formatted for Puppet, Ansible, Chef...
|
||||||
--batch nrpe Produce machine readable output formatted for NRPE
|
--batch nrpe Produce machine readable output formatted for NRPE
|
||||||
@ -114,6 +116,7 @@ opt_allvariants=1
|
|||||||
opt_no_sysfs=0
|
opt_no_sysfs=0
|
||||||
opt_sysfs_only=0
|
opt_sysfs_only=0
|
||||||
opt_coreos=0
|
opt_coreos=0
|
||||||
|
opt_arch_prefix=''
|
||||||
|
|
||||||
global_critical=0
|
global_critical=0
|
||||||
global_unknown=0
|
global_unknown=0
|
||||||
@ -392,6 +395,9 @@ while [ -n "$1" ]; do
|
|||||||
[ $ret -ne 0 ] && exit 255
|
[ $ret -ne 0 ] && exit 255
|
||||||
shift 2
|
shift 2
|
||||||
opt_live=0
|
opt_live=0
|
||||||
|
elif [ "$1" = "--arch-prefix" ]; then
|
||||||
|
opt_arch_prefix="$2"
|
||||||
|
shift 2
|
||||||
elif [ "$1" = "--live" ]; then
|
elif [ "$1" = "--live" ]; then
|
||||||
opt_live_explicit=1
|
opt_live_explicit=1
|
||||||
shift
|
shift
|
||||||
@ -556,7 +562,7 @@ vmlinux=''
|
|||||||
vmlinux_err=''
|
vmlinux_err=''
|
||||||
check_vmlinux()
|
check_vmlinux()
|
||||||
{
|
{
|
||||||
readelf -h "$1" >/dev/null 2>&1 && return 0
|
"${opt_arch_prefix}readelf" -h "$1" >/dev/null 2>&1 && return 0
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -995,9 +1001,9 @@ if [ "$bad_accuracy" = 1 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -e "$opt_kernel" ]; then
|
if [ -e "$opt_kernel" ]; then
|
||||||
if ! which readelf >/dev/null 2>&1; then
|
if ! which "${opt_arch_prefix}readelf" >/dev/null 2>&1; then
|
||||||
_debug "readelf not found"
|
_debug "readelf not found"
|
||||||
vmlinux_err="missing 'readelf' tool, please install it, usually it's in the 'binutils' package"
|
vmlinux_err="missing '${opt_arch_prefix}readelf' tool, please install it, usually it's in the 'binutils' package"
|
||||||
elif [ "$opt_sysfs_only" = 1 ]; then
|
elif [ "$opt_sysfs_only" = 1 ]; then
|
||||||
vmlinux_err='kernel image decompression skipped'
|
vmlinux_err='kernel image decompression skipped'
|
||||||
else
|
else
|
||||||
@ -1010,10 +1016,10 @@ fi
|
|||||||
if [ -z "$vmlinux" ] || [ ! -r "$vmlinux" ]; then
|
if [ -z "$vmlinux" ] || [ ! -r "$vmlinux" ]; then
|
||||||
[ -z "$vmlinux_err" ] && vmlinux_err="couldn't extract your kernel from $opt_kernel"
|
[ -z "$vmlinux_err" ] && vmlinux_err="couldn't extract your kernel from $opt_kernel"
|
||||||
else
|
else
|
||||||
vmlinux_version=$(strings "$vmlinux" 2>/dev/null | grep '^Linux version ' | head -1)
|
vmlinux_version=$("${opt_arch_prefix}strings" "$vmlinux" 2>/dev/null | grep '^Linux version ' | head -1)
|
||||||
if [ -z "$vmlinux_version" ]; then
|
if [ -z "$vmlinux_version" ]; then
|
||||||
# try harder with some kernels (such as Red Hat) that don't have ^Linux version before their version string
|
# try harder with some kernels (such as Red Hat) that don't have ^Linux version before their version string
|
||||||
vmlinux_version=$(strings "$vmlinux" 2>/dev/null | grep -E '^[[:alnum:]][^[:space:]]+ \([^[:space:]]+\) #[0-9]+ .+ (19|20)[0-9][0-9]$' | head -1)
|
vmlinux_version=$("${opt_arch_prefix}strings" "$vmlinux" 2>/dev/null | grep -E '^[[:alnum:]][^[:space:]]+ \([^[:space:]]+\) #[0-9]+ .+ (19|20)[0-9][0-9]$' | head -1)
|
||||||
fi
|
fi
|
||||||
if [ -n "$vmlinux_version" ]; then
|
if [ -n "$vmlinux_version" ]; then
|
||||||
# in live mode, check if the img we found is the correct one
|
# in live mode, check if the img we found is the correct one
|
||||||
@ -1292,7 +1298,7 @@ check_cpu()
|
|||||||
val=$ret
|
val=$ret
|
||||||
val_cap_msr=$capabilities
|
val_cap_msr=$capabilities
|
||||||
else
|
else
|
||||||
if [ "$ret" -eq "$val" -a "$capabilities" -eq "$val_cap_msr" ]; then
|
if [ "$ret" -eq "$val" ] && [ "$capabilities" -eq "$val_cap_msr" ]; then
|
||||||
continue
|
continue
|
||||||
else
|
else
|
||||||
cpu_mismatch=1
|
cpu_mismatch=1
|
||||||
@ -1361,7 +1367,7 @@ check_redhat_canonical_spectre()
|
|||||||
# if we were already called, don't do it again
|
# if we were already called, don't do it again
|
||||||
[ -n "$redhat_canonical_spectre" ] && return
|
[ -n "$redhat_canonical_spectre" ] && return
|
||||||
|
|
||||||
if ! which strings >/dev/null 2>&1; then
|
if ! which "${opt_arch_prefix}strings" >/dev/null 2>&1; then
|
||||||
redhat_canonical_spectre=-1
|
redhat_canonical_spectre=-1
|
||||||
elif [ -n "$vmlinux_err" ]; then
|
elif [ -n "$vmlinux_err" ]; then
|
||||||
redhat_canonical_spectre=-2
|
redhat_canonical_spectre=-2
|
||||||
@ -1370,7 +1376,7 @@ check_redhat_canonical_spectre()
|
|||||||
# let's use the same way than the official Red Hat detection script,
|
# let's use the same way than the official Red Hat detection script,
|
||||||
# and detect their specific variant2 patch. If it's present, it means
|
# and detect their specific variant2 patch. If it's present, it means
|
||||||
# that the variant1 patch is also present (both were merged at the same time)
|
# that the variant1 patch is also present (both were merged at the same time)
|
||||||
if strings "$vmlinux" | grep -qw noibrs && strings "$vmlinux" | grep -qw noibpb; then
|
if "${opt_arch_prefix}strings" "$vmlinux" | grep -qw noibrs && "${opt_arch_prefix}strings" "$vmlinux" | grep -qw noibpb; then
|
||||||
_debug "found redhat/canonical version of the variant2 patch (implies variant1)"
|
_debug "found redhat/canonical version of the variant2 patch (implies variant1)"
|
||||||
redhat_canonical_spectre=1
|
redhat_canonical_spectre=1
|
||||||
else
|
else
|
||||||
@ -1433,7 +1439,7 @@ check_variant1()
|
|||||||
_info_nol "* Kernel has the Red Hat/Ubuntu patch: "
|
_info_nol "* Kernel has the Red Hat/Ubuntu patch: "
|
||||||
check_redhat_canonical_spectre
|
check_redhat_canonical_spectre
|
||||||
if [ "$redhat_canonical_spectre" = -1 ]; then
|
if [ "$redhat_canonical_spectre" = -1 ]; then
|
||||||
pstatus yellow UNKNOWN "missing 'strings' tool, please install it, usually it's in the binutils package"
|
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}strings' tool, please install it, usually it's in the binutils package"
|
||||||
elif [ "$redhat_canonical_spectre" = -2 ]; then
|
elif [ "$redhat_canonical_spectre" = -2 ]; then
|
||||||
pstatus yellow UNKNOWN "couldn't check ($vmlinux_err)"
|
pstatus yellow UNKNOWN "couldn't check ($vmlinux_err)"
|
||||||
elif [ "$redhat_canonical_spectre" = 1 ]; then
|
elif [ "$redhat_canonical_spectre" = 1 ]; then
|
||||||
@ -1449,8 +1455,8 @@ check_variant1()
|
|||||||
if [ -n "$vmlinux_err" ]; then
|
if [ -n "$vmlinux_err" ]; then
|
||||||
pstatus yellow UNKNOWN "couldn't check ($vmlinux_err)"
|
pstatus yellow UNKNOWN "couldn't check ($vmlinux_err)"
|
||||||
else
|
else
|
||||||
if ! which objdump >/dev/null 2>&1; then
|
if ! which "${opt_arch_prefix}objdump" >/dev/null 2>&1; then
|
||||||
pstatus yellow UNKNOWN "missing 'objdump' tool, please install it, usually it's in the binutils package"
|
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package"
|
||||||
else
|
else
|
||||||
# here we disassemble the kernel and count the number of occurrences of the LFENCE opcode
|
# here we disassemble the kernel and count the number of occurrences of the LFENCE opcode
|
||||||
# in non-patched kernels, this has been empirically determined as being around 40-50
|
# in non-patched kernels, this has been empirically determined as being around 40-50
|
||||||
@ -1459,7 +1465,7 @@ check_variant1()
|
|||||||
# so let's push the threshold to 70.
|
# so let's push the threshold to 70.
|
||||||
# v0.33+: now only count lfence opcodes after a jump, way less error-prone
|
# v0.33+: now only count lfence opcodes after a jump, way less error-prone
|
||||||
# non patched kernel have between 0 and 20 matches, patched ones have at least 40-45
|
# non patched kernel have between 0 and 20 matches, patched ones have at least 40-45
|
||||||
nb_lfence=$(objdump -d "$vmlinux" | grep -w -B1 lfence | grep -Ewc 'jmp|jne|je')
|
nb_lfence=$("${opt_arch_prefix}objdump" -d "$vmlinux" | grep -w -B1 lfence | grep -Ewc 'jmp|jne|je')
|
||||||
if [ "$nb_lfence" -lt 30 ]; then
|
if [ "$nb_lfence" -lt 30 ]; then
|
||||||
pstatus red NO "only $nb_lfence jump-then-lfence instructions found, should be >= 30 (heuristic)"
|
pstatus red NO "only $nb_lfence jump-then-lfence instructions found, should be >= 30 (heuristic)"
|
||||||
else
|
else
|
||||||
@ -1716,9 +1722,9 @@ check_variant2()
|
|||||||
fi
|
fi
|
||||||
elif [ -n "$vmlinux" ]; then
|
elif [ -n "$vmlinux" ]; then
|
||||||
# look for the symbol
|
# look for the symbol
|
||||||
if which nm >/dev/null 2>&1; then
|
if which "${opt_arch_prefix}nm" >/dev/null 2>&1; then
|
||||||
# the proper way: use nm and look for the symbol
|
# the proper way: use nm and look for the symbol
|
||||||
if nm "$vmlinux" 2>/dev/null | grep -qw 'noretpoline_setup'; then
|
if "${opt_arch_prefix}nm" "$vmlinux" 2>/dev/null | grep -qw 'noretpoline_setup'; then
|
||||||
retpoline_compiler=1
|
retpoline_compiler=1
|
||||||
pstatus green YES "noretpoline_setup found in vmlinux symbols"
|
pstatus green YES "noretpoline_setup found in vmlinux symbols"
|
||||||
else
|
else
|
||||||
@ -1827,10 +1833,10 @@ check_variant3()
|
|||||||
# same as above but in case we don't have System.map and only vmlinux, look for the
|
# same as above but in case we don't have System.map and only vmlinux, look for the
|
||||||
# nopti option that is part of the patch (kernel command line option)
|
# nopti option that is part of the patch (kernel command line option)
|
||||||
kpti_can_tell=1
|
kpti_can_tell=1
|
||||||
if ! which strings >/dev/null 2>&1; then
|
if ! which "${opt_arch_prefix}strings" >/dev/null 2>&1; then
|
||||||
pstatus yellow UNKNOWN "missing 'strings' tool, please install it, usually it's in the binutils package"
|
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}strings' tool, please install it, usually it's in the binutils package"
|
||||||
else
|
else
|
||||||
if strings "$vmlinux" | grep -qw nopti; then
|
if "${opt_arch_prefix}strings" "$vmlinux" | grep -qw nopti; then
|
||||||
_debug "kpti_support: found nopti string in $vmlinux"
|
_debug "kpti_support: found nopti string in $vmlinux"
|
||||||
kpti_support=1
|
kpti_support=1
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user