feat: speed up kernel version detection

This commit is contained in:
Stéphane Lesimple 2018-03-25 13:42:06 +02:00
parent 0b8a09ec70
commit aa74315df4
1 changed files with 43 additions and 45 deletions

View File

@ -1198,19 +1198,17 @@ 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=$("${opt_arch_prefix}strings" "$vmlinux" 2>/dev/null | grep '^Linux version ' | head -1) # vanilla kernels have with ^Linux version
if [ -z "$vmlinux_version" ]; then # also 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 # and check for FreeBSD
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) vmlinux_version=$("${opt_arch_prefix}strings" "$vmlinux" 2>/dev/null | grep -E \
fi -e '^Linux version ' \
-e '^[[:alnum:]][^[:space:]]+ \([^[:space:]]+\) #[0-9]+ .+ (19|20)[0-9][0-9]$' \
-e '^FreeBSD [0-9]' | head -1)
if [ -z "$vmlinux_version" ]; then if [ -z "$vmlinux_version" ]; then
# try even harder with some kernels (such as ARM) that split the release (uname -r) and version (uname -v) in 2 adjacent strings # try even harder with some kernels (such as ARM) that split the release (uname -r) and version (uname -v) in 2 adjacent strings
vmlinux_version=$("${opt_arch_prefix}strings" "$vmlinux" 2>/dev/null | grep -E -B1 '^#[0-9]+ .+ (19|20)[0-9][0-9]$' | tr "\n" " ") vmlinux_version=$("${opt_arch_prefix}strings" "$vmlinux" 2>/dev/null | grep -E -B1 '^#[0-9]+ .+ (19|20)[0-9][0-9]$' | tr "\n" " ")
fi fi
if [ -z "$vmlinux_version" ]; then
# FreeBSD?
vmlinux_version=$("${opt_arch_prefix}strings" "$vmlinux" 2>/dev/null | grep -E '^FreeBSD [0-9]' | head -1)
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
if [ "$opt_live" = 1 ]; then if [ "$opt_live" = 1 ]; then
@ -1248,10 +1246,10 @@ sys_interface_check()
elif grep -qi '^vulnerable' "$1"; then elif grep -qi '^vulnerable' "$1"; then
# Vulnerable # Vulnerable
status=VULN status=VULN
pstatus red NO "kernel confirms your system is vulnerable" pstatus yellow NO "kernel confirms your system is vulnerable"
else else
status=UNK status=UNK
pstatus yellow UNKNOWN "unknown value reported by kernel" pstatus blue UNKNOWN "unknown value reported by kernel"
fi fi
msg=$(cat "$1") msg=$(cat "$1")
_debug "sys_interface_check: $1=$msg" _debug "sys_interface_check: $1=$msg"
@ -1333,7 +1331,7 @@ check_cpu()
fi fi
if [ ! -e /dev/cpu/0/msr ] && [ ! -e /dev/cpuctl0 ]; then if [ ! -e /dev/cpu/0/msr ] && [ ! -e /dev/cpuctl0 ]; then
spec_ctrl_msr=-1 spec_ctrl_msr=-1
pstatus yellow UNKNOWN "is msr kernel module available?" pstatus blue UNKNOWN "is msr kernel module available?"
else else
# the new MSR 'SPEC_CTRL' is at offset 0x48 # the new MSR 'SPEC_CTRL' is at offset 0x48
# here we use dd, it's the same as using 'rdmsr 0x48' but without needing the rdmsr tool # here we use dd, it's the same as using 'rdmsr 0x48' but without needing the rdmsr tool
@ -1364,7 +1362,7 @@ check_cpu()
fi fi
else else
spec_ctrl_msr=0 spec_ctrl_msr=0
pstatus red NO pstatus yellow NO
fi fi
fi fi
@ -1375,9 +1373,9 @@ check_cpu()
pstatus green YES "SPEC_CTRL feature bit" pstatus green YES "SPEC_CTRL feature bit"
cpuid_spec_ctrl=1 cpuid_spec_ctrl=1
elif [ $ret -eq 2 ]; then elif [ $ret -eq 2 ]; then
pstatus yellow UNKNOWN "is cpuid kernel module available?" pstatus blue UNKNOWN "is cpuid kernel module available?"
else else
pstatus red NO pstatus yellow NO
fi fi
# hardware support according to kernel # hardware support according to kernel
@ -1429,7 +1427,7 @@ check_cpu()
pstatus green YES "But not in all CPUs" pstatus green YES "But not in all CPUs"
fi fi
else else
pstatus red NO pstatus yellow NO
fi fi
fi fi
@ -1443,7 +1441,7 @@ check_cpu()
elif [ $ret -eq 2 ]; then elif [ $ret -eq 2 ]; then
pstatus yellow UNKNOWN "is cpuid kernel module available?" pstatus yellow UNKNOWN "is cpuid kernel module available?"
else else
pstatus red NO pstatus yellow NO
fi fi
# STIBP # STIBP
@ -1452,7 +1450,7 @@ check_cpu()
if [ "$spec_ctrl_msr" = 1 ]; then if [ "$spec_ctrl_msr" = 1 ]; then
pstatus green YES pstatus green YES
elif [ "$spec_ctrl_msr" = 0 ]; then elif [ "$spec_ctrl_msr" = 0 ]; then
pstatus red NO pstatus yellow NO
else else
pstatus yellow UNKNOWN "is cpuid kernel module available?" pstatus yellow UNKNOWN "is cpuid kernel module available?"
fi fi
@ -1465,7 +1463,7 @@ check_cpu()
elif [ $ret -eq 2 ]; then elif [ $ret -eq 2 ]; then
pstatus yellow UNKNOWN "is cpuid kernel module available?" pstatus yellow UNKNOWN "is cpuid kernel module available?"
else else
pstatus red NO pstatus yellow NO
fi fi
_info " * Enhanced IBRS (IBRS_ALL)" _info " * Enhanced IBRS (IBRS_ALL)"
@ -1479,7 +1477,7 @@ check_cpu()
elif [ $ret -eq 2 ]; then elif [ $ret -eq 2 ]; then
pstatus yellow UNKNOWN "is cpuid kernel module available?" pstatus yellow UNKNOWN "is cpuid kernel module available?"
else else
pstatus red NO pstatus yellow NO
cpuid_arch_capabilities=0 cpuid_arch_capabilities=0
fi fi
@ -1491,7 +1489,7 @@ check_cpu()
elif [ "$cpuid_arch_capabilities" != 1 ]; then elif [ "$cpuid_arch_capabilities" != 1 ]; then
capabilities_rdcl_no=0 capabilities_rdcl_no=0
capabilities_ibrs_all=0 capabilities_ibrs_all=0
pstatus red NO pstatus yellow NO
elif [ ! -e /dev/cpu/0/msr ] && [ ! -e /dev/cpuctl0 ]; then elif [ ! -e /dev/cpu/0/msr ] && [ ! -e /dev/cpuctl0 ]; then
spec_ctrl_msr=-1 spec_ctrl_msr=-1
pstatus yellow UNKNOWN "is msr kernel module available?" pstatus yellow UNKNOWN "is msr kernel module available?"
@ -1532,7 +1530,7 @@ check_cpu()
pstatus green YES "But not in all CPUs" pstatus green YES "But not in all CPUs"
fi fi
else else
pstatus red NO pstatus yellow NO
fi fi
else else
pstatus yellow UNKNOWN pstatus yellow UNKNOWN
@ -1659,7 +1657,7 @@ check_variant1_linux()
pstatus green YES "$ret occurence(s) found of 32 bits array_index_mask_nospec()" pstatus green YES "$ret occurence(s) found of 32 bits array_index_mask_nospec()"
v1_mask_nospec=1 v1_mask_nospec=1
else else
pstatus red NO pstatus yellow NO
fi fi
fi fi
fi fi
@ -1675,7 +1673,7 @@ check_variant1_linux()
elif [ "$redhat_canonical_spectre" = 2 ]; then elif [ "$redhat_canonical_spectre" = 2 ]; then
pstatus green YES "but without IBRS" pstatus green YES "but without IBRS"
else else
pstatus red NO pstatus yellow NO
fi fi
if [ "$opt_verbose" -ge 2 ] || ( [ "$v1_mask_nospec" != 1 ] && [ "$redhat_canonical_spectre" != 1 ] && [ "$redhat_canonical_spectre" != 2 ] ); then if [ "$opt_verbose" -ge 2 ] || ( [ "$v1_mask_nospec" != 1 ] && [ "$redhat_canonical_spectre" != 1 ] && [ "$redhat_canonical_spectre" != 2 ] ); then
@ -1697,7 +1695,7 @@ check_variant1_linux()
# 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=$("${opt_arch_prefix}objdump" -d "$vmlinux" 2>/dev/null | grep -w -B1 lfence | grep -Ewc 'jmp|jne|je') nb_lfence=$("${opt_arch_prefix}objdump" -d "$vmlinux" 2>/dev/null | 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 yellow NO "only $nb_lfence jump-then-lfence instructions found, should be >= 30 (heuristic)"
else else
v1_lfence=1 v1_lfence=1
pstatus green YES "$nb_lfence jump-then-lfence instructions found, which is >= 30 (heuristic)" pstatus green YES "$nb_lfence jump-then-lfence instructions found, which is >= 30 (heuristic)"
@ -1840,7 +1838,7 @@ check_variant2_linux()
fi fi
if [ "$ibrs_supported" != 1 ]; then if [ "$ibrs_supported" != 1 ]; then
if [ "$ibrs_can_tell" = 1 ]; then if [ "$ibrs_can_tell" = 1 ]; then
pstatus red NO pstatus yellow NO
else else
# if we're in offline mode without System.map, we can't really know # if we're in offline mode without System.map, we can't really know
pstatus yellow UNKNOWN "in offline mode, we need System.map to be able to tell" pstatus yellow UNKNOWN "in offline mode, we need System.map to be able to tell"
@ -1862,11 +1860,11 @@ check_variant2_linux()
if [ "$ibrs_supported" = 1 ]; then if [ "$ibrs_supported" = 1 ]; then
pstatus yellow UNKNOWN pstatus yellow UNKNOWN
else else
pstatus red NO pstatus yellow NO
fi fi
;; ;;
0) 0)
pstatus red NO pstatus yellow NO
_verbose " - To enable, \`echo 1 > $ibrs_knob_dir/ibrs_enabled' as root. If you don't have hardware support, you'll get an error." _verbose " - To enable, \`echo 1 > $ibrs_knob_dir/ibrs_enabled' as root. If you don't have hardware support, you'll get an error."
;; ;;
1 | 2) pstatus green YES;; 1 | 2) pstatus green YES;;
@ -1888,11 +1886,11 @@ check_variant2_linux()
if [ "$ibrs_supported" = 1 ]; then if [ "$ibrs_supported" = 1 ]; then
pstatus yellow UNKNOWN pstatus yellow UNKNOWN
else else
pstatus red NO pstatus yellow NO
fi fi
;; ;;
0 | 1) 0 | 1)
pstatus red NO pstatus yellow NO
_verbose " - To enable, \`echo 2 > $ibrs_knob_dir/ibrs_enabled' as root. If you don't have hardware support, you'll get an error." _verbose " - To enable, \`echo 2 > $ibrs_knob_dir/ibrs_enabled' as root. If you don't have hardware support, you'll get an error."
;; ;;
2) pstatus green YES;; 2) pstatus green YES;;
@ -1910,11 +1908,11 @@ check_variant2_linux()
if [ "$ibrs_supported" = 1 ]; then if [ "$ibrs_supported" = 1 ]; then
pstatus yellow UNKNOWN pstatus yellow UNKNOWN
else else
pstatus red NO pstatus yellow NO
fi fi
;; ;;
0) 0)
pstatus red NO pstatus yellow NO
_verbose " - To enable, \`echo 1 > $ibrs_knob_dir/ibpb_enabled' as root. If you don't have hardware support, you'll get an error." _verbose " - To enable, \`echo 1 > $ibrs_knob_dir/ibpb_enabled' as root. If you don't have hardware support, you'll get an error."
;; ;;
1) pstatus green YES;; 1) pstatus green YES;;
@ -1935,7 +1933,7 @@ check_variant2_linux()
# shellcheck disable=SC2046 # shellcheck disable=SC2046
_debug 'retpoline: found '$(grep '^CONFIG_RETPOLINE' "$opt_config")" in $opt_config" _debug 'retpoline: found '$(grep '^CONFIG_RETPOLINE' "$opt_config")" in $opt_config"
else else
pstatus red NO pstatus yellow NO
fi fi
else else
pstatus yellow UNKNOWN "couldn't read your kernel configuration" pstatus yellow UNKNOWN "couldn't read your kernel configuration"
@ -1949,7 +1947,7 @@ check_variant2_linux()
# *AND* if the compiler is retpoline-compliant, so look for that symbol # *AND* if the compiler is retpoline-compliant, so look for that symbol
if [ -e "/sys/devices/system/cpu/vulnerabilities/spectre_v2" ]; then if [ -e "/sys/devices/system/cpu/vulnerabilities/spectre_v2" ]; then
if grep -qw Minimal /sys/devices/system/cpu/vulnerabilities/spectre_v2; then if grep -qw Minimal /sys/devices/system/cpu/vulnerabilities/spectre_v2; then
pstatus red NO "kernel reports minimal retpoline compilation" pstatus yellow NO "kernel reports minimal retpoline compilation"
elif grep -qw Full /sys/devices/system/cpu/vulnerabilities/spectre_v2; then elif grep -qw Full /sys/devices/system/cpu/vulnerabilities/spectre_v2; then
retpoline_compiler=1 retpoline_compiler=1
pstatus green YES "kernel reports full retpoline compilation" pstatus green YES "kernel reports full retpoline compilation"
@ -1957,7 +1955,7 @@ check_variant2_linux()
if [ "$retpoline" = 1 ]; then if [ "$retpoline" = 1 ]; then
pstatus yellow UNKNOWN pstatus yellow UNKNOWN
else else
pstatus red NO pstatus yellow NO
fi fi
fi fi
elif [ -n "$opt_map" ]; then elif [ -n "$opt_map" ]; then
@ -1969,7 +1967,7 @@ check_variant2_linux()
if [ "$retpoline" = 1 ]; then if [ "$retpoline" = 1 ]; then
pstatus yellow UNKNOWN pstatus yellow UNKNOWN
else else
pstatus red NO pstatus yellow NO
fi fi
fi fi
elif [ -n "$vmlinux" ]; then elif [ -n "$vmlinux" ]; then
@ -1983,7 +1981,7 @@ check_variant2_linux()
if [ "$retpoline" = 1 ]; then if [ "$retpoline" = 1 ]; then
pstatus yellow UNKNOWN pstatus yellow UNKNOWN
else else
pstatus red NO pstatus yellow NO
fi fi
fi fi
elif grep -q noretpoline_setup "$vmlinux"; then elif grep -q noretpoline_setup "$vmlinux"; then
@ -1995,14 +1993,14 @@ check_variant2_linux()
if [ "$retpoline" = 1 ]; then if [ "$retpoline" = 1 ]; then
pstatus yellow UNKNOWN pstatus yellow UNKNOWN
else else
pstatus red NO pstatus yellow NO
fi fi
fi fi
else else
if [ "$retpoline" = 1 ]; then if [ "$retpoline" = 1 ]; then
pstatus yellow UNKNOWN "couldn't find your kernel image or System.map" pstatus yellow UNKNOWN "couldn't find your kernel image or System.map"
else else
pstatus red NO pstatus yellow NO
fi fi
fi fi
elif [ "$sys_interface_available" = 0 ]; then elif [ "$sys_interface_available" = 0 ]; then
@ -2052,7 +2050,7 @@ check_variant2_bsd()
_info_nol "* Kernel supports IBRS: " _info_nol "* Kernel supports IBRS: "
ibrs_disabled=$(sysctl -n hw.ibrs_disable 2>/dev/null) ibrs_disabled=$(sysctl -n hw.ibrs_disable 2>/dev/null)
if [ -z "$ibrs_disabled" ]; then if [ -z "$ibrs_disabled" ]; then
pstatus red NO pstatus yellow NO
else else
pstatus green YES pstatus green YES
fi fi
@ -2062,7 +2060,7 @@ check_variant2_bsd()
if [ "$ibrs_active" = 1 ]; then if [ "$ibrs_active" = 1 ]; then
pstatus green YES pstatus green YES
else else
pstatus red NO pstatus yellow NO
fi fi
cve='CVE-2017-5715' cve='CVE-2017-5715'
@ -2141,7 +2139,7 @@ check_variant3_linux()
if [ "$kpti_support" = 1 ]; then if [ "$kpti_support" = 1 ]; then
pstatus green YES pstatus green YES
elif [ "$kpti_can_tell" = 1 ]; then elif [ "$kpti_can_tell" = 1 ]; then
pstatus red NO pstatus yellow NO
else else
pstatus yellow UNKNOWN "couldn't read your kernel configuration nor System.map file" pstatus yellow UNKNOWN "couldn't read your kernel configuration nor System.map file"
fi fi
@ -2184,7 +2182,7 @@ check_variant3_linux()
elif [ "$kpti_enabled" = -1 ]; then elif [ "$kpti_enabled" = -1 ]; then
pstatus yellow UNKNOWN "dmesg truncated, please reboot and relaunch this script" pstatus yellow UNKNOWN "dmesg truncated, please reboot and relaunch this script"
else else
pstatus red NO pstatus yellow NO
fi fi
else else
pstatus blue N/A "can't verify if PTI is enabled in offline mode" pstatus blue N/A "can't verify if PTI is enabled in offline mode"
@ -2302,7 +2300,7 @@ check_variant3_bsd()
_info_nol "* Kernel supports Page Table Isolation (PTI): " _info_nol "* Kernel supports Page Table Isolation (PTI): "
kpti_enabled=$(sysctl -n vm.pmap.pti 2>/dev/null) kpti_enabled=$(sysctl -n vm.pmap.pti 2>/dev/null)
if [ -z "$kpti_enabled" ]; then if [ -z "$kpti_enabled" ]; then
pstatus red NO pstatus yellow NO
else else
pstatus green YES pstatus green YES
fi fi
@ -2311,7 +2309,7 @@ check_variant3_bsd()
if [ "$kpti_enabled" = 1 ]; then if [ "$kpti_enabled" = 1 ]; then
pstatus green YES pstatus green YES
else else
pstatus red NO pstatus yellow NO
fi fi
cve='CVE-2017-5754' cve='CVE-2017-5754'