[PATCH v2 3/8] selftests/mm: Test that the seal on system mappings is enforced
Chris Down
chris at chrisdown.name
Tue Nov 3 07:18:15 PST 2026
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 at 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
More information about the linux-riscv
mailing list