[PATCH v2 0/5] Add support for memory sealing
Adhemerval Zanella
adhemerval.zanella@linaro.org
Wed Jul 31 20:02:03 GMT 2024
The Linux 6.10 (8be7258aad44b5e25977a98db136f677fa6f4370) added the mseal
syscall that allows blocking some memory operations on the VMA range:
* Unmapping, moving to another location, extending or shrinking the
size, munmap, and mremap.
* Moving or expanding a different VMA into the current location, via
mremap.
* Modifying the memory range with mmap along with flag MAP_FIXED.
* Expanding the size with mremap.
* Change the protection flags with mprotect or pkey_mprotect.
* Destructive behaviors on anonymous memory, such as madvice with
MADV_DONTNEED.
Memory sealing might be useful as a hardening mechanism to avoid either
remapping the memory segments or changing the memory protection segments
layout by the dynamic loader (for instance, the RELRO hardening).
A similar hardening is done by OpenBSD with the mimmutable syscall [1].
The first patch expands the use of RTLD_NODELETE for objects that should
not be deallocated during process execution. The flag will be used later
to decide whether to seal the link_map:
* on dlopen dependencies for objects opened with RTLD_NODELETE
* For the main map executable.
* For the main map DT_NEEDED dependencies.
* On __libc_unwind_link_get for libgcc_s.so (used for backtrace and
unwind).
The second patch adds the mseal support for Linux. Although most
programs will not use it directly, some specific ones, like Chrome,
intend to use it.
The third patch adds memory sealing in multiple places where the memory
is supposed to be immutable over 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 links. In both cases,
it is up either to binary or the loader to set up the sealing.
* Any preload libraries.
* Any library loaded with dlopen with RTLD_NODELETE flag (including
libgcc.so loaded to enable process unwind and thread cancellation).
* Audit modules.
* The loader bump allocator.
For binary dependencies, the RTLD_NODELETE signals the link_map should be
sealed. It also makes dlopen objects with the flag sealed as well.
The sealing is also controlled by a new tunable, glibc.rtld.seal, with
three different states:
0. Disabled, where no memory sealing is done.
1. Enabled, where the loader will issue the mseal syscall on the
memory mappings, and any failure is ignored. This is the default.
2. Enforce, similar to Enabled and any failure from the mseal terminates
the process.
The final patch adds support for GNU_PROPERTY_NO_MEMORY_SEAL, where the
binary can be marked to avoid sealing (i.e., on Firefox hack to bypass the
dynamic loader and enable DT_RELR on older glibc [3]). In this case, it is
up to the module to apply memory sealing itself. I have a patch to
binutils to add -Wl,-z,no-memory-seal option to enable it.
This patchset does not delay RELRO activation until after their ELF
constructors have been executed, as suggested on the previous RFC for
mseal support. It is not strictly required, and it requires extensive
changes on_dl_start_user to either make _dl_init call RELRO/sealing setup
after ctor/initarray is done, or call it after _dl_init. There is also the
question of whether to apply RELRO/sealing per module after dtor/initarray
or in bulk after _dt_init.
I tested on both x86_64-linux-gnu and aarch64-linux-gnu with Linux
6.11-rc1, along with some testing on a powerpc64le-linux-gnu VM. I also
enabled glibc.rtld.seal=2 to check for possible mseal failures.
[1] https://man.openbsd.org/mimmutable.2
[2] https://docs.google.com/document/d/1O2jwK4dxI3nRcOJuPYkonhTkNQfbmwdvxQMyXgeaRHo/edit#heading=h.bvaojj9fu6hc
[3] https://glandium.org/blog/?p=4297
Adhemerval Zanella (5):
elf: Use RTLD_NODELETE is more places
linux: Add mseal syscall support
elf: Add support to memory sealing
elf: Also parse gnu properties for static linked binaries
elf: Add support for GNU_PROPERTY_NO_MEMORY_SEAL
NEWS | 15 +
configure | 35 +++
configure.ac | 5 +
elf/dl-load.c | 4 +
elf/dl-map-segments.h | 5 +
elf/dl-minimal-malloc.c | 2 +
elf/dl-mseal-mode.h | 29 ++
elf/dl-open.c | 7 +-
elf/dl-reloc.c | 47 +++
elf/dl-support.c | 20 ++
elf/dl-tunables.list | 6 +
elf/elf.h | 2 +
elf/rtld.c | 13 +-
elf/setup-vdso.h | 2 +
elf/tst-rtld-list-tunables.exp | 1 +
include/dlfcn.h | 2 +
include/link.h | 7 +
manual/memory.texi | 66 +++++
manual/tunables.texi | 42 +++
misc/unwind-link.c | 5 +-
sysdeps/aarch64/dl-prop.h | 5 +
sysdeps/generic/dl-mseal.h | 23 ++
sysdeps/generic/dl-prop-mseal.h | 38 +++
sysdeps/generic/dl-prop.h | 5 +
sysdeps/generic/ldsodefs.h | 9 +
sysdeps/unix/sysv/linux/Makefile | 94 ++++++
sysdeps/unix/sysv/linux/Versions | 3 +
sysdeps/unix/sysv/linux/aarch64/libc.abilist | 1 +
sysdeps/unix/sysv/linux/alpha/libc.abilist | 1 +
sysdeps/unix/sysv/linux/arc/libc.abilist | 1 +
sysdeps/unix/sysv/linux/arm/be/libc.abilist | 1 +
sysdeps/unix/sysv/linux/arm/le/libc.abilist | 1 +
sysdeps/unix/sysv/linux/bits/mman-shared.h | 8 +
sysdeps/unix/sysv/linux/csky/libc.abilist | 1 +
sysdeps/unix/sysv/linux/dl-mseal.c | 51 ++++
sysdeps/unix/sysv/linux/dl-mseal.h | 27 ++
sysdeps/unix/sysv/linux/hppa/libc.abilist | 1 +
sysdeps/unix/sysv/linux/i386/libc.abilist | 1 +
sysdeps/unix/sysv/linux/kernel-features.h | 8 +
.../sysv/linux/loongarch/lp64/libc.abilist | 1 +
.../sysv/linux/m68k/coldfire/libc.abilist | 1 +
.../unix/sysv/linux/m68k/m680x0/libc.abilist | 1 +
.../sysv/linux/microblaze/be/libc.abilist | 1 +
.../sysv/linux/microblaze/le/libc.abilist | 1 +
.../sysv/linux/mips/mips32/fpu/libc.abilist | 1 +
.../sysv/linux/mips/mips64/n32/libc.abilist | 1 +
.../sysv/linux/mips/mips64/n64/libc.abilist | 1 +
sysdeps/unix/sysv/linux/nios2/libc.abilist | 1 +
sysdeps/unix/sysv/linux/or1k/libc.abilist | 1 +
.../linux/powerpc/powerpc32/fpu/libc.abilist | 1 +
.../powerpc/powerpc32/nofpu/libc.abilist | 1 +
.../linux/powerpc/powerpc64/be/libc.abilist | 1 +
.../linux/powerpc/powerpc64/le/libc.abilist | 1 +
.../unix/sysv/linux/riscv/rv32/libc.abilist | 1 +
.../unix/sysv/linux/riscv/rv64/libc.abilist | 1 +
.../unix/sysv/linux/s390/s390-32/libc.abilist | 1 +
.../unix/sysv/linux/s390/s390-64/libc.abilist | 1 +
sysdeps/unix/sysv/linux/sh/be/libc.abilist | 1 +
sysdeps/unix/sysv/linux/sh/le/libc.abilist | 1 +
.../sysv/linux/sparc/sparc32/libc.abilist | 1 +
.../sysv/linux/sparc/sparc64/libc.abilist | 1 +
sysdeps/unix/sysv/linux/syscalls.list | 1 +
.../unix/sysv/linux/tst-dl_mseal-auditmod.c | 23 ++
.../unix/sysv/linux/tst-dl_mseal-dlopen-1-1.c | 19 ++
.../unix/sysv/linux/tst-dl_mseal-dlopen-1.c | 19 ++
.../unix/sysv/linux/tst-dl_mseal-dlopen-2-1.c | 19 ++
.../unix/sysv/linux/tst-dl_mseal-dlopen-2.c | 19 ++
.../tst-dl_mseal-dlopen-no-memory-seal-2-1.c | 19 ++
.../tst-dl_mseal-dlopen-no-memory-seal-2.c | 19 ++
sysdeps/unix/sysv/linux/tst-dl_mseal-mod-1.c | 19 ++
sysdeps/unix/sysv/linux/tst-dl_mseal-mod-2.c | 19 ++
.../linux/tst-dl_mseal-mod-no-memory-seal-1.c | 19 ++
.../linux/tst-dl_mseal-mod-no-memory-seal-2.c | 19 ++
.../tst-dl_mseal-no-memory-seal-auditmod.c | 1 +
.../tst-dl_mseal-no-memory-seal-preload.c | 1 +
.../sysv/linux/tst-dl_mseal-no-memory-seal.c | 65 +++++
.../unix/sysv/linux/tst-dl_mseal-preload.c | 19 ++
.../unix/sysv/linux/tst-dl_mseal-skeleton.c | 272 ++++++++++++++++++
.../tst-dl_mseal-static-no-memory-seal.c | 38 +++
sysdeps/unix/sysv/linux/tst-dl_mseal-static.c | 36 +++
sysdeps/unix/sysv/linux/tst-dl_mseal.c | 67 +++++
sysdeps/unix/sysv/linux/tst-mseal.c | 67 +++++
.../unix/sysv/linux/x86_64/64/libc.abilist | 1 +
.../unix/sysv/linux/x86_64/x32/libc.abilist | 1 +
sysdeps/x86/dl-prop.h | 4 +
85 files changed, 1396 insertions(+), 6 deletions(-)
create mode 100644 elf/dl-mseal-mode.h
create mode 100644 sysdeps/generic/dl-mseal.h
create mode 100644 sysdeps/generic/dl-prop-mseal.h
create mode 100644 sysdeps/unix/sysv/linux/dl-mseal.c
create mode 100644 sysdeps/unix/sysv/linux/dl-mseal.h
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-auditmod.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-1-1.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-1.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-2-1.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-2.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2-1.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-mod-1.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-mod-2.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-1.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-2.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-auditmod.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-preload.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-preload.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-skeleton.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-static-no-memory-seal.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-static.c
create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal.c
create mode 100644 sysdeps/unix/sysv/linux/tst-mseal.c
--
2.43.0
More information about the Libc-alpha
mailing list