mbox series

[RFC,0/5] Add support for memory sealing

Message ID 20240611153220.165430-1-adhemerval.zanella@linaro.org
Headers show
Series Add support for memory sealing | expand

Message

Adhemerval Zanella Netto June 11, 2024, 3:27 p.m. UTC
The Linux 6.10 (8be7258aad44b5e25977a98db136f677fa6f4370) added the
mseal syscall that allows blocking some memory operations on 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 removes an unrequired knob for modules without
GNU_PT_STACK that prevents the RELRO memory sealing of libc.

The second patch adds the mseal support for Linux.  Most of the programs
will not use it directly, however, some specific ones like Chrome do have
the plan 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
    It is up either to binary or the loader to set up the sealing.

  * The vDSO vma provided by the kernel (if existent).

  * Any preload libraries.

  * Any library loaded with dlopen with RTLD_NODELETE flag.

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 sealing is done.

  1. Enabled, where the loader will issue the mseal syscall on the
     memory mappings but any failure will be ignored. This is the default.

  2. Enforce, similar to Enabled but any failure from the mseal
     will terminate the process.

The fourth patch adds support for the libgcc_s.so loaded during process
execution. The fifth is for adding support audit modules.

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 ctor/initarray
or in bulk after _dt_init.  I am still investigate this.

One drawback of the Linux approach is I do not see an easy way to memory
seal the stack without kernel support.  The stack is not fully mapped by
the kernel at program start, so even trying to add some hack on loader
initialization might not be sufficient.

I have tested on both x86_64-linux-gnu and aarch64-linux-gnu with Linux
6.10-rc2, 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

