From owner-svn-src-stable-11@freebsd.org Tue May 30 12:44:03 2017 Return-Path: Delivered-To: svn-src-stable-11@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 25F9CB7C086; Tue, 30 May 2017 12:44:03 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id EED9E84785; Tue, 30 May 2017 12:44:02 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v4UCi2sh096020; Tue, 30 May 2017 12:44:02 GMT (envelope-from andrew@FreeBSD.org) Received: (from andrew@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v4UCi1t1096018; Tue, 30 May 2017 12:44:01 GMT (envelope-from andrew@FreeBSD.org) Message-Id: <201705301244.v4UCi1t1096018@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: andrew set sender to andrew@FreeBSD.org using -f From: Andrew Turner Date: Tue, 30 May 2017 12:44:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r319203 - in stable/11/sys/arm64: arm64 include X-SVN-Group: stable-11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-11@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 11-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 30 May 2017 12:44:03 -0000 Author: andrew Date: Tue May 30 12:44:01 2017 New Revision: 319203 URL: https://svnweb.freebsd.org/changeset/base/319203 Log: MFC r316734, r316761: Support Execute-Never bit in the arm64 pmap. r316734: Start to use the User and Privileged execute-never bits in the arm64 pagetables. This sets both bits when entering an address we know shouldn't be executed. I expect we could mark all userspace pages as Privileged execute-never to ensure the kernel doesn't branch to one of these addresses. While here add the ARMv8.1 upper attributes. r316761: Set the arm64 Execute-never bits in more places. We need to set the Execute-never bits when mapping device memory as the hardware may perform speculative instruction fetches. Set the Privileged Execute-ever bit on userspace memory to stop the kernel if it is tricked into executing it. Modified: stable/11/sys/arm64/arm64/pmap.c stable/11/sys/arm64/include/pte.h Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/arm64/arm64/pmap.c ============================================================================== --- stable/11/sys/arm64/arm64/pmap.c Tue May 30 12:26:36 2017 (r319202) +++ stable/11/sys/arm64/arm64/pmap.c Tue May 30 12:44:01 2017 (r319203) @@ -606,7 +606,7 @@ pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t mi l1_slot = ((va - DMAP_MIN_ADDRESS) >> L1_SHIFT); pmap_load_store(&pagetable_dmap[l1_slot], - (pa & ~L1_OFFSET) | ATTR_DEFAULT | + (pa & ~L1_OFFSET) | ATTR_DEFAULT | ATTR_XN | ATTR_IDX(CACHED_MEMORY) | L1_BLOCK); } @@ -1127,7 +1127,7 @@ static void pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_t pa, int mode) { pd_entry_t *pde; - pt_entry_t *pte; + pt_entry_t *pte, attr; vm_offset_t va; int lvl; @@ -1138,6 +1138,10 @@ pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_ KASSERT((size & PAGE_MASK) == 0, ("pmap_kenter: Mapping is not page-sized")); + attr = ATTR_DEFAULT | ATTR_IDX(mode) | L3_PAGE; + if (mode == DEVICE_MEMORY) + attr |= ATTR_XN; + va = sva; while (size != 0) { pde = pmap_pde(kernel_pmap, va, &lvl); @@ -1146,8 +1150,7 @@ pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_ KASSERT(lvl == 2, ("pmap_kenter: Invalid level %d", lvl)); pte = pmap_l2_to_l3(pde, va); - pmap_load_store(pte, (pa & ~L3_OFFSET) | ATTR_DEFAULT | - ATTR_IDX(mode) | L3_PAGE); + pmap_load_store(pte, (pa & ~L3_OFFSET) | attr); PTE_SYNC(pte); va += PAGE_SIZE; @@ -1259,6 +1262,8 @@ pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count) m = ma[i]; pa = VM_PAGE_TO_PHYS(m) | ATTR_DEFAULT | ATTR_AP(ATTR_AP_RW) | ATTR_IDX(m->md.pv_memattr) | L3_PAGE; + if (m->md.pv_memattr == DEVICE_MEMORY) + pa |= ATTR_XN; pte = pmap_l2_to_l3(pde, va); pmap_load_store(pte, pa); PTE_SYNC(pte); @@ -2428,14 +2433,16 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t { vm_offset_t va, va_next; pd_entry_t *l0, *l1, *l2; - pt_entry_t *l3p, l3; + pt_entry_t *l3p, l3, nbits; - if ((prot & VM_PROT_READ) == VM_PROT_NONE) { + KASSERT((prot & ~VM_PROT_ALL) == 0, ("invalid prot %x", prot)); + if (prot == VM_PROT_NONE) { pmap_remove(pmap, sva, eva); return; } - if ((prot & VM_PROT_WRITE) == VM_PROT_WRITE) + if ((prot & (VM_PROT_WRITE | VM_PROT_EXECUTE)) == + (VM_PROT_WRITE | VM_PROT_EXECUTE)) return; PMAP_LOCK(pmap); @@ -2480,17 +2487,25 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t for (l3p = pmap_l2_to_l3(l2, sva); sva != va_next; l3p++, sva += L3_SIZE) { l3 = pmap_load(l3p); - if (pmap_l3_valid(l3)) { + if (!pmap_l3_valid(l3)) + continue; + + nbits = 0; + if ((prot & VM_PROT_WRITE) == 0) { if ((l3 & ATTR_SW_MANAGED) && pmap_page_dirty(l3)) { vm_page_dirty(PHYS_TO_VM_PAGE(l3 & ~ATTR_MASK)); } - pmap_set(l3p, ATTR_AP(ATTR_AP_RO)); - PTE_SYNC(l3p); - /* XXX: Use pmap_invalidate_range */ - pmap_invalidate_page(pmap, va); + nbits |= ATTR_AP(ATTR_AP_RO); } + if ((prot & VM_PROT_EXECUTE) == 0) + nbits |= ATTR_XN; + + pmap_set(l3p, nbits); + PTE_SYNC(l3p); + /* XXX: Use pmap_invalidate_range */ + pmap_invalidate_page(pmap, va); } } PMAP_UNLOCK(pmap); @@ -2709,10 +2724,12 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, v L3_PAGE); if ((prot & VM_PROT_WRITE) == 0) new_l3 |= ATTR_AP(ATTR_AP_RO); + if ((prot & VM_PROT_EXECUTE) == 0 || m->md.pv_memattr == DEVICE_MEMORY) + new_l3 |= ATTR_XN; if ((flags & PMAP_ENTER_WIRED) != 0) new_l3 |= ATTR_SW_WIRED; if ((va >> 63) == 0) - new_l3 |= ATTR_AP(ATTR_AP_USER); + new_l3 |= ATTR_AP(ATTR_AP_USER) | ATTR_PXN; CTR2(KTR_PMAP, "pmap_enter: %.16lx -> %.16lx", va, pa); @@ -3115,6 +3132,10 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, v pa = VM_PAGE_TO_PHYS(m) | ATTR_DEFAULT | ATTR_IDX(m->md.pv_memattr) | ATTR_AP(ATTR_AP_RO) | L3_PAGE; + if ((prot & VM_PROT_EXECUTE) == 0 || m->md.pv_memattr == DEVICE_MEMORY) + pa |= ATTR_XN; + else if (va < VM_MAXUSER_ADDRESS) + pa |= ATTR_PXN; /* * Now validate mapping with RO protection @@ -4251,6 +4272,8 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size l3 = pmap_load(pte); l3 &= ~ATTR_IDX_MASK; l3 |= ATTR_IDX(mode); + if (mode == DEVICE_MEMORY) + l3 |= ATTR_XN; pmap_update_entry(kernel_pmap, pte, l3, tmpva, PAGE_SIZE); Modified: stable/11/sys/arm64/include/pte.h ============================================================================== --- stable/11/sys/arm64/include/pte.h Tue May 30 12:26:36 2017 (r319202) +++ stable/11/sys/arm64/include/pte.h Tue May 30 12:44:01 2017 (r319203) @@ -46,6 +46,11 @@ typedef uint64_t pt_entry_t; /* page table entry */ /* Bits 58:55 are reserved for software */ #define ATTR_SW_MANAGED (1UL << 56) #define ATTR_SW_WIRED (1UL << 55) +#define ATTR_UXN (1UL << 54) +#define ATTR_PXN (1UL << 53) +#define ATTR_XN (ATTR_PXN | ATTR_UXN) +#define ATTR_CONTIGUOUS (1UL << 52) +#define ATTR_DBM (1UL << 51) #define ATTR_nG (1 << 11) #define ATTR_AF (1 << 10) #define ATTR_SH(x) ((x) << 8)