diff options
author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2024-07-08 16:38:10 -0300 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2024-07-31 17:02:05 -0300 |
commit | 52ddeb99b2db8247a7095ae1354acb3ca3e4ea4a (patch) | |
tree | 483786f0c7d72de96b718a3902e493ec26eb2dfe | |
parent | 8d2a331b64c8d299d11826058c43d29643cf6b86 (diff) | |
download | glibc-azanella/mseal.tar.gz glibc-azanella/mseal.tar.xz glibc-azanella/mseal.zip |
elf: Add support for GNU_PROPERTY_NO_MEMORY_SEAL azanella/mseal
The GNU_PROPERTY_NO_MEMORY_SEAL is a GNU property per module instructing the glibc not to seal the object PT_LOAD. It can be used for any reason the modules require to seal not to be enabled (i.e., on Firefox hack to bypass the dynamic loader and enable DT_RELR on older glibc [1]). In this case, it is up to the module to apply memory sealing itself. The sealing is applied by default, and it is always enforced with glibc.rtld.seal=2. Checked on aarch64-linux-gnu, x86_64-linux-gnu, and powerpc64le-linux-gnu. [1] https://glandium.org/blog/?p=4297
27 files changed, 350 insertions, 32 deletions
diff --git a/configure b/configure index 1d543548cd..31deacc983 100755 --- a/configure +++ b/configure @@ -7102,6 +7102,41 @@ printf "%s\n" "$libc_linker_feature" >&6; } config_vars="$config_vars have-no-dynamic-linker = $libc_cv_no_dynamic_linker" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z no-memory-seal" >&5 +printf %s "checking for linker that supports -z no-memory-seal... " >&6; } +libc_linker_feature=no +cat > conftest.c <<EOF +int _start (void) { return 42; } +EOF +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp + -Wl,-z,no-memory-seal -nostdlib -nostartfiles + -fPIC -shared -o conftest.so conftest.c + 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-z,no-memory-seal -nostdlib \ + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \ + | grep "warning: -z no-memory-seal ignored" > /dev/null 2>&1; then + true + else + libc_linker_feature=yes + fi +fi +rm -f conftest* +if test $libc_linker_feature = yes; then + libc_cv_z_no_memory_seal=yes +else + libc_cv_z_no_memory_seal=no +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 +printf "%s\n" "$libc_linker_feature" >&6; } +config_vars="$config_vars +have-z-no-memory-seal = $libc_cv_z_no_memory_seal" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -static-pie" >&5 printf %s "checking for -static-pie... " >&6; } if test ${libc_cv_static_pie+y} diff --git a/configure.ac b/configure.ac index 9cbc0bf68f..a8fc276cfb 100644 --- a/configure.ac +++ b/configure.ac @@ -1278,6 +1278,11 @@ LIBC_LINKER_FEATURE([--no-dynamic-linker], [libc_cv_no_dynamic_linker=no]) LIBC_CONFIG_VAR([have-no-dynamic-linker], [$libc_cv_no_dynamic_linker]) +LIBC_LINKER_FEATURE([-z no-memory-seal], + [-Wl,-z,no-memory-seal], + [libc_cv_z_no_memory_seal=yes], [libc_cv_z_no_memory_seal=no]) +LIBC_CONFIG_VAR([have-z-no-memory-seal], [$libc_cv_z_no_memory_seal]) + AC_CACHE_CHECK(for -static-pie, libc_cv_static_pie, [dnl LIBC_TRY_CC_OPTION([-static-pie], [libc_cv_static_pie=yes], diff --git a/elf/dl-load.c b/elf/dl-load.c index 4c2371ec46..17b64363f7 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1431,7 +1431,9 @@ cannot enable executable stack as shared object requires"); /* Assign the next available module ID. */ _dl_assign_tls_modid (l); - l->l_seal = mode & RTLD_NODELETE ? lt_seal_toseal : lt_seal_dont; + /* Do not alter the sealing if the GNU property disables it. */ + if (l->l_seal == lt_seal_undefined && mode & RTLD_NODELETE) + l->l_seal = lt_seal_toseal; #ifdef DL_AFTER_LOAD DL_AFTER_LOAD (l); diff --git a/elf/dl-open.c b/elf/dl-open.c index f53b1b0572..7cc39fba5b 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -841,7 +841,7 @@ dl_open_worker (void *a) /* The seal flag is set only for NEW, however its dependencies could not be unloaded and thus can also be sealed. */ - _dl_mseal_map (new, true); + _dl_mseal_map (new, true, false); } void * diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index 6bb424f789..4a81c3914c 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -352,7 +352,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], /* Seal the memory mapping after RELRO setup, we can use the PT_LOAD segments because even if relro splits the the original RW VMA, mseal works with multiple VMAs with different flags. */ - _dl_mseal_map (l, false); + _dl_mseal_map (l, false, false); } @@ -376,11 +376,10 @@ cannot apply additional memory protection after relocation"); } static void -_dl_mseal_map_1 (struct link_map *l) +_dl_mseal_map_1 (struct link_map *l, bool force) { - /* We only checked if the map is already sealed here so we can seal audit - module dependencies after the initial audit setup. */ - if (l->l_seal == lt_seal_sealed) + if (l->l_seal == lt_seal_dont + || (!force && (l->l_seal != lt_seal_toseal))) return; int r = -1; @@ -408,16 +407,13 @@ _dl_mseal_map_1 (struct link_map *l) } void -_dl_mseal_map (struct link_map *l, bool dep) +_dl_mseal_map (struct link_map *l, bool dep, bool force) { - if (l->l_seal == lt_seal_dont || l->l_seal == lt_seal_sealed) - return; - if (l->l_searchlist.r_list == NULL || !dep) - _dl_mseal_map_1 (l); + _dl_mseal_map_1 (l, force); else for (unsigned int i = 0; i < l->l_searchlist.r_nlist; ++i) - _dl_mseal_map_1 (l->l_searchlist.r_list[i]); + _dl_mseal_map_1 (l->l_searchlist.r_list[i], force); } void diff --git a/elf/dl-support.c b/elf/dl-support.c index a02ae712b3..dd02943dd0 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -101,7 +101,7 @@ static struct link_map _dl_main_map = .l_used = 1, .l_tls_offset = NO_TLS_OFFSET, .l_serial = 1, - .l_seal = SUPPORT_MSEAL, + .l_seal = lt_seal_toseal, }; /* Namespace information. */ @@ -359,7 +359,7 @@ _dl_non_dynamic_init (void) /* Seal the memory mapping after RELRO setup, we can use the PT_LOAD segments because even if relro splits the the original RW VMA, mseal works with multiple VMAs with different flags. */ - _dl_mseal_map (&_dl_main_map, false); + _dl_mseal_map (&_dl_main_map, false, false); } #ifdef DL_SYSINFO_IMPLEMENTATION diff --git a/elf/elf.h b/elf/elf.h index 33aea7f743..62f493b9ee 100644 --- a/elf/elf.h +++ b/elf/elf.h @@ -1357,6 +1357,8 @@ typedef struct #define GNU_PROPERTY_STACK_SIZE 1 /* No copy relocation on protected data symbol. */ #define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2 +/* No memory sealing. */ +#define GNU_PROPERTY_NO_MEMORY_SEAL 3 /* A 4-byte unsigned integer property: A bit is set if it is set in all relocatable inputs. */ diff --git a/elf/rtld.c b/elf/rtld.c index efe7e97b04..23b651ee55 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -478,7 +478,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info) GL(dl_rtld_map).l_real = &GL(dl_rtld_map); GL(dl_rtld_map).l_map_start = (ElfW(Addr)) &__ehdr_start; GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end; - GL(dl_rtld_map).l_seal = 1; + GL(dl_rtld_map).l_seal = lt_seal_toseal; /* Copy the TLS related data if necessary. */ #ifndef DONT_USE_BOOTSTRAP_MAP # if NO_TLS_OFFSET != 0 @@ -1046,9 +1046,9 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d); /* Mark the DSO as being used for auditing. */ dlmargs.map->l_auditing = 1; - /* Seal the audit modules and their dependencies. */ - dlmargs.map->l_seal = lt_seal_toseal; - _dl_mseal_map (dlmargs.map, true); + /* Since audit modules can not be loaded with RTLD_NODELETE, force the + sealing of the modules and its dependencies. */ + _dl_mseal_map (dlmargs.map, true, true); } /* Load all audit modules. */ @@ -1131,7 +1131,7 @@ rtld_setup_main_map (struct link_map *main_map) /* And it was opened directly. */ ++main_map->l_direct_opencount; main_map->l_contiguous = 1; - main_map->l_seal = 1; + main_map->l_seal = lt_seal_toseal; /* A PT_LOAD segment at an unexpected address will clear the l_contiguous flag. The ELF specification says that PT_LOAD diff --git a/include/link.h b/include/link.h index fd8e7f25bf..176f4abddd 100644 --- a/include/link.h +++ b/include/link.h @@ -214,6 +214,7 @@ struct link_map lt_library map. */ enum /* Memory sealing status. */ { + lt_seal_undefined = 0, /* No set. */ lt_seal_dont, /* Do not seal the object. */ lt_seal_toseal, /* The library is marked to be sealed. */ lt_seal_sealed /* The library is sealed. */ diff --git a/string/strerrorname_np.c b/string/strerrorname_np.c index e0e22fa79e..042cea381c 100644 --- a/string/strerrorname_np.c +++ b/string/strerrorname_np.c @@ -17,7 +17,6 @@ <https://www.gnu.org/licenses/>. */ #include <stdio.h> -#include <string.h> const char * strerrorname_np (int errnum) diff --git a/sysdeps/aarch64/dl-prop.h b/sysdeps/aarch64/dl-prop.h index df05c0211d..c66d9a49f0 100644 --- a/sysdeps/aarch64/dl-prop.h +++ b/sysdeps/aarch64/dl-prop.h @@ -19,6 +19,8 @@ #ifndef _DL_PROP_H #define _DL_PROP_H +#include <dl-prop-mseal.h> + extern void _dl_bti_protect (struct link_map *, int) attribute_hidden; extern void _dl_bti_check (struct link_map *, const char *) @@ -45,6 +47,9 @@ static inline int _dl_process_gnu_property (struct link_map *l, int fd, uint32_t type, uint32_t datasz, void *data) { + if (_dl_process_gnu_property_seal (l, fd, type, datasz, data)) + return 0; + if (!GLRO(dl_aarch64_cpu_features).bti) /* Skip note processing. */ return 0; diff --git a/sysdeps/generic/dl-mseal.h b/sysdeps/generic/dl-mseal.h index d542fcac75..dccf78ae38 100644 --- a/sysdeps/generic/dl-mseal.h +++ b/sysdeps/generic/dl-mseal.h @@ -21,5 +21,3 @@ _dl_mseal (void *addr, size_t len) { return 0; } - -#define SUPPORT_MSEAL lt_seal_dont diff --git a/sysdeps/generic/dl-prop-mseal.h b/sysdeps/generic/dl-prop-mseal.h new file mode 100644 index 0000000000..b9dbd24fa5 --- /dev/null +++ b/sysdeps/generic/dl-prop-mseal.h @@ -0,0 +1,38 @@ +/* Support for GNU properties. Generic version. + Copyright (C) 2024 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 _DL_PROP_MSEAL_H +#define _LD_PROP_MSEAL_H + +#include <dl-tunables.h> +#include <dl-mseal-mode.h> + +static __always_inline bool +_dl_process_gnu_property_seal (struct link_map *l, int fd, uint32_t type, + uint32_t datasz, void *data) +{ + if (type == GNU_PROPERTY_NO_MEMORY_SEAL && datasz == 0) + { + int32_t mode = TUNABLE_GET (glibc, rtld, seal, int32_t, NULL); + l->l_seal = (mode == DL_SEAL_ENFORCE) ? lt_seal_toseal : lt_seal_dont; + return true; + } + return false; +} + +#endif diff --git a/sysdeps/generic/dl-prop.h b/sysdeps/generic/dl-prop.h index 1d92920a96..5fac690c81 100644 --- a/sysdeps/generic/dl-prop.h +++ b/sysdeps/generic/dl-prop.h @@ -19,6 +19,8 @@ #ifndef _DL_PROP_H #define _DL_PROP_H +#include <dl-prop-mseal.h> + /* The following functions are used by the dynamic loader and the dlopen machinery to process PT_NOTE and PT_GNU_PROPERTY entries in the binary or shared object. The notes can be used to change the @@ -47,6 +49,9 @@ static inline int __attribute__ ((always_inline)) _dl_process_gnu_property (struct link_map *l, int fd, uint32_t type, uint32_t datasz, void *data) { + if (_dl_process_gnu_property_seal (l, fd, type, datasz, data)) + return 0; + /* Continue until GNU_PROPERTY_1_NEEDED is found. */ if (type == GNU_PROPERTY_1_NEEDED) { diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index aad5a219df..577f3ae06b 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1017,10 +1017,13 @@ extern void _dl_relocate_object (struct link_map *map, /* Protect PT_GNU_RELRO area. */ extern void _dl_protect_relro (struct link_map *map) attribute_hidden; -/* Protect MAP with mseal. If MAP is contiguous the while region is - sealed, otherwise iterate over the phdr to seal each PT_LOAD. The DEP - specify whether to seal the dependencies as well. */ -extern void _dl_mseal_map (struct link_map *map, bool dep) +/* Issue memory sealing for the link map MAP. If MAP is contiguous the + whole region is sealed, otherwise iterate over the program headerrs and + seal each PT_LOAD segment.i + The DEP specify whether to seal the dependencies as well, while FORCE + ignores if previous seal configuration (such as + GNU_PROPERTY_NO_MEMORY_SEAL mark). */ +extern void _dl_mseal_map (struct link_map *map, bool dep, bool force) attribute_hidden; /* Call _dl_signal_error with a message about an unhandled reloc type. diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 3161363db1..c82aeb3403 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -685,6 +685,52 @@ $(objpfx)tst-dl_mseal-dlopen-2.so: $(objpfx)tst-dl_mseal-dlopen-2-1.so LDFLAGS-tst-dl_mseal-dlopen-2.so = -Wl,--no-as-needed tst-dl_mseal-static-ARGS = -- $(host-test-program-cmd) + +ifeq ($(have-z-no-memory-seal),yes) +tests-static += \ + tst-dl_mseal-static-no-memory-seal \ + # tests-static + +tests += \ + tst-dl_mseal-no-memory-seal \ + tst-dl_mseal-static-no-memory-seal \ + # tests + +modules-names += \ + tst-dl_mseal-dlopen-no-memory-seal-2 \ + tst-dl_mseal-dlopen-no-memory-seal-2-1 \ + tst-dl_mseal-mod-no-memory-seal-1 \ + tst-dl_mseal-mod-no-memory-seal-2 \ + tst-dl_mseal-no-memory-seal-auditmod \ + tst-dl_mseal-no-memory-seal-preload \ + # modules-names + +$(objpfx)tst-dl_mseal-no-memory-seal.out: \ + $(objpfx)tst-dl_mseal-no-memory-seal-auditmod.so \ + $(objpfx)tst-dl_mseal-no-memory-seal-preload.so \ + $(objpfx)tst-dl_mseal-mod-no-memory-seal-1.so \ + $(objpfx)tst-dl_mseal-mod-no-memory-seal-2.so \ + $(objpfx)tst-dl_mseal-dlopen-1.so \ + $(objpfx)tst-dl_mseal-dlopen-1-1.so \ + $(objpfx)tst-dl_mseal-dlopen-no-memory-seal-2.so \ + $(objpfx)tst-dl_mseal-dlopen-no-memory-seal-2-1.so + +tst-dl_mseal-no-memory-seal-ARGS = -- $(host-test-program-cmd) + +LDFLAGS-tst-dl_mseal-no-memory-seal-preload.so = -Wl,-z,no-memory-seal + +LDFLAGS-tst-dl_mseal-no-memory-seal-auditmod.so = -Wl,-z,no-memory-seal +$(objpfx)tst-dl_mseal-no-memory-seal: $(objpfx)tst-dl_mseal-mod-no-memory-seal-1.so +LDFLAGS-tst-dl_mseal-no-memory-seal = -Wl,-z,no-memory-seal -Wl,--no-as-needed +$(objpfx)tst-dl_mseal-mod-no-memory-seal-1.so: $(objpfx)tst-dl_mseal-mod-no-memory-seal-2.so +LDFLAGS-tst-dl_mseal-mod-no-memory-seal-1.so = -Wl,--no-as-needed +LDFLAGS-tst-dl_mseal-mod-no-memory-seal-2.so = -Wl,-z,no-memory-seal -Wl,--no-as-needed +$(objpfx)tst-dl_mseal-dlopen-no-memory-seal-2.so: $(objpfx)tst-dl_mseal-dlopen-no-memory-seal-2-1.so +LDFLAGS-tst-dl_mseal-dlopen-no-memory-seal-2.so = -Wl,--no-as-needed -Wl,-z,no-memory-seal + +LDFLAGS-tst-dl_mseal-static-no-memory-seal = -Wl,-z,no-memory-seal +tst-dl_mseal-static-no-memory-seal-ARGS = -- $(host-test-program-cmd) +endif endif ifeq ($(subdir),rt) diff --git a/sysdeps/unix/sysv/linux/dl-mseal.h b/sysdeps/unix/sysv/linux/dl-mseal.h index 89b19e33c4..25e3f724dc 100644 --- a/sysdeps/unix/sysv/linux/dl-mseal.h +++ b/sysdeps/unix/sysv/linux/dl-mseal.h @@ -25,5 +25,3 @@ Return 0 in case of success or a negative value otherwise (a negative errno). */ int _dl_mseal (void *addr, size_t len) attribute_hidden; - -#define SUPPORT_MSEAL lt_seal_toseal diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2-1.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2-1.c new file mode 100644 index 0000000000..0cd647de46 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2-1.c @@ -0,0 +1,19 @@ +/* Additional module for tst-dl_mseal test. + Copyright (C) 2024 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/>. */ + +int bar2_1 (void) { return 42; } diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2.c new file mode 100644 index 0000000000..f719dd3cba --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2.c @@ -0,0 +1,19 @@ +/* Additional module for tst-dl_mseal test. + Copyright (C) 2024 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/>. */ + +int bar2 (void) { return 42; } diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-1.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-1.c new file mode 100644 index 0000000000..3bd188efe8 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-1.c @@ -0,0 +1,19 @@ +/* Additional module for tst-dl_mseal test. + Copyright (C) 2024 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/>. */ + +int foo1 (void) { return 42; } diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-2.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-2.c new file mode 100644 index 0000000000..636e9777af --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-2.c @@ -0,0 +1,19 @@ +/* Additional module for tst-dl_mseal test. + Copyright (C) 2024 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/>. */ + +int bar1 (void) { return 42; } diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-auditmod.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-auditmod.c new file mode 100644 index 0000000000..a5b257d05e --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-auditmod.c @@ -0,0 +1 @@ +#include "tst-dl_mseal-auditmod.c" diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-preload.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-preload.c new file mode 100644 index 0000000000..32b4153e79 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-preload.c @@ -0,0 +1 @@ +#include "tst-dl_mseal-preload.c" diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal.c new file mode 100644 index 0000000000..014a8e76c7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal.c @@ -0,0 +1,65 @@ +/* Basic tests for sealing. + Copyright (C) 2024 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/>. */ + +#include <gnu/lib-names.h> + +/* This test checks the GNU_PROPERTY_NO_MEMORY_SEAL handling on multiple + places: + + - On the binary itself. + - On a LD_PRELOAD library. + - On a depedency module (tst-dl_mseal-mod-no-memory-seal-2.so). + - On a audit modules (tst-dl_mseal-no-memory-seal-auditmod.so). + - On a dlopen dependency opened with RTLD_NODELET + (tst-dl_mseal-dlopen-no-memory-seal-2.so). +*/ + +#define LIB_PRELOAD "tst-dl_mseal-no-memory-seal-preload.so" +#define GLIBC_RTLD_SEAL "1" + +#define LIB_DLOPEN_DEFAULT "tst-dl_mseal-dlopen-1.so" +#define LIB_DLOPEN_DEFAULT_DEP "tst-dl_mseal-dlopen-1-1.so" +#define LIB_DLOPEN_NODELETE "tst-dl_mseal-dlopen-no-memory-seal-2.so" +#define LIB_DLOPEN_NODELETE_DEP "tst-dl_mseal-dlopen-no-memory-seal-2-1.so" + +#define LIB_AUDIT "tst-dl_mseal-no-memory-seal-auditmod.so" + +/* Expected libraries that loader will seal. */ +static const char *expected_sealed_libs[] = +{ + "libc.so", + "ld.so", + "tst-dl_mseal-mod-no-memory-seal-1.so", + LIB_DLOPEN_NODELETE_DEP, + LIBGCC_S_SO, +}; + +/* Expected non sealed libraries. */ +static const char *expected_non_sealed_libs[] = +{ + "[vdso]", + "tst-dl_mseal-no-memory-seal", + LIB_PRELOAD, + LIB_AUDIT, + "tst-dl_mseal-mod-no-memory-seal-2.so", + LIB_DLOPEN_DEFAULT, + LIB_DLOPEN_DEFAULT_DEP, + LIB_DLOPEN_NODELETE, +}; + +#include "tst-dl_mseal-skeleton.c" diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-skeleton.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-skeleton.c index fbf18d9b7c..6c77b14d86 100644 --- a/sysdeps/unix/sysv/linux/tst-dl_mseal-skeleton.c +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-skeleton.c @@ -1,4 +1,4 @@ -/* Basic tests for sealing. Static version. +/* Basic tests for sealing. Copyright (C) 2024 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -198,7 +198,7 @@ handle_restart (void) /* Also check if all the expected sealed maps were found. */ for (int i = 0; i < array_length (expected_sealed_libs); i++) - if (!found_expected[i]) + if (expected_sealed_libs[i][0] && !found_expected[i]) FAIL_EXIT1 ("expected VMA %s not sealed\n", expected_sealed_libs[i]); return 0; @@ -239,7 +239,7 @@ do_test (int argc, char *argv[]) spargv[i] = NULL; char *envvarss[4]; - envvarss[0] = (char *) "GLIBC_TUNABLES=glibc.rtld.seal=2"; + envvarss[0] = (char *) "GLIBC_TUNABLES=glibc.rtld.seal=" GLIBC_RTLD_SEAL; #ifndef TEST_STATIC envvarss[1] = (char *) "LD_PRELOAD=" LIB_PRELOAD; envvarss[2] = (char *) "LD_AUDIT=" LIB_AUDIT, diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-static-no-memory-seal.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-static-no-memory-seal.c new file mode 100644 index 0000000000..257500ea47 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-static-no-memory-seal.c @@ -0,0 +1,38 @@ +/* Basic tests for sealing. Static version. + Copyright (C) 2024 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/>. */ + +/* This test checks the GNU_PROPERTY_NO_MEMORY_SEAL handling on a statically + built binary. In this case only the vDSO (if existent) will be sealed. */ + +#define GLIBC_RTLD_SEAL "1" +#define TEST_STATIC 1 + +/* Expected libraries that loader will seal. */ +static const char *expected_sealed_libs[] = +{ + "", +}; + +/* Expected non sealed libraries. */ +static const char *expected_non_sealed_libs[] = +{ + "[vdso]", + "tst-dl_mseal-static-no-memory-seal", +}; + +#include "tst-dl_mseal-skeleton.c" diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h index 08387dfaff..26a687d611 100644 --- a/sysdeps/x86/dl-prop.h +++ b/sysdeps/x86/dl-prop.h @@ -19,6 +19,7 @@ #ifndef _DL_PROP_H #define _DL_PROP_H +#include <dl-prop-mseal.h> #include <libintl.h> extern void _dl_cet_check (struct link_map *, const char *) @@ -241,6 +242,9 @@ _dl_process_gnu_property (struct link_map *l, int fd, uint32_t type, uint32_t datasz, void *data) { /* This is called on each GNU property. */ + if (_dl_process_gnu_property_seal (l, fd, type, datasz, data)) + return 0; + unsigned int needed_1 = 0; unsigned int feature_1_and = 0; unsigned int isa_1_needed = 0; |