Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

guix: Pointer Authentication and Branch Target Identification for aarch64 Linux (Guix) #24123

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

fanquake
Copy link
Member

@fanquake fanquake commented Jan 21, 2022

Based on #29987.

Arm Pointer Authentication (PAC) is a method of hardening code from Return Oriented Programming (ROP) attacks. It uses a tag in a pointer to sign and verify pointers. Branch Target Identification (BTI) is another code hardening method, where the branch/jump target is identified with a special landing pad instruction. Outside of some system support in glibc+kernel, packages gain the additional hardening by compiling with the -mbranch-protection=flag available in recent versions of GCC. In particular -mbranch-protection=standard enables both BTI and PAC, with backwards compatible to armv8.0 code sequences that activate on v8.3 (PAC) & v8.5 (BTI) enabled Arm machines. (taken from Fedora).

Requirements for building/running with these features:

  • Compiler support for -mbranch-protection= flag:
    • Introduced in GCC 9.1 (our minimum required is 8). GCC 8 has a (now deprecated) msign-return-address flag.
    • Introduced in Clang 8 (our minimum required is 7).
  • (maybe) Linker support for -force-bti && -pac-plt:
    • binutils ld has supported both since it's 2.33.1 release.
    • LLVM 9 lld had a --pac-plt, which became -z,pac-plt in LLVM 10. More info.
  • TODO: Kernel / runtime requirements?

Creation of a BTI enabled binary also requires that everything being linked in be BTI enabled. This means you currently cannot, for example, cross-compile using a Ubuntu based aarch64 toolchain, if you're wanting to use this feature. This can be shown using -Wl,z,force-bti, which will emit warnings for linked objects that are not BTI enabled (this is used in configure to detect when to disable using the flags). i.e:

int main() { return 0; }
# gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)
aarch64-linux-gnu-g++ test.cpp -mbranch-protection=standard -Wl,-z,force-bti
/usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: /usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/lib/../lib/Scrt1.o: warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.
/usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: /usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/lib/../lib/crti.o: warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.
/usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: /usr/lib/gcc-cross/aarch64-linux-gnu/9/crtbeginS.o: warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.
/usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: /usr/aarch64-linux-gnu/lib/libc_nonshared.a(elf-init.oS): warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.
/usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: /usr/lib/gcc-cross/aarch64-linux-gnu/9/crtendS.o: warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.
/usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: /usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/lib/../lib/crtn.o: warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.

However, if you compile on a system where the toolchain has been built with the additional hardening, i.e Fedora 33 and onwards:

# gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)
aarch64-redhat-linux-g++ test.cpp -mbranch-protection=standard -Wl,-z,force-bti
...
# readelf -n a.out 

Displaying notes found in: .note.gnu.property
  Owner                Data size 	Description
  GNU                  0x00000010	NT_GNU_PROPERTY_TYPE_0
      Properties: AArch64 feature: BTI, PAC

Note the BTI and PAC properties. More about Fedora use of -mbranch-protection=standard by throughout it's packages can be seen in the rpc repos. i.e:
Part of the base compiler flags for aarch64 && Used by default when building glibc.

I've built and tested binaries on an aarch64 machine, (Neoverse-N1, Armv8.2-A) running Fedora 34.

make -C depends/ -j5 NO_QT=1 NO_WALLET=1 NO_ZMQ=1 NO_UPNP=1 NO_NATPMP=1
./autogen.sh
CONFIG_SITE=/home/fedora/bitcoin/depends/aarch64-unknown-linux-gnu/share/config.site ./configure
make -j9
...
/usr/bin/ld: secp256k1/.libs/libsecp256k1.a(libsecp256k1_la-secp256k1.o): warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.
/usr/bin/ld: secp256k1/.libs/libsecp256k1.a(libsecp256k1_la-secp256k1.o): warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.

Unit and functional tests pass. Note section contains (not no PAC):

readelf -n src/bitcoind
...
  Owner                Data size 	Description
  GNU                  0x00000010	NT_GNU_PROPERTY_TYPE_0
      Properties: AArch64 feature: BTI

I am running a sync with -assumevalid=0. However given that this machine does not support PAC or BTI, as it's Armv8.2, I'll have to find some newer aarch64 hardware to test other things on. Although this is still a demonstration that the PAC / BTI instructions are nops when running on older hardware.

Further reading:
https://fedoraproject.org/wiki/Changes/Aarch64_PointerAuthentication
https://developer.arm.com/documentation/102433/latest/Return-oriented-programming
https://lwn.net/Articles/789370/

Related to #19075.

@DrahtBot
Copy link
Contributor

DrahtBot commented Jan 21, 2022

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage

For detailed information about the code coverage, see the test coverage report.

Reviews

See the guideline for information on the review process.

