@@ -26,6 +26,12 @@ Major new features:
* A new configure option, "--enable-memory-sealing", can be used to build
the GNU C Library libraries and programs with memory sealing.
+* A new tunable, glibc.rtld.seal, can enable memory sealing on the program
+ and all its dependencies. The tunable accepts two different values, where
+ '0' disable memory sealing (even if the GNU_PROPERTY_MEMORY_SEAL attribute
+ is present), while '1' applies sealing accordingly to the sealing
+ attribute.
+
Deprecated and removed features, and other changes affecting compatibility:
[Add deprecations, removals and changes affecting compatibility here]
@@ -141,6 +141,12 @@ glibc {
maxval: 1
default: 1
}
+ seal {
+ type: INT_32
+ minval: 0
+ maxval: 1
+ default: 1
+ }
}
mem {
@@ -16,3 +16,4 @@ glibc.rtld.enable_secure: 0 (min: 0, max: 1)
glibc.rtld.execstack: 1 (min: 0, max: 1)
glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+)
+glibc.rtld.seal: 1 (min: 0, max: 1)
@@ -383,6 +383,42 @@ main program does not require an executable stack at loading time. This
is enforced regardless of the tunable value.
@end deftp
+@deftp Tunable glibc.rtld.seal
+Sets whether to enable memory sealing during program execution. The sealed
+memory prevents further changes to the metadata associated with an ELF mapped
+memory region, such as shrinking or expanding its size, mapping another
+segment over a pre-existing region, or changing the memory protection flags
+(check the @code{mseal} for more information).
+
+The sealing is done in multiple places where the memory is supposed to be
+immutable over program execution:
+
+@itemize @bullet
+@item
+All shared library dependencies from the binary, including the read-only segments
+after @code{PT_GNU_RELRO} setup.
+
+@item
+The binary itself, including dynamic and static linked ones. In both cases, it is
+up either to binary or the loader to set up the sealing.
+
+@item
+Any preload libraries.
+
+@item
+Any library loaded with @code{dlopen} with @code{RTLD_NODELETE} flag.
+
+@item
+All audit modules and their dependencies.
+@end itemize
+
+The tunable accepts two values: @samp{0} where sealing is disabled even if the
+program has the GNU attribute @code{GNU_PROPERTY_MEMORY_SEAL} if present,
+and @samp{1} where sealing is aplied accondingly to the GNU attribute existent.
+
+The default value of this tunable is @samp{1}.
+@end deftp
+
@node Elision Tunables
@section Elision Tunables
@cindex elision tunables
@@ -698,6 +698,7 @@ tests += \
$(tests-static) \
tst-dl_mseal \
tst-dl_mseal-noseal \
+ tst-dl_mseal-tunable \
# tests
modules-names += \
@@ -713,25 +714,22 @@ modules-names += \
tst-dl_mseal-preload \
# modules-names
-$(objpfx)tst-dl_mseal.out: \
+test-dl_mseal-mods = \
$(objpfx)tst-dl_mseal-auditmod.so \
- $(objpfx)tst-dl_mseal-preload.so \
- $(objpfx)tst-dl_mseal-mod-1.so \
- $(objpfx)tst-dl_mseal-mod-2.so \
- $(objpfx)tst-dl_mseal-dlopen-1.so \
$(objpfx)tst-dl_mseal-dlopen-1-1.so \
+ $(objpfx)tst-dl_mseal-dlopen-1.so \
+ $(objpfx)tst-dl_mseal-dlopen-2-1.so \
$(objpfx)tst-dl_mseal-dlopen-2.so \
- $(objpfx)tst-dl_mseal-dlopen-2-1.so
-
-$(objpfx)tst-dl_mseal-noseal.out: \
- $(objpfx)tst-dl_mseal-auditmod.so \
- $(objpfx)tst-dl_mseal-preload.so \
$(objpfx)tst-dl_mseal-mod-1.so \
$(objpfx)tst-dl_mseal-mod-2.so \
- $(objpfx)tst-dl_mseal-dlopen-1.so \
- $(objpfx)tst-dl_mseal-dlopen-1-1.so \
- $(objpfx)tst-dl_mseal-dlopen-2.so \
- $(objpfx)tst-dl_mseal-dlopen-2-1.so
+ $(objpfx)tst-dl_mseal-preload.so \
+ # test-dl_mseal-mods
+
+$(objpfx)tst-dl_mseal.out: $(test-dl_mseal-mods)
+
+$(objpfx)tst-dl_mseal-noseal.out: $(test-dl_mseal-mods)
+
+$(objpfx)tst-dl_mseal-tunable.out: $(test-dl_mseal-mods)
$(objpfx)tst-dl_mseal-mutable.out: \
$(objpfx)tst-dl_mseal-mutable-mod.so \
@@ -771,6 +769,7 @@ tst-dl_mseal-ARGS = -- $(host-test-program-cmd)
tst-dl_mseal-static-ARGS = -- $(host-test-program-cmd)
tst-dl_mseal-noseal-ARGS = -- $(host-test-program-cmd)
tst-dl_mseal-static-noseal-ARGS = -- $(host-test-program-cmd)
+tst-dl_mseal-tunable-ARGS = -- $(host-test-program-cmd)
ifeq ($(have-pt-gnu-mutable),yes)
tests-static += \
@@ -22,9 +22,18 @@
#include <ldsodefs.h>
#include <libintl.h>
+static inline bool
+is_sealing_enable (void)
+{
+ return TUNABLE_GET (glibc, rtld, seal, int32_t, NULL) == 1;
+}
+
void
_dl_mseal (void *addr, size_t len, const char *object)
{
+ if (__glibc_unlikely (!is_sealing_enable ()))
+ return;
+
int r = 0;
bool fail = false;
#if __ASSUME_MSEAL
@@ -32,6 +32,10 @@
#include "tst-dl_mseal-common.h"
+#ifndef TEST_NAME
+# define TEST_NAME "tst-dl_mseal-noseal"
+#endif
+
/* Expected libraries that loader will seal. */
static const char *expected_sealed_vmas[] =
{
@@ -43,7 +47,7 @@ static const char *expected_non_sealed_vmas[] =
{
"libc.so",
"ld.so",
- "tst-dl_mseal-noseal",
+ TEST_NAME,
LIB_PRELOAD,
LIB_AUDIT,
LIB_MODULE1,
@@ -235,6 +235,9 @@ do_test (int argc, char *argv[])
#endif
#ifdef LD_AUDIT
(char *) "LD_AUDIT=" LD_AUDIT,
+#endif
+#ifdef TUNABLE_ENV_VAR
+ TUNABLE_ENV_VAR,
#endif
NULL
};
new file mode 100644
@@ -0,0 +1,24 @@
+/* Check glibc.rtld.seal tunable.
+ 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/>. */
+
+/* Check if memory sealing is not applied if glibc.rtld.seal is set to 0. */
+
+#define TUNABLE_ENV_VAR (char *)"GLIBC_TUNABLES=glibc.rtld.seal=0"
+
+#define TEST_NAME "tst-dl_mseal-tunable"
+#include "tst-dl_mseal-noseal.c"