Skip to content

Commit ceb647b

Browse files
jgross1Ingo Molnar
authored andcommitted
x86/pat: Introduce lookup_address_in_pgd_attr()
Add lookup_address_in_pgd_attr() doing the same as the already existing lookup_address_in_pgd(), but returning the effective settings of the NX and RW bits of all walked page table levels, too. This will be needed in order to match hardware behavior when looking for effective access rights, especially for detecting writable code pages. In order to avoid code duplication, let lookup_address_in_pgd() call lookup_address_in_pgd_attr() with dummy parameters. Signed-off-by: Juergen Gross <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 72374d7 commit ceb647b

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

arch/x86/include/asm/pgtable_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,8 @@ static inline void update_page_count(int level, unsigned long pages) { }
566566
extern pte_t *lookup_address(unsigned long address, unsigned int *level);
567567
extern pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
568568
unsigned int *level);
569+
pte_t *lookup_address_in_pgd_attr(pgd_t *pgd, unsigned long address,
570+
unsigned int *level, bool *nx, bool *rw);
569571
extern pmd_t *lookup_pmd_address(unsigned long address);
570572
extern phys_addr_t slow_virt_to_phys(void *__address);
571573
extern int __init kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn,

arch/x86/mm/pat/set_memory.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -657,20 +657,26 @@ static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long star
657657

658658
/*
659659
* Lookup the page table entry for a virtual address in a specific pgd.
660-
* Return a pointer to the entry and the level of the mapping.
660+
* Return a pointer to the entry, the level of the mapping, and the effective
661+
* NX and RW bits of all page table levels.
661662
*/
662-
pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
663-
unsigned int *level)
663+
pte_t *lookup_address_in_pgd_attr(pgd_t *pgd, unsigned long address,
664+
unsigned int *level, bool *nx, bool *rw)
664665
{
665666
p4d_t *p4d;
666667
pud_t *pud;
667668
pmd_t *pmd;
668669

669670
*level = PG_LEVEL_NONE;
671+
*nx = false;
672+
*rw = true;
670673

671674
if (pgd_none(*pgd))
672675
return NULL;
673676

677+
*nx |= pgd_flags(*pgd) & _PAGE_NX;
678+
*rw &= pgd_flags(*pgd) & _PAGE_RW;
679+
674680
p4d = p4d_offset(pgd, address);
675681
if (p4d_none(*p4d))
676682
return NULL;
@@ -679,6 +685,9 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
679685
if (p4d_leaf(*p4d) || !p4d_present(*p4d))
680686
return (pte_t *)p4d;
681687

688+
*nx |= p4d_flags(*p4d) & _PAGE_NX;
689+
*rw &= p4d_flags(*p4d) & _PAGE_RW;
690+
682691
pud = pud_offset(p4d, address);
683692
if (pud_none(*pud))
684693
return NULL;
@@ -687,6 +696,9 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
687696
if (pud_leaf(*pud) || !pud_present(*pud))
688697
return (pte_t *)pud;
689698

699+
*nx |= pud_flags(*pud) & _PAGE_NX;
700+
*rw &= pud_flags(*pud) & _PAGE_RW;
701+
690702
pmd = pmd_offset(pud, address);
691703
if (pmd_none(*pmd))
692704
return NULL;
@@ -695,11 +707,26 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
695707
if (pmd_leaf(*pmd) || !pmd_present(*pmd))
696708
return (pte_t *)pmd;
697709

710+
*nx |= pmd_flags(*pmd) & _PAGE_NX;
711+
*rw &= pmd_flags(*pmd) & _PAGE_RW;
712+
698713
*level = PG_LEVEL_4K;
699714

700715
return pte_offset_kernel(pmd, address);
701716
}
702717

718+
/*
719+
* Lookup the page table entry for a virtual address in a specific pgd.
720+
* Return a pointer to the entry and the level of the mapping.
721+
*/
722+
pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
723+
unsigned int *level)
724+
{
725+
bool nx, rw;
726+
727+
return lookup_address_in_pgd_attr(pgd, address, level, &nx, &rw);
728+
}
729+
703730
/*
704731
* Lookup the page table entry for a virtual address. Return a pointer
705732
* to the entry and the level of the mapping.

0 commit comments

Comments
 (0)