Skip to content

Commit 6b0a02e

Browse files
committed
Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 pti updates from Thomas Gleixner: "Another series of PTI related changes: - Remove the manual stack switch for user entries from the idtentry code. This debloats entry by 5k+ bytes of text. - Use the proper types for the asm/bootparam.h defines to prevent user space compile errors. - Use PAGE_GLOBAL for !PCID systems to gain back performance - Prevent setting of huge PUD/PMD entries when the entries are not leaf entries otherwise the entries to which the PUD/PMD points to and are populated get lost" * 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/pgtable: Don't set huge PUD/PMD on non-leaf entries x86/pti: Leave kernel text global for !PCID x86/pti: Never implicitly clear _PAGE_GLOBAL for kernel image x86/pti: Enable global pages for shared areas x86/mm: Do not forbid _PAGE_RW before init for __ro_after_init x86/mm: Comment _PAGE_GLOBAL mystery x86/mm: Remove extra filtering in pageattr code x86/mm: Do not auto-massage page protections x86/espfix: Document use of _PAGE_GLOBAL x86/mm: Introduce "default" kernel PTE mask x86/mm: Undo double _PAGE_PSE clearing x86/mm: Factor out pageattr _PAGE_GLOBAL setting x86/entry/64: Drop idtentry's manual stack switch for user entries x86/uapi: Fix asm/bootparam.h userspace compilation errors
2 parents 71b8ebb + e3e2881 commit 6b0a02e

File tree

22 files changed

+329
-105
lines changed

22 files changed

+329
-105
lines changed

arch/x86/boot/compressed/kaslr.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ unsigned int ptrs_per_p4d __ro_after_init = 1;
5454

5555
extern unsigned long get_cmd_line_ptr(void);
5656

57+
/* Used by PAGE_KERN* macros: */
58+
pteval_t __default_kernel_pte_mask __read_mostly = ~0;
59+
5760
/* Simplified build-specific string for starting entropy. */
5861
static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
5962
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;

arch/x86/entry/entry_64.S

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,7 @@ ENTRY(\sym)
913913
pushq $-1 /* ORIG_RAX: no syscall to restart */
914914
.endif
915915

916-
.if \paranoid < 2
916+
.if \paranoid == 1
917917
testb $3, CS-ORIG_RAX(%rsp) /* If coming from userspace, switch stacks */
918918
jnz .Lfrom_usermode_switch_stack_\@
919919
.endif
@@ -960,7 +960,7 @@ ENTRY(\sym)
960960
jmp error_exit
961961
.endif
962962

963-
.if \paranoid < 2
963+
.if \paranoid == 1
964964
/*
965965
* Entry from userspace. Switch stacks and treat it
966966
* as a normal entry. This means that paranoid handlers

arch/x86/include/asm/pgtable.h

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -526,22 +526,39 @@ static inline pgprotval_t massage_pgprot(pgprot_t pgprot)
526526
return protval;
527527
}
528528

529+
static inline pgprotval_t check_pgprot(pgprot_t pgprot)
530+
{
531+
pgprotval_t massaged_val = massage_pgprot(pgprot);
532+
533+
/* mmdebug.h can not be included here because of dependencies */
534+
#ifdef CONFIG_DEBUG_VM
535+
WARN_ONCE(pgprot_val(pgprot) != massaged_val,
536+
"attempted to set unsupported pgprot: %016llx "
537+
"bits: %016llx supported: %016llx\n",
538+
(u64)pgprot_val(pgprot),
539+
(u64)pgprot_val(pgprot) ^ massaged_val,
540+
(u64)__supported_pte_mask);
541+
#endif
542+
543+
return massaged_val;
544+
}
545+
529546
static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
530547
{
531548
return __pte(((phys_addr_t)page_nr << PAGE_SHIFT) |
532-
massage_pgprot(pgprot));
549+
check_pgprot(pgprot));
533550
}
534551

535552
static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
536553
{
537554
return __pmd(((phys_addr_t)page_nr << PAGE_SHIFT) |
538-
massage_pgprot(pgprot));
555+
check_pgprot(pgprot));
539556
}
540557

541558
static inline pud_t pfn_pud(unsigned long page_nr, pgprot_t pgprot)
542559
{
543560
return __pud(((phys_addr_t)page_nr << PAGE_SHIFT) |
544-
massage_pgprot(pgprot));
561+
check_pgprot(pgprot));
545562
}
546563

547564
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
@@ -553,7 +570,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
553570
* the newprot (if present):
554571
*/
555572
val &= _PAGE_CHG_MASK;
556-
val |= massage_pgprot(newprot) & ~_PAGE_CHG_MASK;
573+
val |= check_pgprot(newprot) & ~_PAGE_CHG_MASK;
557574

