]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
elf: Add support to memory sealing
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 6 Dec 2024 17:37:54 +0000 (14:37 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 7 Mar 2025 11:46:48 +0000 (08:46 -0300)
The new Linux mseal syscall allows mark a memory mapping to avoid
further changes (such as changng the protection flags).  The memory
sealing is done in multiple places where the memory is supposed to
be immutable during program execution:

  * All shared library dependencies from the binary, including the
    read-only segments after PT_GNU_RELRO setup.

  * 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.

  * Any preload libraries, including depedencies.

  * Any library loaded with dlopen with RTLD_NODELETE flag.

  * Audit modules.

  * The loader bump allocator.

The memory sealing is controled by a new gnu attribute,
GNU_PROPERTY_MEMORY_SEAL, added by the new static linker option
'-z memory-seal'.  It is set per binary, including statically linked
and shared objects.

The GNU_PROPERTY_MEMORY_SEAL enforcement depends on whether the kernel
supports the mseal syscall and how glibc is configured.  On the default
configuration that aims to support older kernel releases, the memory
sealing attribute is taken as a hint. If glibc is configured with a
minimum kernel of 6.10, where mseal is implied to be supported,
sealing is enforced.

Checked on x86_64-linux-gnu and aarch64-linux-gnu.

19 files changed:
NEWS
elf/dl-load.c
elf/dl-map-segments.h
elf/dl-minimal-malloc.c
elf/dl-reloc.c
elf/dl-support.c
elf/elf.h
elf/rtld.c
elf/setup-vdso.h
include/link.h
sysdeps/aarch64/dl-prop.h
sysdeps/generic/dl-mseal.h [new file with mode: 0644]
sysdeps/generic/dl-prop-mseal.h [new file with mode: 0644]
sysdeps/generic/dl-prop.h
sysdeps/generic/ldsodefs.h
sysdeps/unix/sysv/linux/Makefile
sysdeps/unix/sysv/linux/dl-mseal.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/dl-mseal.h [new file with mode: 0644]
sysdeps/x86/dl-prop.h

diff --git a/NEWS b/NEWS
index 4732ec2522000732489382b1d46d5ebfe59e39d5..fc460ede05a7d5f77eeac0bda358107b261f5b83 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,16 @@ Major new features:
   mappings to avoid further change during process execution such as protection
   permissions, unmapping, moving to another location, or shrinking the size.
 
+* The loader will memory seal all libraries that contains the new gnu
+  attribute GNU_PROPERTY_MEMORY_SEAL.  The memory sealing uses the new Linux
+  mseal syscall, and it will be applied to all shared libraries dependencies,
+  the binary, any preload and audit modules, and aby library loaded with
+  RTLD_NODELETE.
+
+  If the GNU_PROPERTY_MEMORY_SEAL gnu attribute it not present on the binary,
+  memory sealing will not be applied for its dependencies (and even if the
+  objects has the memory sealing attribute).
+
 Deprecated and removed features, and other changes affecting compatibility:
 
   [Add deprecations, removals and changes affecting compatibility here]
index 4998652adff36568d517d402ffc198e87b3d22fa..f104cc75441a041c5398dd629c96da261d457b8e 100644 (file)
@@ -1447,6 +1447,10 @@ cannot enable executable stack as shared object requires");
     /* Assign the next available module ID.  */
     _dl_assign_tls_modid (l);
 
+  if (l->l_seal == lt_seal_toseal
+      && (mode & __RTLD_DLOPEN) && !(mode & RTLD_NODELETE))
+    l->l_seal = lt_seal_dont_dlopen;
+
 #ifdef DL_AFTER_LOAD
   DL_AFTER_LOAD (l);
 #endif
index ee68dda550a8220362731195fc378bac212dfd2b..b154b14836ab9310b4b523f76866e2038bff1148 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <dl-load.h>
 #include <setvmaname.h>
+#include <dl-mseal.h>
 
 /* Map a segment and align it properly.  */
 
@@ -116,11 +117,15 @@ _dl_map_segments (struct link_map *l, int fd,
          if (__glibc_unlikely (loadcmds[nloadcmds - 1].mapstart <
                                c->mapend))
            return N_("ELF load command address/offset not page-aligned");
+
+         caddr_t hole_start = (caddr_t) (l->l_addr + c->mapend);
+         size_t hole_size = loadcmds[nloadcmds - 1].mapstart - c->mapend;
+
           if (__glibc_unlikely
-              (__mprotect ((caddr_t) (l->l_addr + c->mapend),
-                           loadcmds[nloadcmds - 1].mapstart - c->mapend,
-                           PROT_NONE) < 0))
+              (__mprotect (hole_start, hole_size, PROT_NONE) < 0))
             return DL_MAP_SEGMENTS_ERROR_MPROTECT;
+         if (GLRO(dl_enable_seal) && l->l_seal == lt_seal_toseal)
+           _dl_mseal (hole_start, hole_size, l->l_name);
         }
 
       l->l_contiguous = 1;
