linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Anshuman Khandual <khandual@linux.vnet.ibm.com>
To: Ram Pai <linuxram@us.ibm.com>,
	linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org
Cc: dave.hansen@intel.com, paulus@samba.org, aneesh.kumar@linux.vnet.ibm.com
Subject: Re: [RFC v2 08/12] powerpc: Handle exceptions caused by violation of pkey protection.
Date: Tue, 20 Jun 2017 12:54:45 +0530	[thread overview]
Message-ID: <a288b72b-3e9c-7bf9-fff4-e5b08bad0374@linux.vnet.ibm.com> (raw)
In-Reply-To: <1497671564-20030-9-git-send-email-linuxram@us.ibm.com>

On 06/17/2017 09:22 AM, Ram Pai wrote:
> Handle Data and Instruction exceptions caused by memory
> protection-key.
> 
> Signed-off-by: Ram Pai <linuxram@us.ibm.com>
> (cherry picked from commit a5e5217619a0c475fe0cacc3b0cf1d3d33c79a09)

To which tree this commit belongs to ?

> 
> Conflicts:
> 	arch/powerpc/include/asm/reg.h
> 	arch/powerpc/kernel/exceptions-64s.S
> ---
>  arch/powerpc/include/asm/mmu_context.h | 12 +++++
>  arch/powerpc/include/asm/pkeys.h       |  9 ++++
>  arch/powerpc/include/asm/reg.h         |  7 +--
>  arch/powerpc/mm/fault.c                | 21 +++++++-
>  arch/powerpc/mm/pkeys.c                | 90 ++++++++++++++++++++++++++++++++++
>  5 files changed, 134 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h
> index da7e943..71fffe0 100644
> --- a/arch/powerpc/include/asm/mmu_context.h
> +++ b/arch/powerpc/include/asm/mmu_context.h
> @@ -175,11 +175,23 @@ static inline void arch_bprm_mm_init(struct mm_struct *mm,
>  {
>  }
> 
> +#ifdef CONFIG_PPC64_MEMORY_PROTECTION_KEYS
> +bool arch_pte_access_permitted(pte_t pte, bool write);
> +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_pte_access_permitted(pte_t pte, bool write)
> +{
> +	/* by default, allow everything */
> +	return true;
> +}
>  static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
>  		bool write, bool execute, bool foreign)
>  {
>  	/* by default, allow everything */
>  	return true;
>  }

Right, these are the two functions the core VM expects the
arch to provide.

> +#endif /* CONFIG_PPC64_MEMORY_PROTECTION_KEYS */
> +
>  #endif /* __KERNEL__ */
>  #endif /* __ASM_POWERPC_MMU_CONTEXT_H */
> diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h
> index 9b6820d..405e7db 100644
> --- a/arch/powerpc/include/asm/pkeys.h
> +++ b/arch/powerpc/include/asm/pkeys.h
> @@ -14,6 +14,15 @@
>  			VM_PKEY_BIT3 | \
>  			VM_PKEY_BIT4)
> 
> +static inline u16 pte_flags_to_pkey(unsigned long pte_flags)
> +{
> +	return ((pte_flags & H_PAGE_PKEY_BIT4) ? 0x1 : 0x0) |
> +		((pte_flags & H_PAGE_PKEY_BIT3) ? 0x2 : 0x0) |
> +		((pte_flags & H_PAGE_PKEY_BIT2) ? 0x4 : 0x0) |
> +		((pte_flags & H_PAGE_PKEY_BIT1) ? 0x8 : 0x0) |
> +		((pte_flags & H_PAGE_PKEY_BIT0) ? 0x10 : 0x0);
> +}

Add defines for the above 0x1, 0x2, 0x4, 0x8 etc ?

> +
>  #define pkey_to_vmflag_bits(key) (((key & 0x1UL) ? VM_PKEY_BIT0 : 0x0UL) | \
>  			((key & 0x2UL) ? VM_PKEY_BIT1 : 0x0UL) |	\
>  			((key & 0x4UL) ? VM_PKEY_BIT2 : 0x0UL) |	\
> diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
> index 2dcb8a1..a11977f 100644
> --- a/arch/powerpc/include/asm/reg.h
> +++ b/arch/powerpc/include/asm/reg.h
> @@ -285,9 +285,10 @@
>  #define   DSISR_UNSUPP_MMU	0x00080000	/* Unsupported MMU config */
>  #define   DSISR_SET_RC		0x00040000	/* Failed setting of R/C bits */
>  #define   DSISR_PGDIRFAULT      0x00020000      /* Fault on page directory */
> -#define   DSISR_PAGE_FAULT_MASK (DSISR_BIT32 | \
> -				DSISR_PAGEATTR_CONFLT | \
> -				DSISR_BADACCESS |       \
> +#define   DSISR_PAGE_FAULT_MASK (DSISR_BIT32 |	\
> +				DSISR_PAGEATTR_CONFLT |	\
> +				DSISR_BADACCESS |	\
> +				DSISR_KEYFAULT |	\
>  				DSISR_BIT43)

