aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-30 14:42:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-30 14:42:14 -0400
commit0fbc4aeabc91f2e39e0dffebe8f81a0eb3648d97 (patch)
tree4ffb5ea64600b09df6331083a9c68ae589096f76
parentd7d5388679312b7a7b6377e38e2b8fb06a82d84e (diff)
parentd79d0d8ad0cb3d782b41631dfeac8eb05e414bcd (diff)
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar: "The biggest diffstat comes from self-test updates, plus there's entry code fixes, 5-level paging related fixes, console debug output fixes, and misc fixes" * 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/mm: Clean up the printk()s in show_fault_oops() x86/mm: Drop unneeded __always_inline for p4d page table helpers x86/efi: Fix efi_call_phys_epilog() with CONFIG_X86_5LEVEL=y selftests/x86/sigreturn: Do minor cleanups selftests/x86/sigreturn/64: Fix spurious failures on AMD CPUs x86/entry/64/compat: Fix "x86/entry/64/compat: Preserve r8-r11 in int $0x80" x86/mm: Don't free P4D table when it is folded at runtime x86/entry/32: Add explicit 'l' instruction suffix x86/mm: Get rid of KERN_CONT in show_fault_oops()
-rw-r--r--arch/x86/entry/entry_32.S2
-rw-r--r--arch/x86/entry/entry_64_compat.S16
-rw-r--r--arch/x86/include/asm/pgalloc.h3
-rw-r--r--arch/x86/include/asm/pgtable.h2
-rw-r--r--arch/x86/include/asm/pgtable_64.h4
-rw-r--r--arch/x86/mm/fault.c21
-rw-r--r--arch/x86/platform/efi/efi_64.c4
-rw-r--r--tools/testing/selftests/x86/sigreturn.c59
8 files changed, 60 insertions, 51 deletions
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 2582881d19ce..c371bfee137a 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -477,7 +477,7 @@ ENTRY(entry_SYSENTER_32)
477 * whereas POPF does not.) 477 * whereas POPF does not.)
478 */ 478 */
479 addl $PT_EFLAGS-PT_DS, %esp /* point esp at pt_regs->flags */ 479 addl $PT_EFLAGS-PT_DS, %esp /* point esp at pt_regs->flags */
480 btr $X86_EFLAGS_IF_BIT, (%esp) 480 btrl $X86_EFLAGS_IF_BIT, (%esp)
481 popfl 481 popfl
482 482
483 /* 483 /*
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index 9de7f1e1dede..7d0df78db727 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -84,13 +84,13 @@ ENTRY(entry_SYSENTER_compat)
84 pushq %rdx /* pt_regs->dx */ 84 pushq %rdx /* pt_regs->dx */
85 pushq %rcx /* pt_regs->cx */ 85 pushq %rcx /* pt_regs->cx */
86 pushq $-ENOSYS /* pt_regs->ax */ 86 pushq $-ENOSYS /* pt_regs->ax */
87 pushq %r8 /* pt_regs->r8 */ 87 pushq $0 /* pt_regs->r8 = 0 */
88 xorl %r8d, %r8d /* nospec r8 */ 88 xorl %r8d, %r8d /* nospec r8 */
89 pushq %r9 /* pt_regs->r9 */ 89 pushq $0 /* pt_regs->r9 = 0 */
90 xorl %r9d, %r9d /* nospec r9 */ 90 xorl %r9d, %r9d /* nospec r9 */
91 pushq %r10 /* pt_regs->r10 */ 91 pushq $0 /* pt_regs->r10 = 0 */
92 xorl %r10d, %r10d /* nospec r10 */ 92 xorl %r10d, %r10d /* nospec r10 */
93 pushq %r11 /* pt_regs->r11 */ 93 pushq $0 /* pt_regs->r11 = 0 */
94 xorl %r11d, %r11d /* nospec r11 */ 94 xorl %r11d, %r11d /* nospec r11 */
95 pushq %rbx /* pt_regs->rbx */ 95 pushq %rbx /* pt_regs->rbx */
96 xorl %ebx, %ebx /* nospec rbx */ 96 xorl %ebx, %ebx /* nospec rbx */
@@ -374,13 +374,13 @@ ENTRY(entry_INT80_compat)
374 pushq %rcx /* pt_regs->cx */ 374 pushq %rcx /* pt_regs->cx */
375 xorl %ecx, %ecx /* nospec cx */ 375 xorl %ecx, %ecx /* nospec cx */
376 pushq $-ENOSYS /* pt_regs->ax */ 376 pushq $-ENOSYS /* pt_regs->ax */
377 pushq $0 /* pt_regs->r8 = 0 */ 377 pushq %r8 /* pt_regs->r8 */
378 xorl %r8d, %r8d /* nospec r8 */ 378 xorl %r8d, %r8d /* nospec r8 */
379 pushq $0 /* pt_regs->r9 = 0 */ 379 pushq %r9 /* pt_regs->r9 */
380 xorl %r9d, %r9d /* nospec r9 */ 380 xorl %r9d, %r9d /* nospec r9 */
381 pushq $0 /* pt_regs->r10 = 0 */ 381 pushq %r10 /* pt_regs->r10*/
382 xorl %r10d, %r10d /* nospec r10 */ 382 xorl %r10d, %r10d /* nospec r10 */
383 pushq $0 /* pt_regs->r11 = 0 */ 383 pushq %r11 /* pt_regs->r11 */
384 xorl %r11d, %r11d /* nospec r11 */ 384 xorl %r11d, %r11d /* nospec r11 */
385 pushq %rbx /* pt_regs->rbx */ 385 pushq %rbx /* pt_regs->rbx */
386 xorl %ebx, %ebx /* nospec rbx */ 386 xorl %ebx, %ebx /* nospec rbx */
diff --git a/arch/x86/include/asm/pgalloc.h b/arch/x86/include/asm/pgalloc.h
index ada6410fd2ec..fbd578daa66e 100644
--- a/arch/x86/include/asm/pgalloc.h
+++ b/arch/x86/include/asm/pgalloc.h
@@ -184,6 +184,9 @@ static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long addr)
184 184
185static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d) 185static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
186{ 186{
187 if (!pgtable_l5_enabled())
188 return;
189
187 BUG_ON((unsigned long)p4d & (PAGE_SIZE-1)); 190 BUG_ON((unsigned long)p4d & (PAGE_SIZE-1));
188 free_page((unsigned long)p4d); 191 free_page((unsigned long)p4d);
189} 192}
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 99ecde23c3ec..5715647fc4fe 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -898,7 +898,7 @@ static inline unsigned long pgd_page_vaddr(pgd_t pgd)
898#define pgd_page(pgd) pfn_to_page(pgd_pfn(pgd)) 898#define pgd_page(pgd) pfn_to_page(pgd_pfn(pgd))
899 899
900/* to find an entry in a page-table-directory. */ 900/* to find an entry in a page-table-directory. */
901static __always_inline p4d_t *p4d_offset(pgd_t *pgd, unsigned long address) 901static inline p4d_t *p4d_offset(pgd_t *pgd, unsigned long address)
902{ 902{
903 if (!pgtable_l5_enabled()) 903 if (!pgtable_l5_enabled())
904 return (p4d_t *)pgd; 904 return (p4d_t *)pgd;
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h
index 0fdcd21dadbd..3c5385f9a88f 100644
--- a/arch/x86/include/asm/pgtable_64.h
+++ b/arch/x86/include/asm/pgtable_64.h
@@ -216,7 +216,7 @@ static inline pgd_t pti_set_user_pgd(pgd_t *pgdp, pgd_t pgd)
216} 216}
217#endif 217#endif
218 218
219static __always_inline void native_set_p4d(p4d_t *p4dp, p4d_t p4d) 219static inline void native_set_p4d(p4d_t *p4dp, p4d_t p4d)
220{ 220{
221 pgd_t pgd; 221 pgd_t pgd;
222 222
@@ -230,7 +230,7 @@ static __always_inline void native_set_p4d(p4d_t *p4dp, p4d_t p4d)
230 *p4dp = native_make_p4d(native_pgd_val(pgd)); 230 *p4dp = native_make_p4d(native_pgd_val(pgd));
231} 231}
232 232
233static __always_inline void native_p4d_clear(p4d_t *p4d) 233static inline void native_p4d_clear(p4d_t *p4d)
234{ 234{
235 native_set_p4d(p4d, native_make_p4d(0)); 235 native_set_p4d(p4d, native_make_p4d(0));
236} 236}
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 9a84a0d08727..2aafa6ab6103 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -641,11 +641,6 @@ static int is_f00f_bug(struct pt_regs *regs, unsigned long address)
641 return 0; 641 return 0;
642} 642}
643 643
644static const char nx_warning[] = KERN_CRIT
645"kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n";
646static const char smep_warning[] = KERN_CRIT
647"unable to execute userspace code (SMEP?) (uid: %d)\n";
648
649static void 644static void
650show_fault_oops(struct pt_regs *regs, unsigned long error_code, 645show_fault_oops(struct pt_regs *regs, unsigned long error_code,
651 unsigned long address) 646 unsigned long address)
@@ -664,20 +659,18 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
664 pte = lookup_address_in_pgd(pgd, address, &level); 659 pte = lookup_address_in_pgd(pgd, address, &level);
665 660
666 if (pte && pte_present(*pte) && !pte_exec(*pte)) 661 if (pte && pte_present(*pte) && !pte_exec(*pte))
667 printk(nx_warning, from_kuid(&init_user_ns, current_uid())); 662 pr_crit("kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n",
663 from_kuid(&init_user_ns, current_uid()));
668 if (pte && pte_present(*pte) && pte_exec(*pte) && 664 if (pte && pte_present(*pte) && pte_exec(*pte) &&
669 (pgd_flags(*pgd) & _PAGE_USER) && 665 (pgd_flags(*pgd) & _PAGE_USER) &&
670 (__read_cr4() & X86_CR4_SMEP)) 666 (__read_cr4() & X86_CR4_SMEP))
671 printk(smep_warning, from_kuid(&init_user_ns, current_uid())); 667 pr_crit("unable to execute userspace code (SMEP?) (uid: %d)\n",
668 from_kuid(&init_user_ns, current_uid()));
672 } 669 }
673 670
674 printk(KERN_ALERT "BUG: unable to handle kernel "); 671 pr_alert("BUG: unable to handle kernel %s at %px\n",
675 if (address < PAGE_SIZE) 672 address < PAGE_SIZE ? "NULL pointer dereference" : "paging request",
676 printk(KERN_CONT "NULL pointer dereference"); 673 (void *)address);
677 else
678 printk(KERN_CONT "paging request");
679
680 printk(KERN_CONT " at %px\n", (void *) address);
681 674
682 dump_pagetable(address); 675 dump_pagetable(address);
683} 676}
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index e01f7ceb9e7a..77873ce700ae 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -166,14 +166,14 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd)
166 pgd = pgd_offset_k(pgd_idx * PGDIR_SIZE); 166 pgd = pgd_offset_k(pgd_idx * PGDIR_SIZE);
167 set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]); 167 set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]);
168 168
169 if (!(pgd_val(*pgd) & _PAGE_PRESENT)) 169 if (!pgd_present(*pgd))
170 continue; 170 continue;
171 171
172 for (i = 0; i < PTRS_PER_P4D; i++) { 172 for (i = 0; i < PTRS_PER_P4D; i++) {
173 p4d = p4d_offset(pgd, 173 p4d = p4d_offset(pgd,
174 pgd_idx * PGDIR_SIZE + i * P4D_SIZE); 174 pgd_idx * PGDIR_SIZE + i * P4D_SIZE);
175 175
176 if (!(p4d_val(*p4d) & _PAGE_PRESENT)) 176 if (!p4d_present(*p4d))
177 continue; 177 continue;
178 178
179 pud = (pud_t *)p4d_page_vaddr(*p4d); 179 pud = (pud_t *)p4d_page_vaddr(*p4d);
diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c
index 246145b84a12..4d9dc3f2fd70 100644
--- a/tools/testing/selftests/x86/sigreturn.c
+++ b/tools/testing/selftests/x86/sigreturn.c
@@ -610,21 +610,41 @@ static int test_valid_sigreturn(int cs_bits, bool use_16bit_ss, int force_ss)
610 */ 610 */
611 for (int i = 0; i < NGREG; i++) { 611 for (int i = 0; i < NGREG; i++) {
612 greg_t req = requested_regs[i], res = resulting_regs[i]; 612 greg_t req = requested_regs[i], res = resulting_regs[i];
613
613 if (i == REG_TRAPNO || i == REG_IP) 614 if (i == REG_TRAPNO || i == REG_IP)
614 continue; /* don't care */ 615 continue; /* don't care */
615 if (i == REG_SP) {
616 printf("\tSP: %llx -> %llx\n", (unsigned long long)req,
617 (unsigned long long)res);
618 616
617 if (i == REG_SP) {
619 /* 618 /*
620 * In many circumstances, the high 32 bits of rsp 619 * If we were using a 16-bit stack segment, then
621 * are zeroed. For example, we could be a real 620 * the kernel is a bit stuck: IRET only restores
622 * 32-bit program, or we could hit any of a number 621 * the low 16 bits of ESP/RSP if SS is 16-bit.
623 * of poorly-documented IRET or segmented ESP 622 * The kernel uses a hack to restore bits 31:16,
624 * oddities. If this happens, it's okay. 623 * but that hack doesn't help with bits 63:32.
624 * On Intel CPUs, bits 63:32 end up zeroed, and, on
625 * AMD CPUs, they leak the high bits of the kernel
626 * espfix64 stack pointer. There's very little that
627 * the kernel can do about it.
628 *
629 * Similarly, if we are returning to a 32-bit context,
630 * the CPU will often lose the high 32 bits of RSP.
625 */ 631 */
626 if (res == (req & 0xFFFFFFFF)) 632
627 continue; /* OK; not expected to work */ 633 if (res == req)
634 continue;
635
636 if (cs_bits != 64 && ((res ^ req) & 0xFFFFFFFF) == 0) {
637 printf("[NOTE]\tSP: %llx -> %llx\n",
638 (unsigned long long)req,
639 (unsigned long long)res);
640 continue;
641 }
642
643 printf("[FAIL]\tSP mismatch: requested 0x%llx; got 0x%llx\n",
644 (unsigned long long)requested_regs[i],
645 (unsigned long long)resulting_regs[i]);
646 nerrs++;
647 continue;
628 } 648 }
629 649
630 bool ignore_reg = false; 650 bool ignore_reg = false;
@@ -654,25 +674,18 @@ static int test_valid_sigreturn(int cs_bits, bool use_16bit_ss, int force_ss)
654#endif 674#endif
655 675
656 /* Sanity check on the kernel */ 676 /* Sanity check on the kernel */
657 if (i == REG_CX && requested_regs[i] != resulting_regs[i]) { 677 if (i == REG_CX && req != res) {
658 printf("[FAIL]\tCX (saved SP) mismatch: requested 0x%llx; got 0x%llx\n", 678 printf("[FAIL]\tCX (saved SP) mismatch: requested 0x%llx; got 0x%llx\n",
659 (unsigned long long)requested_regs[i], 679 (unsigned long long)req,
660 (unsigned long long)resulting_regs[i]); 680 (unsigned long long)res);
661 nerrs++; 681 nerrs++;
662 continue; 682 continue;
663 } 683 }
664 684
665 if (requested_regs[i] != resulting_regs[i] && !ignore_reg) { 685 if (req != res && !ignore_reg) {
666 /*
667 * SP is particularly interesting here. The
668 * usual cause of failures is that we hit the
669 * nasty IRET case of returning to a 16-bit SS,
670 * in which case bits 16:31 of the *kernel*
671 * stack pointer persist in ESP.
672 */
673 printf("[FAIL]\tReg %d mismatch: requested 0x%llx; got 0x%llx\n", 686 printf("[FAIL]\tReg %d mismatch: requested 0x%llx; got 0x%llx\n",
674 i, (unsigned long long)requested_regs[i], 687 i, (unsigned long long)req,
675 (unsigned long long)resulting_regs[i]); 688 (unsigned long long)res);
676 nerrs++; 689 nerrs++;
677 } 690 }
678 } 691 }