aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Chagin <dchagin@FreeBSD.org>2023-08-08 15:12:09 +0000
committerDmitry Chagin <dchagin@FreeBSD.org>2023-08-08 15:12:09 +0000
commit8920c5f2a1175c22631780bd236026d15e2d3d72 (patch)
tree7217d572abae79e2298e1f2e8e19efe434a99214
parent58a46cfd751ac726ddca8544bf73a290b0154a57 (diff)
downloadsrc-8920c5f2a1175c22631780bd236026d15e2d3d72.tar.gz
src-8920c5f2a1175c22631780bd236026d15e2d3d72.zip
tests: Add stack grows tests
Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D41320 MFC after: 2 weeks
-rw-r--r--etc/mtree/BSD.tests.dist2
-rw-r--r--tests/sys/vm/Makefile5
-rw-r--r--tests/sys/vm/soxstack/Makefile17
-rw-r--r--tests/sys/vm/soxstack/soxstack.c51
-rw-r--r--tests/sys/vm/stack/Makefile15
-rw-r--r--tests/sys/vm/stack/stack_dlopen_exec_test.c64
-rw-r--r--tests/sys/vm/stack/stack_dt_need_exec_test.c50
-rw-r--r--tests/sys/vm/stack/stack_mprotect_exec_test.c48
8 files changed, 252 insertions, 0 deletions
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 <dchagin@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 <dchagin@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 <dchagin@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 <dchagin@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());
+}