* [PATCH v2 1/8] selftests/mm: Move sysmap_is_sealed into mm
2026-11-03 15:17 [PATCH v2 0/8] mseal sysmap: Choose system mapping sealing at boot Chris Down
@ 2026-11-03 15:17 ` Chris Down
2026-11-03 15:18 ` [PATCH v2 2/8] selftests/mm: Skip sysmap_is_sealed when system mappings aren't sealed Chris Down
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Chris Down @ 2026-11-03 15:17 UTC (permalink / raw)
To: Andrew Morton, Liam R. Howlett, Lorenzo Stoakes
Cc: Jeff Xu, David Hildenbrand, Vlastimil Babka, Jann Horn,
Pedro Falcato, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Kees Cook, Andrey Vagin, Alexander Mikhalitsyn, Shuah Khan,
Oleg Nesterov, Masami Hiramatsu, Peter Zijlstra, Jiri Olsa,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Catalin Marinas, Will Deacon,
Mark Rutland, Huacai Chen, WANG Xuerui, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Vincenzo Frascino, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Randy Dunlap, linux-mm,
linux-hardening, linux-kselftest, linux-doc,
linux-security-module, linux-trace-kernel, x86, linux-arm-kernel,
loongarch, linux-riscv, linux-s390, linux-kernel, kernel-team
System mapping sealing is an mm feature, but its test has its own
directory under tools/testing/selftests rather than living with the
other mm tests.
Let's move it into tools/testing/selftests/mm and run it with the mmap
tests. Its config now comes from mm's config fragment. The test itself
is unchanged.
Suggested-by: Lorenzo Stoakes <ljs@kernel.org>
Signed-off-by: Chris Down <chris@chrisdown.name>
---
tools/testing/selftests/Makefile | 1 -
tools/testing/selftests/mm/Makefile | 1 +
tools/testing/selftests/mm/config | 1 +
tools/testing/selftests/mm/run_vmtests.sh | 1 +
.../{mseal_system_mappings => mm}/sysmap_is_sealed.c | 0
tools/testing/selftests/mseal_system_mappings/.gitignore | 2 --
tools/testing/selftests/mseal_system_mappings/Makefile | 6 ------
tools/testing/selftests/mseal_system_mappings/config | 1 -
8 files changed, 3 insertions(+), 10 deletions(-)
rename tools/testing/selftests/{mseal_system_mappings => mm}/sysmap_is_sealed.c (100%)
delete mode 100644 tools/testing/selftests/mseal_system_mappings/.gitignore
delete mode 100644 tools/testing/selftests/mseal_system_mappings/Makefile
delete mode 100644 tools/testing/selftests/mseal_system_mappings/config
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 07c3719f8b04..94276b1310de 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -84,7 +84,6 @@ TARGETS += mount
TARGETS += mount_setattr
TARGETS += move_mount_set_group
TARGETS += mqueue
-TARGETS += mseal_system_mappings
TARGETS += nci
TARGETS += net
TARGETS += net/af_unix
diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
index 675ec57d47de..94e305643c8d 100644
--- a/tools/testing/selftests/mm/Makefile
+++ b/tools/testing/selftests/mm/Makefile
@@ -110,6 +110,7 @@ TEST_GEN_FILES += folio_order_check
TEST_GEN_FILES += khugepaged_sync_check
TEST_GEN_FILES += khugepaged_race
TEST_GEN_FILES += soft-dirty
+TEST_GEN_FILES += sysmap_is_sealed
ifeq ($(ARCH),x86_64)
CAN_BUILD_I386 := $(shell ./../x86/check_cc.sh "$(CC)" ../x86/trivial_32bit_program.c -m32)
diff --git a/tools/testing/selftests/mm/config b/tools/testing/selftests/mm/config
index 06f78bd232e2..b93b49cd675f 100644
--- a/tools/testing/selftests/mm/config
+++ b/tools/testing/selftests/mm/config
@@ -14,3 +14,4 @@ CONFIG_UPROBES=y
CONFIG_MEMORY_FAILURE=y
CONFIG_HWPOISON_INJECT=m
CONFIG_PROC_MEM_ALWAYS_FORCE=y
+CONFIG_MSEAL_SYSTEM_MAPPINGS=y
diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh
index 973cb715b326..573da5006268 100755
--- a/tools/testing/selftests/mm/run_vmtests.sh
+++ b/tools/testing/selftests/mm/run_vmtests.sh
@@ -307,6 +307,7 @@ fi
CATEGORY="mmap" run_test ./map_populate
CATEGORY="mmap" run_test ./droppable
+CATEGORY="mmap" run_test ./sysmap_is_sealed
CATEGORY="mlock" run_test ./mlock-random-test
diff --git a/tools/testing/selftests/mseal_system_mappings/sysmap_is_sealed.c b/tools/testing/selftests/mm/sysmap_is_sealed.c
similarity index 100%
rename from tools/testing/selftests/mseal_system_mappings/sysmap_is_sealed.c
rename to tools/testing/selftests/mm/sysmap_is_sealed.c
diff --git a/tools/testing/selftests/mseal_system_mappings/.gitignore b/tools/testing/selftests/mseal_system_mappings/.gitignore
deleted file mode 100644
index 319c497a595e..000000000000
--- a/tools/testing/selftests/mseal_system_mappings/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-sysmap_is_sealed
diff --git a/tools/testing/selftests/mseal_system_mappings/Makefile b/tools/testing/selftests/mseal_system_mappings/Makefile
deleted file mode 100644
index 2b4504e2f52f..000000000000
--- a/tools/testing/selftests/mseal_system_mappings/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-CFLAGS += -std=c99 -pthread -Wall $(KHDR_INCLUDES)
-
-TEST_GEN_PROGS := sysmap_is_sealed
-
-include ../lib.mk
diff --git a/tools/testing/selftests/mseal_system_mappings/config b/tools/testing/selftests/mseal_system_mappings/config
deleted file mode 100644
index 675cb9f37b86..000000000000
--- a/tools/testing/selftests/mseal_system_mappings/config
+++ /dev/null
@@ -1 +0,0 @@
-CONFIG_MSEAL_SYSTEM_MAPPINGS=y
--
2.54.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v2 2/8] selftests/mm: Skip sysmap_is_sealed when system mappings aren't sealed
2026-11-03 15:17 [PATCH v2 0/8] mseal sysmap: Choose system mapping sealing at boot Chris Down
2026-11-03 15:17 ` [PATCH v2 1/8] selftests/mm: Move sysmap_is_sealed into mm Chris Down
@ 2026-11-03 15:18 ` Chris Down
2026-11-03 15:18 ` [PATCH v2 3/8] selftests/mm: Test that the seal on system mappings is enforced Chris Down
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Chris Down @ 2026-11-03 15:18 UTC (permalink / raw)
To: Andrew Morton, Liam R. Howlett, Lorenzo Stoakes
Cc: Jeff Xu, David Hildenbrand, Vlastimil Babka, Jann Horn,
Pedro Falcato, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Kees Cook, Andrey Vagin, Alexander Mikhalitsyn, Shuah Khan,
Oleg Nesterov, Masami Hiramatsu, Peter Zijlstra, Jiri Olsa,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Catalin Marinas, Will Deacon,
Mark Rutland, Huacai Chen, WANG Xuerui, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Vincenzo Frascino, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Randy Dunlap, linux-mm,
linux-hardening, linux-kselftest, linux-doc,
linux-security-module, linux-trace-kernel, x86, linux-arm-kernel,
loongarch, linux-riscv, linux-s390, linux-kernel, kernel-team
Now that sysmap_is_sealed runs with the other mm tests, it also runs on
kernels built without CONFIG_MSEAL_SYSTEM_MAPPINGS, where it fails.
Userspace can't tell whether the option is enabled, but a sealed [vdso]
in a new process means that it is.
So let's use [vdso] as the reference: skip if it isn't sealed, and
otherwise expect the other system mappings to be sealed too, and [stack]
not to be.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
tools/testing/selftests/mm/run_vmtests.sh | 7 +++++-
tools/testing/selftests/mm/sysmap_is_sealed.c | 22 +++++++++++++++++++
tools/testing/selftests/mm/vm_util.c | 5 +++++
tools/testing/selftests/mm/vm_util.h | 1 +
4 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh
index 573da5006268..1134a2e82610 100755
--- a/tools/testing/selftests/mm/run_vmtests.sh
+++ b/tools/testing/selftests/mm/run_vmtests.sh
@@ -307,7 +307,12 @@ fi
CATEGORY="mmap" run_test ./map_populate
CATEGORY="mmap" run_test ./droppable
-CATEGORY="mmap" run_test ./sysmap_is_sealed
+if gzip -dcfq /proc/config.gz "/boot/config-$(uname -r)" 2>/dev/null |
+ grep -q "^CONFIG_MSEAL_SYSTEM_MAPPINGS=y"; then
+ CATEGORY="mmap" run_test ./sysmap_is_sealed
+else
+ CATEGORY="mmap" run_test ./sysmap_is_sealed -T expect_sealed
+fi
CATEGORY="mlock" run_test ./mlock-random-test
diff --git a/tools/testing/selftests/mm/sysmap_is_sealed.c b/tools/testing/selftests/mm/sysmap_is_sealed.c
index cb0ca6ed7ebe..d5ab2b0d8ca7 100644
--- a/tools/testing/selftests/mm/sysmap_is_sealed.c
+++ b/tools/testing/selftests/mm/sysmap_is_sealed.c
@@ -10,9 +10,11 @@
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
+#include <sys/auxv.h>
#include "kselftest.h"
#include "kselftest_harness.h"
+#include "vm_util.h"
#define VMFLAGS "VmFlags:"
#define MSEAL_FLAGS "sl"
@@ -46,6 +48,23 @@ bool mapping_is_sealed(char *name, FILE *maps)
return false;
}
+static bool sysmaps_sealed(void)
+{
+ void *vdso = (void *)getauxval(AT_SYSINFO_EHDR);
+
+ return vdso && check_vmflag_sealed(vdso);
+}
+
+/*
+ * Kernels built without CONFIG_MSEAL_SYSTEM_MAPPINGS don't seal system
+ * mappings either, so check_sealed skips if they aren't sealed. This fails
+ * instead, so run_vmtests.sh only runs it when that's set.
+ */
+TEST(expect_sealed)
+{
+ EXPECT_TRUE(sysmaps_sealed());
+}
+
FIXTURE(basic) {
FILE *maps;
};
@@ -107,6 +126,9 @@ FIXTURE_VARIANT_ADD(basic, stack) {
TEST_F(basic, check_sealed)
{
+ if (!sysmaps_sealed())
+ SKIP(return, "system mappings are not sealed");
+
if (!has_mapping(variant->name, self->maps)) {
SKIP(return, "could not find the mapping, %s",
variant->name);
diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
index 8ef226107d78..6732f76b7e61 100644
--- a/tools/testing/selftests/mm/vm_util.c
+++ b/tools/testing/selftests/mm/vm_util.c
@@ -785,6 +785,11 @@ bool check_vmflag_guard(void *addr)
return check_vmflag(addr, "gu");
}
+bool check_vmflag_sealed(void *addr)
+{
+ return check_vmflag(addr, "sl");
+}
+
bool softdirty_supported(void)
{
char *addr;
diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h
index d32cb79d9905..0e94793b0d21 100644
--- a/tools/testing/selftests/mm/vm_util.h
+++ b/tools/testing/selftests/mm/vm_util.h
@@ -117,6 +117,7 @@ int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len,
bool check_vmflag_io(void *addr);
bool check_vmflag_pfnmap(void *addr);
bool check_vmflag_guard(void *addr);
+bool check_vmflag_sealed(void *addr);
int open_procmap(pid_t pid, struct procmap_fd *procmap_out);
int query_procmap(struct procmap_fd *procmap);
bool find_vma_procmap(struct procmap_fd *procmap, void *address);
--
2.54.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v2 3/8] selftests/mm: Test that the seal on system mappings is enforced
2026-11-03 15:17 [PATCH v2 0/8] mseal sysmap: Choose system mapping sealing at boot Chris Down
2026-11-03 15:17 ` [PATCH v2 1/8] selftests/mm: Move sysmap_is_sealed into mm Chris Down
2026-11-03 15:18 ` [PATCH v2 2/8] selftests/mm: Skip sysmap_is_sealed when system mappings aren't sealed Chris Down
@ 2026-11-03 15:18 ` Chris Down
2026-11-03 15:18 ` [PATCH v2 4/8] mm/mseal: Move MSEAL_SYSTEM_MAPPINGS to mm/Kconfig Chris Down
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Chris Down @ 2026-11-03 15:18 UTC (permalink / raw)
To: Andrew Morton, Liam R. Howlett, Lorenzo Stoakes
Cc: Jeff Xu, David Hildenbrand, Vlastimil Babka, Jann Horn,
Pedro Falcato, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Kees Cook, Andrey Vagin, Alexander Mikhalitsyn, Shuah Khan,
Oleg Nesterov, Masami Hiramatsu, Peter Zijlstra, Jiri Olsa,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Catalin Marinas, Will Deacon,
Mark Rutland, Huacai Chen, WANG Xuerui, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Vincenzo Frascino, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Randy Dunlap, linux-mm,
linux-hardening, linux-kselftest, linux-doc,
linux-security-module, linux-trace-kernel, x86, linux-arm-kernel,
loongarch, linux-riscv, linux-s390, linux-kernel, kernel-team
sysmap_is_sealed checks that system mappings are marked as sealed in
smaps, but not that the seal is actually enforced. The rest of this
series changes how system mappings get sealed, so let's make sure that
is covered first.
Add tests that munmap(), mremap() and mprotect() of [vdso] fail with
EPERM when it's sealed, and succeed when it isn't.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
tools/testing/selftests/mm/sysmap_is_sealed.c | 101 ++++++++++++++++++
1 file changed, 101 insertions(+)
diff --git a/tools/testing/selftests/mm/sysmap_is_sealed.c b/tools/testing/selftests/mm/sysmap_is_sealed.c
index d5ab2b0d8ca7..bfa140e01d8a 100644
--- a/tools/testing/selftests/mm/sysmap_is_sealed.c
+++ b/tools/testing/selftests/mm/sysmap_is_sealed.c
@@ -11,6 +11,7 @@
#include <string.h>
#include <stdbool.h>
#include <sys/auxv.h>
+#include <sys/mman.h>
#include "kselftest.h"
#include "kselftest_harness.h"
@@ -138,4 +139,104 @@ TEST_F(basic, check_sealed)
mapping_is_sealed(variant->name, self->maps));
};
+static void *find_vdso(struct procmap_fd *procmap, size_t *size)
+{
+ void *vdso = (void *)getauxval(AT_SYSINFO_EHDR);
+
+ if (!vdso || !find_vma_procmap(procmap, vdso))
+ return NULL;
+ *size = procmap->query.vma_end - procmap->query.vma_start;
+ return (void *)(uintptr_t)procmap->query.vma_start;
+}
+
+/*
+ * When [vdso] isn't sealed, these leave libc with a vDSO which it can't use,
+ * which is fine since each test runs in its own child. Skip if AT_SYSINFO
+ * is set, since libc may also use the vDSO for syscalls.
+ */
+TEST(vdso_munmap)
+{
+ struct procmap_fd procmap;
+ bool sealed;
+ size_t size;
+ void *vdso;
+ int ret;
+
+ ASSERT_EQ(0, open_self_procmap(&procmap));
+ vdso = find_vdso(&procmap, &size);
+ if (!vdso)
+ SKIP(return, "could not find the mapping, [vdso]");
+ sealed = check_vmflag_sealed(vdso);
+ if (!sealed && getauxval(AT_SYSINFO))
+ SKIP(return, "libc makes syscalls through the vDSO");
+
+ ret = munmap(vdso, size);
+ if (sealed) {
+ EXPECT_EQ(-1, ret);
+ EXPECT_EQ(EPERM, errno);
+ } else {
+ EXPECT_EQ(0, ret);
+ }
+ EXPECT_EQ(sealed, find_vma_procmap(&procmap, vdso));
+ close_procmap(&procmap);
+}
+
+TEST(vdso_mremap)
+{
+ struct procmap_fd procmap;
+ void *vdso, *dst, *ret;
+ bool sealed;
+ size_t size;
+
+ ASSERT_EQ(0, open_self_procmap(&procmap));
+ vdso = find_vdso(&procmap, &size);
+ if (!vdso)
+ SKIP(return, "could not find the mapping, [vdso]");
+ sealed = check_vmflag_sealed(vdso);
+ if (!sealed && getauxval(AT_SYSINFO))
+ SKIP(return, "libc makes syscalls through the vDSO");
+
+ dst = mmap(NULL, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ ASSERT_NE(MAP_FAILED, dst);
+
+ ret = mremap(vdso, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, dst);
+ if (sealed) {
+ EXPECT_EQ(MAP_FAILED, ret);
+ EXPECT_EQ(EPERM, errno);
+ } else {
+ EXPECT_EQ(dst, ret);
+ }
+ EXPECT_EQ(sealed, find_vma_procmap(&procmap, vdso));
+ close_procmap(&procmap);
+}
+
+TEST(vdso_mprotect)
+{
+ struct procmap_fd procmap;
+ bool sealed;
+ size_t size;
+ void *vdso;
+ int ret;
+
+ ASSERT_EQ(0, open_self_procmap(&procmap));
+ vdso = find_vdso(&procmap, &size);
+ if (!vdso)
+ SKIP(return, "could not find the mapping, [vdso]");
+ sealed = check_vmflag_sealed(vdso);
+ if (!sealed && getauxval(AT_SYSINFO))
+ SKIP(return, "libc makes syscalls through the vDSO");
+
+ ret = mprotect(vdso, size, PROT_READ | PROT_WRITE);
+ if (sealed) {
+ EXPECT_EQ(-1, ret);
+ EXPECT_EQ(EPERM, errno);
+ } else {
+ EXPECT_EQ(0, ret);
+ }
+ ASSERT_TRUE(find_vma_procmap(&procmap, vdso));
+ EXPECT_EQ(sealed,
+ !(procmap.query.vma_flags & PROCMAP_QUERY_VMA_WRITABLE));
+ close_procmap(&procmap);
+}
+
TEST_HARNESS_MAIN
--
2.54.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v2 4/8] mm/mseal: Move MSEAL_SYSTEM_MAPPINGS to mm/Kconfig
2026-11-03 15:17 [PATCH v2 0/8] mseal sysmap: Choose system mapping sealing at boot Chris Down
` (2 preceding siblings ...)
2026-11-03 15:18 ` [PATCH v2 3/8] selftests/mm: Test that the seal on system mappings is enforced Chris Down
@ 2026-11-03 15:18 ` Chris Down
2026-11-03 15:18 ` [PATCH v2 5/8] uprobes/x86: Leave sealed trampolines in place on optimisation failure Chris Down
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Chris Down @ 2026-11-03 15:18 UTC (permalink / raw)
To: Andrew Morton, Liam R. Howlett, Lorenzo Stoakes
Cc: Jeff Xu, David Hildenbrand, Vlastimil Babka, Jann Horn,
Pedro Falcato, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Kees Cook, Andrey Vagin, Alexander Mikhalitsyn, Shuah Khan,
Oleg Nesterov, Masami Hiramatsu, Peter Zijlstra, Jiri Olsa,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Catalin Marinas, Will Deacon,
Mark Rutland, Huacai Chen, WANG Xuerui, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Vincenzo Frascino, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Randy Dunlap, linux-mm,
linux-hardening, linux-kselftest, linux-doc,
linux-security-module, linux-trace-kernel, x86, linux-arm-kernel,
loongarch, linux-riscv, linux-s390, linux-kernel, kernel-team
MSEAL_SYSTEM_MAPPINGS is in security/Kconfig, but it's an mm feature,
it's implemented in mm, and changes to it need to go past mm.
Let's move it to mm/Kconfig, next to the other VMA features. No
functional change.
Suggested-by: Lorenzo Stoakes <ljs@kernel.org>
Signed-off-by: Chris Down <chris@chrisdown.name>
---
mm/Kconfig | 21 +++++++++++++++++++++
security/Kconfig | 21 ---------------------
2 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/mm/Kconfig b/mm/Kconfig
index afff1b25b543..40172787dfa7 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -1355,6 +1355,27 @@ config ANON_VMA_NAME
area from being merged with adjacent virtual memory areas due to the
difference in their name.
+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.
+
+ 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.
+
+ For complete descriptions of memory sealing, please see
+ Documentation/userspace-api/mseal.rst
+
config HAVE_ARCH_USERFAULTFD_WP
bool
help
diff --git a/security/Kconfig b/security/Kconfig
index f7bf6cdc6229..1679e8d009c3 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -49,27 +49,6 @@ config PROC_MEM_NO_FORCE
endchoice
-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.
-
- 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.
-
- For complete descriptions of memory sealing, please see
- Documentation/userspace-api/mseal.rst
-
config SECURITY
bool "Enable different security models"
depends on SYSFS
--
2.54.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v2 5/8] uprobes/x86: Leave sealed trampolines in place on optimisation failure
2026-11-03 15:17 [PATCH v2 0/8] mseal sysmap: Choose system mapping sealing at boot Chris Down
` (3 preceding siblings ...)
2026-11-03 15:18 ` [PATCH v2 4/8] mm/mseal: Move MSEAL_SYSTEM_MAPPINGS to mm/Kconfig Chris Down
@ 2026-11-03 15:18 ` Chris Down
2026-11-03 15:18 ` [PATCH v2 6/8] mm/mseal: Seal system mappings in __install_special_mapping() Chris Down
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Chris Down @ 2026-11-03 15:18 UTC (permalink / raw)
To: Andrew Morton, Liam R. Howlett, Lorenzo Stoakes
Cc: Jeff Xu, David Hildenbrand, Vlastimil Babka, Jann Horn,
Pedro Falcato, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Kees Cook, Andrey Vagin, Alexander Mikhalitsyn, Shuah Khan,
Oleg Nesterov, Masami Hiramatsu, Peter Zijlstra, Jiri Olsa,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Catalin Marinas, Will Deacon,
Mark Rutland, Huacai Chen, WANG Xuerui, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Vincenzo Frascino, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Randy Dunlap, linux-mm,
linux-hardening, linux-kselftest, linux-doc,
linux-security-module, linux-trace-kernel, x86, linux-arm-kernel,
loongarch, linux-riscv, linux-s390, linux-kernel, kernel-team
If swbp_optimize() fails, __arch_uprobe_optimize() unmaps the
trampoline it has just created. The next patch seals all special
mappings when CONFIG_MSEAL_SYSTEM_MAPPINGS is enabled, which includes
uprobe trampolines, and then this do_munmap() would fail with -EPERM
and warn a second time.
Nothing is really leaked if we leave the trampoline mapped in that
case, since get_uprobe_trampoline() reuses any existing trampoline
which is in reach of the probe. So let's just leave it in place when
it's sealed.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
arch/x86/kernel/uprobes.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index 0f60c0d076b6..fb895bfc09e0 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -1183,7 +1183,7 @@ static int __arch_uprobe_optimize(struct arch_uprobe *auprobe, struct mm_struct
if (IS_ERR(tramp))
return PTR_ERR(tramp);
ret = swbp_optimize(auprobe, vma, vaddr, tramp->vm_start);
- if (WARN_ON_ONCE(ret) && new_mapping)
+ if (WARN_ON_ONCE(ret) && new_mapping && !vma_test(tramp, VMA_SEALED_BIT))
WARN_ON_ONCE(do_munmap(mm, tramp->vm_start, PAGE_SIZE, NULL));
return ret;
}
--
2.54.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v2 6/8] mm/mseal: Seal system mappings in __install_special_mapping()
2026-11-03 15:17 [PATCH v2 0/8] mseal sysmap: Choose system mapping sealing at boot Chris Down
` (4 preceding siblings ...)
2026-11-03 15:18 ` [PATCH v2 5/8] uprobes/x86: Leave sealed trampolines in place on optimisation failure Chris Down
@ 2026-11-03 15:18 ` Chris Down
2026-11-03 15:18 ` [PATCH v2 7/8] mm/mseal: Add no_mseal_sys_mappings boot parameter Chris Down
2026-11-03 15:19 ` [PATCH v2 8/8] selftests/mm: Check that no_mseal_sys_mappings unseals system mappings Chris Down
7 siblings, 0 replies; 9+ messages in thread
From: Chris Down @ 2026-11-03 15:18 UTC (permalink / raw)
To: Andrew Morton, Liam R. Howlett, Lorenzo Stoakes
Cc: Jeff Xu, David Hildenbrand, Vlastimil Babka, Jann Horn,
Pedro Falcato, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Kees Cook, Andrey Vagin, Alexander Mikhalitsyn, Shuah Khan,
Oleg Nesterov, Masami Hiramatsu, Peter Zijlstra, Jiri Olsa,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Catalin Marinas, Will Deacon,
Mark Rutland, Huacai Chen, WANG Xuerui, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Vincenzo Frascino, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Randy Dunlap, linux-mm,
linux-hardening, linux-kselftest, linux-doc,
linux-security-module, linux-trace-kernel, x86, linux-arm-kernel,
loongarch, linux-riscv, linux-s390, linux-kernel, kernel-team
VM_SEALED_SYSMAP isn't really a VMA flag, it's an alias for VM_SEALED or
VM_NONE depending on CONFIG_MSEAL_SYSTEM_MAPPINGS. Every caller of
_install_special_mapping() on an architecture which supports sealing
system mappings has to remember to pass it, and it keeps those callers
on the legacy vm_flags_t API.
Let's instead have __install_special_mapping() seal the mapping itself
when mseal_system_mappings() says so, and remove VM_SEALED_SYSMAP.
The only special mapping on these architectures which didn't already
pass VM_SEALED_SYSMAP is the x86 uprobe trampoline, which is now sealed
as well. The previous patch makes sure that's safe.
Since this seals all special mappings, the architecture opt-in now
requires that none of them are moved or unmapped.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
Documentation/userspace-api/mseal.rst | 3 ++-
arch/arm64/kernel/vdso.c | 9 +++------
arch/loongarch/kernel/vdso.c | 3 +--
arch/riscv/kernel/vdso.c | 2 +-
arch/s390/kernel/vdso.c | 2 +-
arch/x86/entry/vdso/vma.c | 5 ++---
include/linux/mm.h | 6 ------
init/Kconfig | 5 ++---
kernel/events/uprobes.c | 2 +-
lib/vdso/datastore.c | 2 +-
mm/Kconfig | 3 ++-
mm/vma.c | 2 ++
mm/vma.h | 5 +++++
13 files changed, 23 insertions(+), 26 deletions(-)
diff --git a/Documentation/userspace-api/mseal.rst b/Documentation/userspace-api/mseal.rst
index c039d782f9f5..060c9829306b 100644
--- a/Documentation/userspace-api/mseal.rst
+++ b/Documentation/userspace-api/mseal.rst
@@ -133,7 +133,8 @@ Use cases
- System mappings:
The system mappings are created by the kernel and include vdso, vvar,
- vvar_vclock, vectors (arm compat-mode), sigpage (arm compat-mode), uprobes.
+ vvar_vclock, vectors (arm compat-mode), sigpage (arm compat-mode), uprobes,
+ uprobe trampolines (x86).
Those system mappings are readonly only or execute only, memory sealing can
protect them from ever changing to writable or unmapped/remapped as different
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 50596dab23f9..542adc47cd02 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -127,8 +127,7 @@ static int __setup_additional_pages(enum vdso_abi abi,
mm->context.vdso = (void *)vdso_base;
ret = _install_special_mapping(mm, vdso_base, vdso_text_len,
VM_READ|VM_EXEC|gp_flags|
- VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
- VM_SEALED_SYSMAP,
+ VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
vdso_info[abi].cm);
if (IS_ERR(ret))
goto up_fail;
@@ -254,8 +253,7 @@ static int aarch32_kuser_helpers_setup(struct mm_struct *mm)
*/
ret = _install_special_mapping(mm, AARCH32_VECTORS_BASE, PAGE_SIZE,
VM_READ | VM_EXEC |
- VM_MAYREAD | VM_MAYEXEC |
- VM_SEALED_SYSMAP,
+ VM_MAYREAD | VM_MAYEXEC,
&aarch32_vdso_maps[AA32_MAP_VECTORS]);
return PTR_ERR_OR_ZERO(ret);
@@ -278,8 +276,7 @@ static int aarch32_sigreturn_setup(struct mm_struct *mm)
*/
ret = _install_special_mapping(mm, addr, PAGE_SIZE,
VM_READ | VM_EXEC | VM_MAYREAD |
- VM_MAYWRITE | VM_MAYEXEC |
- VM_SEALED_SYSMAP,
+ VM_MAYWRITE | VM_MAYEXEC,
&aarch32_vdso_maps[AA32_MAP_SIGPAGE]);
if (IS_ERR(ret))
goto out;
diff --git a/arch/loongarch/kernel/vdso.c b/arch/loongarch/kernel/vdso.c
index 1edc8fb720de..c9ffc124bfb1 100644
--- a/arch/loongarch/kernel/vdso.c
+++ b/arch/loongarch/kernel/vdso.c
@@ -109,8 +109,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
vdso_addr = data_addr + VVAR_SIZE;
vma = _install_special_mapping(mm, vdso_addr, info->size,
VM_READ | VM_EXEC |
- VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC |
- VM_SEALED_SYSMAP,
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
&info->code_mapping);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c
index 5666cec180ac..4213de6afb9a 100644
--- a/arch/riscv/kernel/vdso.c
+++ b/arch/riscv/kernel/vdso.c
@@ -140,7 +140,7 @@ static int __setup_additional_pages(struct mm_struct *mm,
ret =
_install_special_mapping(mm, vdso_base, vdso_text_len,
- (VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC | VM_SEALED_SYSMAP),
+ (VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC),
vdso_info->cm);
if (IS_ERR(ret))
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index a905f989f910..a9dd3876e7fd 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -65,7 +65,7 @@ static int map_vdso(unsigned long addr, unsigned long vdso_mapping_len)
vdso_text_start = vvar_start + VDSO_NR_PAGES * PAGE_SIZE;
/* VM_MAYWRITE for COW so gdb can set breakpoints */
vma = _install_special_mapping(mm, vdso_text_start, vdso_text_len,
- VM_READ|VM_EXEC|VM_SEALED_SYSMAP|
+ VM_READ|VM_EXEC|
VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
&vdso_mapping);
if (IS_ERR(vma)) {
diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index 4bd3b22beea9..e49d4e4d7b67 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -178,8 +178,7 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
text_start,
image->size,
VM_READ|VM_EXEC|
- VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
- VM_SEALED_SYSMAP,
+ VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
&vdso_mapping);
if (IS_ERR(vma)) {
@@ -198,7 +197,7 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
VDSO_VCLOCK_PAGES_START(addr),
VDSO_NR_VCLOCK_PAGES * PAGE_SIZE,
VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP|
- VM_PFNMAP|VM_SEALED_SYSMAP,
+ VM_PFNMAP,
&vvar_vclock_mapping);
if (IS_ERR(vma)) {
diff --git a/include/linux/mm.h b/include/linux/mm.h
index d89e6f823c9f..09c047dc9faf 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -567,12 +567,6 @@ enum {
/* Temporary until VMA flags conversion complete. */
#define VM_STACK_FLAGS vma_flags_to_legacy(VMA_STACK_FLAGS)
-#ifdef CONFIG_MSEAL_SYSTEM_MAPPINGS
-#define VM_SEALED_SYSMAP VM_SEALED
-#else
-#define VM_SEALED_SYSMAP VM_NONE
-#endif
-
/* VMA basic access permission flags */
#define VM_ACCESS_FLAGS (VM_READ | VM_WRITE | VM_EXEC)
#define VMA_ACCESS_FLAGS mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT)
diff --git a/init/Kconfig b/init/Kconfig
index 4013781e0a02..35d349cff1a3 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1955,9 +1955,8 @@ config ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS
A 64-bit kernel is required for the memory sealing feature.
No specific hardware features from the CPU are needed.
- To enable this feature, the architecture needs to update their
- special mappings calls to include the sealing flag and confirm
- that it doesn't unmap/remap system mappings during the life
+ To enable this feature, the architecture needs to confirm that it
+ doesn't unmap/remap any of its special mappings during the life
time of the process. The existence of this flag for an architecture
implies that it does not require the remapping of the system
mappings during process lifetime, so sealing these mappings is safe
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index caf444762a27..2290a4cbebf8 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1727,7 +1727,7 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
vma = _install_special_mapping(mm, area->vaddr, PAGE_SIZE,
VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|
- VM_MIXEDMAP|VM_SEALED_SYSMAP,
+ VM_MIXEDMAP,
&xol_mapping);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c
index 1426bf4e0c12..e8933ff44aa4 100644
--- a/lib/vdso/datastore.c
+++ b/lib/vdso/datastore.c
@@ -124,6 +124,6 @@ struct vm_area_struct *vdso_install_vvar_mapping(struct mm_struct *mm, unsigned
{
return _install_special_mapping(mm, addr, VDSO_NR_PAGES * PAGE_SIZE,
VM_READ | VM_MAYREAD | VM_DONTDUMP |
- VM_MIXEDMAP | VM_SEALED_SYSMAP,
+ VM_MIXEDMAP,
&vdso_vvar_mapping);
}
diff --git a/mm/Kconfig b/mm/Kconfig
index 40172787dfa7..316515589cdb 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -1363,7 +1363,8 @@ config MSEAL_SYSTEM_MAPPINGS
help
Apply mseal on system mappings.
The system mappings includes vdso, vvar, vvar_vclock,
- vectors (arm compat-mode), sigpage (arm compat-mode), uprobes.
+ 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.
diff --git a/mm/vma.c b/mm/vma.c
index 423383d59c59..67116be0260a 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -3705,6 +3705,8 @@ struct vm_area_struct *__install_special_mapping(
vma_flags_set_mask(&vma_flags, mm->def_vma_flags);
vma_flags_set(&vma_flags, VMA_DONTEXPAND_BIT);
+ if (mseal_system_mappings())
+ vma_flags_set(&vma_flags, VMA_SEALED_BIT);
if (pgtable_supports_soft_dirty())
vma_flags_set(&vma_flags, VMA_SOFTDIRTY_BIT);
vma_flags_clear_mask(&vma_flags, VMA_LOCKED_MASK);
diff --git a/mm/vma.h b/mm/vma.h
index 3fc3b47a954b..3982b239d0b4 100644
--- a/mm/vma.h
+++ b/mm/vma.h
@@ -800,6 +800,11 @@ static inline bool vma_is_sealed(struct vm_area_struct *vma)
}
#endif
+static inline bool mseal_system_mappings(void)
+{
+ return IS_ENABLED(CONFIG_MSEAL_SYSTEM_MAPPINGS);
+}
+
#if defined(CONFIG_STACK_GROWSUP)
int expand_upwards(struct vm_area_struct *vma, unsigned long address);
#endif
--
2.54.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v2 7/8] mm/mseal: Add no_mseal_sys_mappings boot parameter
2026-11-03 15:17 [PATCH v2 0/8] mseal sysmap: Choose system mapping sealing at boot Chris Down
` (5 preceding siblings ...)
2026-11-03 15:18 ` [PATCH v2 6/8] mm/mseal: Seal system mappings in __install_special_mapping() Chris Down
@ 2026-11-03 15:18 ` Chris Down
2026-11-03 15:19 ` [PATCH v2 8/8] selftests/mm: Check that no_mseal_sys_mappings unseals system mappings Chris Down
7 siblings, 0 replies; 9+ messages in thread
From: Chris Down @ 2026-11-03 15:18 UTC (permalink / raw)
To: Andrew Morton, Liam R. Howlett, Lorenzo Stoakes
Cc: Jeff Xu, David Hildenbrand, Vlastimil Babka, Jann Horn,
Pedro Falcato, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Kees Cook, Andrey Vagin, Alexander Mikhalitsyn, Shuah Khan,
Oleg Nesterov, Masami Hiramatsu, Peter Zijlstra, Jiri Olsa,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Catalin Marinas, Will Deacon,
Mark Rutland, Huacai Chen, WANG Xuerui, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Vincenzo Frascino, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Randy Dunlap, linux-mm,
linux-hardening, linux-kselftest, linux-doc,
linux-security-module, linux-trace-kernel, x86, linux-arm-kernel,
loongarch, linux-riscv, linux-s390, linux-kernel, kernel-team
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 <chris@chrisdown.name>
---
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 <jeffxu@chromium.org>
*/
+#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
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v2 8/8] selftests/mm: Check that no_mseal_sys_mappings unseals system mappings
2026-11-03 15:17 [PATCH v2 0/8] mseal sysmap: Choose system mapping sealing at boot Chris Down
` (6 preceding siblings ...)
2026-11-03 15:18 ` [PATCH v2 7/8] mm/mseal: Add no_mseal_sys_mappings boot parameter Chris Down
@ 2026-11-03 15:19 ` Chris Down
7 siblings, 0 replies; 9+ messages in thread
From: Chris Down @ 2026-11-03 15:19 UTC (permalink / raw)
To: Andrew Morton, Liam R. Howlett, Lorenzo Stoakes
Cc: Jeff Xu, David Hildenbrand, Vlastimil Babka, Jann Horn,
Pedro Falcato, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Kees Cook, Andrey Vagin, Alexander Mikhalitsyn, Shuah Khan,
Oleg Nesterov, Masami Hiramatsu, Peter Zijlstra, Jiri Olsa,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Catalin Marinas, Will Deacon,
Mark Rutland, Huacai Chen, WANG Xuerui, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Vincenzo Frascino, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Randy Dunlap, linux-mm,
linux-hardening, linux-kselftest, linux-doc,
linux-security-module, linux-trace-kernel, x86, linux-arm-kernel,
loongarch, linux-riscv, linux-s390, linux-kernel, kernel-team
Booting with no_mseal_sys_mappings currently makes check_sealed skip and
expect_sealed fail, so nothing checks that the parameter actually turns
sealing off.
So let's check /proc/cmdline for it, and when it's there, expect [vdso]
and the other system mappings to be unsealed rather than skipping or
failing. The vdso tests already expect munmap(), mremap() and mprotect()
to succeed when [vdso] isn't sealed, so that covers what the parameter
allows as well.
Suggested-by: Jeff Xu <jeffxu@google.com>
Signed-off-by: Chris Down <chris@chrisdown.name>
---
tools/testing/selftests/mm/sysmap_is_sealed.c | 25 ++++++++++++++++---
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/mm/sysmap_is_sealed.c b/tools/testing/selftests/mm/sysmap_is_sealed.c
index bfa140e01d8a..158e116ca3b4 100644
--- a/tools/testing/selftests/mm/sysmap_is_sealed.c
+++ b/tools/testing/selftests/mm/sysmap_is_sealed.c
@@ -56,6 +56,21 @@ static bool sysmaps_sealed(void)
return vdso && check_vmflag_sealed(vdso);
}
+static bool sysmaps_disabled(void)
+{
+ char cmdline[4096];
+ bool disabled = false;
+ FILE *f;
+
+ f = fopen("/proc/cmdline", "r");
+ if (!f)
+ return false;
+ if (fgets(cmdline, sizeof(cmdline), f))
+ disabled = strstr(cmdline, "no_mseal_sys_mappings");
+ fclose(f);
+ return disabled;
+}
+
/*
* Kernels built without CONFIG_MSEAL_SYSTEM_MAPPINGS don't seal system
* mappings either, so check_sealed skips if they aren't sealed. This fails
@@ -63,7 +78,7 @@ static bool sysmaps_sealed(void)
*/
TEST(expect_sealed)
{
- EXPECT_TRUE(sysmaps_sealed());
+ EXPECT_EQ(!sysmaps_disabled(), sysmaps_sealed());
}
FIXTURE(basic) {
@@ -127,7 +142,9 @@ FIXTURE_VARIANT_ADD(basic, stack) {
TEST_F(basic, check_sealed)
{
- if (!sysmaps_sealed())
+ bool disabled = sysmaps_disabled();
+
+ if (!disabled && !sysmaps_sealed())
SKIP(return, "system mappings are not sealed");
if (!has_mapping(variant->name, self->maps)) {
@@ -135,8 +152,8 @@ TEST_F(basic, check_sealed)
variant->name);
}
- EXPECT_EQ(variant->sealed,
- mapping_is_sealed(variant->name, self->maps));
+ EXPECT_EQ(variant->sealed && !disabled,
+ mapping_is_sealed(variant->name, self->maps));
};
static void *find_vdso(struct procmap_fd *procmap, size_t *size)
--
2.54.0
^ permalink raw reply [flat|nested] 9+ messages in thread