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