Add a regression test for the kernel stack exhaustion bug.
authorvisa <visa@openbsd.org>
Fri, 24 Aug 2018 12:46:39 +0000 (12:46 +0000)
committervisa <visa@openbsd.org>
Fri, 24 Aug 2018 12:46:39 +0000 (12:46 +0000)
OK anton@

regress/sys/kern/kqueue/Makefile
regress/sys/kern/kqueue/kqueue-regress.c

index b2d2a83..f53c3c7 100644 (file)
@@ -1,4 +1,4 @@
-#      $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
@@ -38,9 +38,12 @@ kq-regress-1: ${PROG}
        ./${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}
index f699b20..bd6f578 100644 (file)
@@ -1,4 +1,4 @@
-/*     $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
  */
@@ -18,6 +18,9 @@
 
 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)
@@ -27,6 +30,8 @@ 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);
        }
@@ -106,3 +111,61 @@ do_regress2(void)
 
        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");
+               }
+       }
+}