Adhemerval Zanella (5):
  linux: Remove __stack_prot
  linux: Add mseal syscall support
  elf: Add support to memory sealing
  elf: Enable RTLD_NODELETE on __libc_unwind_link_get
  elf: Add support to memory sealing for audit modules

 NEWS                                          |   4 +
 elf/dl-load.c                                 |  48 +--
 elf/dl-mseal-mode.h                           |  29 ++
 elf/dl-open.c                                 |   4 +
 elf/dl-reloc.c                                |  49 +++
 elf/dl-support.c                              |   7 +
 elf/dl-tunables.list                          |   6 +
 elf/rtld.c                                    |  14 +-
 elf/setup-vdso.h                              |   3 +
 elf/tst-rtld-list-tunables.exp                |   1 +
 include/dlfcn.h                               |   2 +
 include/link.h                                |   6 +
 manual/memory.texi                            |  66 ++++
 manual/tunables.texi                          |  42 +++
 misc/unwind-link.c                            |   5 +-
 string/strerrorname_np.c                      |   1 +
 sysdeps/generic/dl-mseal.h                    |  25 ++
 sysdeps/generic/ldsodefs.h                    |   6 +
 sysdeps/unix/sysv/linux/Makefile              |  48 +++
 sysdeps/unix/sysv/linux/Versions              |   3 +
 .../unix/sysv/linux/aarch64/arch-syscall.h    |   1 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |   1 +
 sysdeps/unix/sysv/linux/alpha/arch-syscall.h  |   1 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/arc/arch-syscall.h    |   1 +
 sysdeps/unix/sysv/linux/arc/libc.abilist      |   1 +
 sysdeps/unix/sysv/linux/arm/arch-syscall.h    |   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/arch-syscall.h   |   1 +
 sysdeps/unix/sysv/linux/csky/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/dl-execstack.c        |  25 +-
 sysdeps/unix/sysv/linux/dl-mseal.c            |  51 ++++
 sysdeps/unix/sysv/linux/dl-mseal.h            |  29 ++
 sysdeps/unix/sysv/linux/hppa/arch-syscall.h   |   1 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/i386/arch-syscall.h   |   1 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/kernel-features.h     |   8 +
 sysdeps/unix/sysv/linux/lib-tst-dl_mseal-1.c  |  19 ++
 sysdeps/unix/sysv/linux/lib-tst-dl_mseal-2.c  |  19 ++
 .../sysv/linux/lib-tst-dl_mseal-dlopen-1-1.c  |  19 ++
 .../sysv/linux/lib-tst-dl_mseal-dlopen-1.c    |  19 ++
 .../sysv/linux/lib-tst-dl_mseal-dlopen-2-1.c  |  19 ++
 .../sysv/linux/lib-tst-dl_mseal-dlopen-2.c    |  19 ++
 .../sysv/linux/lib-tst-dl_mseal-preload.c     |  19 ++
 .../unix/sysv/linux/loongarch/arch-syscall.h  |   1 +
 .../sysv/linux/loongarch/lp64/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/m68k/arch-syscall.h   |   1 +
 .../sysv/linux/m68k/coldfire/libc.abilist     |   1 +
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |   1 +
 .../unix/sysv/linux/microblaze/arch-syscall.h |   1 +
 .../sysv/linux/microblaze/be/libc.abilist     |   1 +
 .../sysv/linux/microblaze/le/libc.abilist     |   1 +
 .../sysv/linux/mips/mips32/arch-syscall.h     |   1 +
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |   1 +
 .../sysv/linux/mips/mips64/n32/arch-syscall.h |   1 +
 .../sysv/linux/mips/mips64/n32/libc.abilist   |   1 +
 .../sysv/linux/mips/mips64/n64/arch-syscall.h |   1 +
 .../sysv/linux/mips/mips64/n64/libc.abilist   |   1 +
 sysdeps/unix/sysv/linux/nios2/arch-syscall.h  |   1 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/or1k/arch-syscall.h   |   1 +
 sysdeps/unix/sysv/linux/or1k/libc.abilist     |   1 +
 .../linux/powerpc/powerpc32/arch-syscall.h    |   1 +
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |   1 +
 .../powerpc/powerpc32/nofpu/libc.abilist      |   1 +
 .../linux/powerpc/powerpc64/arch-syscall.h    |   1 +
 .../linux/powerpc/powerpc64/be/libc.abilist   |   1 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |   1 +
 .../unix/sysv/linux/riscv/rv32/arch-syscall.h |   1 +
 .../unix/sysv/linux/riscv/rv32/libc.abilist   |   1 +
 .../unix/sysv/linux/riscv/rv64/arch-syscall.h |   1 +
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |   1 +
 .../sysv/linux/s390/s390-32/arch-syscall.h    |   1 +
 .../unix/sysv/linux/s390/s390-32/libc.abilist |   1 +
 .../sysv/linux/s390/s390-64/arch-syscall.h    |   1 +
 .../unix/sysv/linux/s390/s390-64/libc.abilist |   1 +
 sysdeps/unix/sysv/linux/sh/arch-syscall.h     |   1 +
 sysdeps/unix/sysv/linux/sh/be/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/sh/le/libc.abilist    |   1 +
 .../sysv/linux/sparc/sparc32/arch-syscall.h   |   1 +
 .../sysv/linux/sparc/sparc32/libc.abilist     |   1 +
 .../sysv/linux/sparc/sparc64/arch-syscall.h   |   1 +
 .../sysv/linux/sparc/sparc64/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/syscall-names.list    |   1 +
 sysdeps/unix/sysv/linux/syscalls.list         |   1 +
 .../unix/sysv/linux/tst-dl_mseal-auditmod.c   |  23 ++
 sysdeps/unix/sysv/linux/tst-dl_mseal-static.c |   2 +
 sysdeps/unix/sysv/linux/tst-dl_mseal.c        | 283 ++++++++++++++++++
 sysdeps/unix/sysv/linux/tst-mseal.c           |  67 +++++
 .../unix/sysv/linux/x86_64/64/arch-syscall.h  |   1 +
 .../unix/sysv/linux/x86_64/64/libc.abilist    |   1 +
 .../unix/sysv/linux/x86_64/x32/arch-syscall.h |   1 +
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |   1 +
 96 files changed, 993 insertions(+), 65 deletions(-)
 create mode 100644 elf/dl-mseal-mode.h
 create mode 100644 sysdeps/generic/dl-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/lib-tst-dl_mseal-1.c
 create mode 100644 sysdeps/unix/sysv/linux/lib-tst-dl_mseal-2.c
 create mode 100644 sysdeps/unix/sysv/linux/lib-tst-dl_mseal-dlopen-1-1.c
 create mode 100644 sysdeps/unix/sysv/linux/lib-tst-dl_mseal-dlopen-1.c
 create mode 100644 sysdeps/unix/sysv/linux/lib-tst-dl_mseal-dlopen-2-1.c
 create mode 100644 sysdeps/unix/sysv/linux/lib-tst-dl_mseal-dlopen-2.c
 create mode 100644 sysdeps/unix/sysv/linux/lib-tst-dl_mseal-preload.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-auditmod.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