[19/25] powerpc: implementation for arch_vma_access_permitted()

Message ID 1504910713-7094-28-git-send-email-linuxram@us.ibm.com
State Changes Requested
Headers show
Series
  • powerpc: Free up RPAGE_RSV bits
Related show

Commit Message

Ram Pai Sept. 8, 2017, 10:45 p.m.
This patch provides the implementation for
arch_vma_access_permitted(). Returns true if the
requested access is allowed by pkey associated with the
vma.

Signed-off-by: Ram Pai <linuxram@us.ibm.com>
---
 arch/powerpc/include/asm/mmu_context.h |    5 +++-
 arch/powerpc/mm/pkeys.c                |   43 ++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 1 deletions(-)

Comments

Balbir Singh Oct. 18, 2017, 11:20 p.m. | #1
On Fri,  8 Sep 2017 15:45:07 -0700
Ram Pai <linuxram@us.ibm.com> wrote:

> This patch provides the implementation for
> arch_vma_access_permitted(). Returns true if the
> requested access is allowed by pkey associated with the
> vma.
> 
> Signed-off-by: Ram Pai <linuxram@us.ibm.com>
> ---
>  arch/powerpc/include/asm/mmu_context.h |    5 +++-
>  arch/powerpc/mm/pkeys.c                |   43 ++++++++++++++++++++++++++++++++
>  2 files changed, 47 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h
> index 04e9221..9a56355 100644
> --- a/arch/powerpc/include/asm/mmu_context.h
> +++ b/arch/powerpc/include/asm/mmu_context.h
> @@ -135,6 +135,10 @@ static inline void arch_bprm_mm_init(struct mm_struct *mm,
>  {
>  }
>  
> +#ifdef CONFIG_PPC64_MEMORY_PROTECTION_KEYS
> +bool arch_vma_access_permitted(struct vm_area_struct *vma,
> +			bool write, bool execute, bool foreign);
> +#else /* CONFIG_PPC64_MEMORY_PROTECTION_KEYS */
>  static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
>  		bool write, bool execute, bool foreign)
>  {
> @@ -142,7 +146,6 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
>  	return true;
>  }
>  
> -#ifndef CONFIG_PPC64_MEMORY_PROTECTION_KEYS
>  #define pkey_initialize()
>  #define pkey_mm_init(mm)
>  
> diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c
> index 24589d9..21c3b42 100644
> --- a/arch/powerpc/mm/pkeys.c
> +++ b/arch/powerpc/mm/pkeys.c
> @@ -320,3 +320,46 @@ bool arch_pte_access_permitted(u64 pte, bool write, bool execute)
>  	return pkey_access_permitted(pte_to_pkey_bits(pte),
>  			write, execute);
>  }
> +
> +/*
> + * We only want to enforce protection keys on the current process
> + * because we effectively have no access to AMR/IAMR for other
> + * processes or any way to tell *which * AMR/IAMR in a threaded
> + * process we could use.
> + *
> + * So do not enforce things if the VMA is not from the current
> + * mm, or if we are in a kernel thread.
> + */
> +static inline bool vma_is_foreign(struct vm_area_struct *vma)
> +{
> +	if (!current->mm)
> +		return true;
> +	/*
> +	 * if the VMA is from another process, then AMR/IAMR has no
> +	 * relevance and should not be enforced.
> +	 */
> +	if (current->mm != vma->vm_mm)
> +		return true;
> +
> +	return false;
> +}
> +
> +bool arch_vma_access_permitted(struct vm_area_struct *vma,
> +		bool write, bool execute, bool foreign)
> +{
> +	int pkey;
> +
> +	if (!pkey_inited)
> +		return true;
> +
> +	/* allow access if the VMA is not one from this process */
> +	if (foreign || vma_is_foreign(vma))
> +		return true;
> +
> +	pkey = vma_pkey(vma);
> +
> +	if (!pkey)
> +		return true;
> +
> +	return pkey_access_permitted(pkey, write, execute);
> +}

Again, I think this is GUP, I don't really understand the top level
use case of enforcing permissions for GUP in a thread context.

Balbir Singh.
Michael Ellerman Oct. 24, 2017, 3:48 p.m. | #2
Ram Pai <linuxram@us.ibm.com> writes:

> diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c
> index 24589d9..21c3b42 100644
> --- a/arch/powerpc/mm/pkeys.c
> +++ b/arch/powerpc/mm/pkeys.c
> @@ -320,3 +320,46 @@ bool arch_pte_access_permitted(u64 pte, bool write, bool execute)
>  	return pkey_access_permitted(pte_to_pkey_bits(pte),
>  			write, execute);
>  }
> +
> +/*
> + * We only want to enforce protection keys on the current process
> + * because we effectively have no access to AMR/IAMR for other
> + * processes or any way to tell *which * AMR/IAMR in a threaded
> + * process we could use.

This comment doesn't match the code, or at least is confusing to me.

A "threaded process" is two tasks that have the same mm. ie. where
current->mm == vma->mm.

And in that case we *do* enforce protection, based on the AMR/IAMR of
the current thread.

> + * So do not enforce things if the VMA is not from the current
> + * mm, or if we are in a kernel thread.
> + */
> +static inline bool vma_is_foreign(struct vm_area_struct *vma)
> +{
> +	if (!current->mm)
> +		return true;
> +	/*
> +	 * if the VMA is from another process, then AMR/IAMR has no
> +	 * relevance and should not be enforced.
> +	 */
> +	if (current->mm != vma->vm_mm)
> +		return true;

ie. threaded processes end up here, because they *do* share an mm.

> +
> +	return false;
> +}
> +
> +bool arch_vma_access_permitted(struct vm_area_struct *vma,
> +		bool write, bool execute, bool foreign)
> +{
> +	int pkey;
> +
> +	if (!pkey_inited)
> +		return true;
> +
> +	/* allow access if the VMA is not one from this process */
> +	if (foreign || vma_is_foreign(vma))
> +		return true;
> +
> +	pkey = vma_pkey(vma);
> +
> +	if (!pkey)
> +		return true;

I think I'd prefer if we didn't special case key 0, instead just let it
go through to pkey_access_permitted().

> +
> +	return pkey_access_permitted(pkey, write, execute);
> +}

cheers

Patch

diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h
index 04e9221..9a56355 100644
--- a/arch/powerpc/include/asm/mmu_context.h
+++ b/arch/powerpc/include/asm/mmu_context.h
@@ -135,6 +135,10 @@  static inline void arch_bprm_mm_init(struct mm_struct *mm,
 {
 }
 
+#ifdef CONFIG_PPC64_MEMORY_PROTECTION_KEYS
+bool arch_vma_access_permitted(struct vm_area_struct *vma,
+			bool write, bool execute, bool foreign);
+#else /* CONFIG_PPC64_MEMORY_PROTECTION_KEYS */
 static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
 		bool write, bool execute, bool foreign)
 {
@@ -142,7 +146,6 @@  static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
 	return true;
 }
 
-#ifndef CONFIG_PPC64_MEMORY_PROTECTION_KEYS
 #define pkey_initialize()
 #define pkey_mm_init(mm)
 
diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c
index 24589d9..21c3b42 100644
--- a/arch/powerpc/mm/pkeys.c
+++ b/arch/powerpc/mm/pkeys.c
@@ -320,3 +320,46 @@  bool arch_pte_access_permitted(u64 pte, bool write, bool execute)
 	return pkey_access_permitted(pte_to_pkey_bits(pte),
 			write, execute);
 }
+
+/*
+ * We only want to enforce protection keys on the current process
+ * because we effectively have no access to AMR/IAMR for other
+ * processes or any way to tell *which * AMR/IAMR in a threaded
+ * process we could use.
+ *
+ * So do not enforce things if the VMA is not from the current
+ * mm, or if we are in a kernel thread.
+ */
+static inline bool vma_is_foreign(struct vm_area_struct *vma)
+{
+	if (!current->mm)
+		return true;
+	/*
+	 * if the VMA is from another process, then AMR/IAMR has no
+	 * relevance and should not be enforced.
+	 */
+	if (current->mm != vma->vm_mm)
+		return true;
+
+	return false;
+}
+
+bool arch_vma_access_permitted(struct vm_area_struct *vma,
+		bool write, bool execute, bool foreign)
+{
+	int pkey;
+
+	if (!pkey_inited)
+		return true;
+
+	/* allow access if the VMA is not one from this process */
+	if (foreign || vma_is_foreign(vma))
+		return true;
+
+	pkey = vma_pkey(vma);
+
+	if (!pkey)
+		return true;
+
+	return pkey_access_permitted(pkey, write, execute);
+}