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:
Thiago Jung Bauermann 2018-01-18 17:50:43 -08:00 committed by Michael Ellerman
parent 99cd130232
commit c5cc1f4df6
5 changed files with 80 additions and 0 deletions

View File

@ -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,

View File

@ -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];

View File

@ -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 = {

View File

@ -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(&current->thread);
memset(&info, 0, sizeof(info));
info.si_signo = signr;
info.si_code = code;

View File

@ -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 */