Skip to content

Commit 639ab3e

Browse files
committed
Merge branch 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 mm changes from Ingo Molnar: "The main changes are: continued PAT work by Toshi Kani, plus a new boot time warning about insecure RWX kernel mappings, by Stephen Smalley. The new CONFIG_DEBUG_WX=y warning is marked default-y if CONFIG_DEBUG_RODATA=y is already eanbled, as a special exception, as these bugs are hard to notice and this check already found several live bugs" * 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/mm: Warn on W^X mappings x86/mm: Fix no-change case in try_preserve_large_page() x86/mm: Fix __split_large_page() to handle large PAT bit x86/mm: Fix try_preserve_large_page() to handle large PAT bit x86/mm: Fix gup_huge_p?d() to handle large PAT bit x86/mm: Fix slow_virt_to_phys() to handle large PAT bit x86/mm: Fix page table dump to show PAT bit x86/asm: Add pud_pgprot() and pmd_pgprot() x86/asm: Fix pud/pmd interfaces to handle large PAT bit x86/asm: Add pud/pmd mask interfaces to handle large PAT bit x86/asm: Move PUD_PAGE macros to page_types.h x86/vdso32: Define PGTABLE_LEVELS to 32bit VDSO
2 parents 4302d50 + e1a5832 commit 639ab3e

File tree

12 files changed

+219
-74
lines changed

12 files changed

+219
-74
lines changed

arch/x86/Kconfig.debug

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,14 @@ config EARLY_PRINTK_EFI
6565
This is useful for kernel debugging when your machine crashes very
6666
early before the console code is initialized.
6767

68+
config X86_PTDUMP_CORE
69+
def_bool n
70+
6871
config X86_PTDUMP
6972
bool "Export kernel pagetable layout to userspace via debugfs"
7073
depends on DEBUG_KERNEL
7174
select DEBUG_FS
75+
select X86_PTDUMP_CORE
7276
---help---
7377
Say Y here if you want to show the kernel pagetable layout in a
7478
debugfs file. This information is only useful for kernel developers
@@ -79,7 +83,8 @@ config X86_PTDUMP
7983

8084
config EFI_PGT_DUMP
8185
bool "Dump the EFI pagetable"
82-
depends on EFI && X86_PTDUMP
86+
depends on EFI
87+
select X86_PTDUMP_CORE
8388
---help---
8489
Enable this if you want to dump the EFI page table before
8590
enabling virtual mode. This can be used to debug miscellaneous
@@ -105,6 +110,35 @@ config DEBUG_RODATA_TEST
105110
feature as well as for the change_page_attr() infrastructure.
106111
If in doubt, say "N"
107112

113+
config DEBUG_WX
114+
bool "Warn on W+X mappings at boot"
115+
depends on DEBUG_RODATA
116+
default y
117+
select X86_PTDUMP_CORE
118+
---help---
119+
Generate a warning if any W+X mappings are found at boot.
120+
121+
This is useful for discovering cases where the kernel is leaving
122+
W+X mappings after applying NX, as such mappings are a security risk.
123+
124+
Look for a message in dmesg output like this:
125+
126+
x86/mm: Checked W+X mappings: passed, no W+X pages found.
127+
128+
or like this, if the check failed:
129+
130+
x86/mm: Checked W+X mappings: FAILED, <N> W+X pages found.
131+
132+
Note that even if the check fails, your kernel is possibly
133+
still fine, as W+X mappings are not a security hole in
134+
themselves, what they do is that they make the exploitation
135+
of other unfixed kernel bugs easier.
136+
137+
There is no runtime or memory usage effect of this option
138+
once the kernel has booted up - it's a one time check.
139+
140+
If in doubt, say "Y".
141+
108142
config DEBUG_SET_MODULE_RONX
109143
bool "Set loadable kernel module data as NX and text as RO"
110144
depends on MODULES

arch/x86/entry/vdso/vdso32/vclock_gettime.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
*/
1515
#undef CONFIG_64BIT
1616
#undef CONFIG_X86_64
17+
#undef CONFIG_PGTABLE_LEVELS
1718
#undef CONFIG_ILLEGAL_POINTER_VALUE
1819
#undef CONFIG_SPARSEMEM_VMEMMAP
1920
#undef CONFIG_NR_CPUS
2021