@@ -218,6 +223,12 @@ _dl_map_segments (struct link_map *l, int fd,
                     }
                   __set_vma_name ((void*)zeropage, zeroend - zeropage, bssname);
                 }
+
+             /* We need to seal this here because it will not be part of
+                the PT_LOAD segments, nor it is taken in RELRO
+                calculation.  */
+             if (GLRO(dl_enable_seal) && l->l_seal == lt_seal_toseal)
+               _dl_mseal (mapat, zeroend - zeropage, l->l_name);
             }
         }
 
index b4bd1628bc4c8c04dc51286e2fb49064c390e1b8..c023d216ce8c528970b2bf6b09eb89410c6c98db 100644 (file)
@@ -27,6 +27,7 @@
 #include <ldsodefs.h>
 #include <malloc/malloc-internal.h>
 #include <setvmaname.h>
+#include <dl-mseal.h>
 
 static void *alloc_ptr, *alloc_end, *alloc_last_block;
 
@@ -62,6 +63,10 @@ __minimal_malloc (size_t n)
       if (page == MAP_FAILED)
        return NULL;
       __set_vma_name (page, nup, " glibc: loader malloc");
+#if IS_IN(rtld)
+      if (GLRO(dl_enable_seal))
+       _dl_mseal (page, nup, _dl_rtld_map.l_name);
+#endif
       if (page != alloc_end)
        alloc_ptr = page;
       alloc_end = page + nup;
index 05bf54bebd3f27e41f57a50df6053a507d3e2616..2b37676182352592f535d02429a01c87ba1b98a5 100644 (file)
@@ -28,6 +28,7 @@
 #include <_itoa.h>
 #include <libc-pointer-arith.h>
 #include "dynamic-link.h"
+#include <dl-mseal.h>
 
 /* Statistics function.  */
 #ifdef SHARED
@@ -345,6 +346,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
     return;
   _dl_relocate_object_no_relro (l, scope, reloc_mode, consider_profiling);
   _dl_protect_relro (l);
+  _dl_mseal_map (l, false);
 }
 
 void
@@ -369,6 +371,58 @@ cannot apply additional memory protection after relocation");
     }
 }
 
+static void
+_dl_mseal_map_1 (struct link_map *l, bool dep)
+{
+  if (!GLRO(dl_enable_seal))
+    return;
+
+  /* The DEP is used internaly to memory seal audit modules after they are
+     dynamic loaded, since they might be unloaded if some constraints are not
+     met (for instance, if la_version is not supported).
+     For dlopen without RTLD_NODELETE, do not apply memory sealing.  */
+  if (l->l_seal == lt_seal_dont
+      || (dep
+         ? l->l_seal != lt_seal_dont_dlopen
+         : l->l_seal == lt_seal_dont_dlopen))
+    return;
+
+  if (l->l_contiguous)
+     _dl_mseal ((void *) l->l_map_start, l->l_map_end - l->l_map_start,
+               l->l_name);
+  else
+    {
+      /* We can use the PT_LOAD segments because even if relro splits the
+        original RW VMA, mseal works with multiple VMAs with different
+        protection flags.  */
+      const ElfW(Phdr) *ph;
+      for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
+       switch (ph->p_type)
+         {
+         case PT_LOAD:
+           {
+             ElfW(Addr) mapstart = l->l_addr
+                 + (ph->p_vaddr & ~(GLRO(dl_pagesize) - 1));
+             ElfW(Addr) allocend = l->l_addr + ph->p_vaddr + ph->p_memsz;
+             _dl_mseal ((void *) mapstart, allocend - mapstart, l->l_name);
+           }
+           break;
+       }
+    }
+
+  l->l_seal = lt_seal_sealed;
+}
+
+void
+_dl_mseal_map (struct link_map *l, bool dep)
+{
+  if (l->l_searchlist.r_list == NULL || !dep)
+    _dl_mseal_map_1 (l, dep);
+  else
+    for (unsigned int i = 0; i < l->l_searchlist.r_nlist; ++i)
+      _dl_mseal_map_1 (l->l_searchlist.r_list[i], dep);
+}
+
 void
 __attribute_noinline__
 _dl_reloc_bad_type (struct link_map *map, unsigned int type, int plt)
