elf: Add support for GNU_PROPERTY_NO_MEMORY_SEAL

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
This commit is contained in:
Adhemerval Zanella 2024-07-08 16:38:10 -03:00
parent 8d2a331b64
commit 52ddeb99b2
27 changed files with 350 additions and 32 deletions

35
configure vendored
View File

@ -7102,6 +7102,41 @@ printf "%s\n" "$libc_linker_feature" >&6; }
config_vars="$config_vars config_vars="$config_vars
have-no-dynamic-linker = $libc_cv_no_dynamic_linker" 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\n" "$as_me:${as_lineno-$LINENO}: checking for -static-pie" >&5
printf %s "checking for -static-pie... " >&6; } printf %s "checking for -static-pie... " >&6; }
if test ${libc_cv_static_pie+y} if test ${libc_cv_static_pie+y}

View File

@ -1278,6 +1278,11 @@ LIBC_LINKER_FEATURE([--no-dynamic-linker],
[libc_cv_no_dynamic_linker=no]) [libc_cv_no_dynamic_linker=no])
LIBC_CONFIG_VAR([have-no-dynamic-linker], [$libc_cv_no_dynamic_linker]) 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 AC_CACHE_CHECK(for -static-pie, libc_cv_static_pie, [dnl
LIBC_TRY_CC_OPTION([-static-pie], LIBC_TRY_CC_OPTION([-static-pie],
[libc_cv_static_pie=yes], [libc_cv_static_pie=yes],

View File

@ -1431,7 +1431,9 @@ cannot enable executable stack as shared object requires");
/* Assign the next available module ID. */ /* Assign the next available module ID. */
_dl_assign_tls_modid (l); _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 #ifdef DL_AFTER_LOAD
DL_AFTER_LOAD (l); DL_AFTER_LOAD (l);

View File

@ -841,7 +841,7 @@ dl_open_worker (void *a)
/* The seal flag is set only for NEW, however its dependencies could not be /* The seal flag is set only for NEW, however its dependencies could not be
unloaded and thus can also be sealed. */ unloaded and thus can also be sealed. */
_dl_mseal_map (new, true); _dl_mseal_map (new, true, false);
} }
void * void *

View File

@ -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 /* Seal the memory mapping after RELRO setup, we can use the PT_LOAD
segments because even if relro splits the the original RW VMA, segments because even if relro splits the the original RW VMA,
mseal works with multiple VMAs with different flags. */ 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 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 if (l->l_seal == lt_seal_dont
module dependencies after the initial audit setup. */ || (!force && (l->l_seal != lt_seal_toseal)))
if (l->l_seal == lt_seal_sealed)
return; return;
int r = -1; int r = -1;
@ -408,16 +407,13 @@ _dl_mseal_map_1 (struct link_map *l)
} }
void 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) if (l->l_searchlist.r_list == NULL || !dep)
_dl_mseal_map_1 (l); _dl_mseal_map_1 (l, force);
else else
for (unsigned int i = 0; i < l->l_searchlist.r_nlist; ++i) 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 void

View File

@ -101,7 +101,7 @@ static struct link_map _dl_main_map =
.l_used = 1, .l_used = 1,
.l_tls_offset = NO_TLS_OFFSET, .l_tls_offset = NO_TLS_OFFSET,
.l_serial = 1, .l_serial = 1,
.l_seal = SUPPORT_MSEAL, .l_seal = lt_seal_toseal,
}; };
/* Namespace information. */ /* Namespace information. */
@ -359,7 +359,7 @@ _dl_non_dynamic_init (void)
/* Seal the memory mapping after RELRO setup, we can use the PT_LOAD /* Seal the memory mapping after RELRO setup, we can use the PT_LOAD
segments because even if relro splits the the original RW VMA, segments because even if relro splits the the original RW VMA,
mseal works with multiple VMAs with different flags. */ 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 #ifdef DL_SYSINFO_IMPLEMENTATION

