Skip to content

Commit 187e91f

Browse files
ramosian-gliderIngo Molnar
authored andcommitted
x86/boot/64/clang: Use fixup_pointer() to access 'next_early_pgt'
__startup_64() is normally using fixup_pointer() to access globals in a position-independent fashion. However 'next_early_pgt' was accessed directly, which wasn't guaranteed to work. Luckily GCC was generating a R_X86_64_PC32 PC-relative relocation for 'next_early_pgt', but Clang emitted a R_X86_64_32S, which led to accessing invalid memory and rebooting the kernel. Signed-off-by: Alexander Potapenko <[email protected]> Acked-by: Kirill A. Shutemov <[email protected]> Cc: Dmitry Vyukov <[email protected]> Cc: Kirill A. Shutemov <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Michael Davidson <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Fixes: c88d715 ("x86/boot/64: Rewrite startup_64() in C") Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 01578e3 commit 187e91f

File tree

1 file changed

+4
-3
lines changed

1 file changed

+4
-3
lines changed

arch/x86/kernel/head64.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ void __head __startup_64(unsigned long physaddr)
5353
pudval_t *pud;
5454
pmdval_t *pmd, pmd_entry;
5555
int i;
56+
unsigned int *next_pgt_ptr;
5657

5758
/* Is the address too large? */
5859
if (physaddr >> MAX_PHYSMEM_BITS)
@@ -91,9 +92,9 @@ void __head __startup_64(unsigned long physaddr)
9192
* creates a bunch of nonsense entries but that is fine --
9293
* it avoids problems around wraparound.
9394
*/
94-
95-
pud = fixup_pointer(early_dynamic_pgts[next_early_pgt++], physaddr);
96-
pmd = fixup_pointer(early_dynamic_pgts[next_early_pgt++], physaddr);
95+
next_pgt_ptr = fixup_pointer(&next_early_pgt, physaddr);
96+
pud = fixup_pointer(early_dynamic_pgts[(*next_pgt_ptr)++], physaddr);
97+
pmd = fixup_pointer(early_dynamic_pgts[(*next_pgt_ptr)++], physaddr);
9798

9899
if (IS_ENABLED(CONFIG_X86_5LEVEL)) {
99100
p4d = fixup_pointer(early_dynamic_pgts[next_early_pgt++], physaddr);

0 commit comments

Comments
 (0)