Message ID | 20231130025404.37179-8-rmclure@linux.ibm.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | Support page table check | expand |
Le 30/11/2023 à 03:53, Rohan McLure a écrit : > Page table checking depends on architectures providing an > implementation of p{te,md,ud}_user_accessible_page. With > refactorisations made on powerpc/mm, the pte_access_permitted() and > similar methods verify whether a userland page is accessible with the > required permissions. > > Since page table checking is the only user of > p{te,md,ud}_user_accessible_page(), implement these for all platforms, > using some of the same preliminay checks taken by pte_access_permitted() > on that platform. pte_access_permitted() returns false on an exec-only page. As far as I can see in arm64, pte_user_accessible_page() returns true on an exec-only page. In addition, pte_access_permitted() is called only from GUP so is garanteed to be called only for user pages. Do we have the same garantee from callers of pte_user_accessible_page() ? If not it is needed to check address in addition, see commit a78587473642 ("powerpc: Rely on address instead of pte_user()") > > Since Commit 8e9bd41e4ce1 ("powerpc/nohash: Replace pte_user() by pte_read()") > pte_user() is no longer required to be present on all platforms as it > may be equivalent to or implied by pte_read(). Hence implementations are > specialised. pte_user() is not equivalent nor implies by pte_read(). In most platforms it is implied by the address being below TASK_SIZE. pte_read() will also return true on kernel readable pages. > > Signed-off-by: Rohan McLure <rmclure@linux.ibm.com> > --- > v9: New implementation > --- > arch/powerpc/include/asm/book3s/32/pgtable.h | 5 +++++ > arch/powerpc/include/asm/book3s/64/pgtable.h | 5 +++++ > arch/powerpc/include/asm/nohash/pgtable.h | 5 +++++ > arch/powerpc/include/asm/pgtable.h | 15 +++++++++++++++ > 4 files changed, 30 insertions(+) > > diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h > index 9cc95a61d2a6..bd6f8cdd25aa 100644 > --- a/arch/powerpc/include/asm/book3s/32/pgtable.h > +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h > @@ -441,6 +441,11 @@ static inline bool pte_access_permitted(pte_t pte, bool write) > return true; > } > > +static inline bool pte_user_accessible_page(pte_t pte) > +{ > + return pte_present(pte) && pte_read(pte); > +} > + > /* Conversion functions: convert a page and protection to a page entry, > * and a page entry and page directory to the page they refer to. > * > diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h > index 2454174b26cb..dd3e7b190ab7 100644 > --- a/arch/powerpc/include/asm/book3s/64/pgtable.h > +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h > @@ -544,6 +544,11 @@ static inline bool pte_access_permitted(pte_t pte, bool write) > return arch_pte_access_permitted(pte_val(pte), write, 0); > } > > +static inline bool pte_user_accessible_page(pte_t pte) > +{ > + return pte_present(pte) && pte_user(pte) && pte_read(pte); > +} > + > /* > * Conversion functions: convert a page and protection to a page entry, > * and a page entry and page directory to the page they refer to. > diff --git a/arch/powerpc/include/asm/nohash/pgtable.h b/arch/powerpc/include/asm/nohash/pgtable.h > index 427db14292c9..33b4a4267f66 100644 > --- a/arch/powerpc/include/asm/nohash/pgtable.h > +++ b/arch/powerpc/include/asm/nohash/pgtable.h > @@ -213,6 +213,11 @@ static inline bool pte_access_permitted(pte_t pte, bool write) > return true; > } > > +static inline bool pte_user_accessible_page(pte_t pte) > +{ > + return pte_present(pte) && pte_read(pte); > +} > + > /* Conversion functions: convert a page and protection to a page entry, > * and a page entry and page directory to the page they refer to. > * > diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h > index d7d0f47760d3..661bf3afca37 100644 > --- a/arch/powerpc/include/asm/pgtable.h > +++ b/arch/powerpc/include/asm/pgtable.h > @@ -250,6 +250,21 @@ static inline pte_t pud_pte(pud_t pud) > return __pte(pud_val(pud)); > } > #endif > + > +static inline bool pmd_user_accessible_page(pmd_t pmd) > +{ > + pte_t pte = pmd_pte(pmd); > + > + return pte_user_accessible_page(pte); No need of that pte local var, can fit as a single line. > +} > + > +static inline bool pud_user_accessible_page(pud_t pud) > +{ > + pte_t pte = pud_pte(pud); > + > + return pte_user_accessible_page(pte); Same. > +} > + > #endif /* __ASSEMBLY__ */ > > #endif /* _ASM_POWERPC_PGTABLE_H */
diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h index 9cc95a61d2a6..bd6f8cdd25aa 100644 --- a/arch/powerpc/include/asm/book3s/32/pgtable.h +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h @@ -441,6 +441,11 @@ static inline bool pte_access_permitted(pte_t pte, bool write) return true; } +static inline bool pte_user_accessible_page(pte_t pte) +{ + return pte_present(pte) && pte_read(pte); +} + /* Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. * diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index 2454174b26cb..dd3e7b190ab7 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h @@ -544,6 +544,11 @@ static inline bool pte_access_permitted(pte_t pte, bool write) return arch_pte_access_permitted(pte_val(pte), write, 0); } +static inline bool pte_user_accessible_page(pte_t pte) +{ + return pte_present(pte) && pte_user(pte) && pte_read(pte); +} + /* * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. diff --git a/arch/powerpc/include/asm/nohash/pgtable.h b/arch/powerpc/include/asm/nohash/pgtable.h index 427db14292c9..33b4a4267f66 100644 --- a/arch/powerpc/include/asm/nohash/pgtable.h +++ b/arch/powerpc/include/asm/nohash/pgtable.h @@ -213,6 +213,11 @@ static inline bool pte_access_permitted(pte_t pte, bool write) return true; } +static inline bool pte_user_accessible_page(pte_t pte) +{ + return pte_present(pte) && pte_read(pte); +} + /* Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. * diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index d7d0f47760d3..661bf3afca37 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -250,6 +250,21 @@ static inline pte_t pud_pte(pud_t pud) return __pte(pud_val(pud)); } #endif + +static inline bool pmd_user_accessible_page(pmd_t pmd) +{ + pte_t pte = pmd_pte(pmd); + + return pte_user_accessible_page(pte); +} + +static inline bool pud_user_accessible_page(pud_t pud) +{ + pte_t pte = pud_pte(pud); + + return pte_user_accessible_page(pte); +} + #endif /* __ASSEMBLY__ */ #endif /* _ASM_POWERPC_PGTABLE_H */
Page table checking depends on architectures providing an implementation of p{te,md,ud}_user_accessible_page. With refactorisations made on powerpc/mm, the pte_access_permitted() and similar methods verify whether a userland page is accessible with the required permissions. Since page table checking is the only user of p{te,md,ud}_user_accessible_page(), implement these for all platforms, using some of the same preliminay checks taken by pte_access_permitted() on that platform. Since Commit 8e9bd41e4ce1 ("powerpc/nohash: Replace pte_user() by pte_read()") pte_user() is no longer required to be present on all platforms as it may be equivalent to or implied by pte_read(). Hence implementations are specialised. Signed-off-by: Rohan McLure <rmclure@linux.ibm.com> --- v9: New implementation --- arch/powerpc/include/asm/book3s/32/pgtable.h | 5 +++++ arch/powerpc/include/asm/book3s/64/pgtable.h | 5 +++++ arch/powerpc/include/asm/nohash/pgtable.h | 5 +++++ arch/powerpc/include/asm/pgtable.h | 15 +++++++++++++++ 4 files changed, 30 insertions(+)