History

arm64: expose user PAC bit positions via ptrace

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.

Mark Rutland committed 7 years ago

Commit ec6e8221 parent 75031976 files · +57 −2Browse files

Unified · Split

6 files
  1. arch/arm64/include/asm/memory.h +3 −0
  2. arch/arm64/include/asm/pointer_auth.h +8 −0
  3. arch/arm64/include/asm/processor.h +0 −2
  4. arch/arm64/include/uapi/asm/ptrace.h +7 −0
  5. arch/arm64/kernel/ptrace.c +38 −0
  6. include/uapi/linux/elf.h +1 −0
arch/arm64/include/asm/memory.h+3−0
@@ -207,6 +207,9 @@ static inline unsigned long kaslr_offset(void) · 206 unmodified lines
207 return kimage_vaddr - KIMAGE_VADDR;207 return kimage_vaddr - KIMAGE_VADDR;
208}208}
209 209
210/* the actual size of a user virtual address */
211extern u64 vabits_user;
212
210/*213/*
211 * Allow all memory at the discovery stage. We will clip it later.214 * Allow all memory at the discovery stage. We will clip it later.
212 */215 */
arch/arm64/include/asm/pointer_auth.h+8−0
@@ -2,9 +2,11 @@ · 1 unmodified line
2#ifndef __ASM_POINTER_AUTH_H2#ifndef __ASM_POINTER_AUTH_H
3#define __ASM_POINTER_AUTH_H3#define __ASM_POINTER_AUTH_H
4 4
5#include <linux/bitops.h>
5#include <linux/random.h>6#include <linux/random.h>
6 7
7#include <asm/cpufeature.h>8#include <asm/cpufeature.h>
9#include <asm/memory.h>
8#include <asm/sysreg.h>10#include <asm/sysreg.h>
9 11
10#ifdef CONFIG_ARM64_PTR_AUTH12#ifdef CONFIG_ARM64_PTR_AUTH
@@ -61,6 +63,12 @@ static inline void ptrauth_keys_switch(struct ptrauth_keys *keys) · 50 unmodified lines
61 __ptrauth_key_install(APGA, keys->apga);63 __ptrauth_key_install(APGA, keys->apga);
62}64}
63 65
66/*
67 * The EL0 pointer bits used by a pointer authentication code.
68 * This is dependent on TBI0 being enabled, or bits 63:56 would also apply.
69 */
70#define ptrauth_user_pac_mask() GENMASK(54, vabits_user)
71
64#define ptrauth_thread_init_user(tsk) \72#define ptrauth_thread_init_user(tsk) \
65do { \73do { \
66 struct task_struct *__ptiu_tsk = (tsk); \74 struct task_struct *__ptiu_tsk = (tsk); \
arch/arm64/include/asm/processor.h+0−2
@@ -53,8 +53,6 @@ · 52 unmodified lines
53 */53 */
54 54
55#define DEFAULT_MAP_WINDOW_64 (UL(1) << VA_BITS)55#define DEFAULT_MAP_WINDOW_64 (UL(1) << VA_BITS)
56
57extern u64 vabits_user;
58#define TASK_SIZE_64 (UL(1) << vabits_user)56#define TASK_SIZE_64 (UL(1) << vabits_user)
59 57
60#ifdef CONFIG_COMPAT58#ifdef CONFIG_COMPAT
arch/arm64/include/uapi/asm/ptrace.h+7−0
@@ -229,6 +229,13 @@ struct user_sve_header { · 228 unmodified lines
229 SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags) \229 SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags) \
230 : SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags))230 : SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags))
231 231
232/* pointer authentication masks (NT_ARM_PAC_MASK) */
233
234struct user_pac_mask {
235 __u64 data_mask;
236 __u64 insn_mask;
237};
238
232#endif /* __ASSEMBLY__ */239#endif /* __ASSEMBLY__ */
233 240
234#endif /* _UAPI__ASM_PTRACE_H */241#endif /* _UAPI__ASM_PTRACE_H */
arch/arm64/kernel/ptrace.c+38−0
@@ -46,6 +46,7 @@ · 45 unmodified lines
46#include <asm/debug-monitors.h>46#include <asm/debug-monitors.h>
47#include <asm/fpsimd.h>47#include <asm/fpsimd.h>
48#include <asm/pgtable.h>48#include <asm/pgtable.h>
49#include <asm/pointer_auth.h>
49#include <asm/stacktrace.h>50#include <asm/stacktrace.h>
50#include <asm/syscall.h>51#include <asm/syscall.h>
51#include <asm/traps.h>52#include <asm/traps.h>
@@ -956,6 +957,30 @@ out: · 904 unmodified lines
956 957
957#endif /* CONFIG_ARM64_SVE */958#endif /* CONFIG_ARM64_SVE */
958 959
960#ifdef CONFIG_ARM64_PTR_AUTH
961static int pac_mask_get(struct task_struct *target,
962 const struct user_regset *regset,
963 unsigned int pos, unsigned int count,
964 void *kbuf, void __user *ubuf)
965{
966 /*
967 * The PAC bits can differ across data and instruction pointers
968 * depending on TCR_EL1.TBID*, which we may make use of in future, so
969 * we expose separate masks.
970 */
971 unsigned long mask = ptrauth_user_pac_mask();
972 struct user_pac_mask uregs = {
973 .data_mask = mask,
974 .insn_mask = mask,
975 };
976
977 if (!system_supports_address_auth())
978 return -EINVAL;
979
980 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &uregs, 0, -1);
981}
982#endif /* CONFIG_ARM64_PTR_AUTH */
983
959enum aarch64_regset {984enum aarch64_regset {
960 REGSET_GPR,985 REGSET_GPR,
961 REGSET_FPR,986 REGSET_FPR,
@@ -968,6 +993,9 @@ enum aarch64_regset { · 6 unmodified lines
968#ifdef CONFIG_ARM64_SVE993#ifdef CONFIG_ARM64_SVE
969 REGSET_SVE,994 REGSET_SVE,
970#endif995#endif
996#ifdef CONFIG_ARM64_PTR_AUTH
997 REGSET_PAC_MASK,
998#endif
971};999};
972 1000
973static const struct user_regset aarch64_regsets[] = {1001static const struct user_regset aarch64_regsets[] = {
@@ -1037,6 +1065,16 @@ static const struct user_regset aarch64_regsets[] = { · 63 unmodified lines
1037 .get_size = sve_get_size,1065 .get_size = sve_get_size,
1038 },1066 },
1039#endif1067#endif
1068#ifdef CONFIG_ARM64_PTR_AUTH
1069 [REGSET_PAC_MASK] = {
1070 .core_note_type = NT_ARM_PAC_MASK,
1071 .n = sizeof(struct user_pac_mask) / sizeof(u64),
1072 .size = sizeof(u64),
1073 .align = sizeof(u64),
1074 .get = pac_mask_get,
1075 /* this cannot be set dynamically */
1076 },
1077#endif
1040};1078};
1041 1079
1042static const struct user_regset_view user_aarch64_view = {1080static const struct user_regset_view user_aarch64_view = {
include/uapi/linux/elf.h+1−0
@@ -420,6 +420,7 @@ typedef struct elf64_shdr { · 419 unmodified lines
420#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */420#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */
421#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */421#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
422#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension registers */422#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension registers */
423#define NT_ARM_PAC_MASK 0x406 /* ARM pointer authentication code masks */
423#define NT_ARC_V2 0x600 /* ARCv2 accumulator/extra registers */424#define NT_ARC_V2 0x600 /* ARCv2 accumulator/extra registers */
424#define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note */425#define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note */
425#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */426#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t