index d8f1dd8ee96b9db3db9b709fb2e03bad3aa63638..ab74f3b51ca29e092dbe5296ce777c422cf21002 100644 (file)
@@ -46,6 +46,7 @@
 #include <dl-symbol-redir-ifunc.h>
 #include <dl-tunables.h>
 #include <dl-prop.h>
+#include <dl-mseal.h>
 
 extern char *__progname;
 char **_dl_argv = &__progname; /* This is checked for some error messages.  */
@@ -100,6 +101,7 @@ static struct link_map _dl_main_map =
     .l_used = 1,
     .l_tls_offset = NO_TLS_OFFSET,
     .l_serial = 1,
+    .l_seal = lt_seal_dont,
   };
 
 /* Namespace information.  */
@@ -164,6 +166,8 @@ uint64_t _dl_hwcap4;
 
 enum dso_sort_algorithm _dl_dso_sort_algo;
 
+bool _dl_enable_seal;
+
 /* The value of the FPU control word the kernel will preset in hardware.  */
 fpu_control_t _dl_fpu_control = _FPU_DEFAULT;
 
@@ -344,6 +348,8 @@ _dl_non_dynamic_init (void)
        break;
       }
 
+  GLRO(dl_enable_seal) = _dl_main_map.l_seal == lt_seal_toseal;
+
   if ((__glibc_unlikely (GL(dl_stack_flags)) & PF_X)
       && TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL) == 0)
     _dl_fatal_printf ("Fatal glibc error: executable stack is not allowed\n");
@@ -352,6 +358,7 @@ _dl_non_dynamic_init (void)
 
   /* Setup relro on the binary itself.  */
   _dl_protect_relro (&_dl_main_map);
+  _dl_mseal_map (&_dl_main_map, false);
 }
 
 #ifdef DL_SYSINFO_IMPLEMENTATION
index c0f61489ecfb227f073371ae34c455f89b0e1bed..f7d38eeffbc0fb1b871456573dbeddc821712b5b 100644 (file)
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -1359,6 +1359,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_MEMORY_SEAL               3
 
 /* A 4-byte unsigned integer property: A bit is set if it is set in all
    relocatable inputs.  */
index c51670143dddacaf609b3b3b5c9ffebe19c13c95..305fbda7139c2f24aca4ee11dcd51dee8b4aeff0 100644 (file)
@@ -52,6 +52,7 @@
 #include <dl-find_object.h>
 #include <dl-audit-check.h>
 #include <dl-call_tls_init_tp.h>
+#include <dl-mseal.h>
 
 #include <assert.h>
 
@@ -478,6 +479,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
   _dl_rtld_map.l_real = &_dl_rtld_map;
   _dl_rtld_map.l_map_start = (ElfW(Addr)) &__ehdr_start;
   _dl_rtld_map.l_map_end = (ElfW(Addr)) _end;
+  _dl_rtld_map.l_seal = lt_seal_dont;
   /* Copy the TLS related data if necessary.  */
 #ifndef DONT_USE_BOOTSTRAP_MAP
 # if NO_TLS_OFFSET != 0
@@ -1023,6 +1025,10 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
 
   /* Mark the DSO as being used for auditing.  */
   dlmargs.map->l_auditing = 1;
+
+  /* Audit modules can not be loaded with RTLD_NODELETE, so apply the sealing
+     after after loading (including its dependencies)   */
+  _dl_mseal_map (dlmargs.map, true);
 }
 
 /* Load all audit modules.  */
