lkml.org 
[lkml]   [2018]   [Dec]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v6 08/13] arm64: expose user PAC bit positions via ptrace
    Date
    From: Mark Rutland <mark.rutland@arm.com>

    When pointer authentication is in use, data/instruction pointers have a
    number of PAC bits inserted into them. The number and position of these
    bits depends on the configured TCR_ELx.TxSZ and whether tagging is
    enabled. ARMv8.3 allows tagging to differ for instruction and data
    pointers.

    For userspace debuggers to unwind the stack and/or to follow pointer
    chains, they need to be able to remove the PAC bits before attempting to
    use a pointer.

    This patch adds a new structure with masks describing the location of
    the PAC bits in userspace instruction and data pointers (i.e. those
    addressable via TTBR0), which userspace can query via PTRACE_GETREGSET.
    By clearing these bits from pointers (and replacing them with the value
    of bit 55), userspace can acquire the PAC-less versions.

    This new regset is exposed when the kernel is built with (user) pointer
    authentication support, and the address authentication feature is
    enabled. Otherwise, the regset is hidden.

    Signed-off-by: Mark Rutland <mark.rutland@arm.com>
    Signed-off-by: Kristina Martsenko <kristina.martsenko@arm.com>
    Cc: Catalin Marinas <catalin.marinas@arm.com>
    Cc: Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
    Cc: Will Deacon <will.deacon@arm.com>
    ---
    arch/arm64/include/asm/pointer_auth.h | 8 ++++++++
    arch/arm64/include/uapi/asm/ptrace.h | 7 +++++++
    arch/arm64/kernel/ptrace.c | 38 +++++++++++++++++++++++++++++++++++
    include/uapi/linux/elf.h | 1 +
    4 files changed, 54 insertions(+)

    diff --git a/arch/arm64/include/asm/pointer_auth.h b/arch/arm64/include/asm/pointer_auth.h
    index fc7ffe8e326f..5721228836c1 100644
    --- a/arch/arm64/include/asm/pointer_auth.h
    +++ b/arch/arm64/include/asm/pointer_auth.h
    @@ -2,9 +2,11 @@
    #ifndef __ASM_POINTER_AUTH_H
    #define __ASM_POINTER_AUTH_H

    +#include <linux/bitops.h>
    #include <linux/random.h>

    #include <asm/cpufeature.h>
    +#include <asm/memory.h>
    #include <asm/sysreg.h>

    #ifdef CONFIG_ARM64_PTR_AUTH
    @@ -57,6 +59,12 @@ static inline void ptrauth_keys_switch(struct ptrauth_keys *keys)
    __ptrauth_key_install(APGA, keys->apga);
    }

    +/*
    + * The EL0 pointer bits used by a pointer authentication code.
    + * This is dependent on TBI0 being enabled, or bits 63:56 would also apply.
    + */
    +#define ptrauth_pac_mask() GENMASK(54, VA_BITS)
    +
    #define ptrauth_thread_init_user(tsk) \
    do { \
    struct task_struct *__ptiu_tsk = (tsk); \
    diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h
    index a36227fdb084..c2f249bcd829 100644
    --- a/arch/arm64/include/uapi/asm/ptrace.h
    +++ b/arch/arm64/include/uapi/asm/ptrace.h
    @@ -229,6 +229,13 @@ struct user_sve_header {
    SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags) \
    : SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags))

    +/* pointer authentication masks (NT_ARM_PAC_MASK) */
    +
    +struct user_pac_mask {
    + __u64 data_mask;
    + __u64 insn_mask;
    +};
    +
    #endif /* __ASSEMBLY__ */

    #endif /* _UAPI__ASM_PTRACE_H */
    diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
    index 1710a2d01669..6c1f63cb6c4e 100644
    --- a/arch/arm64/kernel/ptrace.c
    +++ b/arch/arm64/kernel/ptrace.c
    @@ -46,6 +46,7 @@
    #include <asm/debug-monitors.h>
    #include <asm/fpsimd.h>
    #include <asm/pgtable.h>
    +#include <asm/pointer_auth.h>
    #include <asm/stacktrace.h>
    #include <asm/syscall.h>
    #include <asm/traps.h>
    @@ -956,6 +957,30 @@ static int sve_set(struct task_struct *target,

    #endif /* CONFIG_ARM64_SVE */

    +#ifdef CONFIG_ARM64_PTR_AUTH
    +static int pac_mask_get(struct task_struct *target,
    + const struct user_regset *regset,
    + unsigned int pos, unsigned int count,
    + void *kbuf, void __user *ubuf)
    +{
    + /*
    + * The PAC bits can differ across data and instruction pointers
    + * depending on TCR_EL1.TBID*, which we may make use of in future, so
    + * we expose separate masks.
    + */
    + unsigned long mask = ptrauth_pac_mask();
    + struct user_pac_mask uregs = {
    + .data_mask = mask,
    + .insn_mask = mask,
    + };
    +
    + if (!system_supports_address_auth())
    + return -EINVAL;
    +
    + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &uregs, 0, -1);
    +}
    +#endif /* CONFIG_ARM64_PTR_AUTH */
    +
    enum aarch64_regset {
    REGSET_GPR,
    REGSET_FPR,
    @@ -968,6 +993,9 @@ enum aarch64_regset {
    #ifdef CONFIG_ARM64_SVE
    REGSET_SVE,
    #endif
    +#ifdef CONFIG_ARM64_PTR_AUTH
    + REGSET_PAC_MASK,
    +#endif
    };

    static const struct user_regset aarch64_regsets[] = {
    @@ -1037,6 +1065,16 @@ static const struct user_regset aarch64_regsets[] = {
    .get_size = sve_get_size,
    },
    #endif
    +#ifdef CONFIG_ARM64_PTR_AUTH
    + [REGSET_PAC_MASK] = {
    + .core_note_type = NT_ARM_PAC_MASK,
    + .n = sizeof(struct user_pac_mask) / sizeof(u64),
    + .size = sizeof(u64),
    + .align = sizeof(u64),
    + .get = pac_mask_get,
    + /* this cannot be set dynamically */
    + },
    +#endif
    };

    static const struct user_regset_view user_aarch64_view = {
    diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
    index c5358e0ae7c5..3f23273d690c 100644
    --- a/include/uapi/linux/elf.h
    +++ b/include/uapi/linux/elf.h
    @@ -420,6 +420,7 @@ typedef struct elf64_shdr {
    #define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */
    #define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
    #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension registers */
    +#define NT_ARM_PAC_MASK 0x406 /* ARM pointer authentication code masks */
    #define NT_ARC_V2 0x600 /* ARCv2 accumulator/extra registers */
    #define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note */
    #define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */
    --
    2.11.0
    \
     
     \ /
      Last update: 2018-12-07 19:42    [W:2.697 / U:0.132 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site