Add support for aarch64-unknown-linux-pauthtest#755
Add support for aarch64-unknown-linux-pauthtest#755jchlanda wants to merge 1 commit intorust-lang:masterfrom
aarch64-unknown-linux-pauthtest#755Conversation
This PR adds support for `aarch64-unknown-linux-pauthtest`, a target that enables Pointer Authentication Code (PAC) support in Rust on AArch64 ELF based Linux systems using a pauthtest ABI (provided by LLVM) and pauthtest-enabled sysroot with custom musl, serving as a reference libc implementation.
| // as uw::_Unwind_FindEnclosingFunction creates a new context so | ||
| // the SP used for signing here would belong to a different frame | ||
| // that the one used for auth-resign. Hence return a raw value. | ||
| self.ip() |
There was a problem hiding this comment.
Why is ip not signed? It is directly the result of _Unwind_GetIP. It should be possible to pass that to _Unwind_FindEnclosingFunction. How else would you even be able to use _Unwind_FindEnclosingFunction otherwise?
There was a problem hiding this comment.
Why is ip not signed? It is directly the result of _Unwind_GetIP.
A raw ip is expected. _Unwind_GetIP authenticates the pointer and returns a stripped version (via ptrauth_auth_data here).
It should be possible to pass that to
_Unwind_FindEnclosingFunction. How
else would you even be able to use_Unwind_FindEnclosingFunctionotherwise?
This is the crux of the issue. _Unwind_FindEnclosingFunction is fundamentally incompatible with the pointer authentication model. The problem is that _Unwind_FindEnclosingFunction does not follow PAC semantics, it blindly creates a fresh unwind cursor and then resets the instruction pointer here: __unw_set_reg(cursor, UNW_REG_IP, pc);. As if to say: "treat this pc as if it belonged to this new cursor's frame".
__unw_set_reg does apply PAC logic internally (authenticates) under the assumption that the ip behaves like a return address for the current frame.
This cannot be fixed on the Rust side. _Unwind_FindEnclosingFunction constructs a new cursor (and therefore a new sp), so there is no way to correctly sign pointer: any signing we would perform would use the wrong context and would still fail authentication inside libunwind.
There was a problem hiding this comment.
That sounds like a bug in libunwind to me. What purpose does _Unwind_FindEnclosingFunction have at all if you can't pass the result of _Unwind_GetIP to it?
There was a problem hiding this comment.
I'm not sure, the documentation seems to be pretty scarce, and one I found is rather quite lax about possible outcomes of the call, explicitly allowing failure.
I personally don't read it as a bug. To me it is more that _Unwind_FindEnclosingFunction was designed before pointer authentication existed, and its API implicitly assumes that instruction pointers are context-free values. But in PAC-aware code PC is only meaningful in the context of the (original) SP.
There was a problem hiding this comment.
Why does _Unwind_FindEnclosingFunction need an authenticated pointer? It doesn't dereference the pointer, only looks it up in a side table with the result not having any security relevance. The only useful thing you can do with it afaik is looking up debuginfo for the function. Due to inlining and outlining you can't guarantee that it points to any particular function.
| // clause, and if this is fixed that test in theory can be run on macOS! | ||
| if cfg!(target_vendor = "apple") { | ||
| self.ip() | ||
| } else if cfg!(target_env = "pauthtest") { |
There was a problem hiding this comment.
Should this not check for the respective target feature being enabled? Not every target with pointer authentication enabled will use that target env, right?
There was a problem hiding this comment.
You are right.
We're in the middle of preparing an upstream patch that introduces a pointer authentication aware target. It just so happens that in there I ended up using (incorrectly) the target environment as the gating mechanism.
We have a follow up task to resolve the target to a set of features, just like it's done in clang where it solves platform/environment specifics on the driver level and later on everything is based on language flags that are there regardless of the platform. And finally are resolved to a concrete signing schema.
This will become a bit more clear once the PR lands and I submit a ticket.
This PR adds support for
aarch64-unknown-linux-pauthtest, a target that enables Pointer Authentication Code (PAC) support in Rust on AArch64 ELF based Linux systems using a pauthtest ABI (provided by LLVM) and pauthtest-enabled sysroot with custom musl, serving as a reference libc implementation.Please consult a rust-lang PR for the details on the target: TODO JKB Add link