@@ -1101,6 +1107,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 = lt_seal_dont;
 
   /* A PT_LOAD segment at an unexpected address will clear the
      l_contiguous flag.  The ELF specification says that PT_LOAD
@@ -1216,6 +1223,8 @@ rtld_setup_main_map (struct link_map *main_map)
        break;
       }
 
+  GLRO(dl_enable_seal) = main_map->l_seal == lt_seal_toseal;
+
   /* Adjust the address of the TLS initialization image in case
      the executable is actually an ET_DYN object.  */
   if (main_map->l_tls_initimage != NULL)
@@ -2318,8 +2327,10 @@ dl_main (const ElfW(Phdr) *phdr,
       __rtld_malloc_init_real (main_map);
     }
 
-  /* All ld.so initialization is complete.  Apply RELRO.  */
+  /* All ld.so initialization is complete.  Apply RELRO and memory
+     sealing.  */
   _dl_protect_relro (&_dl_rtld_map);
+  _dl_mseal_map (&_dl_rtld_map, false);
 
   /* Relocation is complete.  Perform early libc initialization.  This
      is the initial libc, even if audit modules have been loaded with
index 935d9e3baf2dc48e7b9760192a0cd9c83ade4db3..5119fa132162938b52a0049d05159cba27f515a9 100644 (file)
@@ -66,6 +66,8 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
 
       /* The vDSO is always used.  */
       l->l_used = 1;
+      /* The PT_LOAD may not cover all the vdso mapping.  */
+      l->l_seal = lt_seal_dont;
 
       /* Initialize l_local_scope to contain just this map.  This allows
         the use of dl_lookup_symbol_x to resolve symbols within the vdso.
index 518bfd1670a98027ef871c3f1a8dc2006e452632..677d82b38bfb77ccfddc7f6fe78c7a82608ee094 100644 (file)
@@ -214,6 +214,14 @@ struct link_map
                                               lt_library map.  */
     unsigned int l_tls_in_slotinfo:1; /* TLS slotinfo updated in dlopen.  */
 
+    enum                       /* Memory sealing status.  */
+      {
+       lt_seal_dont = 0,       /* Do not seal the object.  */
+       lt_seal_dont_dlopen,    /* Do not seal from a dlopen.  */
+       lt_seal_toseal,         /* The library is marked to be sealed.  */
+       lt_seal_sealed          /* The library is sealed.  */
+      } l_seal:2;
+
     /* NODELETE status of the map.  Only valid for maps of type
        lt_loaded.  Lazy binding sets l_nodelete_active directly,
        potentially from signal handlers.  Initial loading of an
index abca2be7fa8e0db57862b9bf0bf686c3c8140022..888308eed003df44009a3f398ed4d5ffa9a6df89 100644 (file)
@@ -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 *)
@@ -50,6 +52,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 1;
+
   if (type == GNU_PROPERTY_AARCH64_FEATURE_1_AND)
     {
       /* Stop if the property note is ill-formed.  */
