Date: Tue, 12 Nov 2019 18:04:28 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r354651 - in stable/11/sys: amd64/amd64 amd64/include dev/cpuctl x86/include Message-ID: <201911121804.xACI4Sw0086627@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Tue Nov 12 18:04:28 2019 New Revision: 354651 URL: https://svnweb.freebsd.org/changeset/base/354651 Log: MFC r354649: Workaround for Intel SKL002/SKL012S errata. Security: CVE-2018-12207 Modified: stable/11/sys/amd64/amd64/pmap.c stable/11/sys/amd64/include/pmap.h stable/11/sys/dev/cpuctl/cpuctl.c stable/11/sys/x86/include/specialreg.h Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/amd64/amd64/pmap.c ============================================================================== --- stable/11/sys/amd64/amd64/pmap.c Tue Nov 12 18:03:26 2019 (r354650) +++ stable/11/sys/amd64/amd64/pmap.c Tue Nov 12 18:04:28 2019 (r354651) @@ -1226,6 +1226,51 @@ pmap_page_init(vm_page_t m) m->md.pat_mode = PAT_WRITE_BACK; } +static int pmap_allow_2m_x_ept; +SYSCTL_INT(_vm_pmap, OID_AUTO, allow_2m_x_ept, CTLFLAG_RWTUN | CTLFLAG_NOFETCH, + &pmap_allow_2m_x_ept, 0, + "Allow executable superpage mappings in EPT"); + +void +pmap_allow_2m_x_ept_recalculate(void) +{ + /* + * SKL002, SKL012S. Since the EPT format is only used by + * Intel CPUs, the vendor check is merely a formality. + */ + if (!(cpu_vendor_id != CPU_VENDOR_INTEL || + (cpu_ia32_arch_caps & IA32_ARCH_CAP_IF_PSCHANGE_MC_NO) != 0 || + (CPUID_TO_FAMILY(cpu_id) == 0x6 && + (CPUID_TO_MODEL(cpu_id) == 0x26 || /* Atoms */ + CPUID_TO_MODEL(cpu_id) == 0x27 || + CPUID_TO_MODEL(cpu_id) == 0x35 || + CPUID_TO_MODEL(cpu_id) == 0x36 || + CPUID_TO_MODEL(cpu_id) == 0x37 || + CPUID_TO_MODEL(cpu_id) == 0x86 || + CPUID_TO_MODEL(cpu_id) == 0x1c || + CPUID_TO_MODEL(cpu_id) == 0x4a || + CPUID_TO_MODEL(cpu_id) == 0x4c || + CPUID_TO_MODEL(cpu_id) == 0x4d || + CPUID_TO_MODEL(cpu_id) == 0x5a || + CPUID_TO_MODEL(cpu_id) == 0x5c || + CPUID_TO_MODEL(cpu_id) == 0x5d || + CPUID_TO_MODEL(cpu_id) == 0x5f || + CPUID_TO_MODEL(cpu_id) == 0x6e || + CPUID_TO_MODEL(cpu_id) == 0x7a || + CPUID_TO_MODEL(cpu_id) == 0x57 || /* Knights */ + CPUID_TO_MODEL(cpu_id) == 0x85)))) + pmap_allow_2m_x_ept = 1; + TUNABLE_INT_FETCH("hw.allow_2m_x_ept", &pmap_allow_2m_x_ept); +} + +static bool +pmap_allow_2m_x_page(pmap_t pmap, bool executable) +{ + + return (pmap->pm_type != PT_EPT || !executable || + !pmap_allow_2m_x_ept); +} + /* * Initialize the pmap module. * Called by vm_init, to initialize any structures that the pmap @@ -1270,6 +1315,9 @@ pmap_init(void) } } + /* IFU */ + pmap_allow_2m_x_ept_recalculate(); + /* * Initialize the vm page array entries for the kernel pmap's * page table pages. @@ -4550,6 +4598,15 @@ retry: } #if VM_NRESERVLEVEL > 0 +static bool +pmap_pde_ept_executable(pmap_t pmap, pd_entry_t pde) +{ + + if (pmap->pm_type != PT_EPT) + return (false); + return ((pde & EPT_PG_EXECUTE) != 0); +} + /* * Tries to promote the 512, contiguous 4KB page mappings that are within a * single page table page (PTP) to a single 2MB page mapping. For promotion @@ -4584,7 +4641,9 @@ pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offs firstpte = (pt_entry_t *)PHYS_TO_DMAP(*pde & PG_FRAME); setpde: newpde = *firstpte; - if ((newpde & ((PG_FRAME & PDRMASK) | PG_A | PG_V)) != (PG_A | PG_V)) { + if ((newpde & ((PG_FRAME & PDRMASK) | PG_A | PG_V)) != (PG_A | PG_V) || + !pmap_allow_2m_x_page(pmap, pmap_pde_ept_executable(pmap, + newpde))) { atomic_add_long(&pmap_pde_p_failures, 1); CTR2(KTR_PMAP, "pmap_promote_pde: failure for va %#lx" " in pmap %p", va, pmap); @@ -5010,6 +5069,12 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, pd_entry_t PG_V = pmap_valid_bit(pmap); PMAP_LOCK_ASSERT(pmap, MA_OWNED); + if (!pmap_allow_2m_x_page(pmap, pmap_pde_ept_executable(pmap, + newpde))) { + CTR2(KTR_PMAP, "pmap_enter_pde: 2m x blocked for va %#lx" + " in pmap %p", va, pmap); + return (KERN_FAILURE); + } if ((pdpg = pmap_allocpde(pmap, va, (flags & PMAP_ENTER_NOSLEEP) != 0 ? NULL : lockp)) == NULL) { CTR2(KTR_PMAP, "pmap_enter_pde: failure for va %#lx" @@ -5139,6 +5204,7 @@ pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_o va = start + ptoa(diff); if ((va & PDRMASK) == 0 && va + NBPDR <= end && m->psind == 1 && pmap_ps_enabled(pmap) && + pmap_allow_2m_x_page(pmap, (prot & VM_PROT_EXECUTE) != 0) && pmap_enter_2mpage(pmap, va, m, prot, &lock)) m = &m[NBPDR / PAGE_SIZE - 1]; else Modified: stable/11/sys/amd64/include/pmap.h ============================================================================== --- stable/11/sys/amd64/include/pmap.h Tue Nov 12 18:03:26 2019 (r354650) +++ stable/11/sys/amd64/include/pmap.h Tue Nov 12 18:04:28 2019 (r354651) @@ -407,6 +407,7 @@ struct thread; void pmap_activate_boot(pmap_t pmap); void pmap_activate_sw(struct thread *); +void pmap_allow_2m_x_ept_recalculate(void); void pmap_bootstrap(vm_paddr_t *); int pmap_cache_bits(pmap_t pmap, int mode, boolean_t is_pde); int pmap_change_attr(vm_offset_t, vm_size_t, int); Modified: stable/11/sys/dev/cpuctl/cpuctl.c ============================================================================== --- stable/11/sys/dev/cpuctl/cpuctl.c Tue Nov 12 18:03:26 2019 (r354650) +++ stable/11/sys/dev/cpuctl/cpuctl.c Tue Nov 12 18:04:28 2019 (r354651) @@ -48,6 +48,10 @@ __FBSDID("$FreeBSD$"); #include <sys/pmckern.h> #include <sys/cpuctl.h> +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> + #include <machine/cpufunc.h> #include <machine/md_var.h> #include <machine/specialreg.h> @@ -535,6 +539,9 @@ cpuctl_do_eval_cpu_features(int cpu, struct thread *td hw_ibrs_recalculate(); restore_cpu(oldcpu, is_bound, td); hw_ssb_recalculate(true); +#ifdef __amd64__ + pmap_allow_2m_x_ept_recalculate(); +#endif hw_mds_recalculate(); printcpuinfo(); return (0); Modified: stable/11/sys/x86/include/specialreg.h ============================================================================== --- stable/11/sys/x86/include/specialreg.h Tue Nov 12 18:03:26 2019 (r354650) +++ stable/11/sys/x86/include/specialreg.h Tue Nov 12 18:04:28 2019 (r354651) @@ -406,6 +406,7 @@ #define IA32_ARCH_CAP_SKIP_L1DFL_VMENTRY 0x00000008 #define IA32_ARCH_CAP_SSB_NO 0x00000010 #define IA32_ARCH_CAP_MDS_NO 0x00000020 +#define IA32_ARCH_CAP_IF_PSCHANGE_MC_NO 0x00000040 /* * CPUID manufacturers identifiers
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201911121804.xACI4Sw0086627>