CONFIG_MSEAL_SYSTEM_MAPPINGS seals each process' system mappings, such as the vDSO, when they are created. These are read-only or execute-only mappings which every process trusts, so sealing them means that a memory corruption bug which can pass a bad pointer to mprotect(), mremap() or munmap() can't be used to make them writable, or to move or replace them.
However, sealing can only be chosen at build time, and it breaks software which moves or modifies these mappings. This is not ideal, since hosts which want sealing and hosts which run such software then can't share a kernel. For example, at Meta, we build sealing into the kernel for our VM hosts, and we'd like it on as much of the rest of the fleet as possible. The problem is that the rest of the fleet also runs things which it breaks. As one example among many, Reverie (which our deterministic execution tool, Hermit, is built on) patches the vDSO of the processes it traces by injecting an mprotect() [0]. So right now the hosts which want sealing need their own kernel image, and this option is one of the things which forces that. So, to improve this, let's add no_mseal_sys_mappings. That way one kernel can be built with CONFIG_MSEAL_SYSTEM_MAPPINGS=y, keep sealing on by default, and turn it off only on the hosts which need it. Kernels built without the option are unchanged. Since sealing can now be turned off at boot, MSEAL_SYSTEM_MAPPINGS also no longer needs to depend on !CHECKPOINT_RESTORE. The option is off by default and already documents that it breaks CRIU, so let's drop the dependency. For the same reason, the documentation no longer needs to say that it can't be enabled universally. Link: https://docs.rs/reverie-core/latest/reverie/vdso/index.html # [0] Signed-off-by: Chris Down <[email protected]> --- Documentation/admin-guide/kernel-parameters.txt | 7 +++++++ Documentation/userspace-api/mseal.rst | 9 +++++---- mm/Kconfig | 15 ++++++++------- mm/mseal.c | 12 ++++++++++++ mm/vma.h | 5 ++++- 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 0b3c140babd9..a72904ebb98d 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4603,6 +4603,13 @@ Kernel parameters nomodule Disable module load + no_mseal_sys_mappings + [KNL,EARLY] With CONFIG_MSEAL_SYSTEM_MAPPINGS, don't + seal system mappings such as the vDSO. Sealing them + breaks software which moves, unmaps or modifies them, + such as CHECKPOINT_RESTORE (CRIU), UML, gVisor and rr. + See Documentation/userspace-api/mseal.rst. + nonmi_ipi [X86] Disable using NMI IPIs during panic/reboot to shutdown the other cpus. Instead use the REBOOT_VECTOR irq. diff --git a/Documentation/userspace-api/mseal.rst b/Documentation/userspace-api/mseal.rst index 060c9829306b..0efdc5469085 100644 --- a/Documentation/userspace-api/mseal.rst +++ b/Documentation/userspace-api/mseal.rst @@ -143,12 +143,13 @@ Use cases If supported by an architecture (CONFIG_ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS), the CONFIG_MSEAL_SYSTEM_MAPPINGS seals all system mappings of this - architecture. + architecture. The ``no_mseal_sys_mappings`` kernel command line parameter + turns this off. WARNING: This feature breaks programs which rely on relocating - or unmapping system mappings. Known broken software at the time - of writing includes CHECKPOINT_RESTORE, UML, gVisor, rr. Therefore - this config can't be enabled universally. + or unmapping system mappings. Software known to break with it + at the time of writing includes CHECKPOINT_RESTORE, UML, gVisor + and rr. When not to use mseal ===================== diff --git a/mm/Kconfig b/mm/Kconfig index 316515589cdb..bb2a60f52c8e 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -1359,24 +1359,25 @@ config MSEAL_SYSTEM_MAPPINGS bool "mseal system mappings" depends on 64BIT depends on ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS - depends on !CHECKPOINT_RESTORE help Apply mseal on system mappings. The system mappings includes vdso, vvar, vvar_vclock, vectors (arm compat-mode), sigpage (arm compat-mode), uprobes, uprobe trampolines (x86). - A 64-bit kernel is required for the memory sealing feature. - No specific hardware features from the CPU are needed. - WARNING: This feature breaks programs which rely on relocating - or unmapping system mappings. Known broken software at the time - of writing includes CHECKPOINT_RESTORE, UML, gVisor, rr. Therefore - this config can't be enabled universally. + or unmapping system mappings. Software known to break with it + at the time of writing includes CHECKPOINT_RESTORE, UML, gVisor + and rr. + + With this configuration option set, the feature can be disabled + with the no_mseal_sys_mappings boot parameter. For complete descriptions of memory sealing, please see Documentation/userspace-api/mseal.rst + If unsure, say N. + config HAVE_ARCH_USERFAULTFD_WP bool help diff --git a/mm/mseal.c b/mm/mseal.c index 7a8ac66dc215..271b44e628c5 100644 --- a/mm/mseal.c +++ b/mm/mseal.c @@ -7,6 +7,7 @@ * Author: Jeff Xu <[email protected]> */ +#include <linux/init.h> #include <linux/mempolicy.h> #include <linux/minmax.h> #include <linux/mman.h> @@ -16,6 +17,17 @@ #include <linux/sched.h> #include "internal.h" +#ifdef CONFIG_MSEAL_SYSTEM_MAPPINGS +bool mseal_system_mappings_disabled __ro_after_init; + +static int __init early_no_mseal_sys_mappings(char *buf) +{ + mseal_system_mappings_disabled = true; + return 0; +} +early_param("no_mseal_sys_mappings", early_no_mseal_sys_mappings); +#endif + static bool range_contains_unmapped(unsigned long start, unsigned long end) { VMA_ITERATOR(vmi, current->mm, start); diff --git a/mm/vma.h b/mm/vma.h index 3982b239d0b4..11ff9c7d6592 100644 --- a/mm/vma.h +++ b/mm/vma.h @@ -800,9 +800,12 @@ static inline bool vma_is_sealed(struct vm_area_struct *vma) } #endif +extern bool mseal_system_mappings_disabled; + static inline bool mseal_system_mappings(void) { - return IS_ENABLED(CONFIG_MSEAL_SYSTEM_MAPPINGS); + return IS_ENABLED(CONFIG_MSEAL_SYSTEM_MAPPINGS) && + !mseal_system_mappings_disabled; } #if defined(CONFIG_STACK_GROWSUP) -- 2.54.0
