diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2018-12-19 21:22:00 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2018-12-19 21:22:00 +0000 |
commit | bc5cb34fecd549c05c70b906b3b39e119f96bb49 (patch) | |
tree | feee80dff4ee14171e47693e9642b04acd1003b6 /regress | |
parent | 0b48f0825b5f99aefc574b93d2fc1b6e051415e5 (diff) |
Test the code path where soreceive(9) sleeps and a control mbuf is
inserted into the stream.
Diffstat (limited to 'regress')
-rw-r--r-- | regress/sys/kern/Makefile | 5 | ||||
-rw-r--r-- | regress/sys/kern/recvwait/Makefile | 11 | ||||
-rw-r--r-- | regress/sys/kern/recvwait/mcontrol-stream.c | 100 |
3 files changed, 114 insertions, 2 deletions
diff --git a/regress/sys/kern/Makefile b/regress/sys/kern/Makefile index 1aabff91c65..43be379abd3 100644 --- a/regress/sys/kern/Makefile +++ b/regress/sys/kern/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.78 2018/11/12 16:50:28 visa Exp $ +# $OpenBSD: Makefile,v 1.79 2018/12/19 21:21:59 bluhm Exp $ SUBDIR+= __syscall access accept cmsgsize SUBDIR+= dup2 dup2_accept dup2_self descrip @@ -9,7 +9,7 @@ SUBDIR+= fcntl_dup SUBDIR+= flock SUBDIR+= ftruncate SUBDIR+= futex -SUBDIR+= getpeereid getrusage gettimeofday itimer +SUBDIR+= getpeereid getrusage gettimeofday itimer SUBDIR+= kqueue mbuf minherit SUBDIR+= main-thread-exited SUBDIR+= mmap mmap2 mmap3 mmap-fail @@ -18,6 +18,7 @@ SUBDIR+= nanosleep noexec SUBDIR+= open SUBDIR+= pledge SUBDIR+= pread preadv ptmget pty pwrite pwritev rcvtimeo +SUBDIR+= recvwait SUBDIR+= rlimit-file SUBDIR+= sigio signal signal-stress sigprof sigsuspend SUBDIR+= sosplice diff --git a/regress/sys/kern/recvwait/Makefile b/regress/sys/kern/recvwait/Makefile new file mode 100644 index 00000000000..dce7b5fd38e --- /dev/null +++ b/regress/sys/kern/recvwait/Makefile @@ -0,0 +1,11 @@ +# $OpenBSD: Makefile,v 1.1 2018/12/19 21:21:59 bluhm Exp $ + +# There is a race where a second control message is inserted into +# the receive socket buffer while it is processed by soreceive(9). +# As this code path is rarely triggered in real life, add a +# regress test. + +PROG= mcontrol-stream +WARNINGS= yes + +.include <bsd.regress.mk> diff --git a/regress/sys/kern/recvwait/mcontrol-stream.c b/regress/sys/kern/recvwait/mcontrol-stream.c new file mode 100644 index 00000000000..7a45b884cff --- /dev/null +++ b/regress/sys/kern/recvwait/mcontrol-stream.c @@ -0,0 +1,100 @@ +/* $OpenBSD: mcontrol-stream.c,v 1.1 2018/12/19 21:21:59 bluhm Exp $ */ +/* + * Copyright (c) 2018 Alexander Bluhm <bluhm@openbsd.org> + * + * 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 <sys/wait.h> + +#include <err.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> + +int +main(int argc, char *argv[]) +{ + pid_t pid; + int fd, s[2], status; + char str[] = "foo"; + struct msghdr msg; + struct cmsghdr *cmsg; + union { + struct cmsghdr hdr; + unsigned char buf[CMSG_SPACE(sizeof(int))]; + } cmsgbuf; + struct iovec io_vector[1]; + + if ((fd = open("/dev/null", O_RDONLY)) == -1) + err(1, "open"); + if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1) + err(1, "socketpair"); + + if ((pid = fork()) == -1) + err(1, "fork"); + if (pid == 0) { + char buf[16]; + ssize_t n; + + /* + * The first recv(2) will block until the second control + * message causes a short read. + */ + if ((n = recv(s[1], buf, sizeof(buf), MSG_WAITALL)) == -1) + err(1, "recv 1"); + if ((size_t)n != strlen(str)) + errx(1, "recv 1: len %zd", n); + if ((n = recv(s[1], buf, sizeof(buf), 0)) == -1) + err(1, "recv 2"); + if ((size_t)n != strlen(str)) + errx(1, "recv 2: len %zd", n); + _exit(0); + } + + io_vector[0].iov_base = str; + io_vector[0].iov_len = strlen(str); + + memset(&msg, 0, sizeof(msg)); + msg.msg_control = &cmsgbuf.buf; + msg.msg_controllen = sizeof(cmsgbuf.buf); + msg.msg_iov = io_vector; + msg.msg_iovlen = 1; + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *)CMSG_DATA(cmsg) = fd; + + if (sendmsg(s[0], &msg, 0) == -1) + err(1, "sendmsg 1"); + + /* Wait until child is blocking in recv(2) MSG_WAITALL syscall. */ + sleep(2); + + /* This will insert a control mbuf while soreceive() is sleeping. */ + if (sendmsg(s[0], &msg, 0) == -1) + err(1, "sendmsg 2"); + + if (close(s[0]) == -1) + err(1, "close"); + + if (waitpid(pid, &status, 0) == -1) + err(1, "waitpid"); + if (status != 0) + errx(1, "child: %d", status); + + return 0; +} |