2122
#define CONFIG_X86_32 1
23+
#define CONFIG_PGTABLE_LEVELS 2
2224
#define CONFIG_PAGE_OFFSET 0
2325
#define CONFIG_ILLEGAL_POINTER_VALUE 0
2426
#define CONFIG_NR_CPUS 1

arch/x86/include/asm/page_64_types.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@
2626
#define MCE_STACK 4
2727
#define N_EXCEPTION_STACKS 4 /* hw limit: 7 */
2828

29-
#define PUD_PAGE_SIZE (_AC(1, UL) << PUD_SHIFT)
30-
#define PUD_PAGE_MASK (~(PUD_PAGE_SIZE-1))
31-
3229
/*
3330
* Set __PAGE_OFFSET to the most negative possible address +
3431
* PGDIR_SIZE*16 (pgd slot 272). The gap is to allow a space for a

arch/x86/include/asm/page_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
#define PMD_PAGE_SIZE (_AC(1, UL) << PMD_SHIFT)
2121
#define PMD_PAGE_MASK (~(PMD_PAGE_SIZE-1))
2222

23+
#define PUD_PAGE_SIZE (_AC(1, UL) << PUD_SHIFT)
24+
#define PUD_PAGE_MASK (~(PUD_PAGE_SIZE-1))
25+
2326
#define HPAGE_SHIFT PMD_SHIFT
2427
#define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT)
2528
#define HPAGE_MASK (~(HPAGE_SIZE - 1))

arch/x86/include/asm/pgtable.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@
1919
#include <asm/x86_init.h>
2020

2121
void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd);
22+
void ptdump_walk_pgd_level_checkwx(void);
23+
24+
#ifdef CONFIG_DEBUG_WX
25+
#define debug_checkwx() ptdump_walk_pgd_level_checkwx()
26+
#else
27+
#define debug_checkwx() do { } while (0)
28+
#endif
2229

2330
/*
2431
* ZERO_PAGE is a global shared page that is always zero: used
@@ -142,12 +149,12 @@ static inline unsigned long pte_pfn(pte_t pte)
142149

143150
static inline unsigned long pmd_pfn(pmd_t pmd)
144151
{
145-
return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT;
152+
return (pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
146153
}
147154

148155
static inline unsigned long pud_pfn(pud_t pud)
149156
{
150-
return (pud_val(pud) & PTE_PFN_MASK) >> PAGE_SHIFT;
157+
return (pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT;
151158
}
152159

153160
#define pte_page(pte) pfn_to_page(pte_pfn(pte))
@@ -379,7 +386,9 @@ static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
379386
return __pgprot(preservebits | addbits);
380387
}
381388

382-
#define pte_pgprot(x) __pgprot(pte_flags(x) & PTE_FLAGS_MASK)
389+
#define pte_pgprot(x) __pgprot(pte_flags(x))
390+
#define pmd_pgprot(x) __pgprot(pmd_flags(x))
391+
#define pud_pgprot(x) __pgprot(pud_flags(x))
383392

384393
#define canon_pgprot(p) __pgprot(massage_pgprot(p))
385394

@@ -502,14 +511,15 @@ static inline int pmd_none(pmd_t pmd)
502511

503512
static inline unsigned long pmd_page_vaddr(pmd_t pmd)
504513
{
505-
return (unsigned long)__va(pmd_val(pmd) & PTE_PFN_MASK);
514+
return (unsigned long)__va(pmd_val(pmd) & pmd_pfn_mask(pmd));
506515
}
507516

508517
/*
509518
* Currently stuck as a macro due to indirect forward reference to
510519
* linux/mmzone.h's __section_mem_map_addr() definition:
511520
*/
512-
#define pmd_page(pmd) pfn_to_page((pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT)
521+
#define pmd_page(pmd) \
522+
pfn_to_page((pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT)
513523

514524
/*
515525
* the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
@@ -570,14 +580,15 @@ static inline int pud_present(pud_t pud)
570580

571581
static inline unsigned long pud_page_vaddr(pud_t pud)
572582
{
573-
return (unsigned long)__va((unsigned long)pud_val(pud) & PTE_PFN_MASK);
583+
return (unsigned long)__va(pud_val(pud) & pud_pfn_mask(pud));
574584
}
575585

576586
/*
577587
* Currently stuck as a macro due to indirect forward reference to
578588
* linux/mmzone.h's __section_mem_map_addr() definition:
579589
*/
580-
#define pud_page(pud) pfn_to_page(pud_val(pud) >> PAGE_SHIFT)
590+
#define pud_page(pud) \
591+
pfn_to_page((pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT)
581592

582593
/* Find an entry in the second-level page table.. */
583594
static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)

arch/x86/include/asm/pgtable_types.h

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,10 @@ enum page_cache_mode {
209209

210210
#include <linux/types.h>
211211

212-
/* PTE_PFN_MASK extracts the PFN from a (pte|pmd|pud|pgd)val_t */
212+
/* Extracts the PFN from a (pte|pmd|pud|pgd)val_t of a 4KB page */
213213
#define PTE_PFN_MASK ((pteval_t)PHYSICAL_PAGE_MASK)
214214

215-
/* PTE_FLAGS_MASK extracts the flags from a (pte|pmd|pud|pgd)val_t */
215+
/* Extracts the flags from a (pte|pmd|pud|pgd)val_t of a 4KB page */
216216
#define PTE_FLAGS_MASK (~PTE_PFN_MASK)
217217

218218
typedef struct pgprot { pgprotval_t pgprot; } pgprot_t;
@@ -276,14 +276,46 @@ static inline pmdval_t native_pmd_val(pmd_t pmd)
276276
}
277277
#endif
278278

279+
static inline pudval_t pud_pfn_mask(pud_t pud)
280+
{
281+
if (native_pud_val(pud) & _PAGE_PSE)
282+
return PUD_PAGE_MASK & PHYSICAL_PAGE_MASK;
283+
else
284+
return PTE_PFN_MASK;
285+
}
286+
287+
static inline pudval_t pud_flags_mask(pud_t pud)
288+
{
289+
if (native_pud_val(pud) & _PAGE_PSE)
290+
return ~(PUD_PAGE_MASK & (pudval_t)PHYSICAL_PAGE_MASK);
291+
else
292+
return ~PTE_PFN_MASK;
293+
}
294+
279295
static inline pudval_t pud_flags(pud_t pud)
280296
{
281-
return native_pud_val(pud) & PTE_FLAGS_MASK;
297+
return native_pud_val(pud) & pud_flags_mask(pud);
298+
}
299+
300+
static inline pmdval_t pmd_pfn_mask(pmd_t pmd)
301+
{
302+
if (native_pmd_val(pmd) & _PAGE_PSE)
303+
return PMD_PAGE_MASK & PHYSICAL_PAGE_MASK;
304+
else
305+
return PTE_PFN_MASK;
306+
}
307+
308+
static inline pmdval_t pmd_flags_mask(pmd_t pmd)
309+
{
310+
if (native_pmd_val(pmd) & _PAGE_PSE)
311+
return ~(PMD_PAGE_MASK & (pmdval_t)PHYSICAL_PAGE_MASK);
312+
else
313+
return ~PTE_PFN_MASK;
282314
}
283315

284316
static inline pmdval_t pmd_flags(pmd_t pmd)
285317
{
286-
return native_pmd_val(pmd) & PTE_FLAGS_MASK;
318+
return native_pmd_val(pmd) & pmd_flags_mask(pmd);
287319
}
288320

289321
static inline pte_t native_make_pte(pteval_t val)

arch/x86/mm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ obj-$(CONFIG_SMP) += tlb.o
1414
obj-$(CONFIG_X86_32) += pgtable_32.o iomap_32.o
1515

1616
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
17-
obj-$(CONFIG_X86_PTDUMP) += dump_pagetables.o
17+
obj-$(CONFIG_X86_PTDUMP_CORE) += dump_pagetables.o
1818

1919
obj-$(CONFIG_HIGHMEM) += highmem_32.o
2020

0 commit comments

Comments
 (0)