Skip to content
Snippets Groups Projects
  • Luis Machado's avatar
    6d002087
    [aarch64] Enable pointer authentication support for aarch64 bare metal/kernel mode addresses · 6d002087
    Luis Machado authored
    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
    6d002087
    History
    [aarch64] Enable pointer authentication support for aarch64 bare metal/kernel mode addresses
    Luis Machado authored
    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
aarch64-tdep.c 145.27 KiB