This should have been cleaned up before adding new
DSISR_KEYFAULT reason code into it. But I guess its
okay.

>  #define SPRN_TBRL	0x10C	/* Time Base Read Lower Register (user, R/O) */
>  #define SPRN_TBRU	0x10D	/* Time Base Read Upper Register (user, R/O) */
> diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
> index 3a7d580..c31624f 100644
> --- a/arch/powerpc/mm/fault.c
> +++ b/arch/powerpc/mm/fault.c
> @@ -216,9 +216,10 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
>  	 * bits we are interested in.  But there are some bits which
>  	 * indicate errors in DSISR but can validly be set in SRR1.
>  	 */
> -	if (trap == 0x400)
> +	if (trap == 0x400) {
>  		error_code &= 0x48200000;
> -	else
> +		flags |= FAULT_FLAG_INSTRUCTION;
> +	} else
>  		is_write = error_code & DSISR_ISSTORE;
>  #else

Why adding the FAULT_FLAG_INSTRUCTION here ?

>  	is_write = error_code & ESR_DST;
> @@ -261,6 +262,13 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
>  	}
>  #endif
> 
> +#ifdef CONFIG_PPC64_MEMORY_PROTECTION_KEYS
> +	if (error_code & DSISR_KEYFAULT) {
> +		code = SEGV_PKUERR;
> +		goto bad_area_nosemaphore;
> +	}
> +#endif /*  CONFIG_PPC64_MEMORY_PROTECTION_KEYS */
> +
>  	/* We restore the interrupt state now */
>  	if (!arch_irq_disabled_regs(regs))
>  		local_irq_enable();
> @@ -441,6 +449,15 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
>  		WARN_ON_ONCE(error_code & DSISR_PROTFAULT);
>  #endif /* CONFIG_PPC_STD_MMU */
> 
> +#ifdef CONFIG_PPC64_MEMORY_PROTECTION_KEYS
> +	if (!arch_vma_access_permitted(vma, flags & FAULT_FLAG_WRITE,
> +					flags & FAULT_FLAG_INSTRUCTION,
> +					0)) {
> +		code = SEGV_PKUERR;
> +		goto bad_area;
> +	}
> +#endif /* CONFIG_PPC64_MEMORY_PROTECTION_KEYS */
> +

I am wondering why both the above checks are required ?

* DSISR should contains DSISR_KEYFAULT

* VMA pkey values whether they matched the fault cause


