10 Commits
v0.13 ... v0.14

Author SHA1 Message Date
206e4b7fbc add detection of retpoline-aware compiler 2018-01-08 16:28:00 +01:00
207168e097 detect if the used compiler supports retpoline (WIP) 2018-01-08 15:45:09 +01:00
f8ca11e56a Merge pull request #12 from sebastianw/fix-double-print
Remove superfluous 'YES' output when checking cpuinfo
2018-01-08 15:05:15 +01:00
c88acdd31d Remove superfluous 'YES' output when checking cpuinfo 2018-01-08 14:50:59 +01:00
88df48f4a7 Merge pull request #11 from sebastianw/kaiser-cpu-flag
Recognize 'kaiser' flag in /proc/cpuinfo
2018-01-08 14:45:40 +01:00
124ce8e27a Recognize 'kaiser' flag in /proc/cpuinfo 2018-01-08 14:38:43 +01:00
7bbcfe0df7 Merge pull request #7 from Feandil/redhat
Redhat support
2018-01-08 14:17:33 +01:00
a792348928 RedHat uses a different configuration name 2018-01-08 12:59:12 +01:00
66f7708095 Refactor RedHat support:
- Isolate file check to different elif (allowing to add more)
- Do the PTI debugfs check first (faster and supposed to be dynamic)
- If pti_enable is 0, don't trust dmesg (supposed to be dynamic)
2018-01-08 12:59:03 +01:00
34ef5ef21b Delay umount (for RedHat access to pti_enable) 2018-01-08 12:58:22 +01:00

View File

