# vim: set ts=4 sw=4 sts=4 et: ############################### # CVE-2017-5754, Meltdown, Rogue Data Cache Load # no security impact but give a hint to the user in verbose mode # about PCID/INVPCID cpuid features that must be present to avoid # Check whether PCID/INVPCID are available to reduce PTI performance impact # refs: # https://marc.info/?t=151532047900001&r=1&w=2 # https://groups.google.com/forum/m/#!topic/mechanical-sympathy/L9mHTbeQLNU pti_performance_check() { local ret pcid invpcid pr_info_nol " * Reduced performance impact of PTI: " if [ -e "$g_procfs/cpuinfo" ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw pcid; then pcid=1 else read_cpuid 0x1 0x0 "$ECX" 17 1 1 ret=$? if [ "$ret" = "$READ_CPUID_RET_OK" ]; then pcid=1 fi fi if [ -e "$g_procfs/cpuinfo" ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw invpcid; then invpcid=1 else read_cpuid 0x7 0x0 "$EBX" 10 1 1 ret=$? if [ "$ret" = "$READ_CPUID_RET_OK" ]; then invpcid=1 fi fi if [ "$invpcid" = 1 ]; then pstatus green YES 'CPU supports INVPCID, performance impact of PTI will be greatly reduced' elif [ "$pcid" = 1 ]; then pstatus green YES 'CPU supports PCID, performance impact of PTI will be reduced' else pstatus blue NO 'PCID/INVPCID not supported, performance impact of PTI will be significant' fi } check_CVE_2017_5754() { check_cve 'CVE-2017-5754' } check_CVE_2017_5754_linux() { local status sys_interface_available msg kpti_support kpti_can_tell kpti_enabled dmesg_grep pti_xen_pv_domU xen_pv_domo xen_pv_domu explain_text status=UNK sys_interface_available=0 msg='' if sys_interface_check "$VULN_SYSFS_BASE/meltdown"; then # this kernel has the /sys interface, trust it over everything sys_interface_available=1 status=$ret_sys_interface_check_status fi if [ "$opt_sysfs_only" != 1 ]; then pr_info_nol "* Kernel supports Page Table Isolation (PTI): " kpti_support='' kpti_can_tell=0 if [ -n "$opt_config" ]; then kpti_can_tell=1 kpti_support=$(grep -E -w -e 'CONFIG_(MITIGATION_)?PAGE_TABLE_ISOLATION=y' -e CONFIG_KAISER=y -e CONFIG_UNMAP_KERNEL_AT_EL0=y "$opt_config") if [ -n "$kpti_support" ]; then pr_debug "kpti_support: found option '$kpti_support' in $opt_config" fi fi if [ -z "$kpti_support" ] && [ -n "$opt_map" ]; then # it's not an elif: some backports don't have the PTI config but still include the patch # so we try to find an exported symbol that is part of the PTI patch in System.map # parse_kpti: arm kpti_can_tell=1 kpti_support=$(grep -w -e kpti_force_enabled -e parse_kpti "$opt_map") if [ -n "$kpti_support" ]; then pr_debug "kpti_support: found '$kpti_support' in $opt_map" fi fi if [ -z "$kpti_support" ] && [ -n "$g_kernel" ]; then # same as above but in case we don't have System.map and only kernel, look for the # nopti option that is part of the patch (kernel command line option) # 'kpti=': arm kpti_can_tell=1 if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then pstatus yellow UNKNOWN "missing '${opt_arch_prefix}strings' tool, please install it, usually it's in the binutils package" else kpti_support=$("${opt_arch_prefix}strings" "$g_kernel" | grep -w -e nopti -e kpti=) if [ -n "$kpti_support" ]; then pr_debug "kpti_support: found '$kpti_support' in $g_kernel" fi fi fi if [ -n "$kpti_support" ]; then if [ "$opt_verbose" -ge 2 ]; then pstatus green YES "found '$kpti_support'" else pstatus green YES fi elif [ "$kpti_can_tell" = 1 ]; then pstatus yellow NO else pstatus yellow UNKNOWN "couldn't read your kernel configuration nor System.map file" fi mount_debugfs pr_info_nol " * PTI enabled and active: " if [ "$opt_live" = 1 ]; then dmesg_grep="Kernel/User page tables isolation: enabled" dmesg_grep="$dmesg_grep|Kernel page table isolation enabled" dmesg_grep="$dmesg_grep|x86/pti: Unmapping kernel while in userspace" # aarch64 dmesg_grep="$dmesg_grep|CPU features: detected( feature)?: Kernel page table isolation \(KPTI\)" if grep ^flags "$g_procfs/cpuinfo" | grep -qw pti; then # vanilla PTI patch sets the 'pti' flag in cpuinfo pr_debug "kpti_enabled: found 'pti' flag in $g_procfs/cpuinfo" kpti_enabled=1 elif grep ^flags "$g_procfs/cpuinfo" | grep -qw kaiser; then # kernel line 4.9 sets the 'kaiser' flag in cpuinfo pr_debug "kpti_enabled: found 'kaiser' flag in $g_procfs/cpuinfo" kpti_enabled=1 elif [ -e "$DEBUGFS_BASE/x86/pti_enabled" ]; then # Red Hat Backport creates a dedicated file, see https://access.redhat.com/articles/3311301 kpti_enabled=$(cat "$DEBUGFS_BASE/x86/pti_enabled" 2>/dev/null) pr_debug "kpti_enabled: file $DEBUGFS_BASE/x86/pti_enabled exists and says: $kpti_enabled" elif is_xen_dom0; then pti_xen_pv_domU=$(xl dmesg 2>/dev/null | grep 'XPTI' | grep 'DomU enabled' | head -n1) [ -n "$pti_xen_pv_domU" ] && kpti_enabled=1 fi if [ -z "$kpti_enabled" ]; then dmesg_grep "$dmesg_grep" ret=$? if [ "$ret" -eq 0 ]; then pr_debug "kpti_enabled: found hint in dmesg: $ret_dmesg_grep_grepped" kpti_enabled=1 elif [ "$ret" -eq 2 ]; then pr_debug "kpti_enabled: dmesg truncated" kpti_enabled=-1 fi fi if [ -z "$kpti_enabled" ]; then pr_debug "kpti_enabled: couldn't find any hint that PTI is enabled" kpti_enabled=0 fi if [ "$kpti_enabled" = 1 ]; then pstatus green YES elif [ "$kpti_enabled" = -1 ]; then pstatus yellow UNKNOWN "dmesg truncated, please reboot and relaunch this script" else pstatus yellow NO fi else pstatus blue N/A "not testable in offline mode" fi pti_performance_check 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 fi # Test if the current host is a Xen PV Dom0 / DomU xen_pv_domo=0 xen_pv_domu=0 is_xen_dom0 && xen_pv_domo=1 is_xen_domU && xen_pv_domu=1 if [ "$opt_live" = 1 ]; then # checking whether we're running under Xen PV 64 bits. If yes, we are affected by affected_variant3 # (unless we are a Dom0) pr_info_nol "* Running as a Xen PV DomU: " if [ "$xen_pv_domu" = 1 ]; then pstatus yellow YES else pstatus blue NO fi 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 [ -z "$msg" ]; then # if msg is empty, sysfs check didn't fill it, rely on our own test if [ "$opt_live" = 1 ]; then if [ "$kpti_enabled" = 1 ]; then pvulnstatus "$cve" OK "PTI mitigates the vulnerability" elif [ "$xen_pv_domo" = 1 ]; then pvulnstatus "$cve" OK "Xen Dom0s are safe and do not require PTI" elif [ "$xen_pv_domu" = 1 ]; then pvulnstatus "$cve" VULN "Xen PV DomUs are vulnerable and need to be run in HVM, PVHVM, PVH mode, or the Xen hypervisor must have the Xen's own PTI patch" explain "Go to https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ for more information" elif [ "$kpti_enabled" = -1 ]; then pvulnstatus "$cve" UNK "couldn't find any clue of PTI activation due to a truncated dmesg, please reboot and relaunch this script" else pvulnstatus "$cve" VULN "PTI is needed to mitigate the vulnerability" if [ -n "$kpti_support" ]; then if [ -e "$DEBUGFS_BASE/x86/pti_enabled" ]; then explain "Your kernel supports PTI but it's disabled, you can enable it with \`echo 1 > $DEBUGFS_BASE/x86/pti_enabled\`" elif echo "$g_kernel_cmdline" | grep -q -w -e nopti -e pti=off; then explain "Your kernel supports PTI but it has been disabled on command-line, remove the nopti or pti=off option from your bootloader configuration" else explain "Your kernel supports PTI but it has been disabled, check \`dmesg\` right after boot to find clues why the system disabled it" fi else explain "If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel with the CONFIG_(MITIGATION_)PAGE_TABLE_ISOLATION option (named CONFIG_KAISER for some kernels), or the CONFIG_UNMAP_KERNEL_AT_EL0 option (for ARM64)" fi fi else if [ -n "$kpti_support" ]; then pvulnstatus "$cve" OK "offline mode: PTI will mitigate the vulnerability if enabled at runtime" elif [ "$kpti_can_tell" = 1 ]; then pvulnstatus "$cve" VULN "PTI is needed to mitigate the vulnerability" explain "If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel with the CONFIG_(MITIGATION_)PAGE_TABLE_ISOLATION option (named CONFIG_KAISER for some kernels), or the CONFIG_UNMAP_KERNEL_AT_EL0 option (for ARM64)" else pvulnstatus "$cve" UNK "offline mode: not enough information" explain "Re-run this script with root privileges, and give it the kernel image (--kernel), the kernel configuration (--config) and the System.map file (--map) corresponding to the kernel you would like to inspect." fi fi else if [ "$xen_pv_domo" = 1 ]; then msg="Xen Dom0s are safe and do not require PTI" status="OK" elif [ "$xen_pv_domu" = 1 ]; then msg="Xen PV DomUs are vulnerable and need to be run in HVM, PVHVM, PVH mode, or the Xen hypervisor must have the Xen's own PTI patch" status="VULN" explain_text="Go to https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ for more information" elif [ "$msg" = "Vulnerable" ]; then msg="PTI is needed to mitigate the vulnerability" explain_text="If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel with the CONFIG_(MITIGATION_)PAGE_TABLE_ISOLATION option (named CONFIG_KAISER for some kernels), or the CONFIG_UNMAP_KERNEL_AT_EL0 option (for ARM64)" fi pvulnstatus "$cve" "$status" "$msg" [ -z "${explain_text:-}" ] && [ "$msg" = "Vulnerable" ] && explain_text="If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel with the CONFIG_(MITIGATION_)PAGE_TABLE_ISOLATION option (named CONFIG_KAISER for some kernels), or the CONFIG_UNMAP_KERNEL_AT_EL0 option (for ARM64)" [ -n "${explain_text:-}" ] && explain "$explain_text" unset explain_text fi # Warn the user about XSA-254 recommended mitigations if [ "$xen_pv_domo" = 1 ]; then pr_warn pr_warn "This host is a Xen Dom0. Please make sure that you are running your DomUs" pr_warn "in HVM, PVHVM or PVH mode to prevent any guest-to-host / host-to-guest attacks." pr_warn pr_warn "See https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ and XSA-254 for details." fi } check_CVE_2017_5754_bsd() { local kpti_enabled pr_info_nol "* Kernel supports Page Table Isolation (PTI): " kpti_enabled=$(sysctl -n vm.pmap.pti 2>/dev/null) if [ -z "$kpti_enabled" ]; then pstatus yellow NO else pstatus green YES fi pr_info_nol " * PTI enabled and active: " if [ "$kpti_enabled" = 1 ]; then pstatus green YES else pstatus yellow NO fi pti_performance_check 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 [ "$kpti_enabled" = 1 ]; then pvulnstatus "$cve" OK "PTI mitigates the vulnerability" elif [ -n "$kpti_enabled" ]; then pvulnstatus "$cve" VULN "PTI is supported but disabled on your system" else pvulnstatus "$cve" VULN "PTI is needed to mitigate the vulnerability" fi }