2022-04-18 11:21:29

by Tong Tiangen

[permalink] [raw]
Subject: [PATCH -next v4 0/4]mm: page_table_check: add support on arm64 and riscv

Page table check performs extra verifications at the time when new
pages become accessible from the userspace by getting their page
table entries (PTEs PMDs etc.) added into the table. It is supported
on X86[1].

This patchset made some simple changes and make it easier to support
new architecture, then we support this feature on ARM64 and RISCV.

[1]https://lore.kernel.org/lkml/[email protected]/

v3 -> v4:
1. Adapt to next-20220414

v2 -> v3:
1. Modify ptep_clear() in include/linux/pgtable.h, using IS_ENABLED
according to the suggestions of Pasha.

v1 -> v2:
1. Fix arm64's pte/pmd/pud_user_accessible_page() according to the
suggestions of Catalin.
2. Also fix riscv's pte_pmd_pud_user_accessible_page().

Kefeng Wang (2):
mm: page_table_check: move pxx_user_accessible_page into x86
arm64: mm: add support for page table check

Tong Tiangen (2):
mm: page_table_check: add hooks to public helpers
riscv: mm: add support for page table check

arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/pgtable.h | 65 ++++++++++++++++++++++++---
arch/riscv/Kconfig | 1 +
arch/riscv/include/asm/pgtable.h | 77 +++++++++++++++++++++++++++++---
arch/x86/include/asm/pgtable.h | 29 +++++++-----
include/linux/pgtable.h | 26 +++++++----
mm/page_table_check.c | 25 ++++-------
7 files changed, 178 insertions(+), 46 deletions(-)

--
2.25.1


2022-04-18 17:57:08

by Tong Tiangen

[permalink] [raw]
Subject: Re: [PATCH -next v4 0/4]mm: page_table_check: add support on arm64 and riscv

Hi Andrew, Catalin, Palmer:

This patch modifies the code related to the mm/x86/arm64/riscv, who can
help me merge it if no object, Maybe Andrew is more appropriate?

Thanks,
Tong.

在 2022/4/18 11:44, Tong Tiangen 写道:
> Page table check performs extra verifications at the time when new
> pages become accessible from the userspace by getting their page
> table entries (PTEs PMDs etc.) added into the table. It is supported
> on X86[1].
>
> This patchset made some simple changes and make it easier to support
> new architecture, then we support this feature on ARM64 and RISCV.
>
> [1]https://lore.kernel.org/lkml/[email protected]/
>
> v3 -> v4:
> 1. Adapt to next-20220414
>
> v2 -> v3:
> 1. Modify ptep_clear() in include/linux/pgtable.h, using IS_ENABLED
> according to the suggestions of Pasha.
>
> v1 -> v2:
> 1. Fix arm64's pte/pmd/pud_user_accessible_page() according to the
> suggestions of Catalin.
> 2. Also fix riscv's pte_pmd_pud_user_accessible_page().
>
> Kefeng Wang (2):
> mm: page_table_check: move pxx_user_accessible_page into x86
> arm64: mm: add support for page table check
>
> Tong Tiangen (2):
> mm: page_table_check: add hooks to public helpers
> riscv: mm: add support for page table check
>
> arch/arm64/Kconfig | 1 +
> arch/arm64/include/asm/pgtable.h | 65 ++++++++++++++++++++++++---
> arch/riscv/Kconfig | 1 +
> arch/riscv/include/asm/pgtable.h | 77 +++++++++++++++++++++++++++++---
> arch/x86/include/asm/pgtable.h | 29 +++++++-----
> include/linux/pgtable.h | 26 +++++++----
> mm/page_table_check.c | 25 ++++-------
> 7 files changed, 178 insertions(+), 46 deletions(-)
>

2022-04-18 18:44:45

by Tong Tiangen

[permalink] [raw]
Subject: [PATCH -next v4 4/4] riscv: mm: add support for page table check

As commit d283d422c6c4 ("x86: mm: add x86_64 support for page table
check"), add some necessary page table check hooks into routines that
modify user page tables.

Signed-off-by: Tong Tiangen <[email protected]>
Reviewed-by: Pasha Tatashin <[email protected]>
---
arch/riscv/Kconfig | 1 +
arch/riscv/include/asm/pgtable.h | 77 +++++++++++++++++++++++++++++---
2 files changed, 72 insertions(+), 6 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 63f7258984f3..66d241cee52c 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -38,6 +38,7 @@ config RISCV
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU
select ARCH_SUPPORTS_HUGETLBFS if MMU
+ select ARCH_SUPPORTS_PAGE_TABLE_CHECK
select ARCH_USE_MEMTEST
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
select ARCH_WANT_FRAME_POINTERS
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 046b44225623..6f22d9580658 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -114,6 +114,8 @@
#include <asm/pgtable-32.h>
#endif /* CONFIG_64BIT */

+#include <linux/page_table_check.h>
+
#ifdef CONFIG_XIP_KERNEL
#define XIP_FIXUP(addr) ({ \
uintptr_t __a = (uintptr_t)(addr); \
@@ -315,6 +317,11 @@ static inline int pte_exec(pte_t pte)
return pte_val(pte) & _PAGE_EXEC;
}

