powerpc/ptrace: Add memory protection key regset
The AMR/IAMR/UAMOR are part of the program context. Allow it to be accessed via ptrace and through core files. Signed-off-by: Ram Pai <linuxram@us.ibm.com> Signed-off-by: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
99cd130232
commit
c5cc1f4df6
@ -202,6 +202,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,
|
||||
|
@ -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];
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <linux/context_tracking.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/pkeys.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/switch_to.h>
|
||||
@ -1787,6 +1788,61 @@ static int pmu_set(struct task_struct *target,
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_MEM_KEYS
|
||||
static int pkey_active(struct task_struct *target,
|
||||
const struct user_regset *regset)
|
||||
{
|
||||
if (!arch_pkeys_enabled())
|
||||
return -ENODEV;
|
||||
|
||||
return regset->n;
|
||||
}
|
||||
|
||||
static int pkey_get(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
void *kbuf, void __user *ubuf)
|
||||
{
|
||||
BUILD_BUG_ON(TSO(amr) + sizeof(unsigned long) != TSO(iamr));
|
||||
BUILD_BUG_ON(TSO(iamr) + sizeof(unsigned long) != TSO(uamor));
|
||||
|
||||
if (!arch_pkeys_enabled())
|
||||
return -ENODEV;
|
||||
|
||||
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.amr, 0,
|
||||
ELF_NPKEY * sizeof(unsigned long));
|
||||
}
|
||||
|
||||
static int pkey_set(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
u64 new_amr;
|
||||
int ret;
|
||||
|
||||
if (!arch_pkeys_enabled())
|
||||
return -ENODEV;
|
||||
|
||||
/* Only the AMR can be set from userspace */
|
||||
if (pos != 0 || count != sizeof(new_amr))
|
||||
return -EINVAL;
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&new_amr, 0, sizeof(new_amr));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* UAMOR determines which bits of the AMR can be set from userspace. */
|
||||
target->thread.amr = (new_amr & target->thread.uamor) |
|
||||
(target->thread.amr & ~target->thread.uamor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PPC_MEM_KEYS */
|
||||
|
||||
/*
|
||||
* These are our native regset flavors.
|
||||
*/
|
||||
@ -1821,6 +1877,9 @@ enum powerpc_regset {
|
||||
REGSET_EBB, /* EBB registers */
|
||||
REGSET_PMR, /* Performance Monitor Registers */
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_MEM_KEYS
|
||||
REGSET_PKEY, /* AMR register */
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct user_regset native_regsets[] = {
|
||||
@ -1926,6 +1985,13 @@ static const struct user_regset native_regsets[] = {
|
||||
.active = pmu_active, .get = pmu_get, .set = pmu_set
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_MEM_KEYS
|
||||
[REGSET_PKEY] = {
|
||||
.core_note_type = NT_PPC_PKEY, .n = ELF_NPKEY,
|
||||
.size = sizeof(u64), .align = sizeof(u64),
|
||||
.active = pkey_active, .get = pkey_get, .set = pkey_set
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct user_regset_view user_ppc_native_view = {
|
||||
|
@ -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;
|
||||
|
@ -396,6 +396,7 @@ typedef struct elf64_shdr {
|
||||
#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 */
|
||||
|
Loading…
Reference in New Issue
Block a user