[PATCH] aarch64: Fix error messages for GCS and BTI incompatible modules
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Fri Dec 19 14:17:55 GMT 2025
On 12/12/25 09:14, Yury Khrustalev wrote:
> When either program path of module name is empty, don't print an
> empty string followed by a colon.
Afaik the module name will be always not empty.
> ---
> sysdeps/aarch64/dl-bti.c | 15 ++++++++++++---
> sysdeps/aarch64/dl-gcs.c | 16 ++++++++++++----
> 2 files changed, 24 insertions(+), 7 deletions(-)
>
> diff --git a/sysdeps/aarch64/dl-bti.c b/sysdeps/aarch64/dl-bti.c
> index e654dde484..c506090485 100644
> --- a/sysdeps/aarch64/dl-bti.c
> +++ b/sysdeps/aarch64/dl-bti.c
> @@ -62,17 +62,26 @@ _dl_bti_protect (struct link_map *map, int fd)
> }
> }
>
> +#define STR_NOT_EMPTY(x) ((x != NULL) && x[0])
>
> static void
> bti_failed (struct link_map *l, const char *program)
> {
> - if (program)
> + if (STR_NOT_EMPTY (program) && STR_NOT_EMPTY (l->l_name))
> + /* A program's dependency is not GCS compatible. */
> _dl_fatal_printf ("%s: %s: failed to turn on BTI protection\n",
> program, l->l_name);
> + else if (STR_NOT_EMPTY (program))
> + /* The program itself is not GCS compatible. */
> + _dl_fatal_printf ("%s: failed to turn on BTI protection\n", program);
> + else if (program)
> + /* For static binaries, program will be an empty string. */
> + _dl_fatal_printf ("error: failed to turn on BTI protection\n");
> else
> - /* Note: the errno value is not available any more. */
> + /* If program is NULL, we are processing a dlopen operation.
> + Note: the errno value is not available any more. */
> _dl_signal_error (0, l->l_name, "dlopen",
> - N_("failed to turn on BTI protection"));
> + "failed to turn on BTI protection");
> }
>
We can assume that l->l_name is always non NULL (even though there is
some code that assumes otherwise) and if is not empty then program
is also non-null:
elf/rtld.c
\_ _rtld_main_check (main_map, _dl_argv[0]);
\_ _dl_bti_check (m, program);
\_ _dl_bti_check
In this case _dl_argv is always non-null as well.
If program is NULL, we can then assume that l->l_name always contains
a proper name (dlopen case)
So I think we can simplify to:
static void
bti_failed (struct link_map *l, const char *program)
{
if (l->l_name[0] == '\0')
{
if (program[0] == '\0')
_dl_fatal_printf ("error: failed to turn on BTI protection\n");
else
_dl_fatal_printf ("%s: failed to turn on BTI protection\n",
program);
}
else
/* Note: the errno value is not available any more. */
_dl_signal_error (0, l->l_name, "dlopen",
N_("failed to turn on BTI protection"));
}
The dynamic linked binaries will now issue:
<program>: failed to turn on BTI protection
And static/static-pie will issue:
error: failed to turn on BTI protection
Unfortunately we can safely enable an 'assert (program != NULL)' on the
startup case because of [1]
[1] https://patchwork.sourceware.org/project/glibc/patch/20251117202613.2565803-5-adhemerval.zanella@linaro.org/
>
> diff --git a/sysdeps/aarch64/dl-gcs.c b/sysdeps/aarch64/dl-gcs.c
> index 4ac86a5d6f..9374fd4931 100644
> --- a/sysdeps/aarch64/dl-gcs.c
> +++ b/sysdeps/aarch64/dl-gcs.c
> @@ -30,21 +30,29 @@
> /* Override binary marking and always enabled GCS. */
> #define GCS_POLICY_OVERRIDE 3
>
> +#define STR_NOT_EMPTY(x) ((x != NULL) && x[0])
> +
> static void
> fail (struct link_map *l, const char *program)
> {
> - if (program && program[0])
> - _dl_fatal_printf ("%s: %s: %s\n", program, l->l_name, "not GCS compatible");
> + if (STR_NOT_EMPTY (program) && STR_NOT_EMPTY (l->l_name))
> + /* A program's dependency is not GCS compatible. */
> + _dl_fatal_printf ("%s: %s: not GCS compatible\n", program, l->l_name);
> + else if (STR_NOT_EMPTY (program))
> + /* The program itself is not GCS compatible. */
> + _dl_fatal_printf ("%s: not GCS compatible\n", program);
> else if (program)
> - _dl_fatal_printf ("%s\n", "not GCS compatible");
> + /* For static binaries, program will be an empty string. */
> + _dl_fatal_printf ("error: not GCS compatible\n");
> else
> + /* If program is NULL, we are processing a dlopen operation. */
> _dl_signal_error (0, l->l_name, "dlopen", "not GCS compatible");
> }
>
> static void
> unsupported (void)
> {
> - _dl_fatal_printf ("%s\n", "unsupported GCS policy");
> + _dl_fatal_printf ("unsupported GCS policy\n");
> }
>
> /* This function is called only when binary markings are not
More information about the Libc-alpha
mailing list