+static inline int pte_user(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_USER;
+}
+
static inline int pte_huge(pte_t pte)
{
return pte_present(pte) && (pte_val(pte) & _PAGE_LEAF);
@@ -446,7 +453,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)

void flush_icache_pte(pte_t pte);

-static inline void set_pte_at(struct mm_struct *mm,
+static inline void __set_pte_at(struct mm_struct *mm,
unsigned long addr, pte_t *ptep, pte_t pteval)
{
if (pte_present(pteval) && pte_exec(pteval))
@@ -455,10 +462,17 @@ static inline void set_pte_at(struct mm_struct *mm,
set_pte(ptep, pteval);
}

+static inline void set_pte_at(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep, pte_t pteval)
+{
+ page_table_check_pte_set(mm, addr, ptep, pteval);
+ __set_pte_at(mm, addr, ptep, pteval);
+}
+
static inline void pte_clear(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
{
- set_pte_at(mm, addr, ptep, __pte(0));
+ __set_pte_at(mm, addr, ptep, __pte(0));
}

#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
@@ -475,11 +489,21 @@ static inline int ptep_set_access_flags(struct vm_area_struct *vma,
return true;
}

+static inline pte_t __ptep_get_and_clear(struct mm_struct *mm,
+ unsigned long address, pte_t *ptep)
+{
+ return __pte(atomic_long_xchg((atomic_long_t *)ptep, 0));
+}
+
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
unsigned long address, pte_t *ptep)
{
- return __pte(atomic_long_xchg((atomic_long_t *)ptep, 0));
+ pte_t pte = __ptep_get_and_clear(mm, address, ptep);
+
+ page_table_check_pte_clear(mm, address, pte);
+
+ return pte;
}

#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
@@ -546,6 +570,13 @@ static inline unsigned long pmd_pfn(pmd_t pmd)
return ((__pmd_to_phys(pmd) & PMD_MASK) >> PAGE_SHIFT);
}

+#define __pud_to_phys(pud) (pud_val(pud) >> _PAGE_PFN_SHIFT << PAGE_SHIFT)
+
+static inline unsigned long pud_pfn(pud_t pud)
+{
+ return ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT);
+}
+
static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
{
return pte_pmd(pte_modify(pmd_pte(pmd), newprot));
@@ -567,6 +598,11 @@ static inline int pmd_young(pmd_t pmd)
return pte_young(pmd_pte(pmd));
}

+static inline int pmd_user(pmd_t pmd)
+{
+ return pte_user(pmd_pte(pmd));
+}
+
static inline pmd_t pmd_mkold(pmd_t pmd)
{
return pte_pmd(pte_mkold(pmd_pte(pmd)));
@@ -600,15 +636,39 @@ static inline pmd_t pmd_mkdirty(pmd_t pmd)
static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
pmd_t *pmdp, pmd_t pmd)
{
- return set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd));
+ page_table_check_pmd_set(mm, addr, pmdp, pmd);
+ return __set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd));
+}
+
+static inline int pud_user(pud_t pud)
+{
+ return pte_user(pud_pte(pud));
}

static inline void set_pud_at(struct mm_struct *mm, unsigned long addr,
pud_t *pudp, pud_t pud)
{
- return set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud));
+ page_table_check_pud_set(mm, addr, pudp, pud);
+ return __set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud));
+}
+
+#ifdef CONFIG_PAGE_TABLE_CHECK
+static inline bool pte_user_accessible_page(pte_t pte)
+{
+ return pte_present(pte) && pte_user(pte);
}

+static inline bool pmd_user_accessible_page(pmd_t pmd)
+{
+ return pmd_leaf(pmd) && pmd_user(pmd);
+}
+
+static inline bool pud_user_accessible_page(pud_t pud)
+{
+ return pud_leaf(pud) && pud_user(pud);
+}
+#endif
+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static inline int pmd_trans_huge(pmd_t pmd)
{
@@ -634,7 +694,11 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
unsigned long address, pmd_t *pmdp)
{
- return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
+ pmd_t pmd = pte_pmd(__ptep_get_and_clear(mm, address, (pte_t *)pmdp));
+
+ page_table_check_pmd_clear(mm, address, pmd);
+
+ return pmd;
}