>  	/*
>  	 * If for any reason at all we couldn't handle the fault,
>  	 * make sure we exit gracefully rather than endlessly redo
> diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c
> index 11a32b3..439241a 100644
> --- a/arch/powerpc/mm/pkeys.c
> +++ b/arch/powerpc/mm/pkeys.c
> @@ -27,6 +27,37 @@ static inline bool pkey_allows_readwrite(int pkey)
>  	return !(read_amr() & ((AMR_AD_BIT|AMR_WD_BIT) << pkey_shift));
>  }
> 
> +static inline bool pkey_allows_read(int pkey)
> +{
> +	int pkey_shift = (arch_max_pkey()-pkey-1) * AMR_BITS_PER_PKEY;
> +
> +	if (!(read_uamor() & (0x3ul << pkey_shift)))
> +		return true;
> +
> +	return !(read_amr() & (AMR_AD_BIT << pkey_shift));
> +}

Get read_amr() into a local variable and save some cycles if we
have to do it again.

> +
> +static inline bool pkey_allows_write(int pkey)
> +{
> +	int pkey_shift = (arch_max_pkey()-pkey-1) * AMR_BITS_PER_PKEY;
> +
> +	if (!(read_uamor() & (0x3ul << pkey_shift)))
> +		return true;
> +
> +	return !(read_amr() & (AMR_WD_BIT << pkey_shift));
> +}
> +

Ditto

> +static inline bool pkey_allows_execute(int pkey)
> +{
> +	int pkey_shift = (arch_max_pkey()-pkey-1) * AMR_BITS_PER_PKEY;
> +
> +	if (!(read_uamor() & (0x3ul << pkey_shift)))
> +		return true;
> +
> +	return !(read_iamr() & (IAMR_EX_BIT << pkey_shift));
> +}

Ditto

> +
> +
>  /*
>   * set the access right in AMR IAMR and UAMOR register
>   * for @pkey to that specified in @init_val.
> @@ -175,3 +206,62 @@ int __arch_override_mprotect_pkey(struct vm_area_struct *vma, int prot,
>  	 */
>  	return vma_pkey(vma);
>  }
> +
> +bool arch_pte_access_permitted(pte_t pte, bool write)
> +{
> +	int pkey = pte_flags_to_pkey(pte_val(pte));
> +
> +	if (!pkey_allows_read(pkey))
> +		return false;
> +	if (write && !pkey_allows_write(pkey))
> +		return false;
> +	return true;
> +}
> +
> +/*
> + * 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;
> +}
> +

This seems pretty generic, should not be moved to core MM ?

  reply	other threads:[~2017-06-20  7:25 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-17  3:52 [RFC v2 00/12] powerpc: Memory Protection Keys Ram Pai
2017-06-17  3:52 ` [RFC v2 01/12] powerpc: Free up four 64K PTE bits in 4K backed hpte pages Ram Pai
2017-06-20 10:20   ` Anshuman Khandual
2017-06-20 23:23     ` Ram Pai
2017-06-21  5:35       ` Anshuman Khandual
2017-06-21  6:34         ` Ram Pai
2017-06-21  6:41   ` Aneesh Kumar K.V
2017-06-21  9:30     ` Ram Pai
2017-06-22  9:07   ` Anshuman Khandual
2017-06-22 16:20     ` Ram Pai
2017-06-17  3:52 ` [RFC v2 02/12] powerpc: Free up four 64K PTE bits in 64K " Ram Pai
2017-06-20 10:51   ` Anshuman Khandual
2017-06-20 23:25     ` Ram Pai
2017-06-21  6:50   ` Aneesh Kumar K.V
2017-06-21  6:54   ` Aneesh Kumar K.V
2017-06-21 20:14     ` Ram Pai
2017-06-17  3:52 ` [RFC v2 03/12] powerpc: Implement sys_pkey_alloc and sys_pkey_free system call Ram Pai
2017-06-19 12:18   ` Michael Ellerman
2017-06-20 22:45     ` Ram Pai
2017-06-17  3:52 ` [RFC v2 04/12] powerpc: store and restore the pkey state across context switches Ram Pai
2017-06-17  3:52 ` [RFC v2 05/12] powerpc: Implementation for sys_mprotect_pkey() system call Ram Pai
2017-06-21  7:16   ` Aneesh Kumar K.V
2017-06-17  3:52 ` [RFC v2 06/12] powerpc: Program HPTE key protection bits Ram Pai
2017-06-20  8:21   ` Anshuman Khandual
2017-06-20 23:26     ` Ram Pai
2017-06-17  3:52 ` [RFC v2 07/12] powerpc: Macro the mask used for checking DSI exception Ram Pai
2017-06-20  8:14   ` Anshuman Khandual
2017-06-20 23:28     ` Ram Pai
2017-06-21  7:25   ` Aneesh Kumar K.V
2017-06-21  9:17     ` Ram Pai
2017-06-17  3:52 ` [RFC v2 08/12] powerpc: Handle exceptions caused by violation of pkey protection Ram Pai
2017-06-20  7:24   ` Anshuman Khandual [this message]
2017-06-20 23:43     ` Ram Pai
2017-06-21  3:54       ` Anshuman Khandual
2017-06-21  6:26         ` Ram Pai
2017-06-17  3:52 ` [RFC v2 09/12] powerpc: Deliver SEGV signal on pkey violation Ram Pai
2017-06-20  6:54   ` Anshuman Khandual
2017-06-20 23:56     ` Ram Pai
2017-06-21  3:18       ` Anshuman Khandual
2017-06-21  6:10         ` Ram Pai
2017-06-17  3:52 ` [RFC v2 10/12] powerpc: Read AMR only if pkey-violation caused the exception Ram Pai
2017-06-19 11:06   ` Michael Ellerman
2017-06-19 17:59     ` Ram Pai
2017-06-20  6:46       ` Anshuman Khandual
2017-06-20 23:58         ` Ram Pai
2017-06-20 23:56     ` Ram Pai
2017-06-17  3:52 ` [RFC v2 11/12]Documentation: Documentation updates Ram Pai
2017-06-20  6:18   ` Anshuman Khandual
2017-06-21  0:04     ` Ram Pai
2017-06-17  3:52 ` [RFC v2 12/12]selftest: Updated protection key selftest Ram Pai
2017-06-19 11:04   ` Michael Ellerman
2017-06-20  6:26   ` Anshuman Khandual
2017-06-21  0:10     ` Ram Pai
2017-06-20  5:10 ` [RFC v2 00/12] powerpc: Memory Protection Keys Balbir Singh
2017-06-20  6:05   ` Anshuman Khandual
2017-06-20  9:56   ` Benjamin Herrenschmidt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a288b72b-3e9c-7bf9-fff4-e5b08bad0374@linux.vnet.ibm.com \
    --to=khandual@linux.vnet.ibm.com \
    --cc=aneesh.kumar@linux.vnet.ibm.com \
    --cc=dave.hansen@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=linuxram@us.ibm.com \
    --cc=paulus@samba.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).