RFR: 8337536: AArch64: Enable BTI branch protection for runtime part [v2]

Fei Gao fgao at openjdk.org
Fri Aug 9 13:37:54 UTC 2024


> This patch enables BTI branch protection for runtime part on Linux/aarch64 platform.
> 
> Motivation
> 
> 1. Since Fedora 33, glibc+kernel are PAC/BTI enabled by default. User-level packages can gain additional hardening by compiling with the GCC/Clang flag `-mbranch-protection=flag`. See [1].
> 
> 2. In JDK-8277204 [2], `--enable-branch-protection` was introduced as one VM configure flag, which would pass `-mbranch-protection=standard` compilation flags to all c/c++ files. Note that `standard` turns on both `pac-ret` and `bti` branch protections. For more details about code reuse attacks and hardware-assisted branch protections on AArch64, see [3].
> 
> However, we checked the `.note.gnu.property` section of all the shared libraries under `jdk/lib` on Fedora 40, and found that only libjvm.so didn't set these two target feature bits:
> 
> 
>   GNU_PROPERTY_AARCH64_FEATURE_1_BTI
>   GNU_PROPERTY_AARCH64_FEATURE_1_PAC
> 
> 
> Note-1: BTI is an all or nothing property for a link unit [4]. That is, libjvm.so is not BTI-enabled.
> 
> Note-2: PAC bit in `.note.gnu.property` section is used to protect `.got.plt` table. It's independent of whether the relocatable objects use PAC or not.
> 
> Goal
> 
> Hence, this patch aims to set PAC/BTI feature bits of the `.note.gnu.property` section for libjvm.so.
> 
> Implementation
> 
> Task-1: find out the problematic input objects
> 
> From [5], "Static linkers processing ELF relocatable objects must set the feature bit in the output object or image only if all the input objects have the corresponding feature bit set." Hence we suspect that the root cause is probably that the PAC/BTI feature bits are not set only for some input objects of libjvm.so.
> 
> In order to find out these inputs, we passed `--force-bti` linker flag [4] in my local test. This linker flag would warn if any input object does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI. We got the following list:
> 
> 
>   src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S
>   src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.S
>   src/hotspot/os_cpu/linux_aarch64/safefetch_linux_aarch64.S
>   src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S
> 
> 
> Task-2: add `.note.gnu.property` section for these assembly files
> 
> As mentioned in Motivation-2 part, `-mbranch-protection=standard` is passed to compile c/c++ files but these assembly files are missed.
> 
> In this patch, we also pass `-mbranch-protection=standard` flag to assembler (See the update in flags-cflags.m4 and flags-other.m4), and add `.note.gnu.property` section at the end...