Type Reviewers
Concept ACK hebasto, laanwj, kristapsk

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #29987 (guix: build with glibc 2.31 by fanquake)
  • #27038 (security-check: test for _FORTIFY_SOURCE usage in release binaries by fanquake)
  • #25573 ([POC] guix: produce a fully -static-pie bitcoind by fanquake)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@hebasto
Copy link
Member

hebasto commented Jan 22, 2022

Concept ACK.

From reading docs it's still unclear to me whether -mbranch-protection=standard implies -mbranch-protection=bti?

$ ./test/lint/lint-git-commit-check.sh 
The subject line of commit hash f799135959461079a220c5ddc97ea9a6b0056b2b is followed by a non-empty line. Subject lines should always be followed by a blank line.

@fanquake fanquake force-pushed the mbranch_protection_aarch64_linux branch from 9313bf6 to c98b6eb Compare January 23, 2022 05:01
@laanwj
Copy link
Member

laanwj commented Jan 25, 2022

Concept ACK.

We might want to wait with doing this until hardware supporting BTI and PAC is available to test on, though.

configure.ac Outdated Show resolved Hide resolved
@fanquake fanquake force-pushed the mbranch_protection_aarch64_linux branch from c98b6eb to b51e648 Compare May 12, 2022 13:18
@DrahtBot
Copy link
Contributor

Guix builds

File commit 225e5b5
(master)
commit 6e02029
(master and this pull)
SHA256SUMS.part 1b58b80ca65983b3... 60902da13322462a...
*-aarch64-linux-gnu-debug.tar.gz 26b50f702207b949... da73c81f36ba2f4f...
*-aarch64-linux-gnu.tar.gz 93156ddbf46f81df... 49d87e2a6f62f992...
*-arm-linux-gnueabihf-debug.tar.gz 448908d67e456427... 6995a4237a002a65...
*-arm-linux-gnueabihf.tar.gz 595189752c32bf97... b3aadb2d8f165b42...
*-arm64-apple-darwin-unsigned.dmg 8fe9a774204a88c7... 068c1b89b9bacaef...
*-arm64-apple-darwin-unsigned.tar.gz 293f411c2dc51edb... c09afa12e0677dc9...
*-arm64-apple-darwin.tar.gz abca1d81d437a08a... c15b198b2d1f03fc...
*-powerpc64-linux-gnu-debug.tar.gz 1744beebac78a5d6... 18afbab08627bbd0...
*-powerpc64-linux-gnu.tar.gz ec4d4712136dc767... 564780d6229517f2...
*-powerpc64le-linux-gnu-debug.tar.gz ac1890b8743df6a5... 08950113d8f8a24a...
*-powerpc64le-linux-gnu.tar.gz b0ebc5e4120bf000... 5033d195b6c3a5f7...
*-riscv64-linux-gnu-debug.tar.gz 702be3dc495a5a10... 06fb203fb1b5161a...
*-riscv64-linux-gnu.tar.gz ad1394d672c7b965... be8de64710848522...
*-win64-debug.zip 5464743530003d4d... c9e8d9c625b5eb35...
*-win64-setup-unsigned.exe 955c755466eb2b07... 7ef06802748bdc8f...
*-win64-unsigned.tar.gz 0126640c2d061f14... 146ee2330f8ddfa4...
*-win64.zip 5b07889e2dce9103... 4e2f315a1f35caee...
*-x86_64-apple-darwin-unsigned.dmg c5526437a0193c3b... 2c0af2ea1cd7545d...
*-x86_64-apple-darwin-unsigned.tar.gz e1d81f18176fab2e... 6bc18c838e5fff4f...
*-x86_64-apple-darwin.tar.gz d34e5f7fe086c51f... 64b3270b92cd3128...
*-x86_64-linux-gnu-debug.tar.gz acb6561a5919c80f... 6f25c5199f7623a8...
*-x86_64-linux-gnu.tar.gz 00bb67a5b4e29ca3... 8645814c4e7e8c7e...
*.tar.gz ab4e54f5d920eb45... 9c521162a3ecfd6e...
guix_build.log 68d9a71f1973680b... 754faf723b062cbf...
guix_build.log.diff 85fe222476c6b46f...

@fanquake
Copy link
Member Author

I've changed the approach here, and this is now based on #25437 and parts of #25484.

This adds --enable-standard-branch-protection to the configure flags when building GCC, which turns on the usage of branch-protection features by default. I've also added a commit that switches to using glibc 2.33 for the aarch64 build. glibc 2.32 was the first to ship with support for aarch64 branch protection features when built with a compatible compiler (see commit message for details). We couldn't actually use this for Guix builds, because it would break out back compat requires (the symbol checks fail), so this is still just for demonstration.

@kristapsk
Copy link
Contributor

Concept ACK

