xref: /openbsd-src/regress/sys/kern/unixsockets/undgram_conclose.c (revision 8f65ac5eb5e061986e0f17fc997f0185225a70ee)
1*8f65ac5eSmvs /* $OpenBSD: undgram_conclose.c,v 1.1 2021/12/10 00:33:25 mvs Exp $ */
2*8f65ac5eSmvs 
3*8f65ac5eSmvs /*
4*8f65ac5eSmvs  * Copyright (c) 2021 Vitaliy Makkoveev <mvs@openbsd.org>
5*8f65ac5eSmvs  *
6*8f65ac5eSmvs  * Permission to use, copy, modify, and distribute this software for any
7*8f65ac5eSmvs  * purpose with or without fee is hereby granted, provided that the above
8*8f65ac5eSmvs  * copyright notice and this permission notice appear in all copies.
9*8f65ac5eSmvs  *
10*8f65ac5eSmvs  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*8f65ac5eSmvs  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*8f65ac5eSmvs  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*8f65ac5eSmvs  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*8f65ac5eSmvs  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*8f65ac5eSmvs  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*8f65ac5eSmvs  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*8f65ac5eSmvs  */
18*8f65ac5eSmvs 
19*8f65ac5eSmvs /*
20*8f65ac5eSmvs  * Try to kill the datagram socket connected to the dying socket while
21*8f65ac5eSmvs  * it cleaning it's list of connected sockets. Incorrect handling of
22*8f65ac5eSmvs  * this case could produce kernel crash.
23*8f65ac5eSmvs  */
24*8f65ac5eSmvs 
25*8f65ac5eSmvs #include <sys/types.h>
26*8f65ac5eSmvs #include <sys/select.h>
27*8f65ac5eSmvs #include <sys/socket.h>
28*8f65ac5eSmvs #include <sys/stat.h>
29*8f65ac5eSmvs #include <sys/sysctl.h>
30*8f65ac5eSmvs #include <sys/un.h>
31*8f65ac5eSmvs #include <stdarg.h>
32*8f65ac5eSmvs #include <stdio.h>
33*8f65ac5eSmvs #include <err.h>
34*8f65ac5eSmvs #include <pthread.h>
35*8f65ac5eSmvs #include <string.h>
36*8f65ac5eSmvs #include <time.h>
37*8f65ac5eSmvs #include <unistd.h>
38*8f65ac5eSmvs 
39*8f65ac5eSmvs static pthread_mutex_t therr_mtx = PTHREAD_MUTEX_INITIALIZER;
40*8f65ac5eSmvs 
41*8f65ac5eSmvs static void
therr(int eval,const char * fmt,...)42*8f65ac5eSmvs therr(int eval, const char *fmt, ...)
43*8f65ac5eSmvs {
44*8f65ac5eSmvs 	va_list ap;
45*8f65ac5eSmvs 
46*8f65ac5eSmvs 	pthread_mutex_lock(&therr_mtx);
47*8f65ac5eSmvs 
48*8f65ac5eSmvs 	va_start(ap, fmt);
49*8f65ac5eSmvs 	verr(eval, fmt, ap);
50*8f65ac5eSmvs 	va_end(ap);
51*8f65ac5eSmvs }
52*8f65ac5eSmvs 
53*8f65ac5eSmvs static void
therrc(int eval,int code,const char * fmt,...)54*8f65ac5eSmvs therrc(int eval, int code, const char *fmt, ...)
55*8f65ac5eSmvs {
56*8f65ac5eSmvs 	va_list ap;
57*8f65ac5eSmvs 
58*8f65ac5eSmvs 	pthread_mutex_lock(&therr_mtx);
59*8f65ac5eSmvs 
60*8f65ac5eSmvs 	va_start(ap, fmt);
61*8f65ac5eSmvs 	verrc(eval, code, fmt, ap);
62*8f65ac5eSmvs 	va_end(ap);
63*8f65ac5eSmvs }
64*8f65ac5eSmvs 
65*8f65ac5eSmvs static void *
thr_close(void * arg)66*8f65ac5eSmvs thr_close(void *arg)
67*8f65ac5eSmvs {
68*8f65ac5eSmvs 	struct sockaddr_un *sun = arg;
69*8f65ac5eSmvs 	int s;
70*8f65ac5eSmvs 
71*8f65ac5eSmvs 	while (1) {
72*8f65ac5eSmvs 		unlink(sun->sun_path);
73*8f65ac5eSmvs 
74*8f65ac5eSmvs 		if ((s = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
75*8f65ac5eSmvs 			therr(1, "socket");
76*8f65ac5eSmvs 		if (bind(s, (struct sockaddr *)sun, sizeof(*sun)) < 0)
77*8f65ac5eSmvs 			therr(1, "bind");
78*8f65ac5eSmvs 		close(s);
79*8f65ac5eSmvs 	}
80*8f65ac5eSmvs 
81*8f65ac5eSmvs 	return NULL;
82*8f65ac5eSmvs }
83*8f65ac5eSmvs 
84*8f65ac5eSmvs static void *
thr_conn(void * arg)85*8f65ac5eSmvs thr_conn(void *arg)
86*8f65ac5eSmvs {
87*8f65ac5eSmvs 	struct sockaddr_un *sun = arg;
88*8f65ac5eSmvs 	int s;
89*8f65ac5eSmvs 
90*8f65ac5eSmvs 	while (1) {
91*8f65ac5eSmvs 		if ((s = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
92*8f65ac5eSmvs 			therr(1, "socket");
93*8f65ac5eSmvs 		connect(s, (struct sockaddr *)sun, sizeof(*sun));
94*8f65ac5eSmvs 		close(s);
95*8f65ac5eSmvs 	}
96*8f65ac5eSmvs 
97*8f65ac5eSmvs 	return NULL;
98*8f65ac5eSmvs }
99*8f65ac5eSmvs 
100*8f65ac5eSmvs static struct sockaddr_un sun;
101*8f65ac5eSmvs 
102*8f65ac5eSmvs int
main(int argc,char * argv[])103*8f65ac5eSmvs main(int argc, char *argv[])
104*8f65ac5eSmvs {
105*8f65ac5eSmvs 	struct timespec testtime = {
106*8f65ac5eSmvs 		.tv_sec = 60,
107*8f65ac5eSmvs 		.tv_nsec = 0,
108*8f65ac5eSmvs 	};
109*8f65ac5eSmvs 
110*8f65ac5eSmvs 	int mib[2], ncpu;
111*8f65ac5eSmvs 	size_t len;
112*8f65ac5eSmvs 
113*8f65ac5eSmvs 	pthread_t thr;
114*8f65ac5eSmvs 	int error, i;
115*8f65ac5eSmvs 
116*8f65ac5eSmvs 	umask(0077);
117*8f65ac5eSmvs 
118*8f65ac5eSmvs 	if (argc == 2 && !strcmp(argv[1], "--infinite"))
119*8f65ac5eSmvs 		testtime.tv_sec = (10 * 365 * 86400);
120*8f65ac5eSmvs 
121*8f65ac5eSmvs 	mib[0] = CTL_HW;
122*8f65ac5eSmvs 	mib[1] = HW_NCPUONLINE;
123*8f65ac5eSmvs 	len = sizeof(ncpu);
124*8f65ac5eSmvs 
125*8f65ac5eSmvs 	if (sysctl(mib, 2, &ncpu, &len, NULL, 0) < 0)
126*8f65ac5eSmvs 		err(1, "sysctl");
127*8f65ac5eSmvs 	if (ncpu <= 0)
128*8f65ac5eSmvs 		errx(1, "Wrong number of CPUs online: %d", ncpu);
129*8f65ac5eSmvs 
130*8f65ac5eSmvs 	memset(&sun, 0, sizeof(sun));
131*8f65ac5eSmvs 	sun.sun_len = sizeof(sun);
132*8f65ac5eSmvs 	sun.sun_family = AF_UNIX;
133*8f65ac5eSmvs 	snprintf(sun.sun_path, sizeof(sun.sun_path) - 1,
134*8f65ac5eSmvs 	    "undgram_conclose.socket");
135*8f65ac5eSmvs 
136*8f65ac5eSmvs 	if ((error = pthread_create(&thr, NULL, thr_close, &sun)))
137*8f65ac5eSmvs 		therrc(1, error, "pthread_create");
138*8f65ac5eSmvs 
139*8f65ac5eSmvs 	for (i = 0; i < (ncpu * 4); ++i) {
140*8f65ac5eSmvs 		if ((error = pthread_create(&thr, NULL, thr_conn, &sun)))
141*8f65ac5eSmvs 			therrc(1, error, "pthread_create");
142*8f65ac5eSmvs 	}
143*8f65ac5eSmvs 
144*8f65ac5eSmvs 	nanosleep(&testtime, NULL);
145*8f65ac5eSmvs 
146*8f65ac5eSmvs 	return 0;
147*8f65ac5eSmvs }
148