RFR: 8264130: PAC-RET protection for Linux/AArch64 [v4]

Alan Hayward duke at openjdk.java.net
Mon Nov 15 11:24:46 UTC 2021


On Mon, 15 Nov 2021 10:15:41 GMT, Andrew Haley <aph at openjdk.org> wrote:

>> Alan Hayward has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains eight commits:
>> 
>>  - Merge master
>>  - Document pauth functions && remove OS split
>>  - Update UseROPProtection description
>>  - Simplify branch protection configure check
>>  - 8264130: PAC-RET protection for Linux/AArch64
>>    
>>    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.
>>  - Add PAC assembly instructions
>>  - Add AArch64 ROP protection runtime flag
>>  - Build with branch protection
>
> src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp line 452:
> 
>> 450:   // patch the return address, this stub will directly return to the exception handler
>> 451:   __ str(r0, Address(rfp, 1*BytesPerWord));
>> 452: 
> 
> Please explain the reason for this change, that leaves `lr` live across `restore_live_registers()`.

In the original code:
*save r0 to the lr location on the stack
*restore_live_registers
*Standard return: remove stack frame, load lr and fp off the stack, jump to lr.
 
With PAC it would now be:
*Sign r0 then save it to the lr location on the stack
*restore_live_registers
*Standard return: remove stack frame, load lr and fp off the stack, auth lr, jump to lr.

After reading the code in restore_live_registers, it doesn't touch lr and so seemed odd to have the save to the stack, only to restore it directly afterwards.

-------------

PR: https://git.openjdk.java.net/jdk/pull/6334



More information about the build-dev mailing list