]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
aarch64: Support enforcing BTI on dependencies
authorYury Khrustalev <yury.khrustalev@arm.com>
Wed, 29 Oct 2025 16:12:14 +0000 (16:12 +0000)
committerYury Khrustalev <yury.khrustalev@arm.com>
Thu, 4 Dec 2025 12:44:42 +0000 (12:44 +0000)
Add glibc.cpu.aarch64_bti tunable with 2 values:

 - permissive (default)
 - enforced

and use this tunable to enforce BTI marking on dependencies
when the enforced option is selected.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Tested-by: Jeremy Linton <jeremy.linton@arm.com>
manual/tunables.texi
sysdeps/aarch64/cpu-features.h
sysdeps/aarch64/dl-bti.c
sysdeps/aarch64/dl-tunables.list
sysdeps/aarch64/linkmap.h
sysdeps/unix/sysv/linux/aarch64/cpu-features.c
sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c

index 4d3c6e993311f8e520827499c5c3f51e2ebf999b..7956df919beeb0b05b93d942e8dd8938ecc4d018 100644 (file)
@@ -598,6 +598,23 @@ This tunable is specific to x86-64 and effective only when the lazy
 binding is disabled.
 @end deftp
 
+@deftp Tunable glibc.cpu.aarch64_bti
+This tunable controls Branch Target Identification (BTI) handling for the
+process. This handling is implemented via protecting the memory mapping
+with @code{PROT_BTI} for modules that are marked with the appropriate ELF
+property @code{GNU_PROPERTY_AARCH64_FEATURE_1_BTI} (see Program Loading in
+@url{https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst}).
+
+Accepted values are:
+
+0 = permissive: BTI protection is enabled only for modules that have BTI
+marking (default).
+
+1 = enforced: if a module that does not have BTI marking is loaded, it is
+an error (either a process abort or a @code{dlopen} error if this binary
+is loaded via @code{dlopen}).
+@end deftp
+
 @deftp Tunable glibc.cpu.aarch64_gcs
 This tunable controls Guarded Control Stack (GCS) for the process.
 
index ef4e947e8c64a5f6a3de030273e152f2837d588b..855990b57577e24206d0a8ef417a98af25023f59 100644 (file)
                             || (MIDR_PARTNUM(midr) == 0x002            \
                                 && MIDR_VARIANT(midr) == 0)))
 
+enum {
+  BTI_CHECK_PERMISSIVE = 0,
+  BTI_CHECK_ENFORCED = 1,
+};
+
 struct cpu_features
 {
   uint64_t midr_el1;
index de6130470ed0b2c211104e6734cec719b43f2309..e654dde484d6c0f23a6b0692b605f3f57d15a33a 100644 (file)
@@ -31,6 +31,9 @@
 void
 _dl_bti_protect (struct link_map *map, int fd)
 {
+  /* If we try to enable BTI protection, MAP must be BTI marked.  */
+  map->l_mach.bti = true;
+
   const size_t pagesz = GLRO(dl_pagesize);
   const ElfW(Phdr) *phdr;
 
@@ -84,10 +87,22 @@ _dl_bti_check (struct link_map *l, const char *program)
   if (l->l_mach.bti_fail)
     bti_failed (l, program);
 
+  /* We enforce BTI if tunable is set and if this object has BTI marking.  */
+  bool enforce_bti = GLRO (dl_aarch64_bti) == BTI_CHECK_ENFORCED;
+
   for (unsigned int i = 0; i < l->l_searchlist.r_nlist; i++)
     {
       struct link_map *dep = l->l_searchlist.r_list[i];
       if (dep->l_mach.bti_fail)
        bti_failed (dep, program);
+#ifdef SHARED
+      /* Ignore BTI marking on ld.so: its properties are not processed, and
+        the kernel is responsible for setting up BTI protection for the
+        loader.  */
+      if (is_rtld_link_map (dep->l_real))
+       continue;
+#endif
+      if (enforce_bti && !dep->l_mach.bti)
+       bti_failed (dep, program);
     }
 }
index d461c1e9db9834a39a497ca8c7da2624985f5022..40757ac0464a71e99f42117b4df363887f80168e 100644 (file)
@@ -21,6 +21,12 @@ glibc {
     name {
       type: STRING
     }
+    aarch64_bti {
+      type: UINT_64
+      minval: 0
+      maxval: 1
+      default: 0
+    }
     aarch64_gcs {
       type: UINT_64
       minval: 0
index e56c890aead58934a0827cf3ff1277d2515b9466..4cd0492209526d3bcf29fdb35453d323d0e88d37 100644 (file)
@@ -24,4 +24,5 @@ struct link_map_machine
   void *tlsdesc_table;   /* Address of TLS descriptor hash table.  */
   bool bti_fail;         /* Failed to enable Branch Target Identification.  */
   bool gcs;              /* Guarded Control Stack marking.  */
+  bool bti;              /* Branch Target Identification marking.  */
 };
index 1acc82d07720541340705141f498cd09b8e51e7c..a05a4ce7946cc8b2cbf0f6b87a7b207b7f009743 100644 (file)
@@ -137,6 +137,8 @@ init_cpu_features (struct cpu_features *cpu_features)
 
   /* Check if BTI is supported.  */
   cpu_features->bti = GLRO (dl_hwcap2) & HWCAP2_BTI;
+  if (cpu_features->bti)
+    GLRO (dl_aarch64_bti) = TUNABLE_GET (glibc, cpu, aarch64_bti, uint64_t, 0);
 
   /* Setup memory tagging support if the HW and kernel support it, and if
      the user has requested it.  */
index 20966e0478a93cc4e24f04d2cfee7c7b2b784d0a..7c34c8ddba0d1fed2ebeab7f8e88755df1850b64 100644 (file)
@@ -56,5 +56,21 @@ PROCINFO_CLASS struct cpu_features _dl_aarch64_cpu_features
 # endif
 #endif
 
+#if !IS_IN (ldconfig)
+# if !defined PROCINFO_DECL && defined SHARED
+  ._dl_aarch64_bti
+# else
+PROCINFO_CLASS unsigned long _dl_aarch64_bti
+# endif
+# ifndef PROCINFO_DECL
+= BTI_CHECK_PERMISSIVE
+# endif
+# if !defined SHARED || defined PROCINFO_DECL
+;
+# else
+,
+# endif
+#endif
+
 #undef PROCINFO_DECL
 #undef PROCINFO_CLASS