The branch main has been updated by dchagin:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=8920c5f2a1175c22631780bd236026d15e2d3d72

commit 8920c5f2a1175c22631780bd236026d15e2d3d72
Author:     Dmitry Chagin <dcha...@freebsd.org>
AuthorDate: 2023-08-08 15:12:09 +0000
Commit:     Dmitry Chagin <dcha...@freebsd.org>
CommitDate: 2023-08-08 15:12:09 +0000

    tests: Add stack grows tests
    
    Reviewed by:            kib
    Differential Revision:  https://reviews.freebsd.org/D41320
    MFC after:              2 weeks
---
 etc/mtree/BSD.tests.dist                      |  2 +
 tests/sys/vm/Makefile                         |  5 +++
 tests/sys/vm/soxstack/Makefile                | 17 +++++++
 tests/sys/vm/soxstack/soxstack.c              | 51 +++++++++++++++++++++
 tests/sys/vm/stack/Makefile                   | 15 +++++++
 tests/sys/vm/stack/stack_dlopen_exec_test.c   | 64 +++++++++++++++++++++++++++
 tests/sys/vm/stack/stack_dt_need_exec_test.c  | 50 +++++++++++++++++++++
 tests/sys/vm/stack/stack_mprotect_exec_test.c | 48 ++++++++++++++++++++
 8 files changed, 252 insertions(+)

diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
index 943924c56bae..b1ce1117071b 100644
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -897,6 +897,8 @@
         vfs
         ..
         vm
+            stack
+            ..
         ..
         vmm
         ..
diff --git a/tests/sys/vm/Makefile b/tests/sys/vm/Makefile
index 9aac49bc5320..44ffb9ae7d7b 100644
--- a/tests/sys/vm/Makefile
+++ b/tests/sys/vm/Makefile
@@ -17,4 +17,9 @@ ATF_TESTS_SH+=        mmap_map_32bit_test
 PROGS+=                mmap_map_32bit_helper
 .endif
 
+SUBDIR=                soxstack
+TESTS_SUBDIRS+=        stack
+
+SUBDIR_DEPENDS_stack=soxstack
+
 .include <bsd.test.mk>
diff --git a/tests/sys/vm/soxstack/Makefile b/tests/sys/vm/soxstack/Makefile
new file mode 100644
index 000000000000..70a22fd278b1
--- /dev/null
+++ b/tests/sys/vm/soxstack/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+SHLIB=         soxstack
+SHLIB_NAME=    libsoxstack.so
+SHLIB_MAJOR=   1
+
+WITHOUT_STATIC=
+WITHOUT_PROFILE=
+WITHOUT_PIC=
+
+SRCS=          soxstack.c
+LDFLAGS+=      -Wl,-z,execstack
+LIBADD+=       procstat
+
+LIBDIR=                ${TESTSBASE}/sys/vm/stack
+
+.include <bsd.lib.mk>
diff --git a/tests/sys/vm/soxstack/soxstack.c b/tests/sys/vm/soxstack/soxstack.c
new file mode 100644
index 000000000000..fe3eb1c03a29
--- /dev/null
+++ b/tests/sys/vm/soxstack/soxstack.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2023 Dmitry Chagin <dcha...@freebsd.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <assert.h>
+#include <libprocstat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int    checkstack(void);
+
+#define        _STACK_FLAG_GROWS       KVME_FLAG_GROWS_UP | 
KVME_FLAG_GROWS_DOWN
+int
+checkstack(void)
+{
+       struct kinfo_vmentry *freep, *kve;
+       struct kinfo_proc *p;
+       struct procstat *prstat;
+       uint64_t stack;
+       int i, cnt;
+
+       prstat = procstat_open_sysctl();
+       assert(prstat != NULL);
+       p = procstat_getprocs(prstat, KERN_PROC_PID, getpid(), &cnt);
+       assert(p != NULL);
+       freep = procstat_getvmmap(prstat, p, &cnt);
+       assert(freep != NULL);
+
+       stack = (uint64_t)&i;
+       for (i = 0; i < cnt; i++) {
+               kve = &freep[i];
+               if (stack < kve->kve_start || stack > kve->kve_end)
+                       continue;
+               if ((kve->kve_flags & _STACK_FLAG_GROWS) != 0 &&
+                   (kve->kve_protection & KVME_PROT_EXEC) != 0)
+                       stack = 0;
+               break;
+       }
+
+       free(freep);
+       procstat_freeprocs(prstat, p);
+       procstat_close(prstat);
+       return (stack != 0);
+}
diff --git a/tests/sys/vm/stack/Makefile b/tests/sys/vm/stack/Makefile
new file mode 100644
index 000000000000..2d56a6231e24
--- /dev/null
+++ b/tests/sys/vm/stack/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+PACKAGE=       tests
+
+TESTSDIR=      ${TESTSBASE}/sys/vm/stack
+
+ATF_TESTS_C+=  stack_dt_need_exec_test
+ATF_TESTS_C+=  stack_dlopen_exec_test
+ATF_TESTS_C+=  stack_mprotect_exec_test
+
+LDFLAGS.stack_dt_need_exec_test+= -Wl,-rpath,${TESTSDIR} 
-L${.OBJDIR:H}/soxstack
+LDADD.stack_dt_need_exec_test+= -lsoxstack
+LDFLAGS.stack_dlopen_exec_test+= -Wl,-rpath,${TESTSDIR}
+
+.include <bsd.test.mk>
diff --git a/tests/sys/vm/stack/stack_dlopen_exec_test.c 
b/tests/sys/vm/stack/stack_dlopen_exec_test.c
new file mode 100644
index 000000000000..d4d5fc7c5cf0
--- /dev/null
+++ b/tests/sys/vm/stack/stack_dlopen_exec_test.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2023 Dmitry Chagin <dcha...@freebsd.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/systm.h>
+#include <vm/vm_param.h>
+
+#include <atf-c.h>
+#include <dlfcn.h>
+
+static int jumpstack0(void) __noinline;
+static int jumpstack1(void) __noinline;
+
+static int (*socheckstack)(void) = NULL;
+
+static int
+checkstack(void)
+{
+       void *fh;
+
+       if (socheckstack == NULL) {
+               fh = dlopen("libsoxstack.so", RTLD_LAZY);
+               ATF_REQUIRE(fh != NULL);
+               socheckstack = dlsym(fh, "checkstack");
+               ATF_REQUIRE(socheckstack != NULL);
+       }
+       return (socheckstack());
+}
+
+static int
+jumpstack0(void)
+{
+       char stack[SGROWSIZ];
+
+       explicit_bzero(stack, sizeof(stack));
+       return (checkstack());
+}
+
+static int
+jumpstack1(void)
+{
+       char stack[SGROWSIZ * 2];
+
+       explicit_bzero(stack, sizeof(stack));
+       return (checkstack());
+}
+
+ATF_TC_WITHOUT_HEAD(dlopen_test);
+ATF_TC_BODY(dlopen_test, tc)
+{
+
+       ATF_REQUIRE(jumpstack0() == 0);
+       ATF_REQUIRE(jumpstack1() == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+       ATF_TP_ADD_TC(tp, dlopen_test);
+
+       return (atf_no_error());
+}
diff --git a/tests/sys/vm/stack/stack_dt_need_exec_test.c 
b/tests/sys/vm/stack/stack_dt_need_exec_test.c
new file mode 100644
index 000000000000..8a234abe3da5
--- /dev/null
+++ b/tests/sys/vm/stack/stack_dt_need_exec_test.c
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 2023 Dmitry Chagin <dcha...@freebsd.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/systm.h>
+#include <vm/vm_param.h>
+
+#include <atf-c.h>
+
+extern int checkstack(void);
+
+static int jumpstack0(void) __noinline;
+static int jumpstack1(void) __noinline;
+
+
+static int
+jumpstack0(void)
+{
+       char stack[SGROWSIZ];
+
+       explicit_bzero(stack, sizeof(stack));
+       return (checkstack());
+}
+
+static int
+jumpstack1(void)
+{
+       char stack[SGROWSIZ * 2];
+
+       explicit_bzero(stack, sizeof(stack));
+       return (checkstack());
+}
+
+ATF_TC_WITHOUT_HEAD(dt_need_test);
+ATF_TC_BODY(dt_need_test, tc)
+{
+
+       ATF_REQUIRE(jumpstack0() == 0);
+       ATF_REQUIRE(jumpstack1() == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+       ATF_TP_ADD_TC(tp, dt_need_test);
+
+       return (atf_no_error());
+}
diff --git a/tests/sys/vm/stack/stack_mprotect_exec_test.c 
b/tests/sys/vm/stack/stack_mprotect_exec_test.c
new file mode 100644
index 000000000000..d12d99ea39ee
--- /dev/null
+++ b/tests/sys/vm/stack/stack_mprotect_exec_test.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2023 Dmitry Chagin <dcha...@freebsd.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * PR: 272585
+ * Test provided by John F. Carr
+ */
+
+#include <sys/systm.h>
+#include <sys/mman.h>
+#include <vm/vm_param.h>
+
+#include <atf-c.h>
+#include <unistd.h>
+
+
+ATF_TC_WITHOUT_HEAD(mprotect_exec_test);
+ATF_TC_BODY(mprotect_exec_test, tc)
+{
+       long pagesize;
+       char *addr, *guard;
+       size_t alloc_size;
+
+       pagesize = sysconf(_SC_PAGESIZE);
+       ATF_REQUIRE(pagesize > 0);
+
+       alloc_size = SGROWSIZ * 2;
+       addr = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE,
+           MAP_STACK | MAP_PRIVATE | MAP_ANON, -1, 0);
+       ATF_REQUIRE(addr != MAP_FAILED);
+
+       /*
+        * Change prot of the last page in the mmaped stack area.
+        */
+       guard = addr + alloc_size - SGROWSIZ;
+       ATF_REQUIRE(mprotect(guard, pagesize, PROT_NONE) == 0);
+
+       ((volatile char *)guard)[-1];
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+       ATF_TP_ADD_TC(tp, mprotect_exec_test);
+
+       return (atf_no_error());
+}

Reply via email to