@DrahtBot DrahtBot mentioned this pull request Mar 8, 2024
@fanquake fanquake force-pushed the mbranch_protection_aarch64_linux branch from 1cbc3ce to 8d5f24b Compare March 14, 2024 15:15
@fanquake fanquake force-pushed the mbranch_protection_aarch64_linux branch from 7af2c21 to 6e5b86d Compare March 22, 2024 09:04
fanquake added a commit to fanquake/bitcoin that referenced this pull request Mar 22, 2024
This includes lief-project/LIEF#975, which I'd
like to use in bitcoin#24123.
fanquake added a commit to fanquake/bitcoin that referenced this pull request Mar 22, 2024
This includes lief-project/LIEF#975, which I'd
like to use in bitcoin#24123.
fanquake added a commit to fanquake/bitcoin that referenced this pull request Mar 26, 2024
This includes lief-project/LIEF#975, which I'd
like to use in bitcoin#24123.
fanquake added a commit to fanquake/bitcoin that referenced this pull request Mar 26, 2024
This includes lief-project/LIEF#975, which I'd
like to use in bitcoin#24123.
fanquake added a commit to fanquake/bitcoin that referenced this pull request Mar 26, 2024
This includes lief-project/LIEF#975, which I'd
like to use in bitcoin#24123.
fanquake added a commit to fanquake/bitcoin that referenced this pull request Mar 26, 2024
This includes lief-project/LIEF#975, which I'd
like to use in bitcoin#24123.
fanquake added a commit that referenced this pull request Mar 26, 2024
7850c5f guix: build GCC with --enable-standard-branch-protection (fanquake)

Pull request description:

  This is one change extracted from #24123 (which now produces fully BTI & PAC enabled bins), which will mean that everything in depends, for Guix builds, is compiled using `-mbranch-protection=standard`.

  Turning this on by default, is similar to what we already do with `--enable-default-ssp`, `--enable-default-pie` etc.

  See: https://gcc.gnu.org/install/specific.html#aarch64-x-x

  > To enable Branch Target Identification Mechanism and Return Address Signing by default at configure time use the `--enable-standard-branch-protection` option.

  > This is equivalent to having `-mbranch-protection=standard` during compilation. This can be explicitly disabled during compilation by passing the `-mbranch-protection=none` option which turns off all types of branch protections.

ACKs for top commit:
  TheCharlatan:
    ACK 7850c5f

Tree-SHA512: 18f898da27021bab502e708ea5fa9b325352f8f6e23d9488a2a0feda87e0af2ac0e4f87b3af9ad6a9a37bbfc99ab0285de4f0bdc174dcd38163d92c122e958e2
@fanquake fanquake changed the title build: Pointer Authentication and Branch Target Identification for aarch64 Linux (Guix) guix: Pointer Authentication and Branch Target Identification for aarch64 Linux (Guix) Mar 26, 2024
@fanquake fanquake force-pushed the mbranch_protection_aarch64_linux branch from 6e5b86d to 67a9b54 Compare March 26, 2024 13:52
@DrahtBot DrahtBot mentioned this pull request Mar 26, 2024
@fanquake fanquake force-pushed the mbranch_protection_aarch64_linux branch from 67a9b54 to 5cd6df7 Compare April 1, 2024 13:58
@fanquake fanquake force-pushed the mbranch_protection_aarch64_linux branch from 5cd6df7 to 9d1f717 Compare April 26, 2024 07:41
Set minimum required glibc to 2.31.
The glibc 2.31 branch is still maintained:
https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/release/2.31/master.

Remove the stack-protector check from test-security-check, as the test
no-longer fails, and given the control we have of the end, the actual
security-check test seems sufficient (this might also be applied to some
of the other checks).
@fanquake fanquake force-pushed the mbranch_protection_aarch64_linux branch from 9d1f717 to 3eb5220 Compare May 16, 2024 04:25
@fanquake
Copy link
Member Author

Rebased on #29987.

glibc 2.32 was the first to ship with support for branch protection when
compiled with a compatible compiler.

glibc 2.32 release notes: https://lwn.net/Articles/828210/

* AArch64 now supports standard branch protection security hardening
  in glibc when it is built with a GCC that is configured with
  --enable-standard-branch-protection (or if -mbranch-protection=standard
  flag is passed when building both GCC target libraries and glibc,
  in either case a custom GCC is needed).  This includes branch target
  identification (BTI) and pointer authentication for return addresses
  (PAC-RET).  They require armv8.5-a and armv8.3-a architecture
  extensions respectively for the protection to be effective,
  otherwise the used instructions are nops.  User code can use PAC-RET
  without libc support, but BTI requires a libc that is built with BTI
  support, otherwise runtime objects linked into user code will not be
  BTI compatible.
@fanquake fanquake force-pushed the mbranch_protection_aarch64_linux branch from 3eb5220 to 146633b Compare May 16, 2024 05:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants