Repository navigation
Arm64: [PAC-RET] Add Pointer Authentication support for Arm64 - #125436
SwapnilGaikwad wants to merge 186 commits into
Conversation
This PR adds support for Pointer Authentication (PAC) on Arm64. Pointer Authentication (PAC) is an Armv8.3+ security feature designed to mitigate Return-Oriented Programming (ROP) attacks by cryptographically signing return addresses. While using PAC, we store a signed return address, instead of the plain address, on the stack and later authenticate it before returning from a function. It ensures control flow returns to the intended caller. More details on PAC and its role in software security can be found ([here](https://llsoftsec.github.io/llsoftsecbook/#sec:pointer-authentication)). - The current implementation of PAC is turned off by default, but can be turned on by setting DOTNET_JitPacEnabled=1. - PAC protects link register (LR) by signing it in the prolog (using `paciasp`) before it is split, using the current SP as the modifier. It then authenticates the LR in the epilog (using `autiasp`) before the function returns. If the signature is invalid, the execution fails with `SIGILL`. - - When the runtime needs to read or overwrite a return address during hijacking for GC, it now strips the PAC (using `xpaclri`) and re-signs the new target address before storing it back. - To simply tracking the SP in return address hijacking, we avoid using the pre-indexed variant of storing FP/LR on stack (e.g., `stp fp,lr,[sp,-#framesz]! `) to simply tracking the SP in return address hijacking. We obtain the value of SP at the time of signing the LR from the location of the current FP. We can't use this approach when the pre-indexed `stp` is used because we don't know the`#framesz`. - The updated prolog/epilog sequences generated by the JIT now look like: // Prolog sub sp, sp, #framesz paciasp ; sign LR with A-key + SP stp fp, lr, [sp] // Epilog ldp fp, lr, [sp] autiasp ; authenticate LR add sp, sp, #framesz ret ToDos: [] Restore the original frame layout that used pre-indexed variant of `stp` to store FP/LR. [] Authenticate the return address instead of stripping in return address hijacking and unwinding. [] Identify increased binary size for System.*.dll [] Determine performance regressions using benchmarks such as OrchirdCMS.
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
Yes, @dhartglassMSFT is right. This PR is for testing purpose only where we enable the PAC feature that is disabled by default on the main branch. We maintained this PR to test PAC changes in CI when enabled. |
|
|
||
| Data.InlinedCallFrame icf = _target.ProcessedData.GetOrAdd<Data.InlinedCallFrame>(framePtr); | ||
| TargetCodePointer returnAddress = icf.CallerReturnAddress; | ||
| TargetCodePointer returnAddress = CodePointerUtils.StripPtrAuthFromReturnAddress(icf.CallerReturnAddress, _target); |
There was a problem hiding this comment.
If we can, I'd like to avoid stripping the pointer authentication on TargetCodePointer. This gives us two different types of TargetCodePointers, without being able to differentiate them.
Instead, I'd suggest we update AddressFromCodePointer to strip the pointer auth and make sure that we don't make assumptions about the TargetCodePointer. There is probably places where we will need to convert from the TargetCodePointer -> TargetPointer.
There was a problem hiding this comment.
We need to strip the pointer authentication only when dealing with return addresses. I would suggest we do the stripping only when converting a return address to a (code) pointer that is used by the rest of the system. It is what we are doing at runtime.
Fixes: dotnet#134912 - Stop treating SP adjustments as evidence of an epilog: they may occur during stack allocation in the function body. - Continue rejecting hijacking after FP or LR has been restored. - For NativeAOT assert that signing SP equals CFA. - Use the caller SP recovered by unwinding to sign hijacked return addresses. This avoids reconstructing signing SP from frame offsets.
Without PAC support `runtime-diagnostics (SOSTests windows-arm64 release SOS)` pipeline is failing for the runtime PR [#125436](dotnet/runtime#125436) Strip pointer authentication bits from saved return-address candidates before checking the preceding call instruction and resolving symbols. DumpStackWorker reads raw stack memory, so needs to strip these bits. Use a 47-bit mask for Windows user-mode addresses and 48-bit mask for non-Windows targets. cc: @dotnet/arm64-contrib @dhartglassMSFT
This PR adds support for Pointer Authentication (PAC) on Arm64. Pointer Authentication (PAC) is an Armv8.3+ security feature designed to mitigate Return-Oriented Programming (ROP) attacks by cryptographically signing return addresses. While using PAC, we store a signed return address, instead of the plain address, on the stack and later authenticate it before returning from a function. It ensures control flow returns to the intended caller.
More details on PAC and its role in software security can be found (here).
paciasp) before it is split, using the current SP as the modifier. It then authenticates the LR in the epilog (usingautiasp) before the function returns. If the signature is invalid, the execution fails withSIGILL.xpaclri) and re-signs the new target address before storing it back.ToDos
stpto store FP/LR.Contributes to #109457