From 6111de54355bed2514e851a48575006f64ad52db Mon Sep 17 00:00:00 2001 From: Oleksandr Bazhaniuk Date: Tue, 6 Feb 2018 11:37:02 -0800 Subject: [PATCH] Check MSR in each CPU/Thread --- spectre-meltdown-checker.sh | 120 ++++++++++++++++++++++++++++++++---- 1 file changed, 109 insertions(+), 11 deletions(-) diff --git a/spectre-meltdown-checker.sh b/spectre-meltdown-checker.sh index 654f4db..ef46f5f 100755 --- a/spectre-meltdown-checker.sh +++ b/spectre-meltdown-checker.sh @@ -1041,6 +1041,38 @@ sys_interface_check() return 0 } +number_of_cpus() +{ + n=$(cat /proc/cpuinfo | grep processor| wc -l) + return $n +} + +# $1 - msr number +# $2 - cpu index +check_msr_enable() +{ + dd if=/dev/cpu/$2/msr of=/dev/null bs=8 count=1 skip=$1 iflag=skip_bytes 2>/dev/null; ret=$? + return $ret +} + +# $1 - msr number +# $2 - cpu index +# $3 - value +write_to_msr() +{ + $echo_cmd -ne $3 | dd of=/dev/cpu/$2/msr bs=8 count=1 seek=$1 oflag=seek_bytes 2>/dev/null; ret=$? + return $ret +} + +# $1 - msr number +# $2 - cpu index +read_msr() +{ + msr=$(dd if=/dev/cpu/$2/msr bs=8 count=1 skip=$1 iflag=skip_bytes 2>/dev/null | od -t u1 -A n | awk '{print $8}'); + return msr +} + + check_cpu() { _info "\033[1;34mHardware check\033[0m" @@ -1048,6 +1080,9 @@ check_cpu() _info "* Hardware support (CPU microcode) for mitigation techniques" _info " * Indirect Branch Restricted Speculation (IBRS)" _info_nol " * SPEC_CTRL MSR is available: " + number_of_cpus + ncpus=$? + idx_max_cpu=$(($ncpus-1)) if [ ! -e /dev/cpu/0/msr ]; then # try to load the module ourselves (and remember it so we can rmmod it afterwards) load_msr @@ -1060,10 +1095,30 @@ check_cpu() # here we use dd, it's the same as using 'rdmsr 0x48' but without needing the rdmsr tool # if we get a read error, the MSR is not there. bs has to be 8 for msr # skip=9 because 8*9=72=0x48 - dd if=/dev/cpu/0/msr of=/dev/null bs=8 count=1 skip=9 2>/dev/null; ret=$? - if [ $ret -eq 0 ]; then - spec_ctrl_msr=1 - pstatus green YES + val=0 + cpu_mismatch=0 + for i in $(seq 0 $idx_max_cpu) + do + check_msr_enable 72 $i + ret=$? + if [ $i -eq 0 ]; then + val=$ret + else + if [ $ret -eq $val ]; then + continue + else + cpu_mismatch=1 + fi + fi + done + if [ $val -eq 0 ]; then + if [ $cpu_mismatch -eq 0 ]; then + spec_ctrl_msr=1 + pstatus green YES + else + spec_ctrl_msr=1 + pstatus green YES "(But not in all CPUs)" + fi else spec_ctrl_msr=0 pstatus red NO @@ -1108,15 +1163,34 @@ check_cpu() # the new MSR 'PRED_CTRL' is at offset 0x49, write-only # here we use dd, it's the same as using 'wrmsr 0x49 0' but without needing the wrmsr tool # if we get a write error, the MSR is not there - $echo_cmd -ne "\0\0\0\0\0\0\0\0" | dd of=/dev/cpu/0/msr bs=8 count=1 seek=73 oflag=seek_bytes 2>/dev/null; ret=$? - if [ $ret -eq 0 ]; then - pstatus green YES + val=0 + cpu_mismatch=0 + for i in $(seq 0 $idx_max_cpu) + do + write_to_msr 73 $i "\0\0\0\0\0\0\0\0" + ret=$? + if [ $i -eq 0 ]; then + val=$ret + else + if [ $ret -eq $val ]; then + continue + else + cpu_mismatch=1 + fi + fi + done + + if [ $val -eq 0 ]; then + if [ $cpu_mismatch -eq 0 ]; then + pstatus green YES + else + pstatus green YES "(But not in all CPUs)" + fi else pstatus red NO fi fi - _info_nol " * CPU indicates IBPB capability: " # CPUID EAX=0x80000008, ECX=0x00 return EBX[12] indicates support for just IBPB. read_cpuid 2147483656 5 16; ret=$? @@ -1183,16 +1257,40 @@ check_cpu() # the new MSR 'ARCH_CAPABILITIES' is at offset 0x10a # here we use dd, it's the same as using 'rdmsr 0x10a' but without needing the rdmsr tool # if we get a read error, the MSR is not there. bs has to be 8 for msr - capabilities=$(dd if=/dev/cpu/0/msr bs=8 count=1 skip=266 iflag=skip_bytes 2>/dev/null | od -t u1 -A n | awk '{print $8}'); ret=$? + val=0 + val_cap_msr=0 + cpu_mismatch=0 + for i in $(seq 0 $idx_max_cpu) + do + check_msr_enable 266 $i + ret=$? + read_msr 266 $i + capabilities=$? + if [ $i -eq 0 ]; then + val=$ret + val_cap_msr=$capabilities + else + if [ $ret -eq $val && $capabilities -eq $val_cap_msr ]; then + continue + else + cpu_mismatch=1 + fi + fi + done + capabilities=$val_cap_msr capabilities_rdcl_no=0 capabilities_ibrs_all=0 - if [ $ret -eq 0 ]; then + if [ $val -eq 0 ]; then _debug "capabilities MSR lower byte is $capabilities (decimal)" [ $(( capabilities & 1 )) -eq 1 ] && capabilities_rdcl_no=1 [ $(( capabilities & 2 )) -eq 2 ] && capabilities_ibrs_all=1 _debug "capabilities says rdcl_no=$capabilities_rdcl_no ibrs_all=$capabilities_ibrs_all" if [ "$capabilities_ibrs_all" = 1 ]; then - pstatus green YES + if [ $cpu_mismatch -eq 0 ]; then + pstatus green YES + else: + pstatus green YES "(But not in all CPUs)" + fi else pstatus red NO fi