View File

@ -1357,6 +1357,8 @@ typedef struct
#define GNU_PROPERTY_STACK_SIZE 1 #define GNU_PROPERTY_STACK_SIZE 1
/* No copy relocation on protected data symbol. */ /* No copy relocation on protected data symbol. */
#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2 #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 /* A 4-byte unsigned integer property: A bit is set if it is set in all
relocatable inputs. */ relocatable inputs. */

View File

@ -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_real = &GL(dl_rtld_map);
GL(dl_rtld_map).l_map_start = (ElfW(Addr)) &__ehdr_start; 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_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. */ /* Copy the TLS related data if necessary. */
#ifndef DONT_USE_BOOTSTRAP_MAP #ifndef DONT_USE_BOOTSTRAP_MAP
# if NO_TLS_OFFSET != 0 # 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. */ /* Mark the DSO as being used for auditing. */
dlmargs.map->l_auditing = 1; dlmargs.map->l_auditing = 1;
/* Seal the audit modules and their dependencies. */ /* Since audit modules can not be loaded with RTLD_NODELETE, force the
dlmargs.map->l_seal = lt_seal_toseal; sealing of the modules and its dependencies. */
_dl_mseal_map (dlmargs.map, true); _dl_mseal_map (dlmargs.map, true, true);
} }
/* Load all audit modules. */ /* Load all audit modules. */
@ -1131,7 +1131,7 @@ rtld_setup_main_map (struct link_map *main_map)
/* And it was opened directly. */ /* And it was opened directly. */
++main_map->l_direct_opencount; ++main_map->l_direct_opencount;
main_map->l_contiguous = 1; 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 /* A PT_LOAD segment at an unexpected address will clear the
l_contiguous flag. The ELF specification says that PT_LOAD l_contiguous flag. The ELF specification says that PT_LOAD

View File

@ -214,6 +214,7 @@ struct link_map
lt_library map. */ lt_library map. */
enum /* Memory sealing status. */ enum /* Memory sealing status. */
{ {
lt_seal_undefined = 0, /* No set. */
lt_seal_dont, /* Do not seal the object. */ lt_seal_dont, /* Do not seal the object. */
lt_seal_toseal, /* The library is marked to be sealed. */ lt_seal_toseal, /* The library is marked to be sealed. */
lt_seal_sealed /* The library is sealed. */ lt_seal_sealed /* The library is sealed. */

View File

@ -17,7 +17,6 @@
<https://www.gnu.org/licenses/>. */ <https://www.gnu.org/licenses/>. */
#include <stdio.h> #include <stdio.h>
#include <string.h>
const char * const char *
strerrorname_np (int errnum) strerrorname_np (int errnum)

View File

@ -19,6 +19,8 @@
#ifndef _DL_PROP_H #ifndef _DL_PROP_H
#define _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_protect (struct link_map *, int) attribute_hidden;
extern void _dl_bti_check (struct link_map *, const char *) 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, _dl_process_gnu_property (struct link_map *l, int fd, uint32_t type,
uint32_t datasz, void *data) 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) if (!GLRO(dl_aarch64_cpu_features).bti)
/* Skip note processing. */ /* Skip note processing. */
return 0; return 0;

View File

@ -21,5 +21,3 @@ _dl_mseal (void *addr, size_t len)
{ {
return 0; return 0;
} }
#define SUPPORT_MSEAL lt_seal_dont

View File

@ -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

View File

@ -19,6 +19,8 @@
#ifndef _DL_PROP_H #ifndef _DL_PROP_H
#define _DL_PROP_H #define _DL_PROP_H
#include <dl-prop-mseal.h>
/* The following functions are used by the dynamic loader and the /* The following functions are used by the dynamic loader and the
dlopen machinery to process PT_NOTE and PT_GNU_PROPERTY entries in 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 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, _dl_process_gnu_property (struct link_map *l, int fd, uint32_t type,
uint32_t datasz, void *data) 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. */ /* Continue until GNU_PROPERTY_1_NEEDED is found. */
if (type == GNU_PROPERTY_1_NEEDED) if (type == GNU_PROPERTY_1_NEEDED)
{ {

View File

@ -1017,10 +1017,13 @@ extern void _dl_relocate_object (struct link_map *map,
/* Protect PT_GNU_RELRO area. */ /* Protect PT_GNU_RELRO area. */
extern void _dl_protect_relro (struct link_map *map) attribute_hidden; extern void _dl_protect_relro (struct link_map *map) attribute_hidden;
/* Protect MAP with mseal. If MAP is contiguous the while region is /* Issue memory sealing for the link map MAP. If MAP is contiguous the
sealed, otherwise iterate over the phdr to seal each PT_LOAD. The DEP whole region is sealed, otherwise iterate over the program headerrs and
specify whether to seal the dependencies as well. */ seal each PT_LOAD segment.i
extern void _dl_mseal_map (struct link_map *map, bool dep) 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; attribute_hidden;
/* Call _dl_signal_error with a message about an unhandled reloc type. /* Call _dl_signal_error with a message about an unhandled reloc type.

View File

@ -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 LDFLAGS-tst-dl_mseal-dlopen-2.so = -Wl,--no-as-needed
tst-dl_mseal-static-ARGS = -- $(host-test-program-cmd) 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 endif
ifeq ($(subdir),rt) ifeq ($(subdir),rt)

View File

@ -25,5 +25,3 @@
Return 0 in case of success or a negative value otherwise (a negative Return 0 in case of success or a negative value otherwise (a negative
errno). */ errno). */
int _dl_mseal (void *addr, size_t len) attribute_hidden; int _dl_mseal (void *addr, size_t len) attribute_hidden;
#define SUPPORT_MSEAL lt_seal_toseal

View File

@ -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; }

View File

@ -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; }

View File

@ -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; }

