diff --git a/manual/tunables.texi b/manual/tunables.texi index 4d3c6e9933..7956df919b 100644 --- a/manual/tunables.texi +++ b/manual/tunables.texi @@ -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. diff --git a/sysdeps/aarch64/cpu-features.h b/sysdeps/aarch64/cpu-features.h index ef4e947e8c..855990b575 100644 --- a/sysdeps/aarch64/cpu-features.h +++ b/sysdeps/aarch64/cpu-features.h @@ -54,6 +54,11 @@ || (MIDR_PARTNUM(midr) == 0x002 \ && MIDR_VARIANT(midr) == 0))) +enum { + BTI_CHECK_PERMISSIVE = 0, + BTI_CHECK_ENFORCED = 1, +}; + struct cpu_features { uint64_t midr_el1; diff --git a/sysdeps/aarch64/dl-bti.c b/sysdeps/aarch64/dl-bti.c index de6130470e..e654dde484 100644 --- a/sysdeps/aarch64/dl-bti.c +++ b/sysdeps/aarch64/dl-bti.c @@ -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); } } diff --git a/sysdeps/aarch64/dl-tunables.list b/sysdeps/aarch64/dl-tunables.list index d461c1e9db..40757ac046 100644 --- a/sysdeps/aarch64/dl-tunables.list +++ b/sysdeps/aarch64/dl-tunables.list @@ -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 diff --git a/sysdeps/aarch64/linkmap.h b/sysdeps/aarch64/linkmap.h index e56c890aea..4cd0492209 100644 --- a/sysdeps/aarch64/linkmap.h +++ b/sysdeps/aarch64/linkmap.h @@ -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. */ }; diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c index 1acc82d077..a05a4ce794 100644 --- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c +++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c @@ -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. */ diff --git a/sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c b/sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c index 20966e0478..7c34c8ddba 100644 --- a/sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c +++ b/sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c @@ -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