#define __HAVE_ARCH_PMDP_SET_WRPROTECT
@@ -648,6 +712,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
unsigned long address, pmd_t *pmdp, pmd_t pmd)
{
+ page_table_check_pmd_set(vma->vm_mm, address, pmdp, pmd);
return __pmd(atomic_long_xchg((atomic_long_t *)pmdp, pmd_val(pmd)));
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
--
2.25.1

2022-04-20 07:28:16

by Tong Tiangen

[permalink] [raw]
Subject: [PATCH -next v4 1/4] mm: page_table_check: move pxx_user_accessible_page into x86

From: Kefeng Wang <[email protected]>

The pxx_user_accessible_page() check the PTE bit, it's
architecture-specific code, move them into x86's pgtable.h,
also add default PMD/PUD_PAGE_SIZE definition, it's prepare
for support page table check feature on new architecture.

Signed-off-by: Kefeng Wang <[email protected]>
Acked-by: Pasha Tatashin <[email protected]>
---
arch/x86/include/asm/pgtable.h | 19 +++++++++++++++++++
mm/page_table_check.c | 25 ++++++++-----------------
2 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index b7464f13e416..564abe42b0f7 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -1447,6 +1447,25 @@ static inline bool arch_has_hw_pte_young(void)
return true;
}

+#ifdef CONFIG_PAGE_TABLE_CHECK
+static inline bool pte_user_accessible_page(pte_t pte)
+{
+ return (pte_val(pte) & _PAGE_PRESENT) && (pte_val(pte) & _PAGE_USER);
+}
+
+static inline bool pmd_user_accessible_page(pmd_t pmd)
+{
+ return pmd_leaf(pmd) && (pmd_val(pmd) & _PAGE_PRESENT) &&
+ (pmd_val(pmd) & _PAGE_USER);
+}
+
+static inline bool pud_user_accessible_page(pud_t pud)
+{
+ return pud_leaf(pud) && (pud_val(pud) & _PAGE_PRESENT) &&
+ (pud_val(pud) & _PAGE_USER);
+}
+#endif
+
#endif /* __ASSEMBLY__ */

#endif /* _ASM_X86_PGTABLE_H */
diff --git a/mm/page_table_check.c b/mm/page_table_check.c
index 2458281bff89..145f059d1c4d 100644
--- a/mm/page_table_check.c
+++ b/mm/page_table_check.c
@@ -10,6 +10,14 @@
#undef pr_fmt
#define pr_fmt(fmt) "page_table_check: " fmt

+#ifndef PMD_PAGE_SIZE
+#define PMD_PAGE_SIZE PMD_SIZE
+#endif
+
+#ifndef PUD_PAGE_SIZE
+#define PUD_PAGE_SIZE PUD_SIZE
+#endif
+
struct page_table_check {
atomic_t anon_map_count;
atomic_t file_map_count;
@@ -52,23 +60,6 @@ static struct page_table_check *get_page_table_check(struct page_ext *page_ext)
return (void *)(page_ext) + page_table_check_ops.offset;
}

-static inline bool pte_user_accessible_page(pte_t pte)
-{
- return (pte_val(pte) & _PAGE_PRESENT) && (pte_val(pte) & _PAGE_USER);
-}
-
-static inline bool pmd_user_accessible_page(pmd_t pmd)
-{
- return pmd_leaf(pmd) && (pmd_val(pmd) & _PAGE_PRESENT) &&
- (pmd_val(pmd) & _PAGE_USER);
-}
-
-static inline bool pud_user_accessible_page(pud_t pud)
-{
- return pud_leaf(pud) && (pud_val(pud) & _PAGE_PRESENT) &&
- (pud_val(pud) & _PAGE_USER);
-}
-
/*
* An enty is removed from the page table, decrement the counters for that page
* verify that it is of correct type and counters do not become negative.
--
2.25.1

2022-04-21 15:11:35

by Pasha Tatashin

[permalink] [raw]
Subject: Re: [PATCH -next v4 1/4] mm: page_table_check: move pxx_user_accessible_page into x86

On Wed, Apr 20, 2022 at 2:45 AM Tong Tiangen <[email protected]> wrote:
>
>
>
> 在 2022/4/19 17:29, Anshuman Khandual 写道:
> >
> >
> > On 4/18/22 09:14, Tong Tiangen wrote:
> >> --- a/mm/page_table_check.c
> >> +++ b/mm/page_table_check.c
> >> @@ -10,6 +10,14 @@
> >> #undef pr_fmt
> >> #define pr_fmt(fmt) "page_table_check: " fmt
> >>
> >> +#ifndef PMD_PAGE_SIZE
> >> +#define PMD_PAGE_SIZE PMD_SIZE
> >> +#endif
> >> +
> >> +#ifndef PUD_PAGE_SIZE
> >> +#define PUD_PAGE_SIZE PUD_SIZE
> >> +#endif
> >
> > Why cannot PMD_SIZE/PUD_SIZE be used on every platform instead ? What is the
> > need for using PUD_PAGE_SIZE/PMD_PAGE_SIZE ? Are they different on x86 ?
> > .
>
> Hi, Pasha:
> I checked the definitions of PMD_SIZE/PUD_SIZE and
> PUD_PAGE_SIZE/PMD_PAGE_SIZE in x86 architecture and their use outside
> the architecture(eg: in mm/, all used PMD_SIZE/PUD_SIZE), Would it be
> better to use a unified PMD_SIZE/PUD_SIZE here?

Hi Tong,

Yes, it makes sense to use PMD_SIZE/PUD_SIZE instead of
PUD_PAGE_SIZE/PMD_PAGE_SIZE in page_table_check to be inline with the
rest of the mm/

Pasha

>
> Thanks,
> Tong.

2022-04-21 19:47:10

by Tong Tiangen

[permalink] [raw]
Subject: Re: [PATCH -next v4 1/4] mm: page_table_check: move pxx_user_accessible_page into x86



在 2022/4/21 11:44, Anshuman Khandual 写道:
>
>
> On 4/21/22 08:35, Tong Tiangen wrote:
>>
>>
>> 在 2022/4/21 0:44, Pasha Tatashin 写道:
>>> On Wed, Apr 20, 2022 at 2:45 AM Tong Tiangen <[email protected]> wrote:
>>>>
>>>>
>>>>
>>>> 在 2022/4/19 17:29, Anshuman Khandual 写道:
>>>>>
>>>>>
>>>>> On 4/18/22 09:14, Tong Tiangen wrote:
>>>>>> --- a/mm/page_table_check.c
>>>>>> +++ b/mm/page_table_check.c
>>>>>> @@ -10,6 +10,14 @@
>>>>>>    #undef pr_fmt
>>>>>>    #define pr_fmt(fmt)        "page_table_check: " fmt
>>>>>>
>>>>>> +#ifndef PMD_PAGE_SIZE
>>>>>> +#define PMD_PAGE_SIZE       PMD_SIZE
>>>>>> +#endif
>>>>>> +
>>>>>> +#ifndef PUD_PAGE_SIZE
>>>>>> +#define PUD_PAGE_SIZE       PUD_SIZE
>>>>>> +#endif
>>>>>
>>>>> Why cannot PMD_SIZE/PUD_SIZE be used on every platform instead ? What is the
>>>>> need for using PUD_PAGE_SIZE/PMD_PAGE_SIZE ? Are they different on x86 ?
>>>>> .
>>>>
>>>> Hi, Pasha:
>>>> I checked the definitions of PMD_SIZE/PUD_SIZE and
>>>> PUD_PAGE_SIZE/PMD_PAGE_SIZE in x86 architecture and their use outside
>>>> the architecture(eg: in mm/, all used PMD_SIZE/PUD_SIZE), Would it be
>>>> better to use a unified PMD_SIZE/PUD_SIZE here?
>>>
>>> Hi Tong,
>>>
>>> Yes, it makes sense to use PMD_SIZE/PUD_SIZE instead of
>>> PUD_PAGE_SIZE/PMD_PAGE_SIZE in page_table_check to be inline with the
>>> rest of the mm/
>>>
>>> Pasha
>>>
>> Hi Pasha and Anshuman:
>>
>> OK, Functional correctness is not affected here, i plan to optimize this point after this patchset is merged.
>
> As page table check is now being proposed to be supported on multiple platforms i.e
> arm64, riscv besides just x86, it should not have any architecture specific macros
> or functions. Hence please do generalize these PMD/PUD sizes in this series itself.
> .

OK, will resend.

Thank you.
Tong.

2022-04-22 21:57:00

by Anshuman Khandual

[permalink] [raw]
Subject: Re: [PATCH -next v4 1/4] mm: page_table_check: move pxx_user_accessible_page into x86



On 4/21/22 08:35, Tong Tiangen wrote:
>
>
> 在 2022/4/21 0:44, Pasha Tatashin 写道:
>> On Wed, Apr 20, 2022 at 2:45 AM Tong Tiangen <[email protected]> wrote:
>>>
>>>
>>>
>>> 在 2022/4/19 17:29, Anshuman Khandual 写道:
>>>>
>>>>
>>>> On 4/18/22 09:14, Tong Tiangen wrote:
>>>>> --- a/mm/page_table_check.c
>>>>> +++ b/mm/page_table_check.c
>>>>> @@ -10,6 +10,14 @@
>>>>>    #undef pr_fmt
>>>>>    #define pr_fmt(fmt)        "page_table_check: " fmt
>>>>>
>>>>> +#ifndef PMD_PAGE_SIZE
>>>>> +#define PMD_PAGE_SIZE       PMD_SIZE
>>>>> +#endif
>>>>> +
>>>>> +#ifndef PUD_PAGE_SIZE
>>>>> +#define PUD_PAGE_SIZE       PUD_SIZE
>>>>> +#endif
>>>>
>>>> Why cannot PMD_SIZE/PUD_SIZE be used on every platform instead ? What is the
>>>> need for using PUD_PAGE_SIZE/PMD_PAGE_SIZE ? Are they different on x86 ?
>>>> .
>>>
>>> Hi, Pasha:
>>> I checked the definitions of PMD_SIZE/PUD_SIZE and
>>> PUD_PAGE_SIZE/PMD_PAGE_SIZE in x86 architecture and their use outside
>>> the architecture(eg: in mm/, all used PMD_SIZE/PUD_SIZE), Would it be
>>> better to use a unified PMD_SIZE/PUD_SIZE here?
>>
>> Hi Tong,
>>
>> Yes, it makes sense to use PMD_SIZE/PUD_SIZE instead of
>> PUD_PAGE_SIZE/PMD_PAGE_SIZE in page_table_check to be inline with the
>> rest of the mm/
>>
>> Pasha
>>
> Hi Pasha and Anshuman:
>
> OK, Functional correctness is not affected here, i plan to optimize this point after this patchset is merged.

As page table check is now being proposed to be supported on multiple platforms i.e
arm64, riscv besides just x86, it should not have any architecture specific macros
or functions. Hence please do generalize these PMD/PUD sizes in this series itself.

2022-04-22 22:32:33

by Tong Tiangen

[permalink] [raw]
Subject: Re: [PATCH -next v4 1/4] mm: page_table_check: move pxx_user_accessible_page into x86



在 2022/4/21 0:44, Pasha Tatashin 写道:
> On Wed, Apr 20, 2022 at 2:45 AM Tong Tiangen <[email protected]> wrote:
>>
>>
>>
>> 在 2022/4/19 17:29, Anshuman Khandual 写道:
>>>
>>>
>>> On 4/18/22 09:14, Tong Tiangen wrote:
>>>> --- a/mm/page_table_check.c
>>>> +++ b/mm/page_table_check.c
>>>> @@ -10,6 +10,14 @@
>>>> #undef pr_fmt
>>>> #define pr_fmt(fmt) "page_table_check: " fmt
>>>>
>>>> +#ifndef PMD_PAGE_SIZE
>>>> +#define PMD_PAGE_SIZE PMD_SIZE
>>>> +#endif
>>>> +
>>>> +#ifndef PUD_PAGE_SIZE
>>>> +#define PUD_PAGE_SIZE PUD_SIZE
>>>> +#endif
>>>
>>> Why cannot PMD_SIZE/PUD_SIZE be used on every platform instead ? What is the
>>> need for using PUD_PAGE_SIZE/PMD_PAGE_SIZE ? Are they different on x86 ?
>>> .
>>
>> Hi, Pasha:
>> I checked the definitions of PMD_SIZE/PUD_SIZE and
>> PUD_PAGE_SIZE/PMD_PAGE_SIZE in x86 architecture and their use outside
>> the architecture(eg: in mm/, all used PMD_SIZE/PUD_SIZE), Would it be
>> better to use a unified PMD_SIZE/PUD_SIZE here?
>
> Hi Tong,
>
> Yes, it makes sense to use PMD_SIZE/PUD_SIZE instead of
> PUD_PAGE_SIZE/PMD_PAGE_SIZE in page_table_check to be inline with the
> rest of the mm/
>
> Pasha
>
Hi Pasha and Anshuman:

OK, Functional correctness is not affected here, i plan to optimize this
point after this patchset is merged.

Tong.

>>
>> Thanks,
>> Tong.
> .