diff mbox series

[v9,5/7] poweprc: mm: Implement *_user_accessible_page() for ptes

Message ID 20231130025404.37179-8-rmclure@linux.ibm.com (mailing list archive)
State Changes Requested
Headers show
Series Support page table check | expand

Commit Message

Rohan McLure Nov. 30, 2023, 2:53 a.m. UTC
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(+)

Comments

Christophe Leroy Nov. 30, 2023, 7:01 a.m. UTC | #1
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 mbox series

Patch

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 */