summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2018-05-28 09:04:44 +0000
committermpi <mpi@openbsd.org>2018-05-28 09:04:44 +0000
commit6a044236e2c52f23e4de25e1184c674dd1211a01 (patch)
tree9da71f8c15cffa0cbab2c4048f1c3708ef3e51e8
parentAdd clock support for i.MX8MQ. Most of the clocks can be configured (diff)
downloadwireguard-openbsd-6a044236e2c52f23e4de25e1184c674dd1211a01.tar.xz
wireguard-openbsd-6a044236e2c52f23e4de25e1184c674dd1211a01.zip
Regress for the dup2(2) vs accept(2) race.
Note that you need a new kernel otherwise this test will make your machine panic!
-rw-r--r--regress/sys/kern/Makefile5
-rw-r--r--regress/sys/kern/dup2_accept/Makefile10
-rw-r--r--regress/sys/kern/dup2_accept/dup2_accept.c99
3 files changed, 112 insertions, 2 deletions
diff --git a/regress/sys/kern/Makefile b/regress/sys/kern/Makefile
index 70077bf101e..0d0a08d69f8 100644
--- a/regress/sys/kern/Makefile
+++ b/regress/sys/kern/Makefile
@@ -1,6 +1,7 @@
-# $OpenBSD: Makefile,v 1.70 2017/07/07 23:15:27 bluhm Exp $
+# $OpenBSD: Makefile,v 1.71 2018/05/28 09:04:44 mpi Exp $
-SUBDIR+= __syscall access accept dup2 dup2_self exec_self execve exit extent
+SUBDIR+= __syscall access accept dup2 dup2_accept dup2_self
+SUBDIR+= exec_self execve exit extent
SUBDIR+= fchdir
SUBDIR+= fcntl_dup
SUBDIR+= flock
diff --git a/regress/sys/kern/dup2_accept/Makefile b/regress/sys/kern/dup2_accept/Makefile
new file mode 100644
index 00000000000..80d56efa22a
--- /dev/null
+++ b/regress/sys/kern/dup2_accept/Makefile
@@ -0,0 +1,10 @@
+# $OpenBSD: Makefile,v 1.1 2018/05/28 09:04:44 mpi Exp $
+
+PROG= dup2_accept
+
+LIBPTHREAD= /usr/lib/libpthread.a
+
+LDADD+= -lpthread
+DPADD+= ${LIBPTHREAD}
+
+.include <bsd.regress.mk>
diff --git a/regress/sys/kern/dup2_accept/dup2_accept.c b/regress/sys/kern/dup2_accept/dup2_accept.c
new file mode 100644
index 00000000000..102d2975ef6
--- /dev/null
+++ b/regress/sys/kern/dup2_accept/dup2_accept.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018 Martin Pieuchot
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <stdlib.h>
+
+/*
+ * Listen on localhost:TEST_PORT for a connection
+ */
+#define TEST_PORT 9876
+
+static void *
+dupper(void *arg)
+{
+ struct sockaddr_in addr;
+ int s;
+
+ sleep(1);
+
+ s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s == -1)
+ err(1, "socket");
+
+ assert(s == 5);
+
+ /*
+ * Make sure that dup'ing a LARVAL file fails with EBUSY.
+ *
+ * Otherwise abort the program before calling connect(2),
+ * this was previously panic'ing the kernel.
+ */
+ if ((dup2(0, 4) != 4) && (errno != EBUSY))
+ err(1, "dup2");
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr.sin_port = htons(TEST_PORT);
+
+ if (connect(5, (struct sockaddr *)&addr, sizeof(addr)) == -1)
+ err(1, "connect");
+
+ return NULL;
+}
+
+int
+main(void)
+{
+ struct sockaddr_in serv_addr;
+ struct sockaddr client_addr;
+ int error, s, len, fd;
+ pthread_t tr;
+
+ if ((error = pthread_create(&tr, NULL, dupper, NULL)))
+ errc(1, error, "pthread_create");
+
+ s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s == -1)
+ err(1, "socket");
+
+ assert(s == 3);
+
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ serv_addr.sin_port = htons(TEST_PORT);
+
+ if (bind(s, (struct sockaddr *)&serv_addr, sizeof(serv_addr)))
+ err(1, "bind");
+
+ if (listen(s, 3))
+ err(1, "listen");
+
+ len = sizeof(client_addr);
+ fd = accept(s, &client_addr, &len);
+
+ return 0;
+}