All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/boot/64: Fix crash if kernel images crosses page table boundary
@ 2019-06-20 11:23 Kirill A. Shutemov
  2019-06-25 19:04 ` Thomas Gleixner
  2019-06-26  5:28 ` [tip:x86/urgent] x86/boot/64: Fix crash if kernel image " tip-bot for Kirill A. Shutemov
  0 siblings, 2 replies; 6+ messages in thread
From: Kirill A. Shutemov @ 2019-06-20 11:23 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Dave Hansen, Andy Lutomirski, Peter Zijlstra
  Cc: x86, linux-kernel, Kirill A. Shutemov

Kernel that boots in 5-level paging mode crashes in small percentage of
cases if KASLR is enabled.

This issue was tracked down to the case when the kernel image unpack in
the way it crosses 1G boundary. The crash was due to overrun of PMD page
table in __startup_64() and corruption of P4D page table allocated next
to it.

The issue is not visible with 4-level paging as we don't use the P4D
page table.

The root cause is that the handling of page table wraparound was lost
when part of startup_64() was rewritten in C.

Restore the handling. It also fixes the issue when the kernel image put
across 512G and, for 5-level paging, 64T boundary.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Fixes: c88d71508e36 ("x86/boot/64: Rewrite startup_64() in C")
---
 arch/x86/kernel/head64.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 4d98ba8063d1..b502c28801fc 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -190,18 +190,18 @@ unsigned long __head __startup_64(unsigned long physaddr,
 		pgd[i + 0] = (pgdval_t)p4d + pgtable_flags;
 		pgd[i + 1] = (pgdval_t)p4d + pgtable_flags;
 
-		i = (physaddr >> P4D_SHIFT) % PTRS_PER_P4D;
-		p4d[i + 0] = (pgdval_t)pud + pgtable_flags;
-		p4d[i + 1] = (pgdval_t)pud + pgtable_flags;
+		i = physaddr >> P4D_SHIFT;
+		p4d[(i + 0) % PTRS_PER_P4D] = (pgdval_t)pud + pgtable_flags;
+		p4d[(i + 1) % PTRS_PER_P4D] = (pgdval_t)pud + pgtable_flags;
 	} else {
 		i = (physaddr >> PGDIR_SHIFT) % PTRS_PER_PGD;
 		pgd[i + 0] = (pgdval_t)pud + pgtable_flags;
 		pgd[i + 1] = (pgdval_t)pud + pgtable_flags;
 	}
 
-	i = (physaddr >> PUD_SHIFT) % PTRS_PER_PUD;
-	pud[i + 0] = (pudval_t)pmd + pgtable_flags;
-	pud[i + 1] = (pudval_t)pmd + pgtable_flags;
+	i = physaddr >> PUD_SHIFT;
+	pud[(i + 0) % PTRS_PER_PUD] = (pudval_t)pmd + pgtable_flags;
+	pud[(i + 1) % PTRS_PER_PUD] = (pudval_t)pmd + pgtable_flags;
 
 	pmd_entry = __PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL;
 	/* Filter out unsupported __PAGE_KERNEL_* bits: */
@@ -211,8 +211,8 @@ unsigned long __head __startup_64(unsigned long physaddr,
 	pmd_entry +=  physaddr;
 
 	for (i = 0; i < DIV_ROUND_UP(_end - _text, PMD_SIZE); i++) {
-		int idx = i + (physaddr >> PMD_SHIFT) % PTRS_PER_PMD;
-		pmd[idx] = pmd_entry + i * PMD_SIZE;
+		int idx = i + (physaddr >> PMD_SHIFT);;
+		pmd[idx % PTRS_PER_PMD] = pmd_entry + i * PMD_SIZE;
 	}
 
 	/*
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-06-26  5:29 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-06-20 11:23 [PATCH] x86/boot/64: Fix crash if kernel images crosses page table boundary Kirill A. Shutemov
2019-06-25 19:04 ` Thomas Gleixner
2019-06-25 19:30   ` Kirill A. Shutemov
2019-06-25 19:56     ` Thomas Gleixner
2019-06-25 20:05       ` Thomas Gleixner
2019-06-26  5:28 ` [tip:x86/urgent] x86/boot/64: Fix crash if kernel image " tip-bot for Kirill A. Shutemov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.