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