Message ID | 1500177424-13695-18-git-send-email-linuxram@us.ibm.com (mailing list archive) |
---|---|
State | RFC |
Headers | show |
Ram Pai <linuxram@us.ibm.com> writes: > @@ -113,10 +117,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 (!pkey_inited) > + return -1; > + return __arch_set_user_pkey_access(tsk, pkey, init_val); > } If non-zero, the return value of this function will be passed to userspace by the pkey_alloc syscall. Shouldn't it be returning an errno macro such as -EPERM? Also, why are there both arch_set_user_pkey_access and __arch_set_user_pkey_access? Is it a speed optimization so that the early return is inlined into the caller? Ditto for execute_only_pkey and __arch_override_mprotect_pkey.
On Thu, Jul 27, 2017 at 11:15:36AM -0300, Thiago Jung Bauermann wrote: > > Ram Pai <linuxram@us.ibm.com> writes: > > @@ -113,10 +117,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 (!pkey_inited) > > + return -1; > > + return __arch_set_user_pkey_access(tsk, pkey, init_val); > > } > > If non-zero, the return value of this function will be passed to > userspace by the pkey_alloc syscall. Shouldn't it be returning an errno > macro such as -EPERM? Yes. it should be -EINVAL. fixed it. > > Also, why are there both arch_set_user_pkey_access and > __arch_set_user_pkey_access? Is it a speed optimization so that the > early return is inlined into the caller? Ditto for execute_only_pkey > and __arch_override_mprotect_pkey. arch_set_user_pkey_access() is the interface expected by the architecture independent code. The __arch_set_user_pkey_access() is an powerpc internal function that implements the bulk of the work. It can be called by any of the pkeys internal code only. This gives me the flexibility to change implementation without having to worry about changing the interface. RP
diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h index 7f5c21d..1943e6b 100644 --- a/arch/powerpc/include/asm/pkeys.h +++ b/arch/powerpc/include/asm/pkeys.h @@ -3,6 +3,10 @@ extern bool pkey_inited; #define arch_max_pkey() 32 +#define AMR_RD_BIT 0x1UL +#define AMR_WR_BIT 0x2UL +#define IAMR_EX_BIT 0x1UL +#define AMR_BITS_PER_PKEY 2 #define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2 | \ VM_PKEY_BIT3 | VM_PKEY_BIT4) #define AMR_BITS_PER_PKEY 2 @@ -113,10 +117,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 (!pkey_inited) + return -1; + return __arch_set_user_pkey_access(tsk, pkey, init_val); } static inline void pkey_mm_init(struct mm_struct *mm) diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c index 04ee361..98d0391 100644 --- a/arch/powerpc/mm/pkeys.c +++ b/arch/powerpc/mm/pkeys.c @@ -17,6 +17,10 @@ bool pkey_inited; #define pkeyshift(pkey) ((arch_max_pkey()-pkey-1) * AMR_BITS_PER_PKEY) +static bool is_pkey_enabled(int pkey) +{ + return !!(read_uamor() & (0x3ul << pkeyshift(pkey))); +} static inline void init_amr(int pkey, u8 init_bits) { @@ -60,3 +64,26 @@ void __arch_deactivate_pkey(int pkey) { pkey_status_change(pkey, false); } + +/* + * set the access right in AMR IAMR and UAMOR register + * 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 -1; + + /* 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; +}
This 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. Signed-off-by: Ram Pai <linuxram@us.ibm.com> --- arch/powerpc/include/asm/pkeys.h | 10 +++++++++- arch/powerpc/mm/pkeys.c | 27 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletions(-)