[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Enabling PAC/BTI support on arm64



Hi!

I would like to ask for suggestions about the best way to enable PAC/BTI
support in glibc and GCC on Debian.

PAC and BTI are two useful Arm security features, see this recent
presentation at the Mini Debconf for all details: [0]

In order to properly support PAC/BTI in Debian we need to enable support
in both GCC and glibc. An executable is marked as BTI compatible only if
all the execution units of the program are BTI compatible. See pages
10-11 on the presentation slides. [1]

One can easily verify if things work fine by building a test program as
follows:

 gcc -mbranch-protection=standard -z force-bti /tmp/test.c

On systems where both GCC and glibc support PAC/BTI, the command above
returns no output, and the resulting executable has "BTI, PAC" listed in
the output of readelf -n:

 readelf -n a.out | grep Properties
        Properties: AArch64 feature: BTI, PAC

If PAC/BTI support is not enabled in GCC/glibc, building the program
with -z force-bti returns something like:

  /usr/bin/ld: /usr/lib/gcc/aarch64-linux-gnu/13/../../../aarch64-linux-gnu/Scrt1.o: warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.
  /usr/bin/ld: /usr/lib/gcc/aarch64-linux-gnu/13/../../../aarch64-linux-gnu/crti.o: warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.
  /usr/bin/ld: /usr/lib/gcc/aarch64-linux-gnu/13/crtbeginS.o: warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.
  /usr/bin/ld: /usr/lib/gcc/aarch64-linux-gnu/13/crtendS.o: warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.
  /usr/bin/ld: /usr/lib/gcc/aarch64-linux-gnu/13/../../../aarch64-linux-gnu/crtn.o: warning: BTI turned on by -z force-bti when all inputs do not have BTI in NOTE section.

To add BTI to the NOTE section of the above, we would need to build both
GCC and glibc with -mbranch-protection=standard. For gcc-13 I have
proposed https://bugs.debian.org/1055711. Given that glibc in Debian is
built with gcc-12, we will also need to build gcc-12 with
-mbranch-protection=standard.

When it comes to glibc itself, there is a configure check to enable BTI
support [2], and it uses CFLAGS as passed to ./configure. I have done
the following here on my arm64 machine:

- built gcc-12 with PAC/BTI (see #1055711)
- built glibc with the PAC/BTI enabled gcc-12 and the attached patch

The resulting GCC and glibc have working PAC/BTI support.

There is maybe a better way in glibc and GCC to achieve the same goal,
do you maintainers have any suggestions?

Thanks!
  Emanuele

[0] https://wiki.debian.org/DebianEvents/gb/2023/MiniDebConfCambridge/Capper
[1] https://wiki.debian.org/DebianEvents/gb/2023/MiniDebConfCambridge/Capper?action=AttachFile&do=view&target=miniconf-2023-PAC-and-BTI.pdf
[2] https://sources.debian.org/src/glibc/2.37-12/sysdeps/aarch64/configure/?hl=184#L188
diff -Nru glibc-2.37/debian/rules glibc-2.37/debian/rules
--- glibc-2.37/debian/rules	2023-10-02 22:29:12.000000000 +0200
+++ glibc-2.37/debian/rules	2023-11-28 10:35:40.000000000 +0100
@@ -112,6 +112,11 @@
 BUILD_CFLAGS = -O2 -g -fdebug-prefix-map=$(CURDIR)=.
 HOST_CFLAGS = -pipe -O2 -g -fdebug-prefix-map=$(CURDIR)=. $(call xx,extra_cflags)
 
+ifeq ($(DEB_BUILD_ARCH),arm64)
+    HOST_CFLAGS += -mbranch-protection=standard
+    HOST_CXXFLAGS += -mbranch-protection=standard
+endif
+
 # 32-bit MIPS builders have a 2GB memory space. This is not enough to
 # build test-tgmath3.o with GCC, unless tweaking the garbage collector.
 ifeq ($(findstring mips,$(DEB_BUILD_ARCH))-$(DEB_BUILD_ARCH_BITS), mips-32)
diff -Nru glibc-2.37/debian/rules.d/build.mk glibc-2.37/debian/rules.d/build.mk
--- glibc-2.37/debian/rules.d/build.mk	2023-10-02 22:29:12.000000000 +0200
+++ glibc-2.37/debian/rules.d/build.mk	2023-11-28 10:35:40.000000000 +0100
@@ -97,6 +97,7 @@
 	echo -n "Build started: " ; date --rfc-2822; \
 	echo "---------------"; \
 	cd $(DEB_BUILDDIR) && \
+		$(if $(filter -mbranch-protection=standard,$(shell dpkg-buildflags --get CFLAGS)),CFLAGS=-mbranch-protection=standard) \
 		CC="$(call xx,CC)" \
 		CXX=$(if $(filter nocheck,$(DEB_BUILD_OPTIONS)),:,"$(call xx,CXX)") \
 		MIG="$(call xx,MIG)" \

Reply to: