# vim: set ts=4 sw=4 sts=4 et: ############################### # CVE-2018-3646, Foreshadow-NG (VMM), L1 Terminal Fault check_CVE_2018_3646() { check_cve 'CVE-2018-3646' } check_CVE_2018_3646_linux() { local status sys_interface_available msg l1d_mode ept_disabled l1d_kernel l1d_kernel_err l1d_xen_hardware l1d_xen_hypervisor l1d_xen_pv_domU smt_enabled status=UNK sys_interface_available=0 msg='' if sys_interface_check "$VULN_SYSFS_BASE/l1tf" '.*' quiet; then # this kernel has the /sys interface, trust it over everything sys_interface_available=1 # quiet mode doesn't set ret_sys_interface_check_status, derive it ourselves. # # Complete sysfs message inventory for l1tf, traced via git blame # on mainline (~/linux) and stable (~/linux-stable): # # all versions: # "Not affected" (cpu_show_common, d1059518b4789) # "Vulnerable" (cpu_show_common fallthrough, d1059518b4789) # # --- mainline --- # 17dbca119312 (v4.18-rc1, initial l1tf sysfs): # "Mitigation: Page Table Inversion" # 72c6d2db64fa (v4.18-rc1, renamed + added VMX reporting): # "Mitigation: PTE Inversion" (no KVM_INTEL, or VMX=AUTO) # "Mitigation: PTE Inversion; VMX: SMT , L1D " (KVM_INTEL enabled) # : auto | vulnerable | conditional cache flushes | cache flushes # a7b9020b06ec (v4.18-rc1, added EPT disabled state): # : + EPT disabled # ea156d192f52 (v4.18-rc7, reordered VMX/SMT fields): # "Mitigation: PTE Inversion; VMX: EPT disabled" (no SMT part) # "Mitigation: PTE Inversion; VMX: vulnerable" (NEVER + SMT active, no SMT part) # "Mitigation: PTE Inversion; VMX: , SMT " (all other cases) # 8e0b2b916662 (v4.18, added flush not necessary): # : + flush not necessary # 130d6f946f6f (v4.20-rc4, no string change): # SMT detection changed from cpu_smt_control to sched_smt_active() # # --- stable backports --- # 4.4.y: no VMX reporting (only "PTE Inversion" / "Vulnerable" / "Not affected"). # initially backported as "Page Table Inversion" (bf0cca01b873), # renamed to "PTE Inversion" in stable-only commit 6db8c0882912 (May 2019). # 4.9.y, 4.14.y: full VMX reporting, post-reorder format. # the pre-reorder format ("SMT , L1D ") and the post-reorder # format ("VMX: , SMT ") landed in the same stable release # (4.9.120, 4.14.63), so no stable release ever shipped the pre-reorder format. # sched_smt_active() backported (same strings, different runtime behavior). # 4.17.y, 4.18.y: full VMX reporting, post-reorder format. # still uses cpu_smt_control (sched_smt_active() not backported to these EOL branches). # # is one of: vulnerable | disabled # # all messages start with either "Not affected", "Mitigation", or "Vulnerable" if echo "$ret_sys_interface_check_fullmsg" | grep -qEi '^(Not affected|Mitigation)'; then status=OK elif echo "$ret_sys_interface_check_fullmsg" | grep -qi '^Vulnerable'; then status=VULN fi fi l1d_mode=-1 if [ "$opt_sysfs_only" != 1 ]; then check_has_vmm pr_info "* Mitigation 1 (KVM)" pr_info_nol " * EPT is disabled: " ept_disabled=-1 if [ "$opt_live" = 1 ]; then if ! [ -r "$SYS_MODULE_BASE/kvm_intel/parameters/ept" ]; then pstatus blue N/A "the kvm_intel module is not loaded" elif [ "$(cat "$SYS_MODULE_BASE/kvm_intel/parameters/ept")" = N ]; then pstatus green YES ept_disabled=1 else pstatus yellow NO fi else pstatus blue N/A "not testable in offline mode" fi pr_info "* Mitigation 2" pr_info_nol " * L1D flush is supported by kernel: " if [ "$opt_live" = 1 ] && grep -qw flush_l1d "$g_procfs/cpuinfo"; then l1d_kernel="found flush_l1d in $g_procfs/cpuinfo" fi if [ -z "$l1d_kernel" ]; then if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then l1d_kernel_err="missing '${opt_arch_prefix}strings' tool, please install it, usually it's in the binutils package" elif [ -n "$g_kernel_err" ]; then l1d_kernel_err="$g_kernel_err" elif "${opt_arch_prefix}strings" "$g_kernel" | grep -qw flush_l1d; then l1d_kernel='found flush_l1d in kernel image' fi fi if [ -n "$l1d_kernel" ]; then pstatus green YES "$l1d_kernel" elif [ -n "$l1d_kernel_err" ]; then pstatus yellow UNKNOWN "$l1d_kernel_err" else pstatus yellow NO fi pr_info_nol " * L1D flush enabled: " if [ "$opt_live" = 1 ]; then if [ -n "$ret_sys_interface_check_fullmsg" ]; then # vanilla: VMX: $l1dstatus, SMT $smtstatus # Red Hat: VMX: SMT $smtstatus, L1D $l1dstatus # $l1dstatus is one of (auto|vulnerable|conditional cache flushes|cache flushes|EPT disabled|flush not necessary) # $smtstatus is one of (vulnerable|disabled) # can also just be "Not affected" if echo "$ret_sys_interface_check_fullmsg" | grep -Eq -e 'Not affected' -e '(VMX:|L1D) (EPT disabled|vulnerable|flush not necessary)'; then l1d_mode=0 pstatus yellow NO elif echo "$ret_sys_interface_check_fullmsg" | grep -Eq '(VMX:|L1D) conditional cache flushes'; then l1d_mode=1 pstatus green YES "conditional flushes" elif echo "$ret_sys_interface_check_fullmsg" | grep -Eq '(VMX:|L1D) cache flushes'; then l1d_mode=2 pstatus green YES "unconditional flushes" else if is_xen_dom0; then l1d_xen_hardware=$(xl dmesg 2>/dev/null | grep 'Hardware features:' | grep 'L1D_FLUSH' | head -n1) l1d_xen_hypervisor=$(xl dmesg 2>/dev/null | grep 'Xen settings:' | grep 'L1D_FLUSH' | head -n1) l1d_xen_pv_domU=$(xl dmesg 2>/dev/null | grep 'PV L1TF shadowing:' | grep 'DomU enabled' | head -n1) if [ -n "$l1d_xen_hardware" ] && [ -n "$l1d_xen_hypervisor" ] && [ -n "$l1d_xen_pv_domU" ]; then l1d_mode=5 pstatus green YES "for XEN guests" elif [ -n "$l1d_xen_hardware" ] && [ -n "$l1d_xen_hypervisor" ]; then l1d_mode=4 pstatus yellow YES "for XEN guests (HVM only)" elif [ -n "$l1d_xen_pv_domU" ]; then l1d_mode=3 pstatus yellow YES "for XEN guests (PV only)" else l1d_mode=0 pstatus yellow NO "for XEN guests" fi else l1d_mode=-1 pstatus yellow UNKNOWN "unrecognized mode" fi fi else l1d_mode=-1 pstatus yellow UNKNOWN "can't find or read $VULN_SYSFS_BASE/l1tf" fi else l1d_mode=-1 pstatus blue N/A "not testable in offline mode" fi pr_info_nol " * Hardware-backed L1D flush supported: " if [ "$opt_live" = 1 ]; then if grep -qw flush_l1d "$g_procfs/cpuinfo" || [ -n "$l1d_xen_hardware" ]; then pstatus green YES "performance impact of the mitigation will be greatly reduced" else pstatus blue NO "flush will be done in software, this is slower" fi else pstatus blue N/A "not testable in offline mode" fi pr_info_nol " * Hyper-Threading (SMT) is enabled: " is_cpu_smt_enabled smt_enabled=$? if [ "$smt_enabled" = 0 ]; then pstatus yellow YES elif [ "$smt_enabled" = 1 ]; then pstatus green NO else pstatus yellow UNKNOWN fi elif [ "$sys_interface_available" = 0 ]; then # we have no sysfs but were asked to use it only! msg="/sys vulnerability interface use forced, but it's not available!" status=UNK l1d_mode=-1 fi if ! is_cpu_affected "$cve"; then # override status & msg in case CPU is not vulnerable after all pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" elif [ "$ret_sys_interface_check_fullmsg" = "Not affected" ]; then # just in case a very recent kernel knows better than we do pvulnstatus "$cve" OK "your kernel reported your CPU model as not affected" elif [ -z "$msg" ]; then if [ "$opt_sysfs_only" != 1 ]; then if [ "$g_has_vmm" = 0 ]; then pvulnstatus "$cve" OK "this system is not running a hypervisor" elif [ "$ept_disabled" = 1 ]; then pvulnstatus "$cve" OK "EPT is disabled which mitigates the vulnerability" elif [ "$opt_paranoid" = 0 ]; then if [ "$l1d_mode" -ge 1 ]; then pvulnstatus "$cve" OK "L1D flushing is enabled and mitigates the vulnerability" else pvulnstatus "$cve" VULN "disable EPT or enable L1D flushing to mitigate the vulnerability" fi else if [ "$l1d_mode" -ge 2 ]; then if [ "$smt_enabled" = 1 ]; then pvulnstatus "$cve" OK "L1D unconditional flushing and Hyper-Threading disabled are mitigating the vulnerability" else pvulnstatus "$cve" VULN "Hyper-Threading must be disabled to fully mitigate the vulnerability" fi else if [ "$smt_enabled" = 1 ]; then pvulnstatus "$cve" VULN "L1D unconditional flushing should be enabled to fully mitigate the vulnerability" else pvulnstatus "$cve" VULN "enable L1D unconditional flushing and disable Hyper-Threading to fully mitigate the vulnerability" fi fi fi if [ "$l1d_mode" -gt 3 ]; then pr_warn pr_warn "This host is a Xen Dom0. Please make sure that you are running your DomUs" pr_warn "with a kernel which contains CVE-2018-3646 mitigations." pr_warn pr_warn "See https://www.suse.com/support/kb/doc/?id=7023078 and XSA-273 for details." fi else # --sysfs-only: sysfs was available (otherwise msg would be set), use its result pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg" fi else # msg was set explicitly: either sysfs-not-available error, or a sysfs override pvulnstatus "$cve" "$status" "$msg" fi } check_CVE_2018_3646_bsd() { local kernel_l1d_supported kernel_l1d_enabled pr_info_nol "* Kernel supports L1D flushing: " if sysctl hw.vmm.vmx.l1d_flush >/dev/null 2>&1; then pstatus green YES kernel_l1d_supported=1 else pstatus yellow NO kernel_l1d_supported=0 fi pr_info_nol "* L1D flushing is enabled: " kernel_l1d_enabled=$(sysctl -n hw.vmm.vmx.l1d_flush 2>/dev/null) case "$kernel_l1d_enabled" in 0) pstatus yellow NO ;; 1) pstatus green YES ;; "") pstatus yellow NO ;; *) pstatus yellow UNKNOWN ;; esac if ! is_cpu_affected "$cve"; then pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" else if [ "$kernel_l1d_enabled" = 1 ]; then pvulnstatus "$cve" OK "L1D flushing mitigates the vulnerability" elif [ "$kernel_l1d_supported" = 1 ]; then pvulnstatus "$cve" VULN "L1D flushing is supported by your kernel but is disabled" else pvulnstatus "$cve" VULN "your kernel needs to be updated" fi fi }