@@ -2704,7 +2704,8 @@ sys_interface_check()
27042704
27052705# write_msr
27062706# param1 (mandatory): MSR, can be in hex or decimal.
2707- # param2 (optional): CPU index, starting from 0. Default 0.
2707+ # param2 (optional): value to write, can be in hex or decimal.
2708+ # param3 (optional): CPU index, starting from 0. Default 0.
27082709WRITE_MSR_RET_OK=0
27092710WRITE_MSR_RET_KO=1
27102711WRITE_MSR_RET_ERR=2
@@ -2740,6 +2741,8 @@ write_msr_one_core()
27402741 _core=" $1 "
27412742 _msr_dec=$(( $2 ))
27422743 _msr=$( printf " 0x%x" " $_msr_dec " )
2744+ _value_dec=$(( $3 ))
2745+ _value=$( printf " 0x%x" " $_value_dec " )
27432746
27442747 write_msr_msg=' unknown error'
27452748 : " ${msr_locked_down:= 0} "
@@ -2764,7 +2767,7 @@ write_msr_one_core()
27642767
27652768 _write_denied=0
27662769 if [ " $os " != Linux ]; then
2767- cpucontrol -m " $_msr =0 " " /dev/cpuctl$_core " > /dev/null 2>&1 ; ret=$?
2770+ cpucontrol -m " $_msr =$_value " " /dev/cpuctl$_core " > /dev/null 2>&1 ; ret=$?
27682771 else
27692772 # for Linux
27702773 # convert to decimal
@@ -2774,24 +2777,24 @@ write_msr_one_core()
27742777 # if wrmsr is available, use it
27752778 elif command -v wrmsr > /dev/null 2>&1 && [ " ${SMC_NO_WRMSR:- } " != 1 ]; then
27762779 _debug " write_msr: using wrmsr"
2777- wrmsr $_msr_dec 0 2> /dev/null; ret=$?
2780+ wrmsr $_msr_dec $_value_dec 2> /dev/null; ret=$?
27782781 # ret=4: msr doesn't exist, ret=127: msr.allow_writes=off
27792782 [ " $ret " = 127 ] && _write_denied=1
27802783 # or fallback to dd if it supports seek_bytes, we prefer it over perl because we can tell the difference between EPERM and EIO
27812784 elif dd if=/dev/null of=/dev/null bs=8 count=1 seek=" $_msr_dec " oflag=seek_bytes 2> /dev/null && [ " ${SMC_NO_DD:- } " != 1 ]; then
27822785 _debug " write_msr: using dd"
2783- dd if=/dev/zero of=/dev/cpu/" $_core " /msr bs=8 count=1 seek=" $_msr_dec " oflag=seek_bytes 2> /dev/null; ret=$?
2786+ awk " BEGIN{printf \" \%c \" , $_value_dec } " | dd of=/dev/cpu/" $_core " /msr bs=8 count=1 seek=" $_msr_dec " oflag=seek_bytes 2> /dev/null; ret=$?
27842787 # if it failed, inspect stderrto look for EPERM
27852788 if [ " $ret " != 0 ]; then
2786- if dd if=/dev/zero of=/dev/cpu/" $_core " /msr bs=8 count=1 seek=" $_msr_dec " oflag=seek_bytes 2>&1 | grep -qF ' Operation not permitted' ; then
2789+ if aws " BEGIN{printf \" %c \" , $_value_dec } " | dd of=/dev/cpu/" $_core " /msr bs=8 count=1 seek=" $_msr_dec " oflag=seek_bytes 2>&1 | grep -qF ' Operation not permitted' ; then
27872790 _write_denied=1
27882791 fi
27892792 fi
27902793 # or if we have perl, use it, any 5.x version will work
27912794 elif command -v perl > /dev/null 2>&1 && [ " ${SMC_NO_PERL:- } " != 1 ]; then
27922795 _debug " write_msr: using perl"
27932796 ret=1
2794- perl -e " open(M,'>','/dev/cpu/$_core /msr') and seek(M,$_msr_dec ,0) and exit(syswrite(M,pack('H16',0 )))" ; [ $? -eq 8 ] && ret=0
2797+ perl -e " open(M,'>','/dev/cpu/$_core /msr') and seek(M,$_msr_dec ,0) and exit(syswrite(M,pack(v4, $_value_dec )))" ; [ $? -eq 8 ] && ret=0
27952798 else
27962799 _debug " write_msr: got no wrmsr, perl or recent enough dd!"
27972800 mockme=$( printf " %b\n%b" " $mockme " " SMC_MOCK_WRMSR_${_msr} _RET=$WRITE_MSR_RET_ERR " )
@@ -2836,7 +2839,7 @@ write_msr_one_core()
28362839 else
28372840 ret=$WRITE_MSR_RET_KO
28382841 fi
2839- _debug " write_msr: for cpu $_core on msr $_msr , ret=$ret "
2842+ _debug " write_msr: for cpu $_core on msr $_msr , value= $_value , ret=$ret "
28402843 mockme=$( printf " %b\n%b" " $mockme " " SMC_MOCK_WRMSR_${_msr} _RET=$ret " )
28412844 return $ret
28422845}
@@ -3530,6 +3533,28 @@ check_cpu()
35303533
35313534 fi
35323535
3536+ if is_amd || is_hygon; then
3537+ _info " * Selective Branch Predictor Barrier (SBPB)"
3538+ _info_nol " * PRED_CMD MSR is available: "
3539+
3540+ if [ " $opt_allow_msr_write " = 1 ]; then
3541+ # the MSR PRED_SBPB is at offset 0x49, BIT(7), write-only
3542+ write_msr 0x49 128; ret=$?
3543+ if [ $ret = $WRITE_MSR_RET_OK ]; then
3544+ pstatus green YES
3545+ cpuid_sbpb=1
3546+ elif [ $ret = $WRITE_MSR_RET_KO ]; then
3547+ pstatus yellow NO
3548+ else
3549+ pstatus yellow UNKNOWN " $write_msr_msg "
3550+ cpuid_sbpb=3
3551+ fi
3552+ else
3553+ pstatus yellow UNKNOWN " not allowed to write msr"
3554+ cpuid_sbpb=3
3555+ fi
3556+ fi
3557+
35333558 _info_nol " * CPU supports Transactional Synchronization Extensions (TSX): "
35343559 ret=$READ_CPUID_RET_KO
35353560 cpuid_rtm=0
@@ -6334,6 +6359,28 @@ check_CVE_2023_20569_linux() {
63346359 pstatus yellow NO
63356360 fi
63366361
6362+ _info_nol " * Kernel compiled with SRSO support "
6363+ if [ -r " $opt_config " ]; then
6364+ if grep -q ' ^CONFIG_CPU_SRSO=y' " $opt_config " ; then
6365+ pstatus green YES
6366+ else
6367+ pstatus yellow NO " required for safe RET and ibpb_on_vmexit mitigations"
6368+ fi
6369+ else
6370+ pstatus yellow UNKNOWN " couldn't read your kernel configuration"
6371+ fi
6372+
6373+ _info_nol " * Kernel compiled with IBPB support "
6374+ if [ -r " $opt_config " ]; then
6375+ if grep -q ' ^CONFIG_CPU_IBPB_ENTRY=y' " $opt_config " ; then
6376+ pstatus green YES
6377+ else
6378+ pstatus yellow NO " required for ibpb mitigation"
6379+ fi
6380+ else
6381+ pstatus yellow UNKNOWN " couldn't read your kernel configuration"
6382+ fi
6383+
63376384 if [ -n " $kernel_sro " ]; then
63386385
63396386 # TODO check mitigation
@@ -6342,20 +6389,30 @@ check_CVE_2023_20569_linux() {
63426389
63436390 # Zen & Zen2 : if the right IBPB microcode applied + SMT off --> not vuln
63446391 if [ " $cpu_family " = $(( 0x17 )) ]; then
6345- _info_nol " * IBPB support: "
6392+ _info_nol " * IBPB support: "
63466393 if [ -n " $cpuid_ibpb " ]; then
63476394 pstatus green YES " $cpuid_ibpb "
63486395 else
63496396 pstatus red NO
63506397 fi
63516398
6352- _info_nol " * SMT is enabled: "
6399+ _info_nol " * SMT is enabled: "
63536400 is_cpu_smt_enabled; smt_enabled=$?
63546401 if [ " $smt_enabled " = 0 ]; then
63556402 pstatus red YES
63566403 else
63576404 pstatus green NO
6358- fi
6405+ fi
6406+ # Zen 3/4 microcode brings SBPB mitigation
6407+ elif [ " $cpu_family " = $(( 0x19 )) ]; then
6408+ _info_nol " * CPU supports SBPB: "
6409+ if [ " $cpuid_sbpb " = 1 ]; then
6410+ pstatus green YES
6411+ elif [ " $cpuid_sbpb " = 3 ]; then
6412+ pstatus yellow UNKNOWN " cannot write MSR"
6413+ else
6414+ pstatus yellow NO
6415+ fi
63596416 fi
63606417
63616418 elif [ " $sys_interface_available " = 0 ]; then
@@ -6367,13 +6424,20 @@ check_CVE_2023_20569_linux() {
63676424 if ! is_cpu_affected " $cve " ; then
63686425 # override status & msg in case CPU is not vulnerable after all
63696426 pvulnstatus " $cve " OK " your CPU vendor reported your CPU model as not affected"
6370- elif [ " $cpu_family " = $(( 0x17 )) ] && [ " $smt_enabled " = 1 ] && [ -n " $cpuid_ibpb " ]; then
6371- pvulnstatus " $cve " OK " IBPB supported and SMT is off"
6427+ elif [ " $cpu_family " = $(( 0x17 )) ]; then
6428+ if [ " $smt_enabled " = 1 ] && [ -n " $cpuid_ibpb " ]; then
6429+ pvulnstatus " $cve " OK " IBPB supported and SMT is off"
6430+ elif [ " $smt_enabled " != 1 ] && [ -n " $cpuid_ibpb " ]; then
6431+ pvulnstatus " $cve " VULN " SMT is enabled"
6432+ elif [ " $smt_enabled " = 1 ]; then
6433+ pvulnstatus " $cve " VULN " IBPB is not supported by your current microcode"
6434+ else
6435+ pvulnstatus " $cve " VULN " SMT is enabled and IBPB is not support by your current microcode"
6436+ fi
63726437 explain " Zen1/2 with SMT off aren't vulnerable after the right IBPB microcode has been applied. (https://github.com/torvalds/linux/commit/138bcddb86d8a4f842e4ed6f0585abc9b1a764ff#diff-17bd24a7a7850613cced545790ac30646097e8d6207348c2bd1845f397acb390R2272)"
63736438 elif [ -z " $msg " ]; then
6374- # if msg is empty, sysfs check didn't fill it, rely on our own test
6375- # TODO
6376- pvulnstatus " $cve " UNK " further checks are required (WIP)"
6439+ # if msg is empty, sysfs check didn't fill it. If the kernel does not bring the mitigation, system vuln.
6440+ pvulnstatus $cve VULN " upgrade your kernel"
63776441 else
63786442 pvulnstatus $cve " $status " " $msg "
63796443 fi
0 commit comments