Skip to content

[PAuth][LLDB] Make signed pointers usable in expressions #61

Open
@atrosinenko

Description

@atrosinenko

Make possible to transparently use signed pointers fetched from the target process in LLDB expressions. Presently, LLDB doesn't take into account pointers being signed when dereferencing them (resulting in SEGV or some other sort of "invalid pointer" error).

Let's consider the following code:

indirect-call-for-lldb.c:

int f(int n) {
  return n + 42;
}

int g(int n) {
  return 1;
}

volatile void *p;

int main(int argc, const char *argv[]) {
  int (*ptr)(int) = argc > 1 ? f : g;
  p = ptr;
  return ptr(1);
}

Compile it using our toolchain (commit 62ce88f) with the following command:

/path/to/bin/clang \
    -fuse-ld=lld -O2 -g3 \
    -target aarch64-linux-gnu-musl \
    -mcpu=cortex-a72+pauth \
    -mbranch-protection=pauthabi \
    --sysroot=./local-with-musl \
    -Wl,--dynamic-linker=/share/pauth-atrosinenko/local-with-musl/lib/ld-musl-aarch64.so.1 \
    indirect-call-for-lldb.c \
    -o indirect-call-for-lldb

Inside QEMU, segmentation fault is observed when trying to perform indirect call.

Note: I use -cpu max,pauth=on,pauth-impdef=on QEMU options to get reasonable simulation performance, so PACs usually don't look very random (0x003c in the below example).

[ast@localhost pauth-atrosinenko]$ ./local-with-musl/bin/lldb -- ./indirect-call-for-lldb
(lldb) target create "./indirect-call-for-lldb"
Current executable set to '/share/pauth-atrosinenko/indirect-call-for-lldb' (aarch64).
(lldb) break set -y indirect-call-for-lldb.c:13
Breakpoint 1: where = indirect-call-for-lldb`main + 36 at indirect-call-for-lldb.c:13:5, address = 0x0000000000010524
(lldb) run
Process 1103 launched: '/share/pauth-atrosinenko/indirect-call-for-lldb' (aarch64)
Process 1103 stopped
* thread #1, name = 'indirect-call-f', stop reason = breakpoint 1.1
    frame #0: 0x0000aaaaaaab0524 indirect-call-for-lldb`main(argc=1, argv=<unavailable>) at indirect-call-for-lldb.c:13:5
   10  
   11   int main(int argc, const char *argv[]) {
   12     int (*ptr)(int) = argc > 1 ? f : g;
-> 13     p = ptr;
   14     return ptr(1);
   15   }
(lldb) p ptr
(int (*)(int)) 0x003caaaaaaab04f0 (actual=0x0000aaaaaaab04f0 indirect-call-for-lldb`g at indirect-call-for-lldb.c:6:3)
(lldb) call ptr(1)
error: Execution was interrupted, reason: signal SIGSEGV: address not mapped to object (fault address: 0x3caaaaaaab04f0).
The process has been returned to the state before expression evaluation.
(lldb) c
Process 1103 resuming
Process 1103 exited with status = 1 (0x00000001) 
(lldb) q

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions