unix_sendtorace.c revision 281974
168349Sobrien/*- 268349Sobrien * Copyright (c) 2006 Robert N. M. Watson 368349Sobrien * All rights reserved. 468349Sobrien * 568349Sobrien * Redistribution and use in source and binary forms, with or without 668349Sobrien * modification, are permitted provided that the following conditions 768349Sobrien * are met: 868349Sobrien * 1. Redistributions of source code must retain the above copyright 968349Sobrien * notice, this list of conditions and the following disclaimer. 1068349Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1168349Sobrien * notice, this list of conditions and the following disclaimer in the 1268349Sobrien * documentation and/or other materials provided with the distribution. 1368349Sobrien * 1468349Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1568349Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1668349Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1768349Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1868349Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1968349Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20133359Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21133359Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2268349Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2368349Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24133359Sobrien * SUCH DAMAGE. 25133359Sobrien * 2668349Sobrien * $FreeBSD: stable/10/tools/regression/sockets/unix_sendtorace/unix_sendtorace.c 281974 2015-04-25 05:31:52Z ngie $ 2768349Sobrien */ 28133359Sobrien 29133359Sobrien/* 3068349Sobrien * Attempts to exercise UNIX domain socket races relating to the non-atomic 3168349Sobrien * connect-and-send properties of sendto(). As the result of such a race is 3268349Sobrien * a kernel panic, this test simply completes or doesn't. 3369216Sobrien * 3469216Sobrien * XXX: Despite implementing support for sendto() on stream sockets with 3569216Sobrien * implied connect, the appropriate flag isn't set in the FreeBSD kernel so 3669216Sobrien * it does not work. For now, don't call the stream test. 3769216Sobrien */ 3869216Sobrien 3969216Sobrien#include <sys/types.h> 4068349Sobrien#include <sys/socket.h> 4169216Sobrien#include <sys/un.h> 4269216Sobrien 4369216Sobrien#include <err.h> 4469216Sobrien#include <signal.h> 4569216Sobrien#include <string.h> 4669216Sobrien#include <unistd.h> 4769216Sobrien 4869216Sobrien#define ITERATIONS 1000000 4969216Sobrien 5069216Sobrienstatic char socket_path[] = "tmp.XXXXXX"; 5169216Sobrien 5268349Sobrienstatic void 5368349Sobrienstream_server(int listenfd) 5468349Sobrien{ 5568349Sobrien int acceptfd; 5668349Sobrien 5768349Sobrien while (1) { 5868349Sobrien acceptfd = accept(listenfd, NULL, NULL); 5968349Sobrien if (acceptfd < 0) { 6068349Sobrien warn("stream_server: accept"); 6168349Sobrien continue; 6268349Sobrien } 6368349Sobrien sleep(1); 6468349Sobrien close(acceptfd); 6568349Sobrien } 6668349Sobrien} 6768349Sobrien 6868349Sobrienstatic void 6968349Sobrienstream_client(void) 7068349Sobrien{ 7168349Sobrien struct sockaddr_un sun; 7268349Sobrien ssize_t len; 7368349Sobrien char c = 0; 7468349Sobrien int fd, i; 7568349Sobrien 7668349Sobrien bzero(&sun, sizeof(sun)); 7768349Sobrien sun.sun_len = sizeof(sun); 7868349Sobrien sun.sun_family = AF_UNIX; 7968349Sobrien strcpy(sun.sun_path, socket_path); 8068349Sobrien for (i = 0; i < ITERATIONS; i++) { 8168349Sobrien fd = socket(PF_UNIX, SOCK_STREAM, 0); 8268349Sobrien if (fd < 0) { 8368349Sobrien warn("stream_client: socket"); 8468349Sobrien return; 8568349Sobrien } 8668349Sobrien len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun, 8768349Sobrien sizeof(sun)); 88103373Sobrien if (len < 0) 8968349Sobrien warn("stream_client: sendto"); 9068349Sobrien close(fd); 9168349Sobrien } 9268349Sobrien} 9368349Sobrien 9468349Sobrienstatic void 9568349Sobrienstream_test(void) 9668349Sobrien{ 9768349Sobrien struct sockaddr_un sun; 9868349Sobrien pid_t childpid; 9968349Sobrien int listenfd; 10068349Sobrien 10168349Sobrien listenfd = socket(PF_UNIX, SOCK_STREAM, 0); 10268349Sobrien if (listenfd < 0) 10368349Sobrien err(-1, "stream_test: socket"); 10468349Sobrien 10568349Sobrien bzero(&sun, sizeof(sun)); 10668349Sobrien sun.sun_len = sizeof(sun); 10768349Sobrien sun.sun_family = AF_UNIX; 10868349Sobrien strcpy(sun.sun_path, socket_path); 10968349Sobrien 11068349Sobrien if (bind(listenfd, (struct sockaddr *)&sun, sizeof(sun)) < 0) 11168349Sobrien err(-1, "stream_test: bind"); 11268349Sobrien 11368349Sobrien if (listen(listenfd, -1) < 0) 11468349Sobrien err(-1, "stream_test: listen"); 11568349Sobrien 11668349Sobrien childpid = fork(); 11768349Sobrien if (childpid < 0) 11868349Sobrien err(-1, "stream_test: fork"); 11968349Sobrien 12068349Sobrien if (childpid != 0) { 12168349Sobrien sleep(1); 12268349Sobrien stream_client(); 12368349Sobrien kill(childpid, SIGTERM); 12468349Sobrien sleep(1); 12568349Sobrien } else 12668349Sobrien stream_server(listenfd); 12768349Sobrien 12868349Sobrien (void)unlink(socket_path); 12968349Sobrien} 13068349Sobrien 13168349Sobrienstatic void 13268349Sobriendatagram_server(int serverfd) 13368349Sobrien{ 13468349Sobrien ssize_t len; 13568349Sobrien char c; 13668349Sobrien 13768349Sobrien while (1) { 13868349Sobrien len = recv(serverfd, &c, sizeof(c), 0); 13968349Sobrien if (len < 0) 14068349Sobrien warn("datagram_server: recv"); 14168349Sobrien } 14268349Sobrien} 14368349Sobrien 14468349Sobrienstatic void 14568349Sobriendatagram_client(void) 14668349Sobrien{ 14768349Sobrien struct sockaddr_un sun; 14868349Sobrien ssize_t len; 14968349Sobrien char c = 0; 15068349Sobrien int fd, i; 151110949Sobrien 152110949Sobrien bzero(&sun, sizeof(sun)); 15368349Sobrien sun.sun_len = sizeof(sun); 154110949Sobrien sun.sun_family = AF_UNIX; 15568349Sobrien strcpy(sun.sun_path, socket_path); 15668349Sobrien for (i = 0; i < ITERATIONS; i++) { 15768349Sobrien fd = socket(PF_UNIX, SOCK_DGRAM, 0); 15868349Sobrien if (fd < 0) { 15968349Sobrien warn("datagram_client: socket"); 16068349Sobrien return; 16168349Sobrien } 16268349Sobrien len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun, 16368349Sobrien sizeof(sun)); 16468349Sobrien if (len < 0) 16568349Sobrien warn("datagram_client: sendto"); 16668349Sobrien close(fd); 167133359Sobrien } 168133359Sobrien} 169133359Sobrien 170133359Sobrienstatic void 171133359Sobriendatagram_test(void) 17268349Sobrien{ 17368349Sobrien struct sockaddr_un sun; 17468349Sobrien pid_t childpid; 17568349Sobrien int serverfd; 17668349Sobrien 17768349Sobrien serverfd = socket(PF_UNIX, SOCK_DGRAM, 0); 17868349Sobrien if (serverfd < 0) 17968349Sobrien err(-1, "datagram_test: socket"); 18068349Sobrien 18168349Sobrien bzero(&sun, sizeof(sun)); 18268349Sobrien sun.sun_len = sizeof(sun); 18368349Sobrien sun.sun_family = AF_UNIX; 18468349Sobrien strcpy(sun.sun_path, socket_path); 18568349Sobrien 18668349Sobrien if (bind(serverfd, (struct sockaddr *)&sun, sizeof(sun)) < 0) 18768349Sobrien err(-1, "datagram_test: bind"); 18868349Sobrien 18968349Sobrien childpid = fork(); 19068349Sobrien if (childpid < 0) 19168349Sobrien err(-1, "datagram_test: fork"); 19268349Sobrien 19368349Sobrien if (childpid != 0) { 19468349Sobrien sleep(1); 19568349Sobrien datagram_client(); 19668349Sobrien kill(childpid, SIGTERM); 19768349Sobrien sleep(1); 19868349Sobrien } else 19968349Sobrien datagram_server(serverfd); 20068349Sobrien 20168349Sobrien (void)unlink(socket_path); 20268349Sobrien} 20368349Sobrien 20468349Sobrienint 20568349Sobrienmain(void) 20668349Sobrien{ 20768349Sobrien 20868349Sobrien if (mkstemp(socket_path) == -1) 20968349Sobrien err(1, "mkstemp failed"); 21068349Sobrien (void)unlink(socket_path); 21168349Sobrien datagram_test(); 21268349Sobrien if (0) 21368349Sobrien stream_test(); 21468349Sobrien return (0); 21568349Sobrien} 21668349Sobrien