Skip to contentSkip to conversation

x86/pti: Make unpoison of pgd for trusted boot work for real

PATCH In review Hugh Dickins 2 participants 2 messages Jan 30, 2018 – Feb 1, 2018 Stable branch

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 x86/pti: Make unpoison of pgd for trusted boot work for real

From: Dave Hansen <[email protected]>

commit 445b69e3b75e42362a5bdc13c8b8f61599e2228a upstream

The inital fix for trusted boot and PTI potentially misses the pgd clearing if pud_alloc() sets a PGD. It probably works in *practice* because for two adjacent calls to map_tboot_page() that share a PGD entry, the first will clear NX, *then* allocate and set the PGD (without NX clear). The second call will *not* allocate but will clear the NX bit.

Defer the NX clearing to a point after it is known that all top-level allocations have occurred. Add a comment to clarify why.

[ tglx: Massaged changelog ]

hughd notes: I have not tested tboot, but this looks to me as necessary and as safe in old-Kaiser backports as it is upstream; I'm not submitting the commit-to-be-fixed 262b6b30087, since it was undone by 445b69e3b75e, and makes conflict trouble because of 5-level's p4d versus 4-level's pgd.

---
 arch/x86/kernel/tboot.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
arch/x86/kernel/tboot.c +10 -0
index 91a4496db434..c77ab1f51fbe 100644
@@ -140,6 +140,16 @@ static int map_tboot_page(unsigned long vaddr, unsigned long pfn,
 		return -1;
 	set_pte_at(&tboot_mm, vaddr, pte, pfn_pte(pfn, prot));
 	pte_unmap(pte);
+
+	/*
+	 * PTI poisons low addresses in the kernel page tables in the
+	 * name of making them unusable for userspace.  To execute
+	 * code at such a low address, the poison must be cleared.
+	 *
+	 * Note: 'pgd' actually gets set in pud_alloc().
+	 */
+	pgd->pgd &= ~_PAGE_NX;
+
 	return 0;
 }
 
Signature · 1 line
2.16.0.rc1.238.g530d649a79-goog
#1 lore raw
Quoted 38 lines · Hugh Dickins

From: Dave Hansen <[email protected]>

commit 445b69e3b75e42362a5bdc13c8b8f61599e2228a upstream

The inital fix for trusted boot and PTI potentially misses the pgd clearing if pud_alloc() sets a PGD. It probably works in *practice* because for two adjacent calls to map_tboot_page() that share a PGD entry, the first will clear NX, *then* allocate and set the PGD (without NX clear). The second call will *not* allocate but will clear the NX bit.

Defer the NX clearing to a point after it is known that all top-level allocations have occurred. Add a comment to clarify why.

[ tglx: Massaged changelog ]

Quoted 4 lines

hughd notes: I have not tested tboot, but this looks to me as necessary and as safe in old-Kaiser backports as it is upstream; I'm not submitting the commit-to-be-fixed 262b6b30087, since it was undone by 445b69e3b75e, and makes conflict trouble because of 5-level's p4d versus 4-level's pgd.

Thanks for the backport, now queued up.

greg k-h