-# $OpenBSD: Makefile,v 1.22 2018/08/13 06:36:29 anton Exp $
+# $OpenBSD: Makefile,v 1.23 2018/08/24 12:46:39 visa Exp $
PROG= kqueue-test
CFLAGS+=-Wall
./${PROG} -R1
kq-regress-2: ${PROG}
./${PROG} -R2
+kq-regress-3: ${PROG}
+ ./${PROG} -R3
REGRESS_TARGETS=kq-pipe kq-fork kq-process kq-random kq-pty kq-signal \
- kq-fdpass kq-flock kq-timer kq-invalid-timer kq-regress-1 kq-regress-2
+ kq-fdpass kq-flock kq-timer kq-invalid-timer kq-regress-1 \
+ kq-regress-2 kq-regress-3
# kq-tun broke at some point, apparently from a change in tun routing
REGRESS_ROOT_TARGETS=${REGRESS_TARGETS}
.PHONY: ${REGRESS_TARGETS}
-/* $OpenBSD: kqueue-regress.c,v 1.2 2018/08/13 06:36:29 anton Exp $ */
+/* $OpenBSD: kqueue-regress.c,v 1.3 2018/08/24 12:46:39 visa Exp $ */
/*
* Written by Anton Lindqvist <anton@openbsd.org> 2018 Public Domain
*/
static int do_regress1(void);
static int do_regress2(void);
+static int do_regress3(void);
+
+static void make_chain(int);
int
do_regress(int n)
return do_regress1();
case 2:
return do_regress2();
+ case 3:
+ return do_regress3();
default:
errx(1, "unknown regress test number %d", n);
}
return 0;
}
+
+/*
+ * Regression test for kernel stack exhaustion.
+ */
+static int
+do_regress3(void)
+{
+ pid_t pid;
+ int dir, status;
+
+ for (dir = 0; dir < 2; dir++) {
+ pid = fork();
+ if (pid == -1)
+ err(1, "fork");
+
+ if (pid == 0) {
+ make_chain(dir);
+ _exit(0);
+ }
+
+ if (waitpid(pid, &status, 0) == -1)
+ err(1, "waitpid");
+ assert(WIFEXITED(status));
+ assert(WEXITSTATUS(status) == 0);
+ }
+
+ return 0;
+}
+
+static void
+make_chain(int dir)
+{
+ struct kevent kev[1];
+ int i, kq, prev;
+
+ /*
+ * Build a chain of kqueues and leave the files open.
+ * If the chain is long enough and properly oriented, a broken kernel
+ * can exhaust the stack when this process exits.
+ */
+ for (i = 0, prev = -1; i < 120; i++, prev = kq) {
+ kq = kqueue();
+ if (kq == -1)
+ err(1, "kqueue");
+ if (prev == -1)
+ continue;
+
+ if (dir == 0) {
+ EV_SET(&kev[0], prev, EVFILT_READ, EV_ADD, 0, 0, NULL);
+ if (kevent(kq, kev, 1, NULL, 0, NULL) == -1)
+ err(1, "kevent");
+ } else {
+ EV_SET(&kev[0], kq, EVFILT_READ, EV_ADD, 0, 0, NULL);
+ if (kevent(prev, kev, 1, NULL, 0, NULL) == -1)
+ err(1, "kevent");
+ }
+ }
+}