RFR: 8277204: Implementation of JEP 8264130: PAC-RET protection for Linux/AArch64 [v14]
David Holmes
dholmes at openjdk.java.net
Mon Jan 31 22:39:18 UTC 2022
On Mon, 24 Jan 2022 15:56:06 GMT, Alan Hayward <duke at openjdk.java.net> wrote:
>> PAC is an optional feature in AArch64 8.3 and is compulsory in v9. One
>> of its uses is to protect against ROP based attacks. This is done by
>> signing the Link Register whenever it is stored on the stack, and
>> authenticating the value when it is loaded back from the stack. If an
>> attacker were to try to change control flow by editing the stack then
>> the authentication check of the Link Register will fail, causing a
>> segfault when the function returns.
>>
>> On a system with PAC enabled, it is expected that all applications will
>> be compiled with ROP protection. Fedora 33 and upwards already provide
>> this. By compiling for ARMv8.0, GCC and LLVM will only use the set of
>> PAC instructions that exist in the NOP space - on hardware without PAC,
>> these instructions act as NOPs, allowing backward compatibility for
>> negligible performance cost (2 NOPs per non-leaf function).
>>
>> Hardware is currently limited to the Apple M1 MacBooks. All testing has
>> been done within a Fedora Docker image. A run of SpecJVM showed no
>> difference to that of noise - which was surprising.
>>
>> The most important part of this patch is simply compiling using branch
>> protection provided by GCC/LLVM. This protects all C++ code from being
>> used in ROP attacks, removing all static ROP gadgets from use.
>>
>> The remainder of the patch adds ROP protection to runtime generated
>> code, in both stubs and compiled Java code. Attacks here are much harder
>> as ROP gadgets must be found dynamically at runtime. If/when AOT
>> compilation is added to JDK, then all stubs and compiled Java will be
>> susceptible ROP gadgets being found by static analysis and therefore
>> potentially as vulnerable as C++ code.
>>
>> There are a number of places where the VM changes control flow by
>> rewriting the stack or otherwise. I’ve done some analysis as to how
>> these could also be used for attacks (which I didn’t want to post here).
>> These areas can be protected ensuring the pointers to various stubs and
>> entry points are stored in memory as signed pointers. These changes are
>> simple to make (they can be reduced to a type change in common code and
>> a few addition sign/auth calls in the backend), but there a lot of them
>> and the total code change is fairly large. I’m happy to provide a few
>> work in progress patches.
>>
>> In order to match the security benefits of the Apple Arm64e ABI across
>> the whole of JDK, then all the changes mentioned above would be
>> required.
>
> Alan Hayward has updated the pull request incrementally with one additional commit since the last revision:
>
> Fix popframe failures
A few stylistic nits below. And one query.
Thanks,
David
src/hotspot/cpu/aarch64/globals_aarch64.hpp line 123:
> 121: range(1, 99) \
> 122: product(ccstr, UseBranchProtection, "none", \
> 123: "Branch Protection to use: none,standard,pac-ret") \
Nit: spaces after commas please.
src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp line 5286:
> 5284:
> 5285: void MacroAssembler::enter()
> 5286: {
Style nit: opening braces go on the same line as the function declaration.
src/hotspot/cpu/aarch64/vm_version_aarch64.cpp line 417:
> 415: // Enable PAC if this code has been built with branch-protection and the CPU/OS supports it.
> 416: #ifdef __ARM_FEATURE_PAC_DEFAULT
> 417: if (_features & CPU_PACA) {
Style nit: no implicit booleans - expand as "if ( A & B != 0)"
src/hotspot/cpu/aarch64/vm_version_aarch64.cpp line 429:
> 427: #else
> 428: warning("UseROPProtection specified, but not supported in the VM.");
> 429: #endif
If we issue these warnings should `_rop_protection` still be set true?
src/hotspot/share/gc/shared/barrierSetNMethod.cpp line 58:
> 56:
> 57: address return_address = *return_address_ptr;
> 58: AARCH64_ONLY(return_address=pauth_strip_pointer(return_address));
Style nit: spaces around binary operators please. There are a couple of occurrences.
src/hotspot/share/runtime/frame.cpp line 1115:
> 1113: AARCH64_ONLY(if (!pauth_ptr_is_raw(x)) {
> 1114: return false;
> 1115: })
Style nit: Use ifdef for multi-line code blocks.
-------------
PR: https://git.openjdk.java.net/jdk/pull/6334
More information about the build-dev
mailing list