mm, x86, powerpc: Memory Protection Keys enhancement
Subsystems (9)
cover mm, x86, powerpc: Memory Protection Keys enhancement
The patch-series enhances memory protection keys feature.
The patch(1) introduces an additional vma bit to support 32 pkeys. PowerPC supports 32 pkeys.
The patch(2,3) introduces a new interface arch_pkeys_enabled(),
this interface can be used by arch-neutral code to display
protection key value in smap.
The patch(4) introduces a syfs interface, to display the static attributes of the protection key. Eg: max number of keys.
The last two patches, (5,6) update documentation.
A separate patch series that enhances selftest will follow. The entire patch series that enables pkeys on powerpc is at
https://github.com/rampai/memorykeys.git memkey.v9-rc1
Testing:
-------
This patches are tested on powerpc platform using a enhaced set of selftests.
Could not test on x86 since I do not have access to one with pkey support.
History:
-------
version v3:
(1) sysfs interface - thanks Thiago.
(2) Documentation update.
version v2:
(1) Documentation is updated to better
capture the semantics.
(2) introduced arch_pkeys_enabled() to find
if an arch enables pkeys. Correspond- ing change in logic that displays key value in smaps.
(3) code rearranged in many places based on
comments from Dave Hansen, Balbir,
Anshuman.
version v1: Initial version
Ram Pai (5):
mm: introduce an additional vma bit for powerpc pkey
mm, x86 : introduce arch_pkeys_enabled()
mm: display pkey in smaps if arch_pkeys_enabled() is true Documentation/x86: Move protecton key documentation to arch neutral
directory
Documentation/vm: PowerPC specific updates to memory protection keys
Thiago Jung Bauermann (1):
mm/mprotect, powerpc/mm/pkeys, x86/mm/pkeys: Add sysfs interface
Documentation/vm/protection-keys.txt | 160 +++++++++++++++++++++++++++++++++ Documentation/x86/protection-keys.txt | 85 ----------------- arch/powerpc/include/asm/pkeys.h | 2 + arch/powerpc/mm/pkeys.c | 20 ++++ arch/x86/include/asm/mmu_context.h | 4 +- arch/x86/include/asm/pkeys.h | 2 + arch/x86/kernel/fpu/xstate.c | 5 + arch/x86/kernel/setup.c | 8 -- arch/x86/mm/pkeys.c | 8 ++ fs/proc/task_mmu.c | 17 ++-- include/linux/mm.h | 16 ++-- include/linux/pkeys.h | 9 ++ mm/mprotect.c | 88 ++++++++++++++++++ 13 files changed, 317 insertions(+), 107 deletions(-) create mode 100644 Documentation/vm/protection-keys.txt delete mode 100644 Documentation/x86/protection-keys.txt
PATCH 1/6 mm: introduce an additional vma bit for powerpc pkey
Currently 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 | 6 ++++-- include/linux/mm.h | 16 ++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-)
fs/proc/task_mmu.c +4 -2
@@ -661,13 +661,15 @@ 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 + /* Additional bit used by ppc64 */ + [ilog2(VM_PKEY_BIT4)] = "", +#endif /* CONFIG_ARCH_HAS_PKEYS */ };size_t i;
include/linux/mm.h +10 -6
@@ -208,21 +208,25 @@ extern int overcommit_kbytes_handler(struct ctl_table *, int, void __user *,#define VM_HIGH_ARCH_BIT_1 33/* bit only usable on 64-bit architectures */ #define VM_HIGH_ARCH_BIT_2 34/* bit only usable on 64-bit architectures */ #define VM_HIGH_ARCH_BIT_3 35/* bit only usable on 64-bit architectures */ +#define VM_HIGH_ARCH_BIT_4 36/* bit only usable on 64-bit architectures */ #define VM_HIGH_ARCH_0 BIT(VM_HIGH_ARCH_BIT_0)#define VM_HIGH_ARCH_1 BIT(VM_HIGH_ARCH_BIT_1)#define VM_HIGH_ARCH_2 BIT(VM_HIGH_ARCH_BIT_2)#define VM_HIGH_ARCH_3 BIT(VM_HIGH_ARCH_BIT_3) +#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_BIT0 VM_HIGH_ARCH_0/* A protection key is a 4-bit value */ +# 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 -#endif +# define VM_PKEY_BIT4 VM_HIGH_ARCH_4 +#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 1/6] mm: introduce an additional vma bit for powerpc pkey
Quoted 6 lines · On Fri, 15 Sep 2017 18:21:05 -0700 Ram Pai <[email protected]> wrote:
Currently 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.
Signed-off-by Ram Pai <[email protected]>---
--
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 2/6 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
@@ -5,6 +5,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
@@ -918,6 +918,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
@@ -34,6 +34,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 3/6 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
@@ -1340,11 +1340,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
@@ -16,6 +16,7 @@#include <linux/mmu_notifier.h> #include <linux/page_idle.h> #include <linux/shmem_fs.h> +#include <linux/pkeys.h> #include <asm/elf.h> #include <linux/uaccess.h>
@@ -714,10 +715,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 vm_area_struct *vma = v;
@@ -803,7 +800,11 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) (vma->vm_flags &VM_LOCKED ) ? (unsigned long)(mss.pss >> (10 + PSS_SHIFT)) : 0); -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 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>
Re: [PATCH 3/6] mm: display pkey in smaps if arch_pkeys_enabled() is true
Quoted 57 lines · On Fri, 15 Sep 2017 18:21:07 -0700 Ram Pai <[email protected]> wrote:
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@@ -1340,11 +1340,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@@ -16,6 +16,7 @@#include <linux/mmu_notifier.h> #include <linux/page_idle.h> #include <linux/shmem_fs.h> +#include <linux/pkeys.h> #include <asm/elf.h> #include <linux/uaccess.h> @@ -714,10 +715,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 vm_area_struct *vma = v;
fs/proc/task_mmu.c static int show_smap(struct seq_file *m, void *v, int is_pid) · line 806
Quoted 8 lines
fs/proc/task_mmu.c +4
-1@@ -803,7 +800,11 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) (vma->vm_flags &VM_LOCKED ) ? (unsigned long)(mss.pss >> (10 + PSS_SHIFT)) : 0); -arch_show_smap (m, vma); +#ifdef CONFIG_ARCH_HAS_PKEYS +if (arch_pkeys_enabled ()) +seq_printf (m,"ProtectionKey: %8u\n" ,vma_pkey (vma)); +#endif
Can CONFIG_ARCH_HAS_PKEYS be true, but the kernel compiled without support for them or it's just not enabled? I think the earlier per_arch function was better
Balbir
Re: [PATCH 3/6] mm: display pkey in smaps if arch_pkeys_enabled() is true
In reply to Ram Paifs/proc/task_mmu.c static int show_smap(struct seq_file *m, void *v, int is_pid) · line 804
Quoted 2 lines · On Fri, 15 Sep 2017 18:21:07 -0700 Ram Pai <[email protected]> wrote:
fs/proc/task_mmu.c +2
-0+#ifdef CONFIG_ARCH_HAS_PKEYS +if (arch_pkeys_enabled ())
Sorry, I missed this bit in my previous review
the patch makes sense
fs/proc/task_mmu.c static int show_smap(struct seq_file *m, void *v, int is_pid) · line 807
Quoted 3 lines
fs/proc/task_mmu.c +3
-0+seq_printf (m,"ProtectionKey: %8u\n" ,vma_pkey (vma)); +#endif +
Balbir
PATCH 4/6 mm/mprotect, powerpc/mm/pkeys, x86/mm/pkeys: Add sysfs interface
In reply to Ram PaiFrom: Thiago Jung Bauermann <[email protected]>
Expose useful information for programs using memory protection keys. Provide implementation for powerpc and x86.
On a powerpc system with pkeys support, here is what is shown:
$ head /sys/kernel/mm/protection_keys/* ==> /sys/kernel/mm/protection_keys/disable_access_supported <== true
==> /sys/kernel/mm/protection_keys/disable_execute_supported <== true
==> /sys/kernel/mm/protection_keys/disable_write_supported <== true
==> /sys/kernel/mm/protection_keys/total_keys <==
32
==> /sys/kernel/mm/protection_keys/usable_keys <== 29
And on an x86 without pkeys support:
$ head /sys/kernel/mm/protection_keys/* ==> /sys/kernel/mm/protection_keys/disable_access_supported <== false
==> /sys/kernel/mm/protection_keys/disable_execute_supported <== false
==> /sys/kernel/mm/protection_keys/disable_write_supported <== false
==> /sys/kernel/mm/protection_keys/total_keys <==
1
==> /sys/kernel/mm/protection_keys/usable_keys <== 0
--- arch/powerpc/include/asm/pkeys.h | 2 + arch/powerpc/mm/pkeys.c | 20 ++++++++ arch/x86/include/asm/mmu_context.h | 4 +- arch/x86/include/asm/pkeys.h | 1 + arch/x86/mm/pkeys.c | 8 +++ include/linux/pkeys.h | 4 ++ mm/mprotect.c | 88 ++++++++++++++++++++++++++++++++++++ 7 files changed, 126 insertions(+), 1 deletions(-)
arch/powerpc/include/asm/pkeys.h +2 -0
@@ -244,6 +244,8 @@ static inline bool pkey_mmu_enabled(void)return cpu_has_feature (CPU_FTR_PKEY ); } +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 +20 -0
@@ -373,3 +373,23 @@ bool arch_vma_access_permitted(struct vm_area_struct *vma,return pkey_access_permitted (pkey, write, execute); } + +unsigned int arch_usable_pkeys (void ) +{ +unsigned int reserved; + +if (!pkey_inited) +return 0 ; + +/* Reserve one more to account for the execute-only pkey. */ + reserved =hweight32 (initial_allocation_mask) +1 ; + +return pkeys_total > reserved ? pkeys_total - reserved :0 ; +} + +bool arch_supports_pkeys (int cap) +{ +if (cap &PKEY_DISABLE_EXECUTE ) +return pkey_execute_disable_support; +return (cap & (PKEY_DISABLE_ACCESS |PKEY_DISABLE_WRITE )); +}
arch/x86/include/asm/mmu_context.h +3 -1
@@ -129,13 +129,15 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)this_cpu_write (cpu_tlbstate.state,TLBSTATE_LAZY ); } +#define PKEY_INITIAL_ALLOCATION_MAP 1 +static inline int init_new_context (struct task_struct *tsk,struct mm_struct *mm) {#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS if (cpu_feature_enabled (X86_FEATURE_OSPKE )) {/* pkey 0 is the default and always allocated */ - mm->context.pkey_allocation_map =0x1 ; + mm->context.pkey_allocation_map =PKEY_INITIAL_ALLOCATION_MAP ;/* -1 means unallocated or invalid */ mm->context.execute_only_pkey =-1 ; }
arch/x86/include/asm/pkeys.h +1 -0
@@ -105,5 +105,6 @@ extern int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,extern int __arch_set_user_pkey_access (struct task_struct *tsk,int pkey,unsigned long init_val);extern void copy_init_pkru_to_fpregs (void ); +extern unsigned int arch_usable_pkeys (void );#endif /*_ASM_X86_PKEYS_H */
arch/x86/mm/pkeys.c +8 -0
@@ -123,6 +123,14 @@ int __arch_override_mprotect_pkey(struct vm_area_struct *vma, int prot, int pkeyreturn vma_pkey (vma); } +unsigned int arch_usable_pkeys (void ) +{ +/* Reserve one more to account for the execute-only pkey. */ +unsigned int reserved =hweight32 (PKEY_INITIAL_ALLOCATION_MAP ) +1 ; + +return arch_max_pkey () > reserved ?arch_max_pkey () - reserved :0 ; +} +#define PKRU_AD_KEY (pkey) (PKRU_AD_BIT << ((pkey) * PKRU_BITS_PER_PKEY))/*
include/linux/pkeys.h +4 -0
@@ -43,6 +43,10 @@ static inline void copy_init_pkru_to_fpregs(void) { } +unsigned int arch_usable_pkeys (void ) +{ +return 0 ; +}#endif /* ! CONFIG_ARCH_HAS_PKEYS */ #endif /* _LINUX_PKEYS_H */
mm/mprotect.c +88 -0
92 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>
Re: [PATCH 4/6] mm/mprotect, powerpc/mm/pkeys, x86/mm/pkeys: Add sysfs interface
Quoted 38 lines · On Fri, 15 Sep 2017 18:21:08 -0700 Ram Pai <[email protected]> wrote:
From: Thiago Jung Bauermann <[email protected]>
Expose useful information for programs using memory protection keys. Provide implementation for powerpc and x86.
On a powerpc system with pkeys support, here is what is shown:
$ head /sys/kernel/mm/protection_keys/* ==> /sys/kernel/mm/protection_keys/disable_access_supported <== true==>
/sys/kernel/mm/protection_keys/disable_execute_supported<== true==>
/sys/kernel/mm/protection_keys/disable_write_supported<== true==>
/sys/kernel/mm/protection_keys/total_keys<==
32==>
/sys/kernel/mm/protection_keys/usable_keys<== 29And on an x86 without pkeys support:
$ head /sys/kernel/mm/protection_keys/* ==> /sys/kernel/mm/protection_keys/disable_access_supported <== false==>
/sys/kernel/mm/protection_keys/disable_execute_supported<== false==>
/sys/kernel/mm/protection_keys/disable_write_supported<== false==>
/sys/kernel/mm/protection_keys/total_keys<==
1
Quoted 6 lines
==>
/sys/kernel/mm/protection_keys/usable_keys<== 0Signed-off-by Ram Pai <[email protected]>Signed-off-by Thiago Jung Bauermann <[email protected]>---
Just curious, how do you see this being used? For debugging or will applications parse these properties and use them? It's hard for an application to partition its address space among keys at runtime, would you agree?
Balbir Singh.
--
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 4/6] mm/mprotect, powerpc/mm/pkeys, x86/mm/pkeys: Add sysfs interface
Quoted 44 lines · Balbir Singh
Quoted 41 lines · On Fri, 15 Sep 2017 18:21:08 -0700 Ram Pai <[email protected]> wrote:
From: Thiago Jung Bauermann <[email protected]>
Expose useful information for programs using memory protection keys. Provide implementation for powerpc and x86.
On a powerpc system with pkeys support, here is what is shown:
$ head /sys/kernel/mm/protection_keys/* ==> /sys/kernel/mm/protection_keys/disable_access_supported <== true==>
/sys/kernel/mm/protection_keys/disable_execute_supported<== true==>
/sys/kernel/mm/protection_keys/disable_write_supported<== true==>
/sys/kernel/mm/protection_keys/total_keys<==
32==>
/sys/kernel/mm/protection_keys/usable_keys<== 29And on an x86 without pkeys support:
$ head /sys/kernel/mm/protection_keys/* ==> /sys/kernel/mm/protection_keys/disable_access_supported <== false==>
/sys/kernel/mm/protection_keys/disable_execute_supported<== false==>
/sys/kernel/mm/protection_keys/disable_write_supported<== false==>
/sys/kernel/mm/protection_keys/total_keys<==
1==>
/sys/kernel/mm/protection_keys/usable_keys<== 0
Quoted 6 lines
Quoted 3 lines
Signed-off-by Ram Pai <[email protected]>Signed-off-by Thiago Jung Bauermann <[email protected]>---
Just curious, how do you see this being used?
For debugging or will applications parse these properties and use them?
Its upto the application to determine the best way to fully exploit all the keys. But that cannot happen if the application has no easy way to determine the number of available keys.
Quoted 2 lines
It's hard for an application to partition its address space among keys at runtime, would you agree?
Why would it be hard? Because the application may not know; in advance, the range of its address space? Well that is true. But that may not be the best strategy. It should not be based on how large its address space range is, rather it should be based on how many unique access-domains it will need. It can associate a key with each domain and it can associate address-ranges to the appropriate domains. The more the number of keys the more the number of access-domains and finer the control.
Quoted 2 lines
Balbir Singh.
Signature · 7 lines
Ram Pai -- 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 5/6 Documentation/x86: Move protecton key documentation to arch neutral directory
In reply to Ram PaiSince PowerPC and Intel both support memory protection keys, moving the documenation to arch-neutral directory.
--- Documentation/vm/protection-keys.txt | 85 +++++++++++++++++++++++++++++++++ Documentation/x86/protection-keys.txt | 85 --------------------------------- 2 files changed, 85 insertions(+), 85 deletions(-) create mode 100644 Documentation/vm/protection-keys.txt delete mode 100644 Documentation/x86/protection-keys.txt
Documentation/vm/protection-keys.txt new file +85 -0
@@ -0,0 +1,85 @@ +Memory Protection Keys for Userspace (PKU aka PKEYs) is a CPU feature +which will be found on future Intel CPUs. + +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. It works by +dedicating 4 previously ignored bits in each page table entry to a +"protection key", giving 16 possible keys. + +There is also a new user-accessible register (PKRU) with two separate +bits (Access Disable and Write Disable) for each key. Being a CPU +register, PKRU is inherently thread-local, potentially giving each +thread a different set of protections from every other thread. + +There are two new instructions (RDPKRU/WRPKRU) for reading and writing +to the new register. The feature is only available in 64-bit mode, +even though there is theoretically space in the PAE PTEs. These +permissions are enforced on data access only and have no effect on +instruction fetches. + +=========================== Syscalls =========================== + +There are 3 system calls which directly interact with pkeys: + + int pkey_alloc(unsigned long flags, unsigned long init_access_rights) + int pkey_free(int pkey); + int pkey_mprotect(unsigned long start, size_t len, + unsigned long prot, int pkey); + +Before a pkey can be used, it must first be allocated with +pkey_alloc(). An application calls the WRPKRU instruction +directly in order to change access permissions to memory covered +with a key. In this example WRPKRU is wrapped by a C function +called pkey_set(). + + int real_prot = PROT_READ|PROT_WRITE; + pkey = pkey_alloc(0, PKEY_DENY_WRITE); + ptr = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); + ret = pkey_mprotect(ptr, PAGE_SIZE, real_prot, pkey); + ... application runs here + +Now, if the application needs to update the data at 'ptr', it can +gain access, do the update, then remove its write access: + + pkey_set(pkey, 0); // clear PKEY_DENY_WRITE + *ptr = foo; // assign something + pkey_set(pkey, PKEY_DENY_WRITE); // set PKEY_DENY_WRITE again + +Now when it frees the memory, it will also free the pkey since it +is no longer in use: + + munmap(ptr, PAGE_SIZE); + pkey_free(pkey); + +(Note: pkey_set() is a wrapper for the RDPKRU and WRPKRU instructions. + An example implementation can be found in + tools/testing/selftests/x86/protection_keys.c) + +=========================== Behavior =========================== + +The kernel attempts to make protection keys consistent with the +behavior of a plain mprotect(). For instance if you do this: + + mprotect(ptr, size, PROT_NONE); + something(ptr); + +you can expect the same effects with protection keys when doing this: + + pkey = pkey_alloc(0, PKEY_DISABLE_WRITE | PKEY_DISABLE_READ); + pkey_mprotect(ptr, size, PROT_READ|PROT_WRITE, pkey); + something(ptr); + +That should be true whether something() is a direct access to 'ptr' +like: + + *ptr = foo; + +or when the kernel does the access on the application's behalf like +with a read(): + + read(fd, ptr, 1); + +The kernel will send a SIGSEGV in both cases, but si_code will be set +to SEGV_PKERR when violating protection keys versus SEGV_ACCERR when +the plain mprotect() permissions are violated.
Documentation/x86/protection-keys.txt deleted +0 -85
85 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH 6/6 Documentation/vm: PowerPC specific updates to memory protection keys
In reply to Ram PaiAdd documentation updates that capture PowerPC specific changes.
--- Documentation/vm/protection-keys.txt | 125 +++++++++++++++++++++++++++------- 1 files changed, 100 insertions(+), 25 deletions(-)
Documentation/vm/protection-keys.txt +100 -25
@@ -1,22 +1,45 @@ -Memory Protection Keys for Userspace (PKU aka PKEYs) is a CPU feature -which will be found on future Intel CPUs. - -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. It works by -dedicating 4 previously ignored bits in each page table entry to a -"protection key", giving 16 possible keys. - -There is also a new user-accessible register (PKRU) with two separate -bits (Access Disable and Write Disable) for each key. Being a CPU -register, PKRU is inherently thread-local, potentially giving each -thread a different set of protections from every other thread. - -There are two new instructions (RDPKRU/WRPKRU) for reading and writing -to the new register. The feature is only available in 64-bit mode, -even though there is theoretically space in the PAE PTEs. These -permissions are enforced on data access only and have no effect on -instruction fetches. +Memory Protection Keys for Userspace (PKU aka PKEYs) is a CPU feature found on +future Intel CPUs and on PowerPC 5 and higher CPUs. + +Memory Protection Keys provide a mechanism for enforcing page-based +protections, but without requiring modification of the page tables when an +application changes protection domains. + +It works by dedicating bits in each page table entry to a "protection key". +There is also a user-accessible register with two separate bits for each +key. Being a CPU register, the user-accessible register is inherently +thread-local, potentially giving each thread a different set of protections +from every other thread. + +On Intel: + + Four previously bits are used the page table entry giving 16 possible keys. + + The user accessible register(PKRU) has a bit each per key to disable + access and to disable write. + + The feature is only available in 64-bit mode, even though there is + theoretically space in the PAE PTEs. These permissions are enforced on + data access only and have no effect on instruction fetches. + +On PowerPC: + + Five bits in the page table entry are used giving 32 possible keys. + This support is currently for Hash Page Table mode only. + + The user accessible register(AMR) has a bit each per key to disable + read and write. Access disable can be achieved by disabling + read and write. + + 'mtspr 0xd, mem' reads the AMR register + 'mfspr mem, 0xd' writes into the AMR register. + + Execution can be disabled by allocating a key with execute-disabled + permission. The execute-permissions on the key; however, cannot be + changed through a user accessible register. The CPU will not allow + execution of instruction in pages that are associated with + execute-disabled key. + =========================== Syscalls ===========================
@@ -28,9 +51,9 @@ There are 3 system calls which directly interact with pkeys: unsigned long prot, int pkey); Before a pkey can be used, it must first be allocated with -pkey_alloc(). An application calls the WRPKRU instruction +pkey_alloc(). An application calls the WRPKRU/AMR instruction directly in order to change access permissions to memory covered -with a key. In this example WRPKRU is wrapped by a C function +with a key. In this example WRPKRU/AMR is wrapped by a C function called pkey_set(). int real_prot = PROT_READ|PROT_WRITE;
@@ -52,11 +75,11 @@ is no longer in use: munmap(ptr, PAGE_SIZE); pkey_free(pkey); -(Note: pkey_set() is a wrapper for the RDPKRU and WRPKRU instructions. +(Note: pkey_set() is a wrapper for the RDPKRU,WRPKRU or AMR instructions. An example implementation can be found in - tools/testing/selftests/x86/protection_keys.c) + tools/testing/selftests/vm/protection_keys.c) -=========================== Behavior =========================== +=========================== Behavior ================================= The kernel attempts to make protection keys consistent with the behavior of a plain mprotect(). For instance if you do this:
@@ -66,7 +89,7 @@ behavior of a plain mprotect(). For instance if you do this: you can expect the same effects with protection keys when doing this: - pkey = pkey_alloc(0, PKEY_DISABLE_WRITE | PKEY_DISABLE_READ); + pkey = pkey_alloc(0, PKEY_DISABLE_ACCESS); pkey_mprotect(ptr, size, PROT_READ|PROT_WRITE, pkey); something(ptr);
@@ -83,3 +106,55 @@ with a read(): The kernel will send a SIGSEGV in both cases, but si_code will be set to SEGV_PKERR when violating protection keys versus SEGV_ACCERR when the plain mprotect() permissions are violated. + +========================== sysfs Interface ========================== + +Information about support of protection keys on the system can be +found in the /sys/kernel/mm/protection_keys directory, which +contains the following files: + +- total_keys: Shows the number of keys supported by the hardware. + Not all of those keys may be available for use by a process + because the platform or operating system may reserve some keys + for their own use. + +- usable_keys: Shows the minimum number of keys guaranteed to be + available for use by a process. In other words: total_keys minus + the keys reserved by the platform or operating system. This + number doesn't change to reflect keys that are already being + used by the process reading the file. + + There may be one more key available than what is advertised in + this file because the kernel may use one key for mprotect() + calls setting up memory with execute-only permissions. This file + assumes that this key is being used, but if it is not the + process will have one more key it can use for other purposes. + +- disable_access_supported: Tells whether the system supports keys + which disallow reading from a given page (i.e., the + PKEY_DISABLE_ACCESS flag is supported). + +- disable_write_supported: Tells whether the system supports keys + which disallow writing to a given page (i.e., the + PKEY_DISABLE_WRITE flag is supported). + +- disable_execute_supported: Tells whether the system supports keys + which disallow code execution from a given page (i.e., the + PKEY_DISABLE_EXECUTE flag is supported). + +==================================================================== + Semantic differences + +The following semantic differences exist between x86 and power. + +a) powerpc (PowerPC8 onwards) *also* allows creation of a key with + execute-disabled. + The following is allowed + pkey = pkey_alloc(0, PKEY_DISABLE_EXECUTE); + +b) changes to the key permission bits from a signal handler do not + persist on x86. The PKRU specific fpregs entry need to be + modified for it to persist. On powerpc the key permission can + be modified by programming the AMR register from the signal + handler. The changes persist across signal boundaries. +=====================================================================
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>