diff options
author | Luis Machado <luis.machado@arm.com> | 2022-09-11 20:47:18 +0100 |
---|---|---|
committer | Luis Machado <luis.machado@arm.com> | 2023-02-21 09:09:24 +0000 |
commit | 6d0020873deb2f2c4e0965dc2ebf227bc1db3140 (patch) | |
tree | 65a67b1ce578389b8f1c1a0e280cb1a35afca484 /gdb/arch | |
parent | fd7f7424f5f68ad5cb16a5319f60ba15a7d23107 (diff) | |
download | gdb-6d0020873deb2f2c4e0965dc2ebf227bc1db3140.zip gdb-6d0020873deb2f2c4e0965dc2ebf227bc1db3140.tar.gz gdb-6d0020873deb2f2c4e0965dc2ebf227bc1db3140.tar.bz2 |
[aarch64] Enable pointer authentication support for aarch64 bare metal/kernel mode addresses
At the moment GDB only handles pointer authentication (pauth) for userspace
addresses and if we're debugging a Linux-hosted program.
The Linux Kernel can be configured to use pauth instructions for some
additional security hardening, but GDB doesn't handle this well.
To overcome this limitation, GDB needs a couple things:
1 - The target needs to advertise pauth support.
2 - The hook to remove non-address bits from a pointer needs to be registered
in aarch64-tdep.c as opposed to aarch64-linux-tdep.c.
There is a patch for QEMU that addresses the first point, and it makes
QEMU's gdbstub expose a couple more pauth mask registers, so overall we will
have up to 4 pauth masks (2 masks or 4 masks):
pauth_dmask
pauth_cmask
pauth_dmask_high
pauth_cmask_high
pauth_dmask and pauth_cmask are the masks used to remove pauth signatures
from userspace addresses. pauth_dmask_high and pauth_cmask_high masks are used
to remove pauth signatures from kernel addresses.
The second point is easily addressed by moving code around.
When debugging a Linux Kernel built with pauth with an unpatched GDB, we get
the following backtrace:
#0 __fput (file=0xffff0000c17a6400) at /repos/linux/fs/file_table.c:296
#1 0xffff8000082bd1f0 in ____fput (work=<optimized out>) at /repos/linux/fs/file_table.c:348
#2 0x30008000080ade30 [PAC] in ?? ()
#3 0x30d48000080ade30 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
With a patched GDB, we get something a lot more meaningful:
#0 __fput (file=0xffff0000c1bcfa00) at /repos/linux/fs/file_table.c:296
#1 0xffff8000082bd1f0 in ____fput (work=<optimized out>) at /repos/linux/fs/file_table.c:348
#2 0xffff8000080ade30 [PAC] in task_work_run () at /repos/linux/kernel/task_work.c:179
#3 0xffff80000801db90 [PAC] in resume_user_mode_work (regs=0xffff80000a96beb0) at /repos/linux/include/linux/resume_user_mode.h:49
#4 do_notify_resume (regs=regs@entry=0xffff80000a96beb0, thread_flags=4) at /repos/linux/arch/arm64/kernel/signal.c:1127
#5 0xffff800008fb9974 [PAC] in prepare_exit_to_user_mode (regs=0xffff80000a96beb0) at /repos/linux/arch/arm64/kernel/entry-common.c:137
#6 exit_to_user_mode (regs=0xffff80000a96beb0) at /repos/linux/arch/arm64/kernel/entry-common.c:142
#7 el0_svc (regs=0xffff80000a96beb0) at /repos/linux/arch/arm64/kernel/entry-common.c:638
#8 0xffff800008fb9d34 [PAC] in el0t_64_sync_handler (regs=<optimized out>) at /repos/linux/arch/arm64/kernel/entry-common.c:655
#9 0xffff800008011548 [PAC] in el0t_64_sync () at /repos/linux/arch/arm64/kernel/entry.S:586
Backtrace stopped: Cannot access memory at address 0xffff80000a96c0c8
Diffstat (limited to 'gdb/arch')
-rw-r--r-- | gdb/arch/aarch64.h | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h index de4461e..4b3f1b8 100644 --- a/gdb/arch/aarch64.h +++ b/gdb/arch/aarch64.h @@ -132,6 +132,12 @@ enum aarch64_regnum #define AARCH64_PAUTH_DMASK_REGNUM(pauth_reg_base) (pauth_reg_base) #define AARCH64_PAUTH_CMASK_REGNUM(pauth_reg_base) (pauth_reg_base + 1) +/* The high versions of these masks are used for bare metal/kernel-mode pointer + authentication support. */ +#define AARCH64_PAUTH_DMASK_HIGH_REGNUM(pauth_reg_base) (pauth_reg_base + 2) +#define AARCH64_PAUTH_CMASK_HIGH_REGNUM(pauth_reg_base) (pauth_reg_base + 3) + +/* This size is only meant for Linux, not bare metal. QEMU exposes 4 masks. */ #define AARCH64_PAUTH_REGS_SIZE (16) #define AARCH64_X_REGS_NUM 31 |