558575
return __pte(val);
559576
}
@@ -563,7 +580,7 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
563580
pmdval_t val = pmd_val(pmd);
564581

565582
val &= _HPAGE_CHG_MASK;
566-
val |= massage_pgprot(newprot) & ~_HPAGE_CHG_MASK;
583+
val |= check_pgprot(newprot) & ~_HPAGE_CHG_MASK;
567584

568585
return __pmd(val);
569586
}

arch/x86/include/asm/pgtable_types.h

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -196,19 +196,21 @@ enum page_cache_mode {
196196
#define __PAGE_KERNEL_NOENC (__PAGE_KERNEL)
197197
#define __PAGE_KERNEL_NOENC_WP (__PAGE_KERNEL_WP)
198198

199-
#define PAGE_KERNEL __pgprot(__PAGE_KERNEL | _PAGE_ENC)
200-
#define PAGE_KERNEL_NOENC __pgprot(__PAGE_KERNEL)
201-
#define PAGE_KERNEL_RO __pgprot(__PAGE_KERNEL_RO | _PAGE_ENC)
202-
#define PAGE_KERNEL_EXEC __pgprot(__PAGE_KERNEL_EXEC | _PAGE_ENC)
203-
#define PAGE_KERNEL_EXEC_NOENC __pgprot(__PAGE_KERNEL_EXEC)
204-
#define PAGE_KERNEL_RX __pgprot(__PAGE_KERNEL_RX | _PAGE_ENC)
205-
#define PAGE_KERNEL_NOCACHE __pgprot(__PAGE_KERNEL_NOCACHE | _PAGE_ENC)
206-
#define PAGE_KERNEL_LARGE __pgprot(__PAGE_KERNEL_LARGE | _PAGE_ENC)
207-
#define PAGE_KERNEL_LARGE_EXEC __pgprot(__PAGE_KERNEL_LARGE_EXEC | _PAGE_ENC)
208-
#define PAGE_KERNEL_VVAR __pgprot(__PAGE_KERNEL_VVAR | _PAGE_ENC)
209-
210-
#define PAGE_KERNEL_IO __pgprot(__PAGE_KERNEL_IO)
211-
#define PAGE_KERNEL_IO_NOCACHE __pgprot(__PAGE_KERNEL_IO_NOCACHE)
199+
#define default_pgprot(x) __pgprot((x) & __default_kernel_pte_mask)
200+
201+
#define PAGE_KERNEL default_pgprot(__PAGE_KERNEL | _PAGE_ENC)
202+
#define PAGE_KERNEL_NOENC default_pgprot(__PAGE_KERNEL)
203+
#define PAGE_KERNEL_RO default_pgprot(__PAGE_KERNEL_RO | _PAGE_ENC)
204+
#define PAGE_KERNEL_EXEC default_pgprot(__PAGE_KERNEL_EXEC | _PAGE_ENC)
205+
#define PAGE_KERNEL_EXEC_NOENC default_pgprot(__PAGE_KERNEL_EXEC)
206+
#define PAGE_KERNEL_RX default_pgprot(__PAGE_KERNEL_RX | _PAGE_ENC)
207+
#define PAGE_KERNEL_NOCACHE default_pgprot(__PAGE_KERNEL_NOCACHE | _PAGE_ENC)
208+
#define PAGE_KERNEL_LARGE default_pgprot(__PAGE_KERNEL_LARGE | _PAGE_ENC)
209+
#define PAGE_KERNEL_LARGE_EXEC default_pgprot(__PAGE_KERNEL_LARGE_EXEC | _PAGE_ENC)
210+
#define PAGE_KERNEL_VVAR default_pgprot(__PAGE_KERNEL_VVAR | _PAGE_ENC)
211+
212+
#define PAGE_KERNEL_IO default_pgprot(__PAGE_KERNEL_IO)
213+
#define PAGE_KERNEL_IO_NOCACHE default_pgprot(__PAGE_KERNEL_IO_NOCACHE)
212214

213215
#endif /* __ASSEMBLY__ */
214216

@@ -483,6 +485,7 @@ static inline pgprot_t pgprot_large_2_4k(pgprot_t pgprot)
483485
typedef struct page *pgtable_t;
484486

485487
extern pteval_t __supported_pte_mask;
488+
extern pteval_t __default_kernel_pte_mask;
486489
extern void set_nx(void);
487490
extern int nx_enabled;
488491

arch/x86/include/asm/pti.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
#ifdef CONFIG_PAGE_TABLE_ISOLATION
77
extern void pti_init(void);
88
extern void pti_check_boottime_disable(void);
9+
extern void pti_clone_kernel_text(void);
910
#else
1011
static inline void pti_check_boottime_disable(void) { }
12+
static inline void pti_clone_kernel_text(void) { }
1113
#endif
1214

1315
#endif /* __ASSEMBLY__ */

arch/x86/include/uapi/asm/bootparam.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,15 @@ struct boot_e820_entry {
137137
* setup data structure.
138138
*/
139139
struct jailhouse_setup_data {
140-
u16 version;
141-
u16 compatible_version;
142-
u16 pm_timer_address;
143-
u16 num_cpus;
144-
u64 pci_mmconfig_base;
145-
u32 tsc_khz;
146-
u32 apic_khz;
147-
u8 standard_ioapic;
148-
u8 cpu_ids[255];
140+
__u16 version;
141+
__u16 compatible_version;
142+
__u16 pm_timer_address;
143+
__u16 num_cpus;
144+
__u64 pci_mmconfig_base;
145+
__u32 tsc_khz;
146+
__u32 apic_khz;
147+
__u8 standard_ioapic;
148+
__u8 cpu_ids[255];
149149
} __attribute__((packed));
150150

151151
/* The so-called "zeropage" */

arch/x86/kernel/espfix_64.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ void init_espfix_ap(int cpu)
195195

196196
pte_p = pte_offset_kernel(&pmd, addr);
197197
stack_page = page_address(alloc_pages_node(node, GFP_KERNEL, 0));
198+
/*
199+
* __PAGE_KERNEL_* includes _PAGE_GLOBAL, which we want since
200+
* this is mapped to userspace.
201+
*/
198202
pte = __pte(__pa(stack_page) | ((__PAGE_KERNEL_RO | _PAGE_ENC) & ptemask));
199203
for (n = 0; n < ESPFIX_PTE_CLONES; n++)
200204
set_pte(&pte_p[n*PTE_STRIDE], pte);

arch/x86/kernel/head64.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ unsigned long __head __startup_64(unsigned long physaddr,
195195
pud[i + 1] = (pudval_t)pmd + pgtable_flags;
196196

197197
pmd_entry = __PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL;
198+
/* Filter out unsupported __PAGE_KERNEL_* bits: */
199+
pmd_entry &= __supported_pte_mask;
198200
pmd_entry += sme_get_me_mask();
199201
pmd_entry += physaddr;
200202

arch/x86/kernel/head_64.S

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,8 +399,13 @@ NEXT_PAGE(level3_ident_pgt)
399399
.quad level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC
400400
.fill 511, 8, 0
401401
NEXT_PAGE(level2_ident_pgt)
402-
/* Since I easily can, map the first 1G.
402+
/*
403+
* Since I easily can, map the first 1G.
403404
* Don't set NX because code runs from these pages.
405+
*
406+
* Note: This sets _PAGE_GLOBAL despite whether
407+
* the CPU supports it or it is enabled. But,
408+
* the CPU should ignore the bit.
404409
*/
405410
PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, PTRS_PER_PMD)
406411
#else
@@ -431,6 +436,10 @@ NEXT_PAGE(level2_kernel_pgt)
431436
* (NOTE: at +512MB starts the module area, see MODULES_VADDR.
432437
* If you want to increase this then increase MODULES_VADDR
433438
* too.)
439+
*
440+
* This table is eventually used by the kernel during normal
441+
* runtime. Care must be taken to clear out undesired bits
442+
* later, like _PAGE_RW or _PAGE_GLOBAL in some cases.
434443
*/
435444
PMDS(0, __PAGE_KERNEL_LARGE_EXEC,
436445
KERNEL_IMAGE_SIZE/PMD_SIZE)

arch/x86/kernel/ldt.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot)
145145
unsigned long offset = i << PAGE_SHIFT;
146146
const void *src = (char *)ldt->entries + offset;
147147
unsigned long pfn;
148+
pgprot_t pte_prot;
148149
pte_t pte, *ptep;
149150

150151
va = (unsigned long)ldt_slot_va(slot) + offset;
@@ -163,7 +164,10 @@ map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot)
163164
* target via some kernel interface which misses a
164165
* permission check.
165166
*/
166-
pte = pfn_pte(pfn, __pgprot(__PAGE_KERNEL_RO & ~_PAGE_GLOBAL));
167+
pte_prot = __pgprot(__PAGE_KERNEL_RO & ~_PAGE_GLOBAL);
168+
/* Filter out unsuppored __PAGE_KERNEL* bits: */
169+
pgprot_val(pte_prot) |= __supported_pte_mask;
170+
pte = pfn_pte(pfn, pte_prot);
167171
set_pte_at(mm, va, ptep, pte);
168172
pte_unmap_unlock(ptep, ptl);
169173
}

0 commit comments

Comments
 (0)