1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2018 Alan Somers 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 #include <sys/socket.h> 30 #include <sys/event.h> 31 #include <sys/select.h> 32 #include <sys/sysctl.h> 33 #include <sys/un.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <poll.h> 39 #include <pthread.h> 40 #include <pthread_np.h> 41 42 #include <atf-c.h> 43 44 static void 45 do_socketpair(int *sv) 46 { 47 int s; 48 49 s = socketpair(PF_LOCAL, SOCK_STREAM, 0, sv); 50 ATF_REQUIRE_EQ(0, s); 51 ATF_REQUIRE(sv[0] >= 0); 52 ATF_REQUIRE(sv[1] >= 0); 53 ATF_REQUIRE(sv[0] != sv[1]); 54 } 55 56 static u_long 57 getsendspace(void) 58 { 59 u_long sendspace; 60 61 ATF_REQUIRE_MSG(sysctlbyname("net.local.stream.sendspace", &sendspace, 62 &(size_t){sizeof(u_long)}, NULL, 0) != -1, 63 "sysctl net.local.stream.sendspace failed: %s", strerror(errno)); 64 65 return (sendspace); 66 } 67 68 /* getpeereid(3) should work with stream sockets created via socketpair(2) */ 69 ATF_TC_WITHOUT_HEAD(getpeereid); 70 ATF_TC_BODY(getpeereid, tc) 71 { 72 int sv[2]; 73 uid_t real_euid, euid; 74 gid_t real_egid, egid; 75 76 real_euid = geteuid(); 77 real_egid = getegid(); 78 79 do_socketpair(sv); 80 81 ATF_REQUIRE_EQ(0, getpeereid(sv[0], &euid, &egid)); 82 ATF_CHECK_EQ(real_euid, euid); 83 ATF_CHECK_EQ(real_egid, egid); 84 85 ATF_REQUIRE_EQ(0, getpeereid(sv[1], &euid, &egid)); 86 ATF_CHECK_EQ(real_euid, euid); 87 ATF_CHECK_EQ(real_egid, egid); 88 89 close(sv[0]); 90 close(sv[1]); 91 } 92 93 /* Sending zero bytes should succeed (once regressed in aba79b0f4a3f). */ 94 ATF_TC_WITHOUT_HEAD(send_0); 95 ATF_TC_BODY(send_0, tc) 96 { 97 int sv[2]; 98 99 do_socketpair(sv); 100 ATF_REQUIRE(send(sv[0], sv, 0, 0) == 0); 101 close(sv[0]); 102 close(sv[1]); 103 } 104 105 static void 106 check_readable_select(int fd, int expect, bool timeout) 107 { 108 fd_set rdfds; 109 int nfds; 110 111 FD_ZERO(&rdfds); 112 FD_SET(fd, &rdfds); 113 nfds = select(fd + 1, &rdfds, NULL, NULL, timeout ? 114 &(struct timeval){.tv_usec = 1000} : NULL); 115 ATF_REQUIRE_MSG(nfds == expect, 116 "select() returns %d errno %d", nfds, errno); 117 } 118 119 static void 120 check_writable_select(int fd, int expect, bool timeout) 121 { 122 fd_set wrfds; 123 int nfds; 124 125 FD_ZERO(&wrfds); 126 FD_SET(fd, &wrfds); 127 nfds = select(fd + 1, NULL, &wrfds, NULL, timeout ? 128 &(struct timeval){.tv_usec = 1000} : NULL); 129 ATF_REQUIRE_MSG(nfds == expect, 130 "select() returns %d errno %d", nfds, errno); 131 } 132 133 static void 134 check_readable_poll(int fd, int expect, bool timeout) 135 { 136 struct pollfd pfd[1]; 137 int nfds; 138 139 pfd[0] = (struct pollfd){ 140 .fd = fd, 141 .events = POLLIN | POLLRDNORM, 142 }; 143 nfds = poll(pfd, 1, timeout ? 1 : INFTIM); 144 ATF_REQUIRE_MSG(nfds == expect, 145 "poll() returns %d errno %d", nfds, errno); 146 } 147 148 static void 149 check_writable_poll(int fd, int expect, bool timeout) 150 { 151 struct pollfd pfd[1]; 152 int nfds; 153 154 pfd[0] = (struct pollfd){ 155 .fd = fd, 156 .events = POLLOUT | POLLWRNORM, 157 }; 158 nfds = poll(pfd, 1, timeout ? 1 : INFTIM); 159 ATF_REQUIRE_MSG(nfds == expect, 160 "poll() returns %d errno %d", nfds, errno); 161 } 162 163 static void 164 check_writable_kevent(int fd, int expect, bool timeout) 165 { 166 struct kevent kev; 167 int nfds, kq; 168 169 ATF_REQUIRE(kq = kqueue()); 170 EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); 171 nfds = kevent(kq, &kev, 1, NULL, 0, NULL); 172 ATF_REQUIRE_MSG(nfds == 0, 173 "kevent() returns %d errno %d", nfds, errno); 174 nfds = kevent(kq, NULL, 0, &kev, 1, timeout ? 175 &(struct timespec){.tv_nsec = 1000000} : NULL); 176 ATF_REQUIRE_MSG(nfds == expect, 177 "kevent() returns %d errno %d", nfds, errno); 178 close(kq); 179 } 180 181 typedef void check_writable_func_t(int, int, bool); 182 struct check_writable_ctx { 183 check_writable_func_t *method; 184 int fd; 185 }; 186 187 static void * 188 check_writable_blocking_thread(void *arg) 189 { 190 struct check_writable_ctx *ctx = arg; 191 192 ctx->method(ctx->fd, 1, false); 193 194 return (NULL); 195 } 196 197 static void 198 full_socketpair(int *sv) 199 { 200 void *buf; 201 u_long sendspace; 202 203 sendspace = getsendspace(); 204 ATF_REQUIRE((buf = malloc(sendspace)) != NULL); 205 do_socketpair(sv); 206 ATF_REQUIRE(fcntl(sv[0], F_SETFL, O_NONBLOCK) != -1); 207 do {} while (send(sv[0], buf, sendspace, 0) == (ssize_t)sendspace); 208 ATF_REQUIRE(errno == EAGAIN); 209 ATF_REQUIRE(fcntl(sv[0], F_SETFL, 0) != -1); 210 free(buf); 211 } 212 213 static void 214 full_writability_check(int *sv, check_writable_func_t method) 215 { 216 struct check_writable_ctx ctx = { 217 .method = method, 218 .fd = sv[0], 219 }; 220 pthread_t thr; 221 void *buf; 222 u_long space; 223 224 space = getsendspace() / 2; 225 ATF_REQUIRE((buf = malloc(space)) != NULL); 226 227 /* First check with timeout, expecting 0 fds returned. */ 228 method(sv[0], 0, true); 229 230 /* Launch blocking thread. */ 231 ATF_REQUIRE(pthread_create(&thr, NULL, check_writable_blocking_thread, 232 &ctx) == 0); 233 234 /* Sleep a bit to make sure that thread is put to sleep. */ 235 usleep(10000); 236 ATF_REQUIRE(pthread_peekjoin_np(thr, NULL) == EBUSY); 237 238 /* Read some data and re-check, the fd is expected to be returned. */ 239 ATF_REQUIRE(read(sv[1], buf, space) == (ssize_t)space); 240 241 method(sv[0], 1, true); 242 243 /* Now check that thread was successfully woken up and exited. */ 244 ATF_REQUIRE(pthread_join(thr, NULL) == 0); 245 246 close(sv[0]); 247 close(sv[1]); 248 free(buf); 249 } 250 251 /* 252 * Make sure that a full socket is not reported as writable by event APIs. 253 */ 254 ATF_TC_WITHOUT_HEAD(full_writability_select); 255 ATF_TC_BODY(full_writability_select, tc) 256 { 257 int sv[2]; 258 259 full_socketpair(sv); 260 full_writability_check(sv, check_writable_select); 261 close(sv[0]); 262 close(sv[1]); 263 } 264 265 ATF_TC_WITHOUT_HEAD(full_writability_poll); 266 ATF_TC_BODY(full_writability_poll, tc) 267 { 268 int sv[2]; 269 270 full_socketpair(sv); 271 full_writability_check(sv, check_writable_poll); 272 close(sv[0]); 273 close(sv[1]); 274 } 275 276 ATF_TC_WITHOUT_HEAD(full_writability_kevent); 277 ATF_TC_BODY(full_writability_kevent, tc) 278 { 279 int sv[2]; 280 281 full_socketpair(sv); 282 full_writability_check(sv, check_writable_kevent); 283 close(sv[0]); 284 close(sv[1]); 285 } 286 287 ATF_TC_WITHOUT_HEAD(connected_writability); 288 ATF_TC_BODY(connected_writability, tc) 289 { 290 int sv[2]; 291 292 do_socketpair(sv); 293 check_writable_select(sv[0], 1, true); 294 check_writable_poll(sv[0], 1, true); 295 check_writable_kevent(sv[0], 1, true); 296 close(sv[0]); 297 close(sv[1]); 298 } 299 300 ATF_TC_WITHOUT_HEAD(unconnected_writability); 301 ATF_TC_BODY(unconnected_writability, tc) 302 { 303 int s; 304 305 ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_STREAM, 0)) > 0); 306 check_writable_select(s, 0, true); 307 check_writable_poll(s, 0, true); 308 check_writable_kevent(s, 0, true); 309 close(s); 310 } 311 312 ATF_TC_WITHOUT_HEAD(peerclosed_writability); 313 ATF_TC_BODY(peerclosed_writability, tc) 314 { 315 struct kevent kev; 316 int sv[2], kq; 317 318 do_socketpair(sv); 319 close(sv[1]); 320 321 check_writable_select(sv[0], 1, false); 322 check_writable_poll(sv[0], 1, false); 323 324 ATF_REQUIRE(kq = kqueue()); 325 EV_SET(&kev, sv[0], EVFILT_WRITE, EV_ADD, 0, 0, NULL); 326 ATF_REQUIRE(kevent(kq, &kev, 1, &kev, 1, NULL) == 1); 327 ATF_REQUIRE(kev.ident == (uintptr_t)sv[0] && 328 kev.filter == EVFILT_WRITE && 329 kev.flags == EV_EOF); 330 331 close(sv[0]); 332 } 333 334 ATF_TC_WITHOUT_HEAD(peershutdown_writability); 335 ATF_TC_BODY(peershutdown_writability, tc) 336 { 337 int sv[2]; 338 339 do_socketpair(sv); 340 shutdown(sv[1], SHUT_RD); 341 342 check_writable_select(sv[0], 1, false); 343 check_writable_poll(sv[0], 1, false); 344 /* 345 * XXXGL: historically unix(4) sockets were not reporting peer's 346 * shutdown(SHUT_RD) as our EV_EOF. The kevent(2) manual page says 347 * "filter will set EV_EOF when the reader disconnects", which is hard 348 * to interpret unambigously. For now leave the historic behavior, 349 * but we may want to change that in uipc_usrreq.c:uipc_filt_sowrite(), 350 * and then this test will look like the peerclosed_writability test. 351 */ 352 check_writable_kevent(sv[0], 1, false); 353 354 close(sv[0]); 355 close(sv[1]); 356 } 357 358 ATF_TC_WITHOUT_HEAD(peershutdown_readability); 359 ATF_TC_BODY(peershutdown_readability, tc) 360 { 361 ssize_t readsz; 362 int sv[2]; 363 char c; 364 365 do_socketpair(sv); 366 shutdown(sv[1], SHUT_WR); 367 368 /* 369 * The other side should flag as readable in select(2) to allow it to 370 * read(2) and observe EOF. Ensure that both poll(2) and select(2) 371 * are consistent here. 372 */ 373 check_readable_select(sv[0], 1, false); 374 check_readable_poll(sv[0], 1, false); 375 376 readsz = read(sv[0], &c, sizeof(c)); 377 ATF_REQUIRE_INTEQ(0, readsz); 378 379 close(sv[0]); 380 close(sv[1]); 381 } 382 383 ATF_TP_ADD_TCS(tp) 384 { 385 ATF_TP_ADD_TC(tp, getpeereid); 386 ATF_TP_ADD_TC(tp, send_0); 387 ATF_TP_ADD_TC(tp, connected_writability); 388 ATF_TP_ADD_TC(tp, unconnected_writability); 389 ATF_TP_ADD_TC(tp, full_writability_select); 390 ATF_TP_ADD_TC(tp, full_writability_poll); 391 ATF_TP_ADD_TC(tp, full_writability_kevent); 392 ATF_TP_ADD_TC(tp, peerclosed_writability); 393 ATF_TP_ADD_TC(tp, peershutdown_writability); 394 ATF_TP_ADD_TC(tp, peershutdown_readability); 395 396 return atf_no_error(); 397 } 398