View File

@ -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; }

View File

@ -0,0 +1 @@
#include "tst-dl_mseal-auditmod.c"

View File

@ -0,0 +1 @@
#include "tst-dl_mseal-preload.c"

View File

@ -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"

View File

@ -1,4 +1,4 @@
/* Basic tests for sealing. Static version. /* Basic tests for sealing.
Copyright (C) 2024 Free Software Foundation, Inc. Copyright (C) 2024 Free Software Foundation, Inc.
This file is part of the GNU C Library. 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. */ /* Also check if all the expected sealed maps were found. */
for (int i = 0; i < array_length (expected_sealed_libs); i++) 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]); FAIL_EXIT1 ("expected VMA %s not sealed\n", expected_sealed_libs[i]);
return 0; return 0;
@ -239,7 +239,7 @@ do_test (int argc, char *argv[])
spargv[i] = NULL; spargv[i] = NULL;
char *envvarss[4]; 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 #ifndef TEST_STATIC
envvarss[1] = (char *) "LD_PRELOAD=" LIB_PRELOAD; envvarss[1] = (char *) "LD_PRELOAD=" LIB_PRELOAD;
envvarss[2] = (char *) "LD_AUDIT=" LIB_AUDIT, envvarss[2] = (char *) "LD_AUDIT=" LIB_AUDIT,

View File

@ -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"

View File

@ -19,6 +19,7 @@
#ifndef _DL_PROP_H #ifndef _DL_PROP_H
#define _DL_PROP_H #define _DL_PROP_H
#include <dl-prop-mseal.h>
#include <libintl.h> #include <libintl.h>
extern void _dl_cet_check (struct link_map *, const char *) 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) uint32_t datasz, void *data)
{ {
/* This is called on each GNU property. */ /* 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 needed_1 = 0;
unsigned int feature_1_and = 0; unsigned int feature_1_and = 0;
unsigned int isa_1_needed = 0; unsigned int isa_1_needed = 0;