@ -1,7 +1,7 @@
#! /bin/sh #! /bin/sh
# Spectre & Meltdown checker # Spectre & Meltdown checker
# Stephane Lesimple # Stephane Lesimple
VERSION=0.13 VERSION=0.14
# print status function # print status function
pstatus() pstatus()
@ -171,15 +171,20 @@ if [ ! -e /sys/kernel/debug/sched_features ]; then
# try to mount the debugfs hierarchy ourselves and remember it to umount afterwards # try to mount the debugfs hierarchy ourselves and remember it to umount afterwards
mount -t debugfs debugfs /sys/kernel/debug 2>/dev/null && mounted_debugfs=1 mount -t debugfs debugfs /sys/kernel/debug 2>/dev/null && mounted_debugfs=1
fi fi
if [ -e /sys/kernel/debug/ibrs_enabled -o -e /sys/kernel/debug/x86/ibrs_enabled ]; then if [ -e /sys/kernel/debug/ibrs_enabled ]; then
# if the file is there, we have IBRS compiled-in # if the file is there, we have IBRS compiled-in
pstatus green YES pstatus green YES
ibrs_supported=1 ibrs_supported=1
ibrs_enabled=$(cat /sys/kernel/debug/ibrs_enabled 2>/dev/null)
elif [ -e /sys/kernel/debug/x86/ibrs_enabled ]; then
# RedHat uses a different path (see https://access.redhat.com/articles/3311301)
pstatus green YES
ibrs_supported=1
ibrs_enabled=$(cat /sys/kernel/debug/x86/ibrs_enabled 2>/dev/null)
else else
pstatus red NO pstatus red NO
fi fi
[ -f /sys/kernel/debug/ibrs_enabled ] && ibrs_enabled=$(cat /sys/kernel/debug/ibrs_enabled 2>/dev/null) || ibrs_enabled=$(cat /sys/kernel/debug/x86/ibrs_enabled 2>/dev/null)
/bin/echo -n "* IBRS enabled for Kernel space: " /bin/echo -n "* IBRS enabled for Kernel space: "
# 0 means disabled # 0 means disabled
# 1 is enabled only for kernel space # 1 is enabled only for kernel space
@ -196,19 +201,12 @@ case "$ibrs_enabled" in
"") [ "$ibrs_supported" = 1 ] && pstatus yellow UNKNOWN || pstatus red NO;; "") [ "$ibrs_supported" = 1 ] && pstatus yellow UNKNOWN || pstatus red NO;;
0 | 1) pstatus red NO;; 0 | 1) pstatus red NO;;
2) pstatus green YES;; 2) pstatus green YES;;
*) pstatus yellow unknown;; *) pstatus yellow UNKNOWN;;
esac esac
if [ "$mounted_debugfs" = 1 ]; then
# umount debugfs if we did mount it ourselves
umount /sys/kernel/debug
fi
/bin/echo "* Mitigation 2" /bin/echo "* Mitigation 2"
/bin/echo -n "* Kernel compiled with retpolines: " /bin/echo -n "* Kernel compiled with retpoline option: "
# We check the RETPOLINE kernel options # We check the RETPOLINE kernel options
# XXX this doesn't mean the kernel has been compiled with a retpoline-aware gcc
# still looking for a way do detect that ...
if [ -e /proc/config.gz ]; then if [ -e /proc/config.gz ]; then
# either the running kernel exports his own config # either the running kernel exports his own config
if zgrep -q '^CONFIG_RETPOLINE=y' /proc/config.gz; then if zgrep -q '^CONFIG_RETPOLINE=y' /proc/config.gz; then
@ -229,15 +227,71 @@ else
pstatus yellow UNKNOWN "couldn't read your kernel configuration" pstatus yellow UNKNOWN "couldn't read your kernel configuration"
fi fi
/bin/echo -n "* Kernel compiled with a retpoline-aware compiler: "
# Now check if the compiler used to compile the kernel knows how to insert retpolines in generated asm
# For gcc, this is -mindirect-branch=thunk-extern (detected by the kernel makefiles)
# See gcc commit https://github.com/hjl-tools/gcc/commit/23b517d4a67c02d3ef80b6109218f2aadad7bd79
# We'll look for the presence of 'retpoline_call_target' in symbols
if [ -n "$vmlinux" ]; then
# look for the symbol
if which nm >/dev/null 2>&1; then
# the proper way: use nm and look for the symbol
if nm "$vmlinux" 2>/dev/null | grep -qw retpoline_call_target; then
retpoline_compiler=1
pstatus green YES "retpoline_call_target found"
fi
else
# if we don't have nm, nevermind, the symbol name is long enough to not have
# any false positive using good old grep directly on the binary
if grep -q retpoline_call_target "$vmlinux"; then
retpoline_compiler=1
pstatus green YES "retpoline_call_target found"
fi
fi
if [ "$retpoline_compiler" != 1 ]; then
# still not ? maybe we just don't have symbols in the kernel image (stripped)
# let's objdump it and look for the asm sequence (here for 64 bits)
#
# ffffffff81000350 <__x86.indirect_thunk>:
# ffffffff81000350: e8 05 00 00 00 callq ffffffff8100035a <retpoline_call_target>
# ffffffff81000355: 0f ae e8 lfence
# ffffffff81000358: eb fb jmp ffffffff81000355 <__x86.indirect_thunk+0x5>
# ffffffff8100035a <retpoline_call_target>:
# ffffffff8100035a: 48 8d 64 24 08 lea 0x8(%rsp),%rsp
# ffffffff8100035f: c3 retq
#
if ! which perl >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing 'perl', please install it"
else
# directly look for the opcode sequence in the binary
# 64 bits version
if perl -ne '/\xe8\x05\x00\x00\x00\x0f\xae\xe8\xeb\xfb\x48\x8d\x64\x24\x08\xc3/ and $found=1; END { exit($found ? 0 : 1) }' "$vmlinux"; then
retpoline_compiler=1
pstatus green YES "retpoline 64 bits asm sequence found"
#elif perl -ne ... 32 bits version of retpoline asm seq
# TODO
# retpoline_compiler=1
# pstatus green YES "retpoline 33 bits asm sequence found"
else
pstatus red NO
fi
fi
fi
else
pstatus yellow UNKNOWN "couldn't find your kernel image"
fi
/bin/echo -ne "> \033[46m\033[30mSTATUS:\033[0m " /bin/echo -ne "> \033[46m\033[30mSTATUS:\033[0m "
if grep -q AMD /proc/cpuinfo; then if grep -q AMD /proc/cpuinfo; then
pstatus green "NOT VULNERABLE" "your CPU is not vulnerable as per the vendor" pstatus green "NOT VULNERABLE" "your CPU is not vulnerable as per the vendor"
elif [ "$ibrs_enabled" = 1 -o "$ibrs_enabled" = 2 ]; then elif [ "$ibrs_enabled" = 1 -o "$ibrs_enabled" = 2 ]; then
pstatus green "NOT VULNERABLE" "IBRS mitigates the vulnerability" pstatus green "NOT VULNERABLE" "IBRS mitigates the vulnerability"
elif [ "$retpoline" = 1 ]; then elif [ "$retpoline" = 1 -a "$retpoline_compiler" = 1 ]; then
pstatus green "NOT VULNERABLE" "retpolines mitigate the vulnerability" pstatus green "NOT VULNERABLE" "retpoline mitigate the vulnerability"
else else
pstatus red VULNERABLE "IBRS hardware + kernel support OR kernel with retpolines are needed to mitigate the vulnerability" pstatus red VULNERABLE "IBRS hardware + kernel support OR kernel with retpoline are needed to mitigate the vulnerability"
fi fi
########## ##########
@ -250,13 +304,13 @@ kpti_can_tell=0
if [ -e /proc/config.gz ]; then if [ -e /proc/config.gz ]; then
# either the running kernel exports his own config # either the running kernel exports his own config
kpti_can_tell=1 kpti_can_tell=1
if zgrep -q '^CONFIG_PAGE_TABLE_ISOLATION=y' /proc/config.gz; then if zgrep -q '^\(CONFIG_PAGE_TABLE_ISOLATION=y\|CONFIG_KAISER=y\)' /proc/config.gz; then
kpti_support=1 kpti_support=1
fi fi
elif [ -e /boot/config-$(uname -r) ]; then elif [ -e /boot/config-$(uname -r) ]; then
# or we can find a config file in /root with the kernel release name # or we can find a config file in /root with the kernel release name
kpti_can_tell=1 kpti_can_tell=1
if grep -q '^CONFIG_PAGE_TABLE_ISOLATION=y' /boot/config-$(uname -r); then if grep -q '^\(CONFIG_PAGE_TABLE_ISOLATION=y\|CONFIG_KAISER=y\)' /boot/config-$(uname -r); then
kpti_support=1 kpti_support=1
fi fi
fi fi
@ -288,19 +342,30 @@ fi
/bin/echo -n "* PTI enabled and active: " /bin/echo -n "* PTI enabled and active: "
if grep ^flags /proc/cpuinfo | grep -qw pti; then if grep ^flags /proc/cpuinfo | grep -qw pti; then
# vanilla PTI patch sets the 'pti' flag in cpuinfo # vanilla PTI patch sets the 'pti' flag in cpuinfo
pstatus green YES
kpti_enabled=1 kpti_enabled=1
elif grep ^flags /proc/cpuinfo | grep -qw kaiser; then
# kernel line 4.9 sets the 'kaiser' flag in cpuinfo
kpti_enabled=1
elif [ -e /sys/kernel/debug/x86/pti_enabled ]; then
# RedHat Backport creates a dedicated file, see https://access.redhat.com/articles/3311301
kpti_enabled=$(cat /sys/kernel/debug/x86/pti_enabled 2>/dev/null)
elif dmesg | grep -Eq 'Kernel/User page tables isolation: enabled|Kernel page table isolation enabled'; then elif dmesg | grep -Eq 'Kernel/User page tables isolation: enabled|Kernel page table isolation enabled'; then
# if we can't find the flag, grep in dmesg # if we can't find the flag, grep in dmesg
pstatus green YES
kpti_enabled=1
elif [ -e /sys/kernel/debug/x86/pti_enabled -a "$(cat /sys/kernel/debug/x86/pti_enabled 2>/dev/null)" = 1 ]; then
pstatus green YES
kpti_enabled=1 kpti_enabled=1
else
kpti_enabled=0
fi
if [ "$kpti_enabled" = 1 ]; then
pstatus green YES
else else
pstatus red NO pstatus red NO
fi fi
if [ "$mounted_debugfs" = 1 ]; then
# umount debugfs if we did mount it ourselves
umount /sys/kernel/debug
fi
/bin/echo -ne "> \033[46m\033[30mSTATUS:\033[0m " /bin/echo -ne "> \033[46m\033[30mSTATUS:\033[0m "
if grep -q AMD /proc/cpuinfo; then if grep -q AMD /proc/cpuinfo; then
pstatus green "NOT VULNERABLE" "your CPU is not vulnerable as per the vendor" pstatus green "NOT VULNERABLE" "your CPU is not vulnerable as per the vendor"