diff --git a/sysdeps/generic/dl-mseal.h b/sysdeps/generic/dl-mseal.h
new file mode 100644 (file)
index 0000000..b100a7c
--- /dev/null
@@ -0,0 +1,22 @@
+/* Memory sealing.  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/>.  */
+
+static inline void
+_dl_mseal (void *addr, size_t len, const char *object)
+{
+}
diff --git a/sysdeps/generic/dl-prop-mseal.h b/sysdeps/generic/dl-prop-mseal.h
new file mode 100644 (file)
index 0000000..36a7e71
--- /dev/null
@@ -0,0 +1,34 @@
+/* Support for GNU properties.  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 _DL_PROP_MSEAL_H
+#define _DL_PROP_MSEAL_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_MEMORY_SEAL && datasz == 0)
+    {
+      l->l_seal = lt_seal_toseal;
+      return true;
+    }
+  return false;
+}
+
+#endif
index 6d4e62ea8463ed373f2d8c912d871da9ef5bedf4..ac53061dea93bf0cacb0b5031b5efe644f545255 100644 (file)
@@ -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 1;
+
   /* Continue until GNU_PROPERTY_1_NEEDED is found.  */
   if (type == GNU_PROPERTY_1_NEEDED)
     {
index 8465cbaa9b2aacf61838dc55a435d6cd7cffdf5a..6c8d6fadbaa520280919365e27061cf43eefca17 100644 (file)
@@ -642,6 +642,8 @@ struct rtld_global_ro
 
   EXTERN enum dso_sort_algorithm _dl_dso_sort_algo;
 
+  EXTERN bool _dl_enable_seal;
+
 #ifdef SHARED
   /* We add a function table to _rtld_global which is then used to
      call the function instead of going through the PLT.  The result
@@ -1021,6 +1023,14 @@ void _dl_relocate_object_no_relro (struct link_map *map,
 /* Protect PT_GNU_RELRO area.  */
 extern void _dl_protect_relro (struct link_map *map) attribute_hidden;
 
+/* 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, and it is
+   used for the case where sealing is done after loading (for instance
+   for audit modules).  */
+extern void _dl_mseal_map (struct link_map *map, bool dep) attribute_hidden;
+
 /* Call _dl_signal_error with a message about an unhandled reloc type.
    TYPE is the result of ELFW(R_TYPE) (r_info), i.e. an R_<CPU>_* value.
    PLT is nonzero if this was a PLT reloc; it just affects the message.  */
index ae46e0726d6d6183b0d7df996ddd32c9ee712ca1..a72635e340a190340f2102671ae703d0e9792110 100644 (file)
@@ -652,6 +652,10 @@ sysdep-rtld-routines += \
   dl-sbrk \
   # sysdep-rtld-routines
 
+dl-routines += \
+  dl-mseal \
+  # dl-routines
+
 others += \
   pldd \
   # others
diff --git a/sysdeps/unix/sysv/linux/dl-mseal.c b/sysdeps/unix/sysv/linux/dl-mseal.c
new file mode 100644 (file)
index 0000000..74ab688
--- /dev/null
@@ -0,0 +1,51 @@
+/* Memory sealing.  Linux 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/>.  */
+
+#include <atomic.h>
+#include <dl-mseal.h>
+#include <dl-tunables.h>
+#include <ldsodefs.h>
+#include <libintl.h>
+
+void
+_dl_mseal (void *addr, size_t len, const char *object)
+{
+  int r = 0;
+  bool fail = false;
+#if __ASSUME_MSEAL
+  r = INTERNAL_SYSCALL_CALL (mseal, addr, len, 0);
+  fail = r != 0;
+#else
+  static int mseal_supported = true;
+  /* Avoid issuing mseal again if it is not supported by the kernel.  */
+  if (atomic_load_relaxed (&mseal_supported))
+    {
+      int r = INTERNAL_SYSCALL_CALL (mseal, addr, len, 0);
+      if (r == -ENOSYS)
+       atomic_store_relaxed (&mseal_supported, false);
+      else
+       fail = r != 0;
+    }
+#endif
+  if (fail)
+    {
+      static const char errstring[] = N_("\
+cannot apply memory sealing");
+      _dl_signal_error (-r, DSO_FILENAME (object), NULL, errstring);
+    }
+}
diff --git a/sysdeps/unix/sysv/linux/dl-mseal.h b/sysdeps/unix/sysv/linux/dl-mseal.h
new file mode 100644 (file)
index 0000000..b0a9e95
--- /dev/null
@@ -0,0 +1,31 @@
+/* Memory sealing.  Linux 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 _DL_MSEAL_H
+#define _DL_MSEAL_H
+
+/* Seal the ADDR or size LEN to protect against fruthermodifications, such as
+   changes on the permission flags (through mprotect), remap (through
+   mmap and/or remap), shrink, destruction changes (madvise with
+   MADV_DONTNEED), or change its size.  The input has the same constraints
+   as the mseal syscall.
+
+   Any error than than unsupported by the kerneltriggers a _dl_signal_error.  */
+void _dl_mseal (void *addr, size_t len, const char *object) attribute_hidden;
+
+#endif
index 9a5e10821c640ccd23e96550f5d1207fbe57865a..e9e1940530ed58807be999039b1b36128b7f70da 100644 (file)
@@ -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 *)
@@ -243,6 +244,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 1;
+
   unsigned int needed_1 = 0;
   unsigned int feature_1_and = 0;
   unsigned int isa_1_needed = 0;