Message ID | 20250311171305.89091-3-adhemerval.zanella@linaro.org |
---|---|
State | New |
Headers | show |
Series | Add support for memory sealing | expand |
On Tue, Mar 11, 2025 at 02:09:49PM -0300, Adhemerval Zanella wrote: > It allows static binary to opt-in of memory sealing. The aarch64 > already does it for GCS, so refactor it to use > __libc_process_gnu_attributes instead. > > Checked on x86_64-linux-gnu. > --- > csu/libc-start.c | 4 ++ > elf/dl-support.c | 13 ++++++ > sysdeps/generic/libc-prop.h | 44 ++++++++++++++++++++ > sysdeps/unix/sysv/linux/aarch64/libc-start.h | 11 ----- > sysdeps/x86/dl-prop.h | 4 +- > 5 files changed, 64 insertions(+), 12 deletions(-) > create mode 100644 sysdeps/generic/libc-prop.h > > + /* Process program headers again, but scan them backwards so > + that PT_NOTE can be skipped if PT_GNU_PROPERTY exits. */ Why do we need to process headers again? > + for (const ElfW(Phdr) *ph = &_dl_phdr[_dl_phnum]; ph != _dl_phdr; --ph) > + switch (ph[-1].p_type) > + { > + case PT_NOTE: > + _dl_process_pt_note (&_dl_main_map, -1, &ph[-1]); > + break; > + case PT_GNU_PROPERTY: > + _dl_process_pt_gnu_property (&_dl_main_map, -1, &ph[-1]); > + break; > + } > > if ((__glibc_unlikely (GL(dl_stack_flags)) & PF_X) > && TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL) == 0) > diff --git a/sysdeps/generic/libc-prop.h b/sysdeps/generic/libc-prop.h > new file mode 100644 > index 0000000000..723575d29b > --- /dev/null > +++ b/sysdeps/generic/libc-prop.h > @@ -0,0 +1,44 @@ > +/* Support for GNU properties for static builds. Generic version. > + Copyright (C) 2025 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#ifndef _LIBC_PROP_H > +#define _LIBC_PROP_H > + > +#include <dl-prop.h> > + > +/* Called at the start of program execution to handle GNU attribute from > + PT_NOTE / PT_GNU_PROPERTY. Must be on a top-level stack frame that does > + not return. */ > +static __always_inline void > +__libc_process_gnu_attributes (void) I think that "__libc_process_gnu_properties" may be a better name. There may be a need in the future to process build attributes [1] and the name of the function above might be confusing. [1] https://github.com/smithp35/abi-aa/blob/build-attributes/buildattr64/buildattr64.rst Kind regardsm Yury
diff --git a/csu/libc-start.c b/csu/libc-start.c index 6f3d52e223..44fe5d5738 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -36,6 +36,7 @@ #include <stdbool.h> #include <elf-initfini.h> #include <shlib-compat.h> +#include <libc-prop.h> #include <elf/dl-tunables.h> @@ -276,6 +277,9 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), /* Perform IREL{,A} relocations. */ ARCH_SETUP_IREL (); + /* Process notes: PT_NOTE / PT_GNU_PROPERTY. */ + __libc_process_gnu_attributes (); + /* The stack guard goes into the TCB, so initialize it early. */ ARCH_SETUP_TLS (); diff --git a/elf/dl-support.c b/elf/dl-support.c index c7860f327a..d8f1dd8ee9 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -45,6 +45,7 @@ #include <array_length.h> #include <dl-symbol-redir-ifunc.h> #include <dl-tunables.h> +#include <dl-prop.h> extern char *__progname; char **_dl_argv = &__progname; /* This is checked for some error messages. */ @@ -330,6 +331,18 @@ _dl_non_dynamic_init (void) _dl_main_map.l_relro_size = ph->p_memsz; break; } + /* Process program headers again, but scan them backwards so + that PT_NOTE can be skipped if PT_GNU_PROPERTY exits. */ + for (const ElfW(Phdr) *ph = &_dl_phdr[_dl_phnum]; ph != _dl_phdr; --ph) + switch (ph[-1].p_type) + { + case PT_NOTE: + _dl_process_pt_note (&_dl_main_map, -1, &ph[-1]); + break; + case PT_GNU_PROPERTY: + _dl_process_pt_gnu_property (&_dl_main_map, -1, &ph[-1]); + break; + } if ((__glibc_unlikely (GL(dl_stack_flags)) & PF_X) && TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL) == 0) diff --git a/sysdeps/generic/libc-prop.h b/sysdeps/generic/libc-prop.h new file mode 100644 index 0000000000..723575d29b --- /dev/null +++ b/sysdeps/generic/libc-prop.h @@ -0,0 +1,44 @@ +/* Support for GNU properties for static builds. Generic version. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _LIBC_PROP_H +#define _LIBC_PROP_H + +#include <dl-prop.h> + +/* Called at the start of program execution to handle GNU attribute from + PT_NOTE / PT_GNU_PROPERTY. Must be on a top-level stack frame that does + not return. */ +static __always_inline void +__libc_process_gnu_attributes (void) +{ +# ifndef SHARED + struct link_map *main_map = _dl_get_dl_main_map (); + const ElfW(Phdr) *phdr = GL(dl_phdr); + const ElfW(Phdr) *ph; + for (ph = phdr; ph < phdr + GL(dl_phnum); ph++) + if (ph->p_type == PT_GNU_PROPERTY) + { + _dl_process_pt_gnu_property (main_map, -1, ph); + _rtld_main_check (main_map, _dl_argv[0]); + break; + } +# endif +} + +#endif diff --git a/sysdeps/unix/sysv/linux/aarch64/libc-start.h b/sysdeps/unix/sysv/linux/aarch64/libc-start.h index 75ae0a884a..64acbdb533 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc-start.h +++ b/sysdeps/unix/sysv/linux/aarch64/libc-start.h @@ -34,17 +34,6 @@ aarch64_libc_setup_tls (void) { __libc_setup_tls (); - struct link_map *main_map = _dl_get_dl_main_map (); - const ElfW(Phdr) *phdr = GL(dl_phdr); - const ElfW(Phdr) *ph; - for (ph = phdr; ph < phdr + GL(dl_phnum); ph++) - if (ph->p_type == PT_GNU_PROPERTY) - { - _dl_process_pt_gnu_property (main_map, -1, ph); - _rtld_main_check (main_map, _dl_argv[0]); - break; - } - if (GL(dl_aarch64_gcs) != 0) { int ret = INLINE_SYSCALL_CALL (prctl, PR_SET_SHADOW_STACK_STATUS, diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h index 8625751427..9a5e10821c 100644 --- a/sysdeps/x86/dl-prop.h +++ b/sysdeps/x86/dl-prop.h @@ -66,9 +66,11 @@ dl_isa_level_check (struct link_map *m, const char *program) static inline void __attribute__ ((always_inline)) _rtld_main_check (struct link_map *m, const char *program) { +#ifdef SAHRED dl_isa_level_check (m, program); -#if CET_ENABLED +# if CET_ENABLED _dl_cet_check (m, program); +# endif #endif }