Arm64: [PAC-RET] Add Pointer Authentication support for Arm64 (Part 1/3: JIT)#127838
Arm64: [PAC-RET] Add Pointer Authentication support for Arm64 (Part 1/3: JIT)#127838SwapnilGaikwad wants to merge 3 commits intodotnet:mainfrom
Conversation
…/3: JIT changes) As suggested in [comment](dotnet#125436 (comment)), this PR covers subset of changes from dotnet#125436 related to the JIT. 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`. - Changes are limited to JIT.
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
| // Tier0 signed LR with the Tier0 caller SP before allocating its frame. | ||
| // Recreate that SP from the current Tier0 body SP so we can authenticate | ||
| // LR before the OSR prolog later re-signs it with the OSR SP via PACIASP. | ||
| genInstrWithConstant(INS_add, EA_PTRSIZE, REG_IP0, REG_SPBASE, patchpointInfo->TotalFrameSize(), REG_IP0, |
There was a problem hiding this comment.
@AndyAyersMS FYI if we want a second set of eyes on the OSR change here
There was a problem hiding this comment.
nit - anyway if you're in here again Swapnil I'd change "authenticate LR" to "authenticate and strip LR" even though the latter is still implied, reads a little clearer to me
There was a problem hiding this comment.
If I understand correctly the tier0 code will have signed LR with the SP as it is on entry, while the OSR method will now sign LR with the value of SP after the tier0 adjustment.
Would it make more sense to just skip signing in the OSR method and then authenticate after both SP adjustments have been done in the epilog?
There was a problem hiding this comment.
It might be possible to avoid authenticating and re-signing with the help of phantom unwind code representing stack allocation. However, it deviates from the simple model to use signing SP from current frame. I'm happy to explore this possibility in the follow-up PR as the current one is getting trickier to maintain 🙂
There was a problem hiding this comment.
The OSR function inherits the frame from the tier0 function, it is part of its frame. What we have now effectively is making OSR functions deviate from all other functions since it is signing with an SP that points into the middle of its frame. I am ok with it, but you may want to make sure the OSR case is well tested.
Also we may want to eventually do some perf testing for runtime async since these prologs can be very hot for runtime async.
help of phantom unwind code representing stack allocation
I think we would emit a phantom pac_sign_lr code, before we emitted the phantom SP adjustment.
|
This PR uses parts of #127949. It would be great if we could get PAC encoding PR earlier. |
As suggested in comment, this PR covers subset of changes from #125436 related to the JIT.
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.NOTE: This PR adds part of the changes for PAC support to simply review process as discussed here. However it cannot pass the tests without the remaining parts. Kindly take a look at the CI status of #125436 to ensure correctness.