powerpc, mm: Memory Protection Keys
Subsystems (10)
v10 cover powerpc, mm: Memory Protection Keys
Memory protection keys enable applications to protect its address space from inadvertent access from or corruption by itself.
These patches along with the pte-bit freeing patch series enables the protection key feature on powerpc; 4k and 64k hashpage kernels.
Will send the documentation and selftest patches separately
All patches can be found at --
https://github.com/rampai/memorykeys.git memkey.v10
The overall idea:
-----------------
A process allocates a key and associates it with an address range within its address space. The process then can dynamically set read/write permissions on the key without involving the kernel. Any code that violates the permissions of the address space; as defined by its associated key, will receive a segmentation fault.
This patch series enables the feature on PPC64 HPTE platform.
ISA3.0 section 5.7.13 describes the detailed
specifications.
Highlevel view of the design:
---------------------------
When an application associates a key with a address address range, program the key in the Linux PTE. When the MMU detects a page fault, allocate a hash page and program the key into HPTE. And finally when the MMU detects a key violation; due to invalid application access, invoke the registered signal handler and provide the violated key number.
Testing:
-------
This patch series has passed all the protection key tests available in the selftest directory.The tests are updated to work on both x86 and powerpc. The selftests have passed on x86 and powerpc hardware.
History:
-------
version v10:
(1) key-fault in page-fault handler is handled as normal fault and not as a bad fault.
(2) changed device tree scanning to unflattened device tree.
(3) fixed a bug in the logic that detected the total number of available pkeys.
(4) dropped two patches. (i) sysfs interface (ii) sys_pkey_modif() syscall
version v9:
(1) used jump-labels to optimize code -- Balbir
(2) fixed a register initialization bug noted by Balbir
(3) fixed inappropriate use of paca to pass siginfo and keys to signal handler
(4) Cleanup of comment style not to be right justified -- mpe
(5) restructured the patches to depend on the availability of VM_PKEY_BIT4 in include/linux/mm.h
(6) Incorporated comments from Dave Hansen towards changes to selftest and got them tested on x86.
version v8:
(1) Contents of the AMR register withdrawn from the siginfo structure. Applications can always read the AMR register.
(2) AMR/IAMR/UAMOR are now available through ptrace system call. -- thanks to Thiago
(3) code changes to handle legacy power cpus that do not support execute-disable.
(4) incorporates many code improvement suggestions.
version v7:
(1) refers to device tree property to enable protection keys.
(2) adds 4K PTE support.
(3) fixes a couple of bugs noticed by Thiago
(4) decouples this patch series from arch- independent code. This patch series can now stand by itself, with one kludge
patch(2).
version v7:
(1) refers to device tree property to enable protection keys.
(2) adds 4K PTE support.
(3) fixes a couple of bugs noticed by Thiago
(4) decouples this patch series from arch- independent code. This patch series can now stand by itself, with one kludge patch(2).
version v6:
(1) selftest changes are broken down into 20 incremental patches.
(2) A separate key allocation mask that includes PKEY_DISABLE_EXECUTE is added for powerpc
(3) pkey feature is enabled for 64K HPT case only. RPT and 4k HPT is disabled.
(4) Documentation is updated to better capture the semantics.
(5) introduced arch_pkeys_enabled() to find if an arch enables pkeys. Correspond- ing change the logic that displays key value in smaps.
(6) code rearranged in many places based on comments from Dave Hansen, Balbir, Anshuman.
(7) fixed one bug where a bogus key could be associated successfully in pkey_mprotect().
version v5:
(1) reverted back to the old design -- store the key in the pte, instead of bypassing it. The v4 design slowed down the hash page path.
(2) detects key violation when kernel is told to access user pages.
(3) further refined the patches into smaller consumable units
(4) page faults handlers captures the fault- ing key
from the pte instead of the vma. This closes a race between where the key update in the vma and a key fault caused by the key programmed in the pte.
(5) a key created with access-denied should also set it up to deny write. Fixed it.
(6) protection-key number is displayed in smaps the x86 way.
version v4:
(1) patches no more depend on the pte bits to program the hpte
-- comment by Balbir
(2) documentation updates
(3) fixed a bug in the selftest.
(4) unlike x86, powerpc lets signal handler change key permission bits; the change will persist across signal handler boundaries. Earlier we allowed the signal handler to modify a field in the siginfo structure which would than be used by the kernel to program the key protection register (AMR) -- resolves a issue raised by Ben. "Calls to sys_swapcontext with a made-up context will end up with a crap AMR if done by code who didn't know about that register".
(5) these changes enable protection keys on 4k-page kernel aswell.
version v3:
(1) split the patches into smaller consumable patches.
(2) added the ability to disable execute permission on a key at creation.
(3) rename calc_pte_to_hpte_pkey_bits() to pte_to_hpte_pkey_bits()
-- suggested by Anshuman
(4) some code optimization and clarity in do_page_fault()
(5) A bug fix while invalidating a hpte slot in __hash_page_4K()
-- noticed by Aneesh
version v2:
(1) documentation and selftest added.
(2) fixed a bug in 4k hpte backed 64k pte where page invalidation was not done correctly, and initialization of second-part-of-the-pte was not done correctly if the pte was not yet Hashed with a hpte.
-- Reported by Aneesh.
(3) Fixed ABI breakage caused in siginfo structure.
-- Reported by Anshuman.
version v1: Initial version
Ram Pai (26):
mm, powerpc, x86: define VM_PKEY_BITx bits if CONFIG_ARCH_HAS_PKEYS
is enabled
mm, powerpc, x86: introduce an additional vma bit for powerpc pkey
powerpc: initial pkey plumbing
powerpc: track allocation status of all pkeys
powerpc: helper function to read,write AMR,IAMR,UAMOR registers
powerpc: helper functions to initialize AMR, IAMR and UAMOR registers
powerpc: cleanup AMR, IAMR when a key is allocated or freed
powerpc: implementation for arch_set_user_pkey_access()
powerpc: ability to create execute-disabled pkeys
powerpc: store and restore the pkey state across context switches
powerpc: introduce execute-only pkey
powerpc: ability to associate pkey to a vma
powerpc: implementation for arch_override_mprotect_pkey()
powerpc: map vma key-protection bits to pte key bits.
powerpc: Program HPTE key protection bits
powerpc: helper to validate key-access permissions of a pte
powerpc: check key protection for user page access
powerpc: implementation for arch_vma_access_permitted()
powerpc: Handle exceptions caused by pkey violation
powerpc: introduce get_mm_addr_key() helper
powerpc: Deliver SEGV signal on pkey violation
powerpc: Enable pkey subsystem
powerpc: sys_pkey_alloc() and sys_pkey_free() system calls
powerpc: sys_pkey_mprotect() system call
mm, x86 : introduce arch_pkeys_enabled()
mm: display pkey in smaps if arch_pkeys_enabled() is true
Thiago Jung Bauermann (1):
powerpc/ptrace: Add memory protection key regset
arch/powerpc/Kconfig | 15 + arch/powerpc/include/asm/book3s/64/mmu-hash.h | 5 + arch/powerpc/include/asm/book3s/64/mmu.h | 10 + arch/powerpc/include/asm/book3s/64/pgtable.h | 48 +++- arch/powerpc/include/asm/bug.h | 1 + arch/powerpc/include/asm/cputable.h | 16 +- arch/powerpc/include/asm/mman.h | 13 +- arch/powerpc/include/asm/mmu.h | 9 + arch/powerpc/include/asm/mmu_context.h | 22 ++ arch/powerpc/include/asm/pkeys.h | 229 ++++++++++++ arch/powerpc/include/asm/processor.h | 5 + arch/powerpc/include/asm/reg.h | 1 - arch/powerpc/include/asm/systbl.h | 3 + arch/powerpc/include/asm/unistd.h | 6 +- arch/powerpc/include/uapi/asm/elf.h | 1 + arch/powerpc/include/uapi/asm/mman.h | 6 + arch/powerpc/include/uapi/asm/unistd.h | 3 + arch/powerpc/kernel/exceptions-64s.S | 2 +- arch/powerpc/kernel/process.c | 7 + arch/powerpc/kernel/ptrace.c | 66 ++++ arch/powerpc/kernel/traps.c | 19 +- arch/powerpc/mm/Makefile | 1 + arch/powerpc/mm/fault.c | 49 +++- arch/powerpc/mm/hash_utils_64.c | 26 ++ arch/powerpc/mm/mmu_context_book3s64.c | 2 + arch/powerpc/mm/pkeys.c | 469 +++++++++++++++++++++++++ arch/x86/include/asm/pkeys.h | 1 + arch/x86/kernel/fpu/xstate.c | 5 + arch/x86/kernel/setup.c | 8 - fs/proc/task_mmu.c | 16 +- include/linux/mm.h | 12 +- include/linux/pkeys.h | 5 + include/uapi/linux/elf.h | 1 + 33 files changed, 1040 insertions(+), 42 deletions(-) create mode 100644 arch/powerpc/include/asm/pkeys.h create mode 100644 arch/powerpc/mm/pkeys.c
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 1/27 mm, powerpc, x86: define VM_PKEY_BITx bits if CONFIG_ARCH_HAS_PKEYS is enabled
VM_PKEY_BITx are defined only if CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS is enabled. Powerpc also needs these bits. Hence lets define the VM_PKEY_BITx bits for any architecture that enables CONFIG_ARCH_HAS_PKEYS.
--- fs/proc/task_mmu.c | 4 ++-- include/linux/mm.h | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-)
fs/proc/task_mmu.c +2 -2
@@ -674,13 +674,13 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) [ilog2(VM_MERGEABLE)] = "mg", [ilog2(VM_UFFD_MISSING)]= "um", [ilog2 (VM_UFFD_WP )] ="uw" , -#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS +#ifdef CONFIG_ARCH_HAS_PKEYS/* These come out via ProtectionKey: */ [ilog2(VM_PKEY_BIT0)] = "", [ilog2(VM_PKEY_BIT1)] = "", [ilog2(VM_PKEY_BIT2)] = "", [ilog2(VM_PKEY_BIT3)] = "", -#endif +#endif /* CONFIG_ARCH_HAS_PKEYS */ };size_t i;
include/linux/mm.h +5 -4
@@ -228,15 +228,16 @@ extern int overcommit_kbytes_handler(struct ctl_table *, int, void __user *,#define VM_HIGH_ARCH_4 BIT(VM_HIGH_ARCH_BIT_4)#endif /* CONFIG_ARCH_USES_HIGH_VMA_FLAGS */ -#if defined(CONFIG_X86 ) -# define VM_PAT VM_ARCH_1/* PAT reserves whole VMA at once (x86) */ -#if defined (CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS ) +#ifdef CONFIG_ARCH_HAS_PKEYS # define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_0# define VM_PKEY_BIT0 VM_HIGH_ARCH_0/* A protection key is a 4-bit value */ # define VM_PKEY_BIT1 VM_HIGH_ARCH_1# define VM_PKEY_BIT2 VM_HIGH_ARCH_2# define VM_PKEY_BIT3 VM_HIGH_ARCH_3 -#endif +#endif /* CONFIG_ARCH_HAS_PKEYS */ + +#if defined(CONFIG_X86 ) +# define VM_PAT VM_ARCH_1/* PAT reserves whole VMA at once (x86) */ #elif defined(CONFIG_PPC )# define VM_SAO VM_ARCH_1/* Strong Access Ordering (powerpc) */ #elif defined(CONFIG_PARISC )
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v10 01/27] mm, powerpc, x86: define VM_PKEY_BITx bits if CONFIG_ARCH_HAS_PKEYS is enabled
Quoted 5 lines · Ram Pai
VM_PKEY_BITxare defined only ifCONFIG_X86_INTEL_MEMORY_PROTECTION_KEYSis enabled. Powerpc also needs these bits. Hence lets define theVM_PKEY_BITxbits for any architecture that enablesCONFIG_ARCH_HAS_PKEYS.
Quoted 59 lines
Signed-off-by Ram Pai <[email protected]>--- fs/proc/task_mmu.c | 4 ++-- include/linux/mm.h | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-)fs/proc/task_mmu.c +2
-2@@ -674,13 +674,13 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) [ilog2(VM_MERGEABLE)] = "mg", [ilog2(VM_UFFD_MISSING)]= "um", [ilog2 (VM_UFFD_WP )] ="uw" , -#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS +#ifdef CONFIG_ARCH_HAS_PKEYS/* These come out via ProtectionKey: */ [ilog2(VM_PKEY_BIT0)] = "", [ilog2(VM_PKEY_BIT1)] = "", [ilog2(VM_PKEY_BIT2)] = "", [ilog2(VM_PKEY_BIT3)] = "", -#endif +#endif /* CONFIG_ARCH_HAS_PKEYS */ };size_t i;include/linux/mm.h +5
-4@@ -228,15 +228,16 @@ extern int overcommit_kbytes_handler(struct ctl_table *, int, void __user *,#define VM_HIGH_ARCH_4 BIT(VM_HIGH_ARCH_BIT_4)#endif /* CONFIG_ARCH_USES_HIGH_VMA_FLAGS */ -#if defined(CONFIG_X86 ) -# define VM_PAT VM_ARCH_1/* PAT reserves whole VMA at once (x86) */ -#if defined (CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS ) +#ifdef CONFIG_ARCH_HAS_PKEYS # define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_0# define VM_PKEY_BIT0 VM_HIGH_ARCH_0/* A protection key is a 4-bit value */ # define VM_PKEY_BIT1 VM_HIGH_ARCH_1# define VM_PKEY_BIT2 VM_HIGH_ARCH_2# define VM_PKEY_BIT3 VM_HIGH_ARCH_3 -#endif +#endif /* CONFIG_ARCH_HAS_PKEYS */ + +#if defined(CONFIG_X86 ) +# define VM_PAT VM_ARCH_1/* PAT reserves whole VMA at once (x86) */ #elif defined(CONFIG_PPC )# define VM_SAO VM_ARCH_1/* Strong Access Ordering (powerpc) */ #elif defined(CONFIG_PARISC )Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v10 01/27] mm, powerpc, x86: define VM_PKEY_BITx bits if CONFIG_ARCH_HAS_PKEYS is enabled
In reply to Ram PaiAndrew,
Please apply the following two patches to your tree.
[PATCH v10 01/27] mm, powerpc, x86: define VM_PKEY_BITx bits if CONFIG_ARCH_HAS_PKEYS is enabled [PATCH v10 02/27] mm, powerpc, x86: introduce an additional vma bit for powerpc pkey
I have not heard any complaints on these changes.
Dave Hansen had comments/suggestions in the initial revisions, which have been incorporated.
Michael Ellermen has accepted the rest of the powerpc related patches in this series.
Thanks,
RP
Quoted 64 lines · Ram Pai
VM_PKEY_BITxare defined only ifCONFIG_X86_INTEL_MEMORY_PROTECTION_KEYSis enabled. Powerpc also needs these bits. Hence lets define theVM_PKEY_BITxbits for any architecture that enablesCONFIG_ARCH_HAS_PKEYS.Signed-off-by Ram Pai <linuxram at us.ibm.com>--- fs/proc/task_mmu.c | 4 ++-- include/linux/mm.h | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-)fs/proc/task_mmu.c +2
-2@@ -674,13 +674,13 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) [ilog2(VM_MERGEABLE)] = "mg", [ilog2(VM_UFFD_MISSING)]= "um", [ilog2 (VM_UFFD_WP )] ="uw" , -#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS +#ifdef CONFIG_ARCH_HAS_PKEYS/* These come out via ProtectionKey: */ [ilog2(VM_PKEY_BIT0)] = "", [ilog2(VM_PKEY_BIT1)] = "", [ilog2(VM_PKEY_BIT2)] = "", [ilog2(VM_PKEY_BIT3)] = "", -#endif +#endif /* CONFIG_ARCH_HAS_PKEYS */ };size_t i;include/linux/mm.h +5
-4@@ -228,15 +228,16 @@ extern int overcommit_kbytes_handler(struct ctl_table *, int, void __user *,#define VM_HIGH_ARCH_4 BIT(VM_HIGH_ARCH_BIT_4)#endif /* CONFIG_ARCH_USES_HIGH_VMA_FLAGS */ -#if defined(CONFIG_X86 ) -# define VM_PAT VM_ARCH_1/* PAT reserves whole VMA at once (x86) */ -#if defined (CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS ) +#ifdef CONFIG_ARCH_HAS_PKEYS # define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_0# define VM_PKEY_BIT0 VM_HIGH_ARCH_0/* A protection key is a 4-bit value */ # define VM_PKEY_BIT1 VM_HIGH_ARCH_1# define VM_PKEY_BIT2 VM_HIGH_ARCH_2# define VM_PKEY_BIT3 VM_HIGH_ARCH_3 -#endif +#endif /* CONFIG_ARCH_HAS_PKEYS */ + +#if defined(CONFIG_X86 ) +# define VM_PAT VM_ARCH_1/* PAT reserves whole VMA at once (x86) */ #elif defined(CONFIG_PPC )# define VM_SAO VM_ARCH_1/* Strong Access Ordering (powerpc) */ #elif defined(CONFIG_PARISC )Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo at kvack.org. For more info on Linux MM, see: https://urldefense.proofpoint.com/v2/url?u=http-3A__www.linux-2Dmm.org_&d=DwIBAg&c=jf_iaSHvJObTbx-siA1ZOg&r=m-UrKChQVkZtnPpjbF6YY99NbT8FBByQ-E-ygV8luxw&m=PsCrC-HVeq8M98fNireZs4GUBJvMwNZme7wZ1YdjMqs&s=V90akzFmL1g-sNEcgmcUn_XJgJ8EaYmmsAS3AcVYScw&e= . Don't email: <a href=mailto:"dont at kvack.org"> email at kvack.org </a>
Signature · 6 lines
Ram Pai -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v10 2/27 mm, powerpc, x86: introduce an additional vma bit for powerpc pkey
In reply to Ram PaiCurrently only 4bits are allocated in the vma flags to hold 16 keys. This is sufficient for x86. PowerPC supports 32 keys, which needs 5bits. This patch allocates an additional bit.
--- fs/proc/task_mmu.c | 1 + include/linux/mm.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletions(-)
fs/proc/task_mmu.c +1 -0
@@ -680,6 +680,7 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) [ilog2(VM_PKEY_BIT1)] = "", [ilog2(VM_PKEY_BIT2)] = "", [ilog2(VM_PKEY_BIT3)] = "", + [ilog2(VM_PKEY_BIT4)] = "",#endif /* CONFIG_ARCH_HAS_PKEYS */ };size_t i;
include/linux/mm.h +2 -1
@@ -231,9 +231,10 @@ extern int overcommit_kbytes_handler(struct ctl_table *, int, void __user *,#ifdef CONFIG_ARCH_HAS_PKEYS # define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_0# define VM_PKEY_BIT0 VM_HIGH_ARCH_0/* A protection key is a 4-bit value */ -# define VM_PKEY_BIT1 VM_HIGH_ARCH_1 +# define VM_PKEY_BIT1 VM_HIGH_ARCH_1/* on x86 and 5-bit value on ppc64 */ # define VM_PKEY_BIT2 VM_HIGH_ARCH_2# define VM_PKEY_BIT3 VM_HIGH_ARCH_3 +# define VM_PKEY_BIT4 VM_HIGH_ARCH_4#endif /* CONFIG_ARCH_HAS_PKEYS */ #if defined(CONFIG_X86 )
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 3/27 powerpc: initial pkey plumbing
In reply to Ram PaiBasic plumbing to initialize the pkey system.
Nothing is enabled yet. A later patch will enable it once all the infrastructure is in place.
--- arch/powerpc/Kconfig | 15 +++++++++ arch/powerpc/include/asm/mmu_context.h | 1 + arch/powerpc/include/asm/pkeys.h | 55 ++++++++++++++++++++++++++++++++ arch/powerpc/mm/Makefile | 1 + arch/powerpc/mm/hash_utils_64.c | 1 + arch/powerpc/mm/pkeys.c | 33 +++++++++++++++++++ 6 files changed, 106 insertions(+), 0 deletions(-) create mode 100644 arch/powerpc/include/asm/pkeys.h create mode 100644 arch/powerpc/mm/pkeys.c
arch/powerpc/Kconfig +15 -0
@@ -867,6 +867,21 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. +config PPC_MEM_KEYS + prompt "PowerPC Memory Protection Keys" + def_bool y + depends on PPC_BOOK3S_64 + select ARCH_USES_HIGH_VMA_FLAGS + select ARCH_HAS_PKEYS + help + Memory Protection Keys provides a mechanism for enforcing + page-based protections, but without requiring modification of the + page tables when an application changes protection domains. + + For details, see Documentation/vm/protection-keys.txt + + If unsure, say y. + endmenu config ISA_DMA_API
arch/powerpc/include/asm/mmu_context.h +1 -0
@@ -192,5 +192,6 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,/* by default, allow everything */ return true; } +#endif /* __KERNEL__ */ #endif /* __ASM_POWERPC_MMU_CONTEXT_H */
arch/powerpc/include/asm/pkeys.h new file +55 -0
55 lines not on this page · raw message
arch/powerpc/mm/Makefile +1 -0
@@ -44,3 +44,4 @@ obj-$(CONFIG_PPC_COPRO_BASE) += copro_fault.o obj-$(CONFIG_SPAPR_TCE_IOMMU) += mmu_context_iommu.o obj-$(CONFIG_PPC_PTDUMP) += dump_linuxpagetables.o obj-$(CONFIG_PPC_HTDUMP) += dump_hashpagetable.o +obj-$(CONFIG_PPC_MEM_KEYS) += pkeys.o
arch/powerpc/mm/hash_utils_64.c +1 -0
@@ -36,6 +36,7 @@#include <linux/memblock.h> #include <linux/context_tracking.h> #include <linux/libfdt.h> +#include <linux/pkeys.h> #include <asm/debugfs.h> #include <asm/processor.h>
arch/powerpc/mm/pkeys.c new file +33 -0
@@ -0,0 +1,33 @@ +/* +* PowerPC Memory Protection Keys management +* Copyright (c) 2017, IBM Corporation. +* Author: Ram Pai <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +*/ + +#include <linux/pkeys.h> + +DEFINE_STATIC_KEY_TRUE (pkey_disabled); +bool pkey_execute_disable_supported; + +int pkey_initialize (void ) +{ +/* +* Disable the pkey system till everything is in place. A subsequent +* patch will enable it. +*/ +static_branch_enable (&pkey_disabled); + +/* +* Disable execute_disable support for now. A subsequent patch will +* enable it. +*/ + pkey_execute_disable_supported = false; +return 0 ; +} + +arch_initcall (pkey_initialize);
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [v10,03/27] powerpc: initial pkey plumbing
Quoted 5 lines · Ram Pai
Basic plumbing to initialize the pkey system.
Nothing is enabled yet. A later patch will enable it once all the infrastructure is in place.Signed-off-by Ram Pai <[email protected]>
Patches 3-27 applied to powerpc next, thanks.
https://git.kernel.org/powerpc/c/92e3da3cf193fd27996909956c12a2
cheers
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 4/27 powerpc: track allocation status of all pkeys
In reply to Ram PaiTotal 32 keys are available on power7 and above. However pkey 0,1 are reserved. So effectively we have 30 pkeys.
On 4K kernels, we do not have 5 bits in the PTE to represent all the keys; we only have 3bits.Two of those keys are reserved; pkey 0 and pkey 1. So effectively we have 6 pkeys.
This patch keeps track of reserved keys, allocated keys and keys that are currently free.
Also it adds skeletal functions and macros, that the architecture-independent code expects to be available.
--- arch/powerpc/include/asm/book3s/64/mmu.h | 9 +++ arch/powerpc/include/asm/mmu_context.h | 4 + arch/powerpc/include/asm/pkeys.h | 90 ++++++++++++++++++++++++++++- arch/powerpc/mm/mmu_context_book3s64.c | 2 + arch/powerpc/mm/pkeys.c | 40 +++++++++++++ 5 files changed, 141 insertions(+), 4 deletions(-)
arch/powerpc/include/asm/book3s/64/mmu.h +9 -0
@@ -108,6 +108,15 @@ struct patb_entry {#ifdef CONFIG_SPAPR_TCE_IOMMU struct list_head iommu_group_mem_list;#endif + +#ifdef CONFIG_PPC_MEM_KEYS +/* +* Each bit represents one protection key. +* bit set -> key allocated +* bit unset -> key available for allocation +*/ +u32 pkey_allocation_map; +#endif } mm_context_t;/*
arch/powerpc/include/asm/mmu_context.h +4 -0
@@ -193,5 +193,9 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,return true; } +#ifndef CONFIG_PPC_MEM_KEYS +#define pkey_mm_init (mm) +#endif /* CONFIG_PPC_MEM_KEYS */ +#endif /* __KERNEL__ */ #endif /* __ASM_POWERPC_MMU_CONTEXT_H */
arch/powerpc/include/asm/pkeys.h +86 -4
111 lines not on this page · raw message
arch/powerpc/mm/mmu_context_book3s64.c +2 -0
@@ -16,6 +16,7 @@#include <linux/string.h> #include <linux/types.h> #include <linux/mm.h> +#include <linux/pkeys.h> #include <linux/spinlock.h> #include <linux/idr.h> #include <linux/export.h>
@@ -118,6 +119,7 @@ static int hash__init_new_context(struct mm_struct *mm)subpage_prot_init_new_context (mm); +pkey_mm_init (mm);return index; }
arch/powerpc/mm/pkeys.c +40 -0
@@ -13,21 +13,61 @@DEFINE_STATIC_KEY_TRUE (pkey_disabled);bool pkey_execute_disable_supported; +int pkeys_total;/* Total pkeys as per device tree */ +u32 initial_allocation_mask;/* Bits set for reserved keys */ int pkey_initialize (void ) { +int os_reserved, i; +/* * Disable the pkey system till everything is in place. A subsequent * patch will enable it. */ static_branch_enable (&pkey_disabled); +/* Lets assume 32 keys */ + pkeys_total =32 ; + +/* +* Adjust the upper limit, based on the number of bits supported by +* arch-neutral code. +*/ + pkeys_total =min_t (int, pkeys_total, + (ARCH_VM_PKEY_FLAGS >>VM_PKEY_SHIFT )); +/* * Disable execute_disable support for now. A subsequent patch will * enable it. */ pkey_execute_disable_supported = false; + +#ifdef CONFIG_PPC_4K_PAGES +/* +* The OS can manage only 8 pkeys due to its inability to represent them +* in the Linux 4K PTE. +*/ + os_reserved = pkeys_total -8 ; +#else + os_reserved =0 ; +#endif +/* +* Bits are in LE format. NOTE: 1, 0 are reserved. +* key 0 is the default key, which allows read/write/execute. +* key 1 is recommended not to be used. PowerISA(3.0) page 1015, +* programming note. +*/ + initial_allocation_mask = ~0x0 ; +for (i =2 ; i < (pkeys_total - os_reserved); i++) + initial_allocation_mask &= ~(0x1 << i);return 0 ; }arch_initcall (pkey_initialize); + +void pkey_mm_init (struct mm_struct *mm) +{ +if (static_branch_likely (&pkey_disabled)) +return ; +mm_pkey_allocation_map (mm) = initial_allocation_mask; +}
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 5/27 powerpc: helper function to read,write AMR,IAMR,UAMOR registers
In reply to Ram PaiImplements helper functions to read and write the key related registers; AMR, IAMR, UAMOR.
AMR register tracks the read,write permission of a key IAMR register tracks the execute permission of a key UAMOR register enables and disables a key
--- arch/powerpc/mm/pkeys.c | 36 ++++++++++++++++++++++++++++++++++++ 1 files changed, 36 insertions(+), 0 deletions(-)
arch/powerpc/mm/pkeys.c +36 -0
@@ -71,3 +71,39 @@ void pkey_mm_init(struct mm_struct *mm)return ;mm_pkey_allocation_map (mm) = initial_allocation_mask; } + +static inline u64 read_amr (void ) +{ +return mfspr (SPRN_AMR ); +} + +static inline void write_amr (u64 value) +{ +mtspr (SPRN_AMR , value); +} + +static inline u64 read_iamr (void ) +{ +if (!likely (pkey_execute_disable_supported)) +return 0x0UL ; + +return mfspr (SPRN_IAMR ); +} + +static inline void write_iamr (u64 value) +{ +if (!likely (pkey_execute_disable_supported)) +return ; + +mtspr (SPRN_IAMR , value); +} + +static inline u64 read_uamor (void ) +{ +return mfspr (SPRN_UAMOR ); +} + +static inline void write_uamor (u64 value) +{ +mtspr (SPRN_UAMOR , value); +}
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 6/27 powerpc: helper functions to initialize AMR, IAMR and UAMOR registers
In reply to Ram PaiIntroduce helper functions that can initialize the bits in the AMR, IAMR and UAMOR register; the bits that correspond to the given pkey.
--- arch/powerpc/mm/pkeys.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 47 insertions(+), 0 deletions(-)
arch/powerpc/mm/pkeys.c +47 -0
@@ -16,6 +16,10 @@int pkeys_total;/* Total pkeys as per device tree */ u32 initial_allocation_mask;/* Bits set for reserved keys */ +#define AMR_BITS_PER_PKEY 2 +#define PKEY_REG_BITS (sizeof(u64)*8) +#define pkeyshift (pkey) (PKEY_REG_BITS - ((pkey+1) * AMR_BITS_PER_PKEY)) +int pkey_initialize (void ) {int os_reserved, i;
@@ -107,3 +111,46 @@ static inline void write_uamor(u64 value) {mtspr (SPRN_UAMOR , value); } + +static inline void init_amr (int pkey,u8 init_bits) +{ +u64 new_amr_bits = (((u64 )init_bits &0x3UL ) <<pkeyshift (pkey)); +u64 old_amr =read_amr () & ~((u64)(0x3ul ) <<pkeyshift (pkey)); + +write_amr (old_amr | new_amr_bits); +} + +static inline void init_iamr (int pkey,u8 init_bits) +{ +u64 new_iamr_bits = (((u64 )init_bits &0x1UL ) <<pkeyshift (pkey)); +u64 old_iamr =read_iamr () & ~((u64)(0x1ul ) <<pkeyshift (pkey)); + +write_iamr (old_iamr | new_iamr_bits); +} + +static void pkey_status_change (int pkey,bool enable) +{ +u64 old_uamor; + +/* Reset the AMR and IAMR bits for this key */ +init_amr (pkey,0x0 ); +init_iamr (pkey,0x0 ); + +/* Enable/disable key */ + old_uamor =read_uamor (); +if (enable) + old_uamor |= (0x3ul <<pkeyshift (pkey)); +else + old_uamor &= ~(0x3ul <<pkeyshift (pkey)); +write_uamor (old_uamor); +} + +void __arch_activate_pkey (int pkey) +{ +pkey_status_change (pkey, true); +} + +void __arch_deactivate_pkey (int pkey) +{ +pkey_status_change (pkey, false); +}
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 7/27 powerpc: cleanup AMR, IAMR when a key is allocated or freed
In reply to Ram PaiCleanup the bits corresponding to a key in the AMR, and IAMR register, when the key is newly allocated/activated or is freed. We dont want some residual bits cause the hardware enforce unintended behavior when the key is activated or freed.
--- arch/powerpc/include/asm/pkeys.h | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-)
arch/powerpc/include/asm/pkeys.h +12 -0
@@ -69,6 +69,8 @@ static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey) __mm_pkey_is_allocated(mm, pkey)); } +extern void __arch_activate_pkey (int pkey); +extern void __arch_deactivate_pkey (int pkey);/* * Returns a positive, 5-bit key on success, or -1 on failure. * Relies on the mmap_sem to protect against concurrency in mm_pkey_alloc() and
@@ -96,6 +98,12 @@ static inline int mm_pkey_alloc(struct mm_struct *mm) ret =ffz ((u32 )mm_pkey_allocation_map (mm));__mm_pkey_allocated (mm, ret); + +/* +* Enable the key in the hardware +*/ +if (ret >0 ) +__arch_activate_pkey (ret);return ret; }
@@ -107,6 +115,10 @@ static inline int mm_pkey_free(struct mm_struct *mm, int pkey)if (!mm_pkey_is_allocated (mm, pkey))return -EINVAL ; +/* +* Disable the key in the hardware +*/ +__arch_deactivate_pkey (pkey);__mm_pkey_free (mm, pkey);return 0 ;
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 8/27 powerpc: implementation for arch_set_user_pkey_access()
In reply to Ram PaiThis patch provides the detailed implementation for a user to allocate a key and enable it in the hardware.
It provides the plumbing, but it cannot be used till the system call is implemented. The next patch will do so.
--- arch/powerpc/include/asm/pkeys.h | 6 ++++- arch/powerpc/mm/pkeys.c | 40 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletions(-)
arch/powerpc/include/asm/pkeys.h +5 -1
@@ -139,10 +139,14 @@ static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,return 0 ; } +extern int __arch_set_user_pkey_access (struct task_struct *tsk,int pkey, +unsigned long init_val);static inline int arch_set_user_pkey_access (struct task_struct *tsk,int pkey,unsigned long init_val) { -return 0 ; +if (static_branch_likely (&pkey_disabled)) +return -EINVAL ; +return __arch_set_user_pkey_access (tsk, pkey, init_val); }extern void pkey_mm_init (struct mm_struct *mm);
arch/powerpc/mm/pkeys.c +40 -0
@@ -9,6 +9,7 @@* (at your option) any later version. */ +#include <asm/mman.h> #include <linux/pkeys.h> DEFINE_STATIC_KEY_TRUE (pkey_disabled);
@@ -17,6 +18,9 @@u32 initial_allocation_mask;/* Bits set for reserved keys */ #define AMR_BITS_PER_PKEY 2 +#define AMR_RD_BIT 0x1UL +#define AMR_WR_BIT 0x2UL +#define IAMR_EX_BIT 0x1UL#define PKEY_REG_BITS (sizeof(u64)*8)#define pkeyshift (pkey) (PKEY_REG_BITS - ((pkey+1) * AMR_BITS_PER_PKEY))
@@ -112,6 +116,20 @@ static inline void write_uamor(u64 value)mtspr (SPRN_UAMOR , value); } +static bool is_pkey_enabled (int pkey) +{ +u64 uamor =read_uamor (); +u64 pkey_bits =0x3ul <<pkeyshift (pkey); +u64 uamor_pkey_bits = (uamor & pkey_bits); + +/* +* Both the bits in UAMOR corresponding to the key should be set or +* reset. +*/ +WARN_ON (uamor_pkey_bits && (uamor_pkey_bits != pkey_bits)); +return !!(uamor_pkey_bits); +} +static inline void init_amr (int pkey,u8 init_bits) {u64 new_amr_bits = (((u64 )init_bits &0x3UL ) <<pkeyshift (pkey));
@@ -154,3 +172,25 @@ void __arch_deactivate_pkey(int pkey) {pkey_status_change (pkey, false); } + +/* +* Set the access rights in AMR IAMR and UAMOR registers for @pkey to that +* specified in @init_val. +*/ +int __arch_set_user_pkey_access (struct task_struct *tsk,int pkey, +unsigned long init_val) +{ +u64 new_amr_bits =0x0ul ; + +if (!is_pkey_enabled (pkey)) +return -EINVAL ; + +/* Set the bits we need in AMR: */ +if (init_val &PKEY_DISABLE_ACCESS ) + new_amr_bits |=AMR_RD_BIT |AMR_WR_BIT ; +else if (init_val &PKEY_DISABLE_WRITE ) + new_amr_bits |=AMR_WR_BIT ; + +init_amr (pkey, new_amr_bits); +return 0 ; +}
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 9/27 powerpc: ability to create execute-disabled pkeys
In reply to Ram Paipowerpc has hardware support to disable execute on a pkey. This patch enables the ability to create execute-disabled keys.
--- arch/powerpc/include/uapi/asm/mman.h | 6 ++++++ arch/powerpc/mm/pkeys.c | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 0 deletions(-)
arch/powerpc/include/uapi/asm/mman.h +6 -0
@@ -30,4 +30,10 @@#define MAP_STACK 0x20000/* give out an address that is best suited for process/thread stacks */ #define MAP_HUGETLB 0x40000/* create a huge page mapping */ +/* Override any generic PKEY permission defines */ +#define PKEY_DISABLE_EXECUTE 0x4 +#undef PKEY_ACCESS_MASK +#define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS |\ + PKEY_DISABLE_WRITE |\ + PKEY_DISABLE_EXECUTE)#endif /* _UAPI_ASM_POWERPC_MMAN_H */
arch/powerpc/mm/pkeys.c +16 -0
@@ -29,6 +29,14 @@ int pkey_initialize(void)int os_reserved, i;/* +* We define PKEY_DISABLE_EXECUTE in addition to the arch-neutral +* generic defines for PKEY_DISABLE_ACCESS and PKEY_DISABLE_WRITE. +* Ensure that the bits a distinct. +*/ +BUILD_BUG_ON (PKEY_DISABLE_EXECUTE & + (PKEY_DISABLE_ACCESS |PKEY_DISABLE_WRITE )); + +/* * Disable the pkey system till everything is in place. A subsequent * patch will enable it. */
@@ -181,10 +189,18 @@ int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey, unsigned long init_val) {u64 new_amr_bits =0x0ul ; +u64 new_iamr_bits =0x0ul ;if (!is_pkey_enabled (pkey))return -EINVAL ; +if (init_val &PKEY_DISABLE_EXECUTE ) { +if (!pkey_execute_disable_supported) +return -EINVAL ; + new_iamr_bits |=IAMR_EX_BIT ; + } +init_iamr (pkey, new_iamr_bits); +/* Set the bits we need in AMR: */ if (init_val &PKEY_DISABLE_ACCESS ) new_amr_bits |=AMR_RD_BIT |AMR_WR_BIT ;
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 10/27 powerpc: store and restore the pkey state across context switches
In reply to Ram PaiStore and restore the AMR, IAMR and UAMOR register state of the task before scheduling out and after scheduling in, respectively.
--- arch/powerpc/include/asm/mmu_context.h | 3 ++ arch/powerpc/include/asm/pkeys.h | 4 ++ arch/powerpc/include/asm/processor.h | 5 +++ arch/powerpc/kernel/process.c | 7 ++++ arch/powerpc/mm/pkeys.c | 52 +++++++++++++++++++++++++++++++- 5 files changed, 70 insertions(+), 1 deletions(-)
arch/powerpc/include/asm/mmu_context.h +3 -0
@@ -195,6 +195,9 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,#ifndef CONFIG_PPC_MEM_KEYS #define pkey_mm_init (mm) +#define thread_pkey_regs_save (thread) +#define thread_pkey_regs_restore (new_thread, old_thread) +#define thread_pkey_regs_init (thread)#endif /* CONFIG_PPC_MEM_KEYS */ #endif /* __KERNEL__ */
arch/powerpc/include/asm/pkeys.h +4 -0
@@ -150,4 +150,8 @@ static inline int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, }extern void pkey_mm_init (struct mm_struct *mm); +extern void thread_pkey_regs_save (struct thread_struct *thread); +extern void thread_pkey_regs_restore (struct thread_struct *new_thread, +struct thread_struct *old_thread); +extern void thread_pkey_regs_init (struct thread_struct *thread);#endif /*_ASM_POWERPC_KEYS_H */
arch/powerpc/include/asm/processor.h +5 -0
@@ -309,6 +309,11 @@ struct thread_struct {struct thread_vr_state ckvr_state;/* Checkpointed VR state */ unsigned long ckvrsave;/* Checkpointed VRSAVE */ #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ +#ifdef CONFIG_PPC_MEM_KEYS +unsigned long amr; +unsigned long iamr; +unsigned long uamor; +#endif #ifdef CONFIG_KVM_BOOK3S_32_HANDLER void * kvm_shadow_vcpu;/* KVM internal data */ #endif /* CONFIG_KVM_BOOK3S_32_HANDLER */
arch/powerpc/kernel/process.c +7 -0
@@ -42,6 +42,7 @@#include <linux/hw_breakpoint.h> #include <linux/uaccess.h> #include <linux/elf-randomize.h> +#include <linux/pkeys.h> #include <asm/pgtable.h> #include <asm/io.h>
@@ -1102,6 +1103,8 @@ static inline void save_sprs(struct thread_struct *t) t->tar =mfspr (SPRN_TAR ); }#endif + +thread_pkey_regs_save (t); } static inline void restore_sprs(struct thread_struct *old_thread,
@@ -1141,6 +1144,8 @@ static inline void restore_sprs(struct thread_struct *old_thread, old_thread->tidr != new_thread->tidr)mtspr (SPRN_TIDR , new_thread->tidr);#endif + +thread_pkey_regs_restore (new_thread, old_thread); }#ifdef CONFIG_PPC_BOOK3S_64
@@ -1865,6 +1870,8 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) current->thread.tm_tfiar =0 ; current->thread.load_tm =0 ;#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ + +thread_pkey_regs_init (¤t->thread); }EXPORT_SYMBOL (start_thread);
arch/powerpc/mm/pkeys.c +51 -1
68 lines not on this page · raw message
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 11/27 powerpc: introduce execute-only pkey
In reply to Ram PaiThis patch provides the implementation of execute-only pkey. The architecture-independent layer expects the arch-dependent layer, to support the ability to create and enable a special key which has execute-only permission.
--- arch/powerpc/include/asm/book3s/64/mmu.h | 1 + arch/powerpc/include/asm/pkeys.h | 6 +++- arch/powerpc/mm/pkeys.c | 58 ++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletions(-)
arch/powerpc/include/asm/book3s/64/mmu.h +1 -0
@@ -116,6 +116,7 @@ struct patb_entry {* bit unset -> key available for allocation */ u32 pkey_allocation_map; +s16 execute_only_pkey;/* key holding execute-only protection */ #endif } mm_context_t;
arch/powerpc/include/asm/pkeys.h +5 -1
@@ -128,9 +128,13 @@ static inline int mm_pkey_free(struct mm_struct *mm, int pkey)* Try to dedicate one of the protection keys to be used as an * execute-only protection key. */ +extern int __execute_only_pkey (struct mm_struct *mm);static inline int execute_only_pkey (struct mm_struct *mm) { -return 0 ; +if (static_branch_likely (&pkey_disabled)) +return -1 ; + +return __execute_only_pkey (mm); } static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,
arch/powerpc/mm/pkeys.c +58 -0
67 lines not on this page · raw message
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 12/27 powerpc: ability to associate pkey to a vma
In reply to Ram Paiarch-independent code expects the arch to map
a pkey into the vma's protection bit setting.
The patch provides that ability.
--- arch/powerpc/include/asm/mman.h | 7 ++++++- arch/powerpc/include/asm/pkeys.h | 11 +++++++++++ arch/powerpc/mm/pkeys.c | 8 ++++++++ 3 files changed, 25 insertions(+), 1 deletions(-)
arch/powerpc/include/asm/mman.h +6 -1
@@ -13,6 +13,7 @@#include <asm/cputable.h> #include <linux/mm.h> +#include <linux/pkeys.h> #include <asm/cpu_has_feature.h> /*
@@ -22,7 +23,11 @@static inline unsigned long arch_calc_vm_prot_bits (unsigned long prot,unsigned long pkey) { -return (prot &PROT_SAO ) ?VM_SAO :0 ; +#ifdef CONFIG_PPC_MEM_KEYS +return (((prot &PROT_SAO ) ?VM_SAO :0 ) |pkey_to_vmflag_bits (pkey)); +#else +return ((prot &PROT_SAO ) ?VM_SAO :0 ); +#endif }#define arch_calc_vm_prot_bits (prot, pkey) arch_calc_vm_prot_bits(prot, pkey)
arch/powerpc/include/asm/pkeys.h +11 -0
@@ -41,6 +41,17 @@#define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2 | \ VM_PKEY_BIT3 | VM_PKEY_BIT4) +/* Override any generic PKEY permission defines */ +#define PKEY_DISABLE_EXECUTE 0x4 +#define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS | \ + PKEY_DISABLE_WRITE | \ + PKEY_DISABLE_EXECUTE) + +static inline u64 pkey_to_vmflag_bits (u16 pkey) +{ +return (((u64 )pkey <<VM_PKEY_SHIFT ) &ARCH_VM_PKEY_FLAGS ); +} +#define arch_max_pkey () pkeys_total#define pkey_alloc_mask (pkey) (0x1 << pkey)
arch/powerpc/mm/pkeys.c +8 -0
@@ -39,6 +39,14 @@ int pkey_initialize(void) (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));/* +* pkey_to_vmflag_bits() assumes that the pkey bits are contiguous +* in the vmaflag. Make sure that is really the case. +*/ +BUILD_BUG_ON (__builtin_clzl (ARCH_VM_PKEY_FLAGS >>VM_PKEY_SHIFT ) + +__builtin_popcountl (ARCH_VM_PKEY_FLAGS >>VM_PKEY_SHIFT ) + != (sizeof (u64) *BITS_PER_BYTE )); + +/* * Disable the pkey system till everything is in place. A subsequent * patch will enable it. */
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 13/27 powerpc: implementation for arch_override_mprotect_pkey()
In reply to Ram Paiarch independent code calls arch_override_mprotect_pkey() to return a pkey that best matches the requested protection.
This patch provides the implementation.
--- arch/powerpc/include/asm/mmu_context.h | 5 ++++ arch/powerpc/include/asm/pkeys.h | 21 +++++++++++++++++- arch/powerpc/mm/pkeys.c | 36 ++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletions(-)
arch/powerpc/include/asm/mmu_context.h +5 -0
@@ -198,6 +198,11 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,#define thread_pkey_regs_save (thread)#define thread_pkey_regs_restore (new_thread, old_thread)#define thread_pkey_regs_init (thread) + +static inline int vma_pkey (struct vm_area_struct *vma) +{ +return 0 ; +}#endif /* CONFIG_PPC_MEM_KEYS */ #endif /* __KERNEL__ */
arch/powerpc/include/asm/pkeys.h +20 -1
@@ -52,6 +52,13 @@ static inline u64 pkey_to_vmflag_bits(u16 pkey)return (((u64 )pkey <<VM_PKEY_SHIFT ) &ARCH_VM_PKEY_FLAGS ); } +static inline int vma_pkey (struct vm_area_struct *vma) +{ +if (static_branch_likely (&pkey_disabled)) +return 0 ; +return (vma->vm_flags &ARCH_VM_PKEY_FLAGS ) >>VM_PKEY_SHIFT ; +} +#define arch_max_pkey () pkeys_total#define pkey_alloc_mask (pkey) (0x1 << pkey)
@@ -148,10 +155,22 @@ static inline int execute_only_pkey(struct mm_struct *mm)return __execute_only_pkey (mm); } +extern int __arch_override_mprotect_pkey (struct vm_area_struct *vma, +int prot,int pkey);static inline int arch_override_mprotect_pkey (struct vm_area_struct *vma,int prot,int pkey) { -return 0 ; +if (static_branch_likely (&pkey_disabled)) +return 0 ; + +/* +* Is this an mprotect_pkey() call? If so, never override the value that +* came from the user. +*/ +if (pkey !=-1 ) +return pkey; + +return __arch_override_mprotect_pkey (vma, prot, pkey); } extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
arch/powerpc/mm/pkeys.c +36 -0
@@ -326,3 +326,39 @@ int __execute_only_pkey(struct mm_struct *mm) mm->context.execute_only_pkey = execute_only_pkey;return execute_only_pkey; } + +static inline bool vma_is_pkey_exec_only (struct vm_area_struct *vma) +{ +/* Do this check first since the vm_flags should be hot */ +if ((vma->vm_flags & (VM_READ |VM_WRITE |VM_EXEC )) !=VM_EXEC ) +return false; + +return (vma_pkey (vma) == vma->vm_mm->context.execute_only_pkey); +} + +/* +* This should only be called for *plain* mprotect calls. +*/ +int __arch_override_mprotect_pkey (struct vm_area_struct *vma,int prot, +int pkey) +{ +/* +* If the currently associated pkey is execute-only, but the requested +* protection requires read or write, move it back to the default pkey. +*/ +if (vma_is_pkey_exec_only (vma) && (prot & (PROT_READ |PROT_WRITE ))) +return 0 ; + +/* +* The requested protection is execute-only. Hence let's use an +* execute-only pkey. +*/ +if (prot ==PROT_EXEC ) { + pkey =execute_only_pkey (vma->vm_mm); +if (pkey >0 ) +return pkey; + } + +/* Nothing to override. */ +return vma_pkey (vma); +}
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 14/27 powerpc: map vma key-protection bits to pte key bits.
In reply to Ram PaiMap the key protection bits of the vma to the pkey bits in the PTE.
The PTE bits used for pkey are 3,4,5,6 and 57. The first four bits are the same four bits that were freed up initially in this patch series. remember? :-) Without those four bits this patch wouldn't be possible.
BUT, on 4k kernel, bit 3, and 4 could not be freed up. remember? Hence we have to be satisfied with 5, 6 and 7.
--- arch/powerpc/include/asm/book3s/64/pgtable.h | 25 ++++++++++++++++++++++++- arch/powerpc/include/asm/mman.h | 6 ++++++ arch/powerpc/include/asm/pkeys.h | 12 ++++++++++++ 3 files changed, 42 insertions(+), 1 deletions(-)
arch/powerpc/include/asm/book3s/64/pgtable.h +24 -1
@@ -39,6 +39,7 @@#define _RPAGE_RSV2 0x0800000000000000UL#define _RPAGE_RSV3 0x0400000000000000UL#define _RPAGE_RSV4 0x0200000000000000UL +#define _RPAGE_RSV5 0x00040UL#define _PAGE_PTE 0x4000000000000000UL/* distinguishes PTEs from pointers */ #define _PAGE_PRESENT 0x8000000000000000UL/* pte contains a translation */
@@ -58,6 +59,25 @@/* Max physical address bit as per radix table */ #define _RPAGE_PA_MAX 57 +#ifdef CONFIG_PPC_MEM_KEYS +#ifdef CONFIG_PPC_64K_PAGES +#define H_PTE_PKEY_BIT0 _RPAGE_RSV1 +#define H_PTE_PKEY_BIT1 _RPAGE_RSV2 +#else /* CONFIG_PPC_64K_PAGES */ +#define H_PTE_PKEY_BIT0 0/* _RPAGE_RSV1 is not available */ +#define H_PTE_PKEY_BIT1 0/* _RPAGE_RSV2 is not available */ +#endif /* CONFIG_PPC_64K_PAGES */ +#define H_PTE_PKEY_BIT2 _RPAGE_RSV3 +#define H_PTE_PKEY_BIT3 _RPAGE_RSV4 +#define H_PTE_PKEY_BIT4 _RPAGE_RSV5 +#else /* CONFIG_PPC_MEM_KEYS */ +#define H_PTE_PKEY_BIT0 0 +#define H_PTE_PKEY_BIT1 0 +#define H_PTE_PKEY_BIT2 0 +#define H_PTE_PKEY_BIT3 0 +#define H_PTE_PKEY_BIT4 0 +#endif /* CONFIG_PPC_MEM_KEYS */ +/* * Max physical address bit we will use for now. *
@@ -121,13 +141,16 @@#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \ _PAGE_ACCESSED | _PAGE_SPECIAL | _PAGE_PTE | \ _PAGE_SOFT_DIRTY) + +#define H_PTE_PKEY (H_PTE_PKEY_BIT0 | H_PTE_PKEY_BIT1 | H_PTE_PKEY_BIT2 | \ + H_PTE_PKEY_BIT3 | H_PTE_PKEY_BIT4)/* * Mask of bits returned by pte_pgprot() */ #define PAGE_PROT_BITS (_PAGE_SAO | _PAGE_NON_IDEMPOTENT | _PAGE_TOLERANT | \ H_PAGE_4K_PFN | _PAGE_PRIVILEGED | _PAGE_ACCESSED | \ _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_EXEC | \ - _PAGE_SOFT_DIRTY) + _PAGE_SOFT_DIRTY | H_PTE_PKEY)/* * We define 2 sets of base prot bits, one for basic pages (ie, * cacheable kernel and user pages) and one for non cacheable
arch/powerpc/include/asm/mman.h +6 -0
@@ -33,7 +33,13 @@ static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot,static inline pgprot_t arch_vm_get_page_prot (unsigned long vm_flags) { +#ifdef CONFIG_PPC_MEM_KEYS +return (vm_flags &VM_SAO ) ? +__pgprot (_PAGE_SAO |vmflag_to_pte_pkey_bits (vm_flags)) : +__pgprot (0 |vmflag_to_pte_pkey_bits (vm_flags)); +#else return (vm_flags &VM_SAO ) ?__pgprot (_PAGE_SAO) :__pgprot (0 ); +#endif }#define arch_vm_get_page_prot (vm_flags) arch_vm_get_page_prot(vm_flags)
arch/powerpc/include/asm/pkeys.h +12 -0
@@ -52,6 +52,18 @@ static inline u64 pkey_to_vmflag_bits(u16 pkey)return (((u64 )pkey <<VM_PKEY_SHIFT ) &ARCH_VM_PKEY_FLAGS ); } +static inline u64 vmflag_to_pte_pkey_bits (u64 vm_flags) +{ +if (static_branch_likely (&pkey_disabled)) +return 0x0UL ; + +return (((vm_flags &VM_PKEY_BIT0 ) ?H_PTE_PKEY_BIT4 :0x0UL ) | + ((vm_flags &VM_PKEY_BIT1 ) ?H_PTE_PKEY_BIT3 :0x0UL ) | + ((vm_flags &VM_PKEY_BIT2 ) ?H_PTE_PKEY_BIT2 :0x0UL ) | + ((vm_flags &VM_PKEY_BIT3 ) ?H_PTE_PKEY_BIT1 :0x0UL ) | + ((vm_flags &VM_PKEY_BIT4 ) ?H_PTE_PKEY_BIT0 :0x0UL )); +} +static inline int vma_pkey (struct vm_area_struct *vma) {if (static_branch_likely (&pkey_disabled))
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 15/27 powerpc: Program HPTE key protection bits
In reply to Ram PaiMap the PTE protection key bits to the HPTE key protection bits, while creating HPTE entries.
--- arch/powerpc/include/asm/book3s/64/mmu-hash.h | 5 +++++ arch/powerpc/include/asm/mmu_context.h | 6 ++++++ arch/powerpc/include/asm/pkeys.h | 9 +++++++++ arch/powerpc/mm/hash_utils_64.c | 1 + 4 files changed, 21 insertions(+), 0 deletions(-)
arch/powerpc/include/asm/book3s/64/mmu-hash.h +5 -0
@@ -90,6 +90,8 @@#define HPTE_R_PP0 ASM_CONST(0x8000000000000000)#define HPTE_R_TS ASM_CONST(0x4000000000000000)#define HPTE_R_KEY_HI ASM_CONST(0x3000000000000000) +#define HPTE_R_KEY_BIT0 ASM_CONST(0x2000000000000000) +#define HPTE_R_KEY_BIT1 ASM_CONST(0x1000000000000000)#define HPTE_R_RPN_SHIFT 12#define HPTE_R_RPN ASM_CONST(0x0ffffffffffff000)#define HPTE_R_RPN_3_0 ASM_CONST(0x01fffffffffff000)
@@ -104,6 +106,9 @@#define HPTE_R_C ASM_CONST(0x0000000000000080)#define HPTE_R_R ASM_CONST(0x0000000000000100)#define HPTE_R_KEY_LO ASM_CONST(0x0000000000000e00) +#define HPTE_R_KEY_BIT2 ASM_CONST(0x0000000000000800) +#define HPTE_R_KEY_BIT3 ASM_CONST(0x0000000000000400) +#define HPTE_R_KEY_BIT4 ASM_CONST(0x0000000000000200)#define HPTE_R_KEY (HPTE_R_KEY_LO | HPTE_R_KEY_HI)#define HPTE_V_1TB_SEG ASM_CONST(0x4000000000000000)
arch/powerpc/include/asm/mmu_context.h +6 -0
@@ -203,6 +203,12 @@ static inline int vma_pkey(struct vm_area_struct *vma) {return 0 ; } + +static inline u64 pte_to_hpte_pkey_bits (u64 pteflags) +{ +return 0x0UL ; +} +#endif /* CONFIG_PPC_MEM_KEYS */ #endif /* __KERNEL__ */
arch/powerpc/include/asm/pkeys.h +9 -0
@@ -73,6 +73,15 @@ static inline int vma_pkey(struct vm_area_struct *vma)#define arch_max_pkey () pkeys_total +static inline u64 pte_to_hpte_pkey_bits (u64 pteflags) +{ +return (((pteflags &H_PTE_PKEY_BIT0 ) ?HPTE_R_KEY_BIT0 :0x0UL ) | + ((pteflags &H_PTE_PKEY_BIT1 ) ?HPTE_R_KEY_BIT1 :0x0UL ) | + ((pteflags &H_PTE_PKEY_BIT2 ) ?HPTE_R_KEY_BIT2 :0x0UL ) | + ((pteflags &H_PTE_PKEY_BIT3 ) ?HPTE_R_KEY_BIT3 :0x0UL ) | + ((pteflags &H_PTE_PKEY_BIT4 ) ?HPTE_R_KEY_BIT4 :0x0UL )); +} +#define pkey_alloc_mask (pkey) (0x1 << pkey)#define mm_pkey_allocation_map (mm) (mm->context.pkey_allocation_map)
arch/powerpc/mm/hash_utils_64.c +1 -0
@@ -233,6 +233,7 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags)*/ rflags |=HPTE_R_M ; + rflags |=pte_to_hpte_pkey_bits (pteflags);return rflags; }
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 16/27 powerpc: helper to validate key-access permissions of a pte
In reply to Ram Paihelper function that checks if the read/write/execute is allowed on the pte.
--- arch/powerpc/include/asm/book3s/64/pgtable.h | 4 +++ arch/powerpc/include/asm/pkeys.h | 9 ++++++++ arch/powerpc/mm/pkeys.c | 28 ++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 0 deletions(-)
arch/powerpc/include/asm/book3s/64/pgtable.h +4 -0
@@ -462,6 +462,10 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,pte_update (mm, addr, ptep,0 , _PAGE_PRIVILEGED,1 ); } +#ifdef CONFIG_PPC_MEM_KEYS +extern bool arch_pte_access_permitted (u64 pte,bool write,bool execute); +#endif /* CONFIG_PPC_MEM_KEYS */ +#define __HAVE_ARCH_PTEP_GET_AND_CLEARstatic inline pte_t ptep_get_and_clear (struct mm_struct *mm,unsigned long addr,pte_t *ptep)
arch/powerpc/include/asm/pkeys.h +9 -0
@@ -82,6 +82,15 @@ static inline u64 pte_to_hpte_pkey_bits(u64 pteflags) ((pteflags & H_PTE_PKEY_BIT4) ? HPTE_R_KEY_BIT4 : 0x0UL)); } +static inline u16 pte_to_pkey_bits (u64 pteflags) +{ +return (((pteflags &H_PTE_PKEY_BIT0 ) ?0x10 :0x0UL ) | + ((pteflags &H_PTE_PKEY_BIT1 ) ?0x8 :0x0UL ) | + ((pteflags &H_PTE_PKEY_BIT2 ) ?0x4 :0x0UL ) | + ((pteflags &H_PTE_PKEY_BIT3 ) ?0x2 :0x0UL ) | + ((pteflags &H_PTE_PKEY_BIT4 ) ?0x1 :0x0UL )); +} +#define pkey_alloc_mask (pkey) (0x1 << pkey)#define mm_pkey_allocation_map (mm) (mm->context.pkey_allocation_map)
arch/powerpc/mm/pkeys.c +28 -0
@@ -362,3 +362,31 @@ int __arch_override_mprotect_pkey(struct vm_area_struct *vma, int prot,/* Nothing to override. */ return vma_pkey (vma); } + +static bool pkey_access_permitted (int pkey,bool write,bool execute) +{ +int pkey_shift; +u64 amr; + +if (!pkey) +return true; + +if (!is_pkey_enabled (pkey)) +return true; + + pkey_shift =pkeyshift (pkey); +if (execute && !(read_iamr () & (IAMR_EX_BIT << pkey_shift))) +return true; + + amr =read_amr ();/* Delay reading amr until absolutely needed */ +return ((!write && !(amr & (AMR_RD_BIT << pkey_shift))) || + (write && !(amr & (AMR_WR_BIT << pkey_shift)))); +} + +bool arch_pte_access_permitted (u64 pte,bool write,bool execute) +{ +if (static_branch_likely (&pkey_disabled)) +return true; + +return pkey_access_permitted (pte_to_pkey_bits (pte), write, execute); +}
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 17/27 powerpc: check key protection for user page access
In reply to Ram PaiMake sure that the kernel does not access user pages without checking their key-protection.
--- arch/powerpc/include/asm/book3s/64/pgtable.h | 19 +++++++++++++++++++ 1 files changed, 19 insertions(+), 0 deletions(-)
arch/powerpc/include/asm/book3s/64/pgtable.h +19 -0
@@ -464,6 +464,25 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,#ifdef CONFIG_PPC_MEM_KEYS extern bool arch_pte_access_permitted (u64 pte,bool write,bool execute); + +#define pte_access_permitted (pte, write) \ + (pte_present(pte) && \ + ((!(write) || pte_write(pte)) && \ + arch_pte_access_permitted(pte_val(pte), !!write, 0))) + +/* +* We store key in pmd/pud for huge pages. Need to check for key protection. +*/ +#define pmd_access_permitted (pmd, write) \ + (pmd_present(pmd) && \ + ((!(write) || pmd_write(pmd)) && \ + arch_pte_access_permitted(pmd_val(pmd), !!write, 0))) + +#define pud_access_permitted (pud, write) \ + (pud_present(pud) && \ + ((!(write) || pud_write(pud)) && \ + arch_pte_access_permitted(pud_val(pud), !!write, 0))) +#endif /* CONFIG_PPC_MEM_KEYS */ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 18/27 powerpc: implementation for arch_vma_access_permitted()
In reply to Ram PaiThis patch provides the implementation for arch_vma_access_permitted(). Returns true if the requested access is allowed by pkey associated with the vma.
--- arch/powerpc/include/asm/mmu_context.h | 5 +++- arch/powerpc/mm/pkeys.c | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletions(-)
arch/powerpc/include/asm/mmu_context.h +4 -1
@@ -186,6 +186,10 @@ static inline void arch_bprm_mm_init(struct mm_struct *mm, { } +#ifdef CONFIG_PPC_MEM_KEYS +bool arch_vma_access_permitted (struct vm_area_struct *vma,bool write, +bool execute,bool foreign); +#else /* CONFIG_PPC_MEM_KEYS */ static inline bool arch_vma_access_permitted (struct vm_area_struct *vma,bool write,bool execute,bool foreign) {
@@ -193,7 +197,6 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,return true; } -#ifndef CONFIG_PPC_MEM_KEYS #define pkey_mm_init (mm)#define thread_pkey_regs_save (thread)#define thread_pkey_regs_restore (new_thread, old_thread)
arch/powerpc/mm/pkeys.c +34 -0
@@ -390,3 +390,37 @@ 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 thread because we +* effectively have no access to AMR/IAMR for other threads 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 it is not our ->mm, it has to be foreign */ +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) +{ +if (static_branch_likely (&pkey_disabled)) +return true; +/* +* Do not enforce our key-permissions on a foreign vma. +*/ +if (foreign ||vma_is_foreign (vma)) +return true; + +return pkey_access_permitted (vma_pkey (vma), write, execute); +}
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 19/27 powerpc: Handle exceptions caused by pkey violation
In reply to Ram PaiHandle Data and Instruction exceptions caused by memory protection-key.
The CPU will detect the key fault if the HPTE is already programmed with the key.
However if the HPTE is not hashed, a key fault will not be detected by the hardware. The software will detect pkey violation in such a case.
--- arch/powerpc/include/asm/reg.h | 1 - arch/powerpc/kernel/exceptions-64s.S | 2 +- arch/powerpc/mm/fault.c | 22 ++++++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-)
arch/powerpc/include/asm/reg.h +0 -1
@@ -312,7 +312,6 @@ DSISR_BAD_EXT_CTRL)#define DSISR_BAD_FAULT_64S (DSISR_BAD_FAULT_32S | \ DSISR_ATTR_CONFLICT | \ - DSISR_KEYFAULT | \ DSISR_UNSUPP_MMU | \ DSISR_PRTABLE_FAULT | \ DSISR_ICSWX_NO_CT | \
arch/powerpc/kernel/exceptions-64s.S +1 -1
@@ -1521,7 +1521,7 @@ USE_TEXT_SECTION() .balign IFETCH_ALIGN_BYTES do_hash_page: #ifdef CONFIG_PPC_BOOK3S_64 - lis r0,(DSISR_BAD_FAULT_64S|DSISR_DABRMATCH)@h + lis r0,(DSISR_BAD_FAULT_64S | DSISR_DABRMATCH | DSISR_KEYFAULT)@h ori r0,r0,DSISR_BAD_FAULT_64S@l and. r0,r4,r0 /* weird error? */ bne- handle_page_fault /* if not, try to insert a HPTE */
arch/powerpc/mm/fault.c +22 -0
@@ -427,6 +427,11 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,perf_sw_event (PERF_COUNT_SW_PAGE_FAULTS ,1 , regs, address); +if (error_code &DSISR_KEYFAULT ) { +_exception (SIGSEGV , regs,SEGV_PKUERR , address); +return 0 ; + } +/* * We want to do this outside mmap_sem, because reading code around nip * can result in fault, which will cause a deadlock when called with
@@ -498,6 +503,23 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,* the fault. */ fault =handle_mm_fault (vma, address, flags); + +#ifdef CONFIG_PPC_MEM_KEYS +/* +* if the HPTE is not hashed, hardware will not detect +* a key fault. Lets check if we failed because of a +* software detected key fault. +*/ +if (unlikely (fault &VM_FAULT_SIGSEGV ) && + !arch_vma_access_permitted (vma, flags &FAULT_FLAG_WRITE , + is_exec,0 )) { +int pkey =vma_pkey (vma); + +if (likely (pkey)) +return __bad_area (regs, address,SEGV_PKUERR ); + } +#endif /* CONFIG_PPC_MEM_KEYS */ + major |= fault &VM_FAULT_MAJOR ;/*
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 20/27 powerpc: introduce get_mm_addr_key() helper
In reply to Ram Paiget_mm_addr_key() helper returns the pkey associated with an address corresponding to a given mm_struct.
--- arch/powerpc/include/asm/mmu.h | 9 +++++++++ arch/powerpc/mm/hash_utils_64.c | 24 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 0 deletions(-)
arch/powerpc/include/asm/mmu.h +9 -0
@@ -260,6 +260,15 @@ static inline bool early_radix_enabled(void) }#endif +#ifdef CONFIG_PPC_MEM_KEYS +extern u16 get_mm_addr_key (struct mm_struct *mm,unsigned long address); +#else +static inline u16 get_mm_addr_key (struct mm_struct *mm,unsigned long address) +{ +return 0 ; +} +#endif /* CONFIG_PPC_MEM_KEYS */ +#endif /* !__ASSEMBLY__ */ /* The kernel use the constants below to index in the page sizes array.
arch/powerpc/mm/hash_utils_64.c +24 -0
@@ -1573,6 +1573,30 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,local_irq_restore (flags); } +#ifdef CONFIG_PPC_MEM_KEYS +/* +* Return the protection key associated with the given address and the +* mm_struct. +*/ +u16 get_mm_addr_key (struct mm_struct *mm,unsigned long address) +{ +pte_t *ptep; +u16 pkey =0 ; +unsigned long flags; + +if (!mm || !mm->pgd) +return 0 ; + +local_irq_save (flags); + ptep =find_linux_pte (mm->pgd, address,NULL ,NULL ); +if (ptep) + pkey =pte_to_pkey_bits (pte_val (READ_ONCE (*ptep))); +local_irq_restore (flags); + +return pkey; +} +#endif /* CONFIG_PPC_MEM_KEYS */ +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM static inline void tm_flush_hash_page (int local) {
Signature · 1 line
1.7.1
PATCH v10 21/27 powerpc: Deliver SEGV signal on pkey violation
In reply to Ram PaiThe value of the pkey, whose protection got violated, is made available in si_pkey field of the siginfo structure.
--- arch/powerpc/include/asm/bug.h | 1 + arch/powerpc/kernel/traps.c | 12 +++++++++++- arch/powerpc/mm/fault.c | 39 +++++++++++++++++++++++++++------------ 3 files changed, 39 insertions(+), 13 deletions(-)
arch/powerpc/include/asm/bug.h +1 -0
@@ -133,6 +133,7 @@extern int do_page_fault (struct pt_regs *,unsigned long ,unsigned long );extern void bad_page_fault (struct pt_regs *,unsigned long ,int );extern void _exception (int ,struct pt_regs *,int ,unsigned long ); +extern void _exception_pkey (int ,struct pt_regs *,int ,unsigned long ,int );extern void die (const char *,struct pt_regs *,long );extern bool die_will_crash (void );
arch/powerpc/kernel/traps.c +11 -1
@@ -20,6 +20,7 @@#include <linux/sched/debug.h> #include <linux/kernel.h> #include <linux/mm.h> +#include <linux/pkeys.h> #include <linux/stddef.h> #include <linux/unistd.h> #include <linux/ptrace.h>
@@ -266,7 +267,9 @@ void user_single_step_siginfo(struct task_struct *tsk, info->si_addr = (void __user *)regs->nip; } -void _exception (int signr,struct pt_regs *regs,int code,unsigned long addr) + +void _exception_pkey (int signr,struct pt_regs *regs,int code, +unsigned long addr,int key) {siginfo_t info;const char fmt32[] =KERN_INFO "%s[%d]: unhandled signal %d " \
@@ -293,9 +296,16 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) info.si_signo = signr; info.si_code = code; info.si_addr = (void __user *) addr; + info.si_pkey = key; +force_sig_info (signr, &info, current); } +void _exception (int signr,struct pt_regs *regs,int code,unsigned long addr) +{ +_exception_pkey (signr, regs, code, addr,0 ); +} +void system_reset_exception (struct pt_regs *regs) {/*
arch/powerpc/mm/fault.c +27 -12
@@ -107,7 +107,8 @@ static bool store_updates_sp(struct pt_regs *regs)*/ static int -__bad_area_nosemaphore (struct pt_regs *regs,unsigned long address,int si_code) +__bad_area_nosemaphore (struct pt_regs *regs,unsigned long address,int si_code, +int pkey) {/* * If we are in kernel mode, bail out with a SEGV, this will
@@ -117,17 +118,18 @@ static bool store_updates_sp(struct pt_regs *regs)if (!user_mode (regs))return SIGSEGV ; -_exception (SIGSEGV , regs, si_code, address); +_exception_pkey (SIGSEGV , regs, si_code, address, pkey);return 0 ; } static noinline int bad_area_nosemaphore(struct pt_regs *regs, unsigned long address) { -return __bad_area_nosemaphore (regs, address,SEGV_MAPERR ); +return __bad_area_nosemaphore (regs, address,SEGV_MAPERR ,0 ); } -static int __bad_area (struct pt_regs *regs,unsigned long address,int si_code) +static int __bad_area (struct pt_regs *regs,unsigned long address,int si_code, +int pkey) {struct mm_struct *mm = current->mm;
@@ -137,12 +139,18 @@ static int __bad_area(struct pt_regs *regs, unsigned long address, int si_code)*/ up_read (&mm->mmap_sem); -return __bad_area_nosemaphore (regs, address, si_code); +return __bad_area_nosemaphore (regs, address, si_code, pkey); } static noinline int bad_area(struct pt_regs *regs, unsigned long address) { -return __bad_area (regs, address,SEGV_MAPERR ); +return __bad_area (regs, address,SEGV_MAPERR ,0 ); +} + +static int bad_key_fault_exception (struct pt_regs *regs,unsigned long address, +int pkey) +{ +return __bad_area_nosemaphore (regs, address,SEGV_PKUERR , pkey); } static int do_sigbus(struct pt_regs *regs, unsigned long address,
@@ -427,10 +435,9 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,perf_sw_event (PERF_COUNT_SW_PAGE_FAULTS ,1 , regs, address); -if (error_code &DSISR_KEYFAULT ) { -_exception (SIGSEGV , regs,SEGV_PKUERR , address); -return 0 ; - } +if (error_code &DSISR_KEYFAULT ) +return bad_key_fault_exception (regs, address, +get_mm_addr_key (mm, address));/* * We want to do this outside mmap_sem, because reading code around nip
@@ -513,10 +520,18 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,if (unlikely (fault &VM_FAULT_SIGSEGV ) && !arch_vma_access_permitted (vma, flags &FAULT_FLAG_WRITE , is_exec,0 )) { +/* +* The PGD-PDT...PMD-PTE tree may not have been fully setup. +* Hence we cannot walk the tree to locate the PTE, to locate +* the key. Hence let's use vma_pkey() to get the key; instead +* of get_mm_addr_key(). +*/ int pkey =vma_pkey (vma); -if (likely (pkey)) -return __bad_area (regs, address,SEGV_PKUERR ); +if (likely (pkey)) { +up_read (&mm->mmap_sem); +return bad_key_fault_exception (regs, address, pkey); + } }#endif /* CONFIG_PPC_MEM_KEYS */
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 22/27 powerpc/ptrace: Add memory protection key regset
In reply to Ram PaiFrom: Thiago Jung Bauermann <[email protected]>
The AMR/IAMR/UAMOR are part of the program context. Allow it to be accessed via ptrace and through core files.
--- arch/powerpc/include/asm/pkeys.h | 5 +++ arch/powerpc/include/uapi/asm/elf.h | 1 + arch/powerpc/kernel/ptrace.c | 66 +++++++++++++++++++++++++++++++++++ arch/powerpc/kernel/traps.c | 7 ++++ include/uapi/linux/elf.h | 1 + 5 files changed, 80 insertions(+), 0 deletions(-)
arch/powerpc/include/asm/pkeys.h +5 -0
@@ -213,6 +213,11 @@ static inline int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,return __arch_set_user_pkey_access (tsk, pkey, init_val); } +static inline bool arch_pkeys_enabled (void ) +{ +return !static_branch_likely (&pkey_disabled); +} +extern void pkey_mm_init (struct mm_struct *mm);extern void thread_pkey_regs_save (struct thread_struct *thread); extern void thread_pkey_regs_restore(struct thread_struct *new_thread,
arch/powerpc/include/uapi/asm/elf.h +1 -0
@@ -97,6 +97,7 @@#define ELF_NTMSPRREG 3/* include tfhar, tfiar, texasr */ #define ELF_NEBB 3/* includes ebbrr, ebbhr, bescr */ #define ELF_NPMU 5/* includes siar, sdar, sier, mmcr2, mmcr0 */ +#define ELF_NPKEY 3/* includes amr, iamr, uamor */ typedef unsigned long elf_greg_t64 ;typedef elf_greg_t64 elf_gregset_t64 [ELF_NGREG ];
arch/powerpc/kernel/ptrace.c +66 -0
90 lines not on this page · raw message
arch/powerpc/kernel/traps.c +7 -0
@@ -292,6 +292,13 @@ void _exception_pkey(int signr, struct pt_regs *regs, int code,local_irq_enable (); current->thread.trap_nr = code; + +/* +* Save all the pkey registers AMR/IAMR/UAMOR. Eg: Core dumps need +* to capture the content, if the task gets killed. +*/ +thread_pkey_regs_save (¤t->thread); +memset (&info,0 ,sizeof (info)); info.si_signo = signr; info.si_code = code;
include/uapi/linux/elf.h +1 -0
@@ -396,6 +396,7 @@#define NT_PPC_TM_CTAR 0x10d/* TM checkpointed Target Address Register */ #define NT_PPC_TM_CPPR 0x10e/* TM checkpointed Program Priority Register */ #define NT_PPC_TM_CDSCR 0x10f/* TM checkpointed Data Stream Control Register */ +#define NT_PPC_PKEY 0x110/* Memory Protection Keys registers */ #define NT_386_TLS 0x200/* i386 TLS slots (struct user_desc) */ #define NT_386_IOPERM 0x201/* x86 io permission bitmap (1=deny) */ #define NT_X86_XSTATE 0x202/* x86 extended state using xsave */
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 23/27 powerpc: Enable pkey subsystem
In reply to Ram PaiPAPR defines 'ibm,processor-storage-keys' property. It exports two values. The first value holds the number of data-access keys and the second holds the number of instruction-access keys. Due to a bug in the firmware, instruction-access keys is always reported as zero. However any key can be configured to disable data-access and/or disable execution-access. The inavailablity of the second value is not a big handicap, though it could have been used to determine if the platform supported disable-execution-access.
Non-PAPR platforms do not define this property in the device tree yet. Fortunately power8 is the only released Non-PAPR platform that is supported. Here, we hardcode the number of supported pkey to 32, by consulting the PowerISA3.0
This patch calculates the number of keys supported by the platform. Also it determines the platform support for read/write/execution access support for pkeys.
--- arch/powerpc/include/asm/cputable.h | 16 ++++++--- arch/powerpc/include/asm/pkeys.h | 3 ++ arch/powerpc/mm/pkeys.c | 61 +++++++++++++++++++++++++++++----- 3 files changed, 65 insertions(+), 15 deletions(-)
arch/powerpc/include/asm/cputable.h +10 -6
@@ -207,7 +207,7 @@ enum {#define CPU_FTR_STCX_CHECKS_ADDRESS LONG_ASM_CONST(0x0004000000000000)#define CPU_FTR_POPCNTB LONG_ASM_CONST(0x0008000000000000)#define CPU_FTR_POPCNTD LONG_ASM_CONST(0x0010000000000000) -/* Free LONG_ASM_CONST(0x0020000000000000) */ +#define CPU_FTR_PKEY LONG_ASM_CONST(0x0020000000000000)#define CPU_FTR_VMX_COPY LONG_ASM_CONST(0x0040000000000000)#define CPU_FTR_TM LONG_ASM_CONST(0x0080000000000000)#define CPU_FTR_CFAR LONG_ASM_CONST(0x0100000000000000)
@@ -215,6 +215,7 @@ enum {#define CPU_FTR_DAWR LONG_ASM_CONST(0x0400000000000000)#define CPU_FTR_DABRX LONG_ASM_CONST(0x0800000000000000)#define CPU_FTR_PMAO_BUG LONG_ASM_CONST(0x1000000000000000) +#define CPU_FTR_PKEY_EXECUTE LONG_ASM_CONST(0x2000000000000000)#define CPU_FTR_POWER9_DD1 LONG_ASM_CONST(0x4000000000000000)#define CPU_FTR_POWER9_DD2_1 LONG_ASM_CONST(0x8000000000000000)
@@ -437,7 +438,8 @@ enum { CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_COHERENT_ICACHE | CPU_FTR_PURR | \ - CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_DABRX) + CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_DABRX | \ + CPU_FTR_PKEY)#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -445,7 +447,7 @@ enum { CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \ CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_CFAR | \ - CPU_FTR_DABRX) + CPU_FTR_DABRX | CPU_FTR_PKEY)#define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\ CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -454,7 +456,7 @@ enum { CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT | \ CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ CPU_FTR_CFAR | CPU_FTR_HVMODE | \ - CPU_FTR_VMX_COPY | CPU_FTR_HAS_PPR | CPU_FTR_DABRX) + CPU_FTR_VMX_COPY | CPU_FTR_HAS_PPR | CPU_FTR_DABRX | CPU_FTR_PKEY)#define CPU_FTRS_POWER8 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\ CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -464,7 +466,8 @@ enum { CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \ - CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP) + CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_PKEY |\ + CPU_FTR_PKEY_EXECUTE)#define CPU_FTRS_POWER8E (CPU_FTRS_POWER8 | CPU_FTR_PMAO_BUG)#define CPU_FTRS_POWER8_DD1 (CPU_FTRS_POWER8 & ~CPU_FTR_DBELL)#define CPU_FTRS_POWER9 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
@@ -476,7 +479,8 @@ enum { CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \ - CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300) + CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | \ + CPU_FTR_PKEY | CPU_FTR_PKEY_EXECUTE)#define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \ (~CPU_FTR_SAO))#define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9
arch/powerpc/include/asm/pkeys.h +3 -0
@@ -13,6 +13,7 @@#define _ASM_POWERPC_KEYS_H#include <linux/jump_label.h> +#include <asm/firmware.h> DECLARE_STATIC_KEY_TRUE (pkey_disabled);extern int pkeys_total;/* total pkeys as per device tree */
@@ -219,6 +220,8 @@ static inline bool arch_pkeys_enabled(void) }extern void pkey_mm_init (struct mm_struct *mm); +extern bool arch_supports_pkeys (int cap); +extern unsigned int arch_usable_pkeys (void );extern void thread_pkey_regs_save (struct thread_struct *thread);extern void thread_pkey_regs_restore (struct thread_struct *new_thread,struct thread_struct *old_thread);
arch/powerpc/mm/pkeys.c +52 -9
94 lines not on this page · raw message
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 24/27 powerpc: sys_pkey_alloc() and sys_pkey_free() system calls
In reply to Ram PaiFinally this patch provides the ability for a process to allocate and free a protection key.
--- arch/powerpc/include/asm/systbl.h | 2 ++ arch/powerpc/include/asm/unistd.h | 4 +--- arch/powerpc/include/uapi/asm/unistd.h | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-)
arch/powerpc/include/asm/systbl.h +2 -0
@@ -389,3 +389,5 @@ COMPAT_SYS_SPU(pwritev2) SYSCALL(kexec_file_load) SYSCALL(statx) +SYSCALL(pkey_alloc) +SYSCALL(pkey_free)
arch/powerpc/include/asm/unistd.h +1 -3
@@ -12,13 +12,11 @@#include <uapi/asm/unistd.h> -#define NR_syscalls 384 +#define NR_syscalls 386#define __NR__exit __NR_exit#define __IGNORE_pkey_mprotect -#define __IGNORE_pkey_alloc -#define __IGNORE_pkey_free#ifndef __ASSEMBLY__
arch/powerpc/include/uapi/asm/unistd.h +2 -0
@@ -395,5 +395,7 @@#define __NR_pwritev2 381#define __NR_kexec_file_load 382#define __NR_statx 383 +#define __NR_pkey_alloc 384 +#define __NR_pkey_free 385#endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 25/27 powerpc: sys_pkey_mprotect() system call
In reply to Ram PaiPatch provides the ability for a process to
associate a pkey with a address range.
--- arch/powerpc/include/asm/systbl.h | 1 + arch/powerpc/include/asm/unistd.h | 4 +--- arch/powerpc/include/uapi/asm/unistd.h | 1 + 3 files changed, 3 insertions(+), 3 deletions(-)
arch/powerpc/include/asm/systbl.h +1 -0
@@ -391,3 +391,4 @@ SYSCALL(statx) SYSCALL(pkey_alloc) SYSCALL(pkey_free) +SYSCALL(pkey_mprotect)
arch/powerpc/include/asm/unistd.h +1 -3
@@ -12,12 +12,10 @@#include <uapi/asm/unistd.h> -#define NR_syscalls 386 +#define NR_syscalls 387#define __NR__exit __NR_exit -#define __IGNORE_pkey_mprotect -#ifndef __ASSEMBLY__#include <linux/types.h>
arch/powerpc/include/uapi/asm/unistd.h +1 -0
@@ -397,5 +397,6 @@#define __NR_statx 383#define __NR_pkey_alloc 384#define __NR_pkey_free 385 +#define __NR_pkey_mprotect 386#endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 26/27 mm, x86 : introduce arch_pkeys_enabled()
In reply to Ram PaiArch neutral code needs to know if the architecture supports protection keys to display protection key in smaps. Hence introducing arch_pkeys_enabled().
This patch also provides x86 implementation forarch_pkeys_enabled().
--- arch/x86/include/asm/pkeys.h | 1 + arch/x86/kernel/fpu/xstate.c | 5 +++++ include/linux/pkeys.h | 5 +++++ 3 files changed, 11 insertions(+), 0 deletions(-)
arch/x86/include/asm/pkeys.h +1 -0
@@ -6,6 +6,7 @@extern int arch_set_user_pkey_access (struct task_struct *tsk,int pkey,unsigned long init_val); +extern bool arch_pkeys_enabled (void );/* * Try to dedicate one of the protection keys to be used as an
arch/x86/kernel/fpu/xstate.c +5 -0
@@ -945,6 +945,11 @@ int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, return 0; } + +bool arch_pkeys_enabled (void ) +{ +return boot_cpu_has (X86_FEATURE_OSPKE ); +}#endif /* ! CONFIG_ARCH_HAS_PKEYS */ /*
include/linux/pkeys.h +5 -0
@@ -35,6 +35,11 @@ static inline int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,return 0 ; } +static inline bool arch_pkeys_enabled (void ) +{ +return false; +} +static inline void copy_init_pkru_to_fpregs (void ) { }
Signature · 7 lines
1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v10 27/27 mm: display pkey in smaps if arch_pkeys_enabled() is true
In reply to Ram PaiCurrently the architecture specific code is expected to display the protection keys in smap for a given vma. This can lead to redundant code and possibly to divergent formats in which the key gets displayed.
This patch changes the implementation. It displays the pkey only if the architecture support pkeys.
x86 arch_show_smap() function is not needed anymore. Delete it.
--- arch/x86/kernel/setup.c | 8 -------- fs/proc/task_mmu.c | 11 ++++++----- 2 files changed, 6 insertions(+), 13 deletions(-)
arch/x86/kernel/setup.c +0 -8
@@ -1326,11 +1326,3 @@ static int __init register_kernel_offset_dumper(void)return 0 ; }__initcall (register_kernel_offset_dumper); - -void arch_show_smap (struct seq_file *m,struct vm_area_struct *vma) -{ -if (!boot_cpu_has (X86_FEATURE_OSPKE )) -return ; - -seq_printf (m,"ProtectionKey: %8u\n" ,vma_pkey (vma)); -}
fs/proc/task_mmu.c +6 -5
@@ -18,6 +18,7 @@#include <linux/page_idle.h> #include <linux/shmem_fs.h> #include <linux/uaccess.h> +#include <linux/pkeys.h> #include <asm/elf.h> #include <asm/tlb.h>
@@ -728,10 +729,6 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask, }#endif /* HUGETLB_PAGE */ -void __weak arch_show_smap (struct seq_file *m,struct vm_area_struct *vma) -{ -} -static int show_smap (struct seq_file *m,void *v,int is_pid) {struct proc_maps_private *priv = m->private;
@@ -851,9 +848,13 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) (unsigned long)(mss->pss >> (10 + PSS_SHIFT)));if (!rollup_mode) { -arch_show_smap (m, vma); +#ifdef CONFIG_ARCH_HAS_PKEYS +if (arch_pkeys_enabled ()) +seq_printf (m,"ProtectionKey: %8u\n" ,vma_pkey (vma)); +#endif show_smap_vma_flags (m, vma); } +m_cache_vma (m, vma);return ret; }
Signature · 6 lines
1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v10 27/27] mm: display pkey in smaps if arch_pkeys_enabled() is true
Quoted 57 lines · Ram Pai
Currently the architecture specific code is expected to display the protection keys in smap for a given vma. This can lead to redundant code and possibly to divergent formats in which the key gets displayed.
This patch changes the implementation. It displays the pkey only if the architecture support pkeys.
x86
arch_show_smap()function is not needed anymore. Delete it.Signed-off-by Ram Pai <[email protected]>--- arch/x86/kernel/setup.c | 8 -------- fs/proc/task_mmu.c | 11 ++++++----- 2 files changed, 6 insertions(+), 13 deletions(-)arch/x86/kernel/setup.c +0
-8@@ -1326,11 +1326,3 @@ static int __init register_kernel_offset_dumper(void)return 0 ; }__initcall (register_kernel_offset_dumper); - -void arch_show_smap (struct seq_file *m,struct vm_area_struct *vma) -{ -if (!boot_cpu_has (X86_FEATURE_OSPKE )) -return ; - -seq_printf (m,"ProtectionKey: %8u\n" ,vma_pkey (vma)); -}fs/proc/task_mmu.c +1
-4@@ -18,6 +18,7 @@#include <linux/page_idle.h> #include <linux/shmem_fs.h> #include <linux/uaccess.h> +#include <linux/pkeys.h> #include <asm/elf.h> #include <asm/tlb.h> @@ -728,10 +729,6 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask, }#endif /* HUGETLB_PAGE */ -void __weak arch_show_smap (struct seq_file *m,struct vm_area_struct *vma) -{ -} -static int show_smap (struct seq_file *m,void *v,int is_pid) {struct proc_maps_private *priv = m->private;
fs/proc/task_mmu.c static int show_smap(struct seq_file *m, void *v, int is_pid) · line 854
Quoted 8 lines
fs/proc/task_mmu.c +4
-1@@ -851,9 +848,13 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) (unsigned long)(mss->pss >> (10 + PSS_SHIFT)));if (!rollup_mode) { -arch_show_smap (m, vma); +#ifdef CONFIG_ARCH_HAS_PKEYS +if (arch_pkeys_enabled ()) +seq_printf (m,"ProtectionKey: %8u\n" ,vma_pkey (vma)); +#endif
Would it be worth it making vma_pkey a noop on architectures that don't support protection keys so that we don't need the #ifdef here?
Eric
Quoted 6 lines
fs/proc/task_mmu.c +1
-0show_smap_vma_flags (m, vma); } +m_cache_vma (m, vma);return ret; }
Re: [PATCH v10 27/27] mm: display pkey in smaps if arch_pkeys_enabled() is true
Quoted 61 lines · Eric W. Biederman
Quoted 59 lines · Ram Pai
Currently the architecture specific code is expected to display the protection keys in smap for a given vma. This can lead to redundant code and possibly to divergent formats in which the key gets displayed.
This patch changes the implementation. It displays the pkey only if the architecture support pkeys.
x86
arch_show_smap()function is not needed anymore. Delete it.Signed-off-by Ram Pai <linuxram at us.ibm.com>--- arch/x86/kernel/setup.c | 8 -------- fs/proc/task_mmu.c | 11 ++++++----- 2 files changed, 6 insertions(+), 13 deletions(-)arch/x86/kernel/setup.c +0
-8@@ -1326,11 +1326,3 @@ static int __init register_kernel_offset_dumper(void)return 0 ; }__initcall (register_kernel_offset_dumper); - -void arch_show_smap (struct seq_file *m,struct vm_area_struct *vma) -{ -if (!boot_cpu_has (X86_FEATURE_OSPKE )) -return ; - -seq_printf (m,"ProtectionKey: %8u\n" ,vma_pkey (vma)); -}fs/proc/task_mmu.c +1
-4@@ -18,6 +18,7 @@#include <linux/page_idle.h> #include <linux/shmem_fs.h> #include <linux/uaccess.h> +#include <linux/pkeys.h> #include <asm/elf.h> #include <asm/tlb.h> @@ -728,10 +729,6 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask, }#endif /* HUGETLB_PAGE */ -void __weak arch_show_smap (struct seq_file *m,struct vm_area_struct *vma) -{ -} -static int show_smap (struct seq_file *m,void *v,int is_pid) {struct proc_maps_private *priv = m->private;@@ -851,9 +848,13 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) (unsigned long)(mss->pss >> (10 + PSS_SHIFT)));
Quoted 9 lines
fs/proc/task_mmu.c static int show_smap(struct seq_file *m, void *v, int is_pid) · line 854
Quoted 6 lines
fs/proc/task_mmu.c +4
-1if (!rollup_mode) { -arch_show_smap (m, vma); +#ifdef CONFIG_ARCH_HAS_PKEYS +if (arch_pkeys_enabled ()) +seq_printf (m,"ProtectionKey: %8u\n" ,vma_pkey (vma)); +#endif Would it be worth it making
vma_pkeya noop on architectures that don't support protection keys so that we don't need the #ifdef here?
You mean something like this?
#define vma_pkey(vma)
It will lead to compilation error.
I can make it
#define vma_pkey(vma) 0
and that will work and get rid of the #ifdef
RP
--
To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v10 27/27] mm: display pkey in smaps if arch_pkeys_enabled() is true
Quoted 73 lines · Ram Pai
Quoted 61 lines · Eric W. Biederman
Quoted 59 lines · Ram Pai
Currently the architecture specific code is expected to display the protection keys in smap for a given vma. This can lead to redundant code and possibly to divergent formats in which the key gets displayed.
This patch changes the implementation. It displays the pkey only if the architecture support pkeys.
x86
arch_show_smap()function is not needed anymore. Delete it.Signed-off-by Ram Pai <[email protected]>--- arch/x86/kernel/setup.c | 8 -------- fs/proc/task_mmu.c | 11 ++++++----- 2 files changed, 6 insertions(+), 13 deletions(-)arch/x86/kernel/setup.c +0
-8@@ -1326,11 +1326,3 @@ static int __init register_kernel_offset_dumper(void)return 0 ; }__initcall (register_kernel_offset_dumper); - -void arch_show_smap (struct seq_file *m,struct vm_area_struct *vma) -{ -if (!boot_cpu_has (X86_FEATURE_OSPKE )) -return ; - -seq_printf (m,"ProtectionKey: %8u\n" ,vma_pkey (vma)); -}fs/proc/task_mmu.c +1
-4@@ -18,6 +18,7 @@#include <linux/page_idle.h> #include <linux/shmem_fs.h> #include <linux/uaccess.h> +#include <linux/pkeys.h> #include <asm/elf.h> #include <asm/tlb.h> @@ -728,10 +729,6 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask, }#endif /* HUGETLB_PAGE */ -void __weak arch_show_smap (struct seq_file *m,struct vm_area_struct *vma) -{ -} -static int show_smap (struct seq_file *m,void *v,int is_pid) {struct proc_maps_private *priv = m->private;@@ -851,9 +848,13 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) (unsigned long)(mss->pss >> (10 + PSS_SHIFT)));Quoted 9 lines
fs/proc/task_mmu.c static int show_smap(struct seq_file *m, void *v, int is_pid) · line 854
Quoted 6 lines
fs/proc/task_mmu.c +4
-1if (!rollup_mode) { -arch_show_smap (m, vma); +#ifdef CONFIG_ARCH_HAS_PKEYS +if (arch_pkeys_enabled ()) +seq_printf (m,"ProtectionKey: %8u\n" ,vma_pkey (vma)); +#endif Would it be worth it making
vma_pkeya noop on architectures that don't support protection keys so that we don't need the #ifdef here?You mean something like this?
Quoted 8 lines
#define vma_pkey(vma)It will lead to compilation error.
I can make it
#define vma_pkey(vma) 0and that will work and get rid of the #ifdef
Yes the second is what I was thinking.
I don't know if it is worth it but #ifdefs can be problematic as the result in code not being compile tested.
Eric
Re: [PATCH v10 27/27] mm: display pkey in smaps if arch_pkeys_enabled() is true
In reply to Ram PaiOn Thu 18-01-18 17:50:48, Ram Pai wrote:
[...]
fs/proc/task_mmu.c static int show_smap(struct seq_file *m, void *v, int is_pid) · line 857
Quoted 12 lines
fs/proc/task_mmu.c +5
-1@@ -851,9 +848,13 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) (unsigned long)(mss->pss >> (10 + PSS_SHIFT)));if (!rollup_mode) { -arch_show_smap (m, vma); +#ifdef CONFIG_ARCH_HAS_PKEYS +if (arch_pkeys_enabled ()) +seq_printf (m,"ProtectionKey: %8u\n" ,vma_pkey (vma)); +#endif show_smap_vma_flags (m, vma); } +
Why do you need to add ifdef here? The previous patch should make arch_pkeys_enabled == F when CONFIG_ARCH_HAS_PKEYS=n. Btw. could you merge those two patches into one. It is usually much easier to review a new helper function if it is added along with a user.
Quoted 5 lines
fs/proc/task_mmu.c +0
-0m_cache_vma (m, vma);return ret; }Signature · 1 line
1.7.1
Signature · 2 lines
Michal Hocko SUSE Labs
Re: [PATCH v10 27/27] mm: display pkey in smaps if arch_pkeys_enabled() is true
Quoted 5 lines · Michal Hocko
On Thu 18-01-18 17:50:48, Ram Pai wrote:
[...]Quoted 3 lines
fs/proc/task_mmu.c +0
-0@@ -851,9 +848,13 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) (unsigned long)(mss->pss >> (10 + PSS_SHIFT)));
Quoted 12 lines
fs/proc/task_mmu.c static int show_smap(struct seq_file *m, void *v, int is_pid) · line 857
Quoted 9 lines
fs/proc/task_mmu.c +5
-1if (!rollup_mode) { -arch_show_smap (m, vma); +#ifdef CONFIG_ARCH_HAS_PKEYS +if (arch_pkeys_enabled ()) +seq_printf (m,"ProtectionKey: %8u\n" ,vma_pkey (vma)); +#endif show_smap_vma_flags (m, vma); } +Why do you need to add ifdef here? The previous patch should make
arch_pkeys_enabled== F whenCONFIG_ARCH_HAS_PKEYS=n.
You are right. it need not be wrapped in CONFIG_ARCH_HAS_PKEYS. I had to do it because vma_pkey(vma) is not defined in some architectures.
I will provide a generic vma_pkey() definition for architectures that do not support PKEYS.
Quoted 3 lines
Btw. could you
merge those two patches into one. It is usually much easier to review a new helper function if it is added along with a user.
ok.
Thanks,
RP