Fei Gao has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains three additional commits since the last revision:

 - Clean up makefile
 - Merge branch 'master' into enable-bti-runtime
 - 8337536: AArch64: Enable BTI branch protection for runtime part
   
   This patch enables BTI branch protection for runtime part on
   Linux/aarch64 platform.
   
   Motivation
   
   1. Since Fedora 33, glibc+kernel are PAC/BTI enabled by default.
   User-level packages can gain additional hardening by compiling with the
   GCC/Clang flag `-mbranch-protection=flag`. See [1].
   
   2. In JDK-8277204 [2], `--enable-branch-protection` was introduced as
   one VM configure flag, which would pass `-mbranch-protection=standard`
   compilation flags to all c/c++ files. Note that `standard` turns on both
   `pac-ret` and `bti` branch protections. For more details about code
   reuse attacks and hardware-assisted branch protections on AArch64, see
   [3].
   
   However, we checked the `.note.gnu.property` section of all the shared
   libraries under `jdk/lib` on Fedora 40, and found that only libjvm.so
   didn't set these two target feature bits:
   
   ```
     GNU_PROPERTY_AARCH64_FEATURE_1_BTI
     GNU_PROPERTY_AARCH64_FEATURE_1_PAC
   ```
   
   Note-1: BTI is an all or nothing property for a link unit [4]. That is,
   libjvm.so is not BTI-enabled.
   
   Note-2: PAC bit in `.note.gnu.property` section is used to protect
   `.got.plt` table. It's independent of whether the relocatable objects
   use PAC or not.
   
   Goal
   
   Hence, this patch aims to set PAC/BTI feature bits of the
   `.note.gnu.property` section for libjvm.so.
   
   Implementation
   
   Task-1: find out the problematic input objects
   
   From [5], "Static linkers processing ELF relocatable objects must set
   the feature bit in the output object or image only if all the input
   objects have the corresponding feature bit set." Hence we suspect that
   the root cause is probably that the PAC/BTI feature bits are not set
   only for some input objects of libjvm.so.
   
   In order to find out these inputs, we passed `--force-bti` linker flag
   [4] in my local test. This linker flag would warn if any input object
   does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI. We got the following
   list:
   
   ```
     src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S
     src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.S
     src/hotspot/os_cpu/linux_aarch64/safefetch_linux_aarch64.S
     src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S
   ```
   
   Task-2: add `.note.gnu.property` section for these assembly files
   
   As mentioned in Motivation-2 part, `-mbranch-protection=standard` is
   passed to compile c/c++ files but these assembly files are missed.
   
   In this patch, we also pass `-mbranch-protection=standard` flag to
   assembler (See the update in flags-cflags.m4 and flags-other.m4), and
   add `.note.gnu.property` section at the end of these assembler files.
   
   With this change, we can see PAC/BTI feature bits in the final
   libjvm.so.
   
   Task-3: add BTI landing pads for hand written assembly
   
   In the local test on Fedora 40 with PAC/BTI-capable hardware, we got
   `SIGILL` error, which is one typical BTI error (branch target exception).
   The root cause is that we should add the missing BTI landing pads for
   hand written assembly in hotspot.
   
   File-1 copy_aarch64.hpp: It's a switch-case statement and we add `bti j`
   for these indirect jumps.
   
   File-2 atomic_linux_aarch64.S: We add landings pads `bti c` at the
   function entries.
   
   File-3 copy_linux_aarch64.S: There is no need to add `bti c` at the
   function entries since they are called via `bl`. And we should handle
   the indirect jumps.
   
   File-4 safefetch_linux_aarch64.S: Similar to file-3, there is no need to
   handle these function entries.
   
   File-5 threadLS_linux_aarch64.S: No need to handle the function entry
   because `paciasp` can act as the landing pad.
   
   Evaluation
   
   1. jtreg test
   
   We ran tier 1-3 jtreg tests on Fedora 40 + GCC 14 + the following AArch64
   hardware and all tests passed.
   
   ```
     1. w/o PAC and w/o BTI
     2. w/ PAC and w/o BTI
     3. w/ PAC and w/ BTI
   ```
   
   We also ran the jtreg tests on Fedora 40 + Clang 18 + hardware w/ PAC
   and w/ BTI. The test passed too.
   
   2. code size
   
   We got about 2% code size increase before and after
   `--enbale-branch-protection` is used. This code size change looks
   reasonable. See the evaluation on glibc [6].
   
   [1] https://fedoraproject.org/wiki/Changes/Aarch64_PointerAuthentication
   [2] https://bugs.openjdk.org/browse/JDK-8277204
   [3] https://community.arm.com/arm-community-blogs/b/tools-software-ides-blog/posts/code-reuse-attacks-the-compiler-story
   [4] https://reviews.llvm.org/D62609
   [5] https://github.com/ARM-software/abi-aa/blob/2a70c42d62e9c3eb5887fa50b71257f20daca6f9/aaelf64/aaelf64.rst#program-property
   [6] https://developer.arm.com/documentation/102433/0100/Applying-these-techniques-to-real-code

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

Changes:
  - all: https://git.openjdk.org/jdk/pull/20491/files
  - new: https://git.openjdk.org/jdk/pull/20491/files/d1506d7d..114953da

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=20491&range=01
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=20491&range=00-01

  Stats: 7788 lines in 182 files changed: 2326 ins; 4845 del; 617 mod
  Patch: https://git.openjdk.org/jdk/pull/20491.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/20491/head:pull/20491

PR: https://git.openjdk.org/jdk/pull/20491


More information about the build-dev mailing list