Applying mimmutable(2) to bss, data and text made the sys/kern/noexec tests fail
authoranton <anton@openbsd.org>
Sun, 27 Nov 2022 15:12:57 +0000 (15:12 +0000)
committeranton <anton@openbsd.org>
Sun, 27 Nov 2022 15:12:57 +0000 (15:12 +0000)
since they try to mutate the permissions of the aforementioned sections which is
no longer possible. Instead, "mimic" the sections by allocating and operating on
memory with the same initial permissions.

With help from deraadt@

regress/sys/kern/noexec/Makefile
regress/sys/kern/noexec/noexec.c

index 9c78ed7..c5f16b3 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.25 2022/10/11 05:45:41 anton Exp $
+#      $OpenBSD: Makefile,v 1.26 2022/11/27 15:12:57 anton Exp $
 
 PROG=          noexec
 SRCS=          noexec.c testfly.S
@@ -12,6 +12,7 @@ REGRESS_TARGETS=      nxtext-mmap     nxtext-mprotect \
                nxheap  nxheap-mmap     nxheap-mprotect \
                nxmmap                  nxmmap-mprotect \
                nxstack nxstack-mmap    nxstack-mprotect
+REGRESS_TARGETS+=      nxmutable nxmutable-mmap nxmutable-mprotect
 .PHONY: ${REGRESS_TARGETS}
 
 nxtext-mmap: ${PROG}
@@ -62,6 +63,15 @@ nxmmap: ${PROG}
 nxmmap-mprotect: ${PROG}
        ./${PROG} -m -p
 
+nxmutable: ${PROG}
+       ./${PROG} -M
+
+nxmutable-mmap: ${PROG}
+       ./${PROG} -M -m
+
+nxmutable-mprotect: ${PROG}
+       ./${PROG} -M -p
+
 .if ${MACHINE} != "alpha" && \
     ${MACHINE} != "amd64" && \
     ${MACHINE} != "arm64" && \
index 9500823..e423146 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: noexec.c,v 1.22 2022/10/11 05:45:41 anton Exp $       */
+/*     $OpenBSD: noexec.c,v 1.23 2022/11/27 15:12:57 anton Exp $       */
 
 /*
  * Copyright (c) 2002,2003 Michael Shalayeff
@@ -49,10 +49,12 @@ int page_size;
 char label[64] = "non-exec ";
 
 #define PAD 64*1024
+#define PAGESIZE (1ULL << _MAX_PAGE_SHIFT)
 #define        MAXPAGESIZE 16384
 #define TESTSZ 256     /* assuming the testfly() will fit */
-u_int64_t data[(PAD + TESTSZ + PAD + MAXPAGESIZE) / 8] = { 0 };
-u_int64_t bss[(PAD + TESTSZ + PAD + MAXPAGESIZE) / 8];
+static u_int64_t mutable[(PAD + TESTSZ + PAD + MAXPAGESIZE) / 8]
+       __attribute__((aligned(PAGESIZE)))
+       __attribute__((section(".openbsd.mutable")));
 
 void testfly(void);
 
@@ -205,24 +207,65 @@ worker(void *arg)
        pflags = MAP_PRIVATE|MAP_ANON|MAP_FIXED;
        func = &noexec;
        size = TESTSZ;
-       while ((ch = getopt(ctx->argc, ctx->argv, "TDBHSmps:")) != -1) {
+       while ((ch = getopt(ctx->argc, ctx->argv, "TDBMHSmps:")) != -1) {
                if (p == NULL) {
                        switch (ch) {
-                       case 'T':
-                               p = &testfly;
+                       case 'T': {
+                               u_int64_t *text;
+                               size_t textsiz = TESTSZ;
+
+                               text = mmap(NULL, textsiz,
+                                   PROT_READ | PROT_WRITE,
+                                   MAP_PRIVATE | MAP_ANON, -1, 0);
+                               if (text == MAP_FAILED)
+                                       err(1, "mmap");
+                               memcpy(text, &testfly, textsiz);
+                               if (mprotect(text, textsiz,
+                                   PROT_READ | PROT_EXEC) == -1)
+                                       err(1, "mprotect");
+                               p = text;
                                pflags &=~ MAP_FIXED;
                                (void) strlcat(label, "text", sizeof(label));
                                continue;
-                       case 'D':
+                       }
+
+                       case 'D': {
+                               u_int64_t *data;
+                               size_t datasiz = (PAD + TESTSZ + PAD +
+                                   MAXPAGESIZE) / 8;
+
+                               data = mmap(NULL, datasiz,
+                                   PROT_READ | PROT_WRITE,
+                                   MAP_PRIVATE | MAP_ANON, -1, 0);
+                               if (data == MAP_FAILED)
+                                       err(1, "mmap");
                                p = &data[(PAD + page_size) / 8];
                                p = (void *)((long)p & ~(page_size - 1));
                                (void) strlcat(label, "data", sizeof(label));
                                continue;
-                       case 'B':
+                       }
+
+                       case 'B': {
+                               u_int64_t *bss;
+                               size_t bsssiz = (PAD + TESTSZ + PAD +
+                                   MAXPAGESIZE) / 8;
+
+                               bss = mmap(NULL, bsssiz,
+                                   PROT_READ | PROT_WRITE,
+                                   MAP_PRIVATE | MAP_ANON, -1, 0);
+                               if (bss == MAP_FAILED)
+                                       err(1, "mmap");
                                p = &bss[(PAD + page_size) / 8];
                                p = (void *)((long)p & ~(page_size - 1));
                                (void) strlcat(label, "bss", sizeof(label));
                                continue;
+                       }
+
+                       case 'M':
+                               p = &mutable[(PAD + page_size) / 8];
+                               p = (void *)((long)p & ~(page_size - 1));
+                               (void)strlcat(label, "mutable", sizeof(label));
+                               continue;
                        case 'H':
                                p = malloc(size + 2 * page_size);
                                if (p == NULL)