From a98ae779c56e6a3fe4c660991e931c067da987ac Mon Sep 17 00:00:00 2001 From: visa Date: Fri, 24 Aug 2018 12:46:39 +0000 Subject: [PATCH] Add a regression test for the kernel stack exhaustion bug. OK anton@ --- regress/sys/kern/kqueue/Makefile | 7 ++- regress/sys/kern/kqueue/kqueue-regress.c | 65 +++++++++++++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/regress/sys/kern/kqueue/Makefile b/regress/sys/kern/kqueue/Makefile index b2d2a838447..f53c3c7f2fb 100644 --- a/regress/sys/kern/kqueue/Makefile +++ b/regress/sys/kern/kqueue/Makefile @@ -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} diff --git a/regress/sys/kern/kqueue/kqueue-regress.c b/regress/sys/kern/kqueue/kqueue-regress.c index f699b20e9df..bd6f578868f 100644 --- a/regress/sys/kern/kqueue/kqueue-regress.c +++ b/regress/sys/kern/kqueue/kqueue-regress.c @@ -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 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"); + } + } +} -- 2.20.1