Skip to content

Commit

Permalink
Enable pac bti support (#3775)
Browse files Browse the repository at this point in the history
* readme: update meson build command

Fixes warning:
WARNING: Running the setup command as `meson [options]` instead of `meson setup [options]` is ambiguous and deprecated.

Signed-off-by: Bill Roberts <bill.roberts@arm.com>

* meson.build: fix suffix on HAVE_NEON_AARCH64

rename HAVE_NEON_AARCH64 to the in-use define for
controlling NEON: HAVE_NEON_AARCH64

Signed-off-by: Bill Roberts <bill.roberts@arm.com>

* aarch64: enable PAC/BTI

Enable Pointer Authentication Codes (PAC) and Branch Target
Identification (BTI) support for ARM 64 targets.

OpenH264 does not require any of the PAC signing and verification as the
leaf functions do not store x30 to the stack. Also, no indirect branches
are performed so no need to annotate branch targets with bti j landing
pad instructions. The only thing required is to label the function entry
points with bti c instructions and ensure the GNU Notes are updated for
their respective features when enabled for ELF files.

A detailed summary on how PAC and BTI work are provided below for
clarity.

PAC works by signing the LR with either an A key or B key and verifying
the return address. There are quite a few instructions capable of doing
this, however, the Linux ARM ABI is to use hint compatible instructions
that can be safely NOP'd on older hardware and can be assembled and
linked with older binutils. This limits the instruction set to paciasp,
pacibsp, autiasp and autibsp. Instructions prefixed with pac are for
signing and instructions prefixed with aut are for signing. Both
instructions are then followed with an a or b to indicate which signing
key they are using. The keys can be controlled using
-mbranch-protection=pac-ret for the A key and
-mbranch-protection=pac-ret+b-key for the B key.

BTI works by marking all indirect call and jump positions with bti c
and bti j instructions respectively. If execution control transfers
to an instruction other than a BTI instruction, the execution is
killed via SIGILL. Note that to remove one instruction, the
aforementioned pac instructions will also work as a BTI landing pad
for bti c usages.

For BTI to work, all object files linked for a unit of execution,
whether an executable or a library must have the GNU Notes section of
the ELF file marked to indicate BTI support. This is so loader/linkers
can apply the proper permission bits (PROT_BRI) on the memory region.

PAC can also be annotated in the GNU ELF notes section, but it's not
required for enablement, as interleaved PAC and non-pac code works as
expected since it's the callee that performs all the checking.

Testing was done under the following CFLAGS and CXXFLAGS for all
combinations:

1. -mbranch-protection=none
2. -mbranch-protection=standard
3. -mbranch-protection=pac-ret
4. -mbranch-protection=pac-ret+b-key
5. -mbranch-protection=bti

Signed-off-by: Bill Roberts <bill.roberts@arm.com>

---------

Signed-off-by: Bill Roberts <bill.roberts@arm.com>
  • Loading branch information
billatarm authored Aug 21, 2024
1 parent cea886e commit 3668daf
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ See <http://mesonbuild.com/Installing.html> for instructions on how to
install meson, then:

``` shell
meson builddir
meson setup builddir
ninja -C builddir
```

Expand Down
85 changes: 85 additions & 0 deletions codec/common/arm64/arm_aarch64_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*!
*@page License
*
* \copy
* Copyright (c) 2024, ARM Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/

#ifndef CODEC_COMMON_ARM64_ARM_AARCH64_COMMON_H_
#define CODEC_COMMON_ARM64_ARM_AARCH64_COMMON_H_

/*
; Support macros for
; - Armv8.3-A Pointer Authentication and
; - Armv8.5-A Branch Target Identification
; Further documentation can be found at:
; - https://developer.arm.com/documentation/101028/0012/5--Feature-test-macros
;
; Since openh264 aarch64 assembly code provides functions with no storage of the
; LR(x30) on the stack, PAC is not needed as modification of the LR value would
; require modification of x30 and not memory. Additionally, no indirect control
; flow changes are performed, so bti j instructions are not needed. Thus, just
; mark the entry points with bti c landing pads and the ELF files as supporting
; BTI and PAC.
*/
#if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1
/* BTI is enabled */
#define BTI_C hint 34
#define GNU_PROPERTY_AARCH64_BTI 0x1 /* Property for notes section in ELF */
#else
/* BTI is NOT enabled */
#define BTI_C
#define GNU_PROPERTY_AARCH64_BTI 0
#endif

#if defined(__ARM_FEATURE_PAC_DEFAULT)
/* PAC is enabled */
#define GNU_PROPERTY_AARCH64_POINTER_AUTH 0x2 /* Property for notes section in ELF */
#else
/* PAC is not enabled */
#define GNU_PROPERTY_AARCH64_POINTER_AUTH 0
#endif

/* Add the notes section to ELF only */
#if defined(__ELF__)
.pushsection .note.gnu.property, "a";
.balign 8;
.long 4;
.long 0x10;
.long 0x5;
.asciz "GNU";
.long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */
.long 4;
.long(GNU_PROPERTY_AARCH64_POINTER_AUTH | GNU_PROPERTY_AARCH64_BTI);
.long 0;
.popsection;
#endif

#endif /* CODEC_COMMON_ARM64_ARM_AARCH64_COMMON_H_ */
3 changes: 3 additions & 0 deletions codec/common/arm64/arm_arch64_common_macro.S
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
*
*/

#include "arm_aarch64_common.h"

#ifdef __APPLE__

.text
Expand Down Expand Up @@ -60,6 +62,7 @@ ret
.func \funcName
#endif
\funcName:
BTI_C
.endm

.macro WELS_ASM_AARCH64_FUNC_END
Expand Down
4 changes: 2 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ if ['linux', 'android', 'ios', 'darwin'].contains(system)
casm_inc = include_directories(join_paths('codec', 'common', 'arm'))
elif cpu_family == 'aarch64'
asm_format = asm_format64
add_project_arguments('-DHAVE_NEON_ARM64', language: 'c')
add_project_arguments('-DHAVE_NEON_ARM64', language: 'cpp')
add_project_arguments('-DHAVE_NEON_AARCH64', language: 'c')
add_project_arguments('-DHAVE_NEON_AARCH64', language: 'cpp')
casm_inc = include_directories(join_paths('codec', 'common', 'arm64'))
elif cpu_family == 'loongarch32'
asm_format = asm_format32
Expand Down

0 comments on commit 3668daf

Please sign in to comment.