From e03a59bc6936927e7b0c94d3c2b4b098f2cafc04 Mon Sep 17 00:00:00 2001 From: anton Date: Mon, 13 Aug 2018 06:36:29 +0000 Subject: [PATCH] Add a test covering the recently fixed issue with dangling knote references upon closing a kqueue file descriptor. --- regress/sys/kern/kqueue/Makefile | 10 +-- regress/sys/kern/kqueue/kqueue-regress.c | 79 +++++++++++++++++++++++- regress/sys/kern/kqueue/main.c | 12 ++-- regress/sys/kern/kqueue/main.h | 4 +- 4 files changed, 92 insertions(+), 13 deletions(-) diff --git a/regress/sys/kern/kqueue/Makefile b/regress/sys/kern/kqueue/Makefile index 87ff52a4d42..b2d2a838447 100644 --- a/regress/sys/kern/kqueue/Makefile +++ b/regress/sys/kern/kqueue/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.21 2018/06/17 08:30:20 anton Exp $ +# $OpenBSD: Makefile,v 1.22 2018/08/13 06:36:29 anton Exp $ PROG= kqueue-test CFLAGS+=-Wall @@ -34,11 +34,13 @@ kq-timer: ${PROG} ./${PROG} -i kq-invalid-timer: ${PROG} ./${PROG} -I -kq-regress: ${PROG} - ./${PROG} -R +kq-regress-1: ${PROG} + ./${PROG} -R1 +kq-regress-2: ${PROG} + ./${PROG} -R2 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 + kq-fdpass kq-flock kq-timer kq-invalid-timer kq-regress-1 kq-regress-2 # 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 7d865e51761..f699b20e9df 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.1 2018/06/17 08:30:20 anton Exp $ */ +/* $OpenBSD: kqueue-regress.c,v 1.2 2018/08/13 06:36:29 anton Exp $ */ /* * Written by Anton Lindqvist 2018 Public Domain */ @@ -6,15 +6,37 @@ #include #include #include +#include +#include #include #include #include +#include #include "main.h" +static int do_regress1(void); +static int do_regress2(void); + int -do_regress(void) +do_regress(int n) +{ + switch (n) { + case 1: + return do_regress1(); + case 2: + return do_regress2(); + default: + errx(1, "unknown regress test number %d", n); + } +} + +/* + * Regression test for NULL-deref in knote_processexit(). + */ +static int +do_regress1(void) { struct kevent kev[2]; int kq; @@ -31,3 +53,56 @@ do_regress(void) return 0; } + +/* + * Regression test for use-after-free in kqueue_close(). + */ +static int +do_regress2(void) +{ + pid_t pid; + int i, status; + + /* Run twice in order to trigger the panic faster, if still present. */ + for (i = 0; i < 2; i++) { + pid = fork(); + if (pid == -1) + err(1, "fork"); + + if (pid == 0) { + struct kevent kev[1]; + int p0[2], p1[2]; + int kq; + + if (pipe(p0) == -1) + err(1, "pipe"); + if (pipe(p1) == -1) + err(1, "pipe"); + + kq = kqueue(); + if (kq == -1) + err(1, "kqueue"); + + EV_SET(&kev[0], p0[0], EVFILT_READ, EV_ADD, 0, 0, NULL); + if (kevent(kq, kev, 1, NULL, 0, NULL) == -1) + err(1, "kevent"); + + EV_SET(&kev[0], p1[1], EVFILT_READ, EV_ADD, 0, 0, NULL); + if (kevent(kq, kev, 1, NULL, 0, NULL) == -1) + err(1, "kevent"); + + EV_SET(&kev[0], p1[0], EVFILT_READ, EV_ADD, 0, 0, NULL); + if (kevent(kq, kev, 1, NULL, 0, NULL) == -1) + err(1, "kevent"); + + _exit(0); + } + + if (waitpid(pid, &status, 0) == -1) + err(1, "waitpid"); + assert(WIFEXITED(status)); + assert(WEXITSTATUS(status) == 0); + } + + return 0; +} diff --git a/regress/sys/kern/kqueue/main.c b/regress/sys/kern/kqueue/main.c index 7ef12b06890..1f124ddb956 100644 --- a/regress/sys/kern/kqueue/main.c +++ b/regress/sys/kern/kqueue/main.c @@ -1,8 +1,9 @@ -/* $OpenBSD: main.c,v 1.12 2018/06/17 08:32:24 anton Exp $ */ +/* $OpenBSD: main.c,v 1.13 2018/08/13 06:36:29 anton Exp $ */ /* * Written by Artur Grabowski 2002 Public Domain */ +#include #include #include #include @@ -13,10 +14,10 @@ int main(int argc, char **argv) { extern char *__progname; - int ret, c; + int r, ret, c; ret = 0; - while ((c = getopt(argc, argv, "fFiIlpPrRstT")) != -1) { + while ((c = getopt(argc, argv, "fFiIlpPrR:stT")) != -1) { switch (c) { case 'f': ret |= check_inheritance(); @@ -43,7 +44,8 @@ main(int argc, char **argv) ret |= do_random(); break; case 'R': - ret |= do_regress(); + r = strtonum(optarg, 1, INT_MAX, NULL); + ret |= do_regress(r); break; case 's': ret |= do_signal(); @@ -55,7 +57,7 @@ main(int argc, char **argv) ret |= do_pty(); break; default: - fprintf(stderr, "usage: %s -[fFiIlpPrRstT]\n", + fprintf(stderr, "usage: %s -[fFiIlpPrstT] [-R n]\n", __progname); exit(1); } diff --git a/regress/sys/kern/kqueue/main.h b/regress/sys/kern/kqueue/main.h index 88930f3c0bb..e4b5069680a 100644 --- a/regress/sys/kern/kqueue/main.h +++ b/regress/sys/kern/kqueue/main.h @@ -1,4 +1,4 @@ -/* $OpenBSD: main.h,v 1.3 2018/06/17 08:30:20 anton Exp $ */ +/* $OpenBSD: main.h,v 1.4 2018/08/13 06:36:29 anton Exp $ */ /* * Written by Alexaner Bluhm 2016 Public Domain */ @@ -23,7 +23,7 @@ int do_pipe(void); int do_process(void); int do_pty(void); int do_random(void); -int do_regress(void); +int do_regress(int); int do_signal(void); int do_timer(void); int do_tun(void); -- 2.20.1