Re: [PATCH 4/6] mm/mprotect, powerpc/mm/pkeys, x86/mm/pkeys: Add sysfs interface

2017-09-22 Thread Ram Pai
On Fri, Sep 22, 2017 at 04:00:19PM +1000, Balbir Singh wrote:
> On Fri, 15 Sep 2017 18:21:08 -0700
> Ram Pai  wrote:
> 
> > From: Thiago Jung Bauermann 
> > 
> > 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
> > 
> > Signed-off-by: Ram Pai 
> > Signed-off-by: Thiago Jung Bauermann 
> > ---
> 
> 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.


> 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.

> 
> Balbir Singh.

-- 
Ram Pai



Re: [PATCH 4/6] mm/mprotect, powerpc/mm/pkeys, x86/mm/pkeys: Add sysfs interface

2017-09-22 Thread Balbir Singh
On Fri, 15 Sep 2017 18:21:08 -0700
Ram Pai  wrote:

> From: Thiago Jung Bauermann 
> 
> 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
> 
> Signed-off-by: Ram Pai 
> Signed-off-by: Thiago Jung Bauermann 
> ---

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.


[PATCH 4/6] mm/mprotect, powerpc/mm/pkeys, x86/mm/pkeys: Add sysfs interface

2017-09-15 Thread Ram Pai
From: Thiago Jung Bauermann 

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

Signed-off-by: Ram Pai 
Signed-off-by: Thiago Jung Bauermann 
---
 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(-)

diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h
index baac435..5924325 100644
--- a/arch/powerpc/include/asm/pkeys.h
+++ b/arch/powerpc/include/asm/pkeys.h
@@ -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);
diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c
index 07e76dc..33c9207 100644
--- a/arch/powerpc/mm/pkeys.c
+++ b/arch/powerpc/mm/pkeys.c
@@ -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));
+}
diff --git a/arch/x86/include/asm/mmu_context.h 
b/arch/x86/include/asm/mmu_context.h
index 265c907..e960ab2 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -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_MAP1
+
 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;
}
diff --git a/arch/x86/include/asm/pkeys.h b/arch/x86/include/asm/pkeys.h
index fa82799..e1b25aa 100644
--- a/arch/x86/include/asm/pkeys.h
+++ b/arch/x86/include/asm/pkeys.h
@@ -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 */
diff --git a/arch/x86/mm/pkeys.c b/arch/x86/mm/pkeys.c
index 2dab69a..6b7f4e1 100644
--- a/arch/x86/mm/pkeys.c
+++ b/arch/x86/mm/pkeys.c
@@ -123,6 +123,14 @@ int __arch_override_mprotect_pkey(struct vm_area_struct 
*vma, int prot, int pkey
return 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)