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/sysctl.h> 32 #include <sys/un.h> 33 #include <errno.h> 34 #include <fcntl.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <poll.h> 38 #include <pthread.h> 39 #include <pthread_np.h> 40 41 #include <atf-c.h> 42 43 static void 44 do_socketpair(int *sv) 45 { 46 int s; 47 48 s = socketpair(PF_LOCAL, SOCK_STREAM, 0, sv); 49 ATF_REQUIRE_EQ(0, s); 50 ATF_REQUIRE(sv[0] >= 0); 51 ATF_REQUIRE(sv[1] >= 0); 52 ATF_REQUIRE(sv[0] != sv[1]); 53 } 54 55 static u_long 56 getsendspace(void) 57 { 58 u_long sendspace; 59 60 ATF_REQUIRE_MSG(sysctlbyname("net.local.stream.sendspace", &sendspace, 61 &(size_t){sizeof(u_long)}, NULL, 0) != -1, 62 "sysctl net.local.stream.sendspace failed: %s", strerror(errno)); 63 64 return (sendspace); 65 } 66 67 /* getpeereid(3) should work with stream sockets created via socketpair(2) */ 68 ATF_TC_WITHOUT_HEAD(getpeereid); 69 ATF_TC_BODY(getpeereid, tc) 70 { 71 int sv[2]; 72 uid_t real_euid, euid; 73 gid_t real_egid, egid; 74 75 real_euid = geteuid(); 76 real_egid = getegid(); 77 78 do_socketpair(sv); 79 80 ATF_REQUIRE_EQ(0, getpeereid(sv[0], &euid, &egid)); 81 ATF_CHECK_EQ(real_euid, euid); 82 ATF_CHECK_EQ(real_egid, egid); 83 84 ATF_REQUIRE_EQ(0, getpeereid(sv[1], &euid, &egid)); 85 ATF_CHECK_EQ(real_euid, euid); 86 ATF_CHECK_EQ(real_egid, egid); 87 88 close(sv[0]); 89 close(sv[1]); 90 } 91 92 /* Sending zero bytes should succeed (once regressed in aba79b0f4a3f). */ 93 ATF_TC_WITHOUT_HEAD(send_0); 94 ATF_TC_BODY(send_0, tc) 95 { 96 int sv[2]; 97 98 do_socketpair(sv); 99 ATF_REQUIRE(send(sv[0], sv, 0, 0) == 0); 100 close(sv[0]); 101 close(sv[1]); 102 } 103 104 static void 105 check_writable_select(int fd, int expect, bool timeout) 106 { 107 fd_set wrfds; 108 int nfds; 109 110 FD_ZERO(&wrfds); 111 FD_SET(fd, &wrfds); 112 nfds = select(fd + 1, NULL, &wrfds, NULL, timeout ? 113 &(struct timeval){.tv_usec = 1000} : NULL); 114 ATF_REQUIRE_MSG(nfds == expect, 115 "select() returns %d errno %d", nfds, errno); 116 } 117 118 static void 119 check_writable_poll(int fd, int expect, bool timeout) 120 { 121 struct pollfd pfd[1]; 122 int nfds; 123 124 pfd[0] = (struct pollfd){ 125 .fd = fd, 126 .events = POLLOUT | POLLWRNORM, 127 }; 128 nfds = poll(pfd, 1, timeout ? 1 : INFTIM); 129 ATF_REQUIRE_MSG(nfds == expect, 130 "poll() returns %d errno %d", nfds, errno); 131 } 132 133 static void 134 check_writable_kevent(int fd, int expect, bool timeout) 135 { 136 struct kevent kev; 137 int nfds, kq; 138 139 ATF_REQUIRE(kq = kqueue()); 140 EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); 141 nfds = kevent(kq, &kev, 1, NULL, 0, NULL); 142 ATF_REQUIRE_MSG(nfds == 0, 143 "kevent() returns %d errno %d", nfds, errno); 144 nfds = kevent(kq, NULL, 0, &kev, 1, timeout ? 145 &(struct timespec){.tv_nsec = 1000000} : NULL); 146 ATF_REQUIRE_MSG(nfds == expect, 147 "kevent() returns %d errno %d", nfds, errno); 148 close(kq); 149 } 150 151 typedef void check_writable_func_t(int, int, bool); 152 struct check_writable_ctx { 153 check_writable_func_t *method; 154 int fd; 155 }; 156 157 static void * 158 check_writable_blocking_thread(void *arg) 159 { 160 struct check_writable_ctx *ctx = arg; 161 162 ctx->method(ctx->fd, 1, false); 163 164 return (NULL); 165 } 166 167 static void 168 full_socketpair(int *sv) 169 { 170 void *buf; 171 u_long sendspace; 172 173 sendspace = getsendspace(); 174 ATF_REQUIRE((buf = malloc(sendspace)) != NULL); 175 do_socketpair(sv); 176 ATF_REQUIRE(fcntl(sv[0], F_SETFL, O_NONBLOCK) != -1); 177 do {} while (send(sv[0], buf, sendspace, 0) == (ssize_t)sendspace); 178 ATF_REQUIRE(errno == EAGAIN); 179 ATF_REQUIRE(fcntl(sv[0], F_SETFL, 0) != -1); 180 free(buf); 181 } 182 183 static void 184 full_writability_check(int *sv, check_writable_func_t method) 185 { 186 struct check_writable_ctx ctx = { 187 .method = method, 188 .fd = sv[0], 189 }; 190 pthread_t thr; 191 void *buf; 192 u_long space; 193 194 space = getsendspace() / 2; 195 ATF_REQUIRE((buf = malloc(space)) != NULL); 196 197 /* First check with timeout, expecting 0 fds returned. */ 198 method(sv[0], 0, true); 199 200 /* Launch blocking thread. */ 201 ATF_REQUIRE(pthread_create(&thr, NULL, check_writable_blocking_thread, 202 &ctx) == 0); 203 204 /* Sleep a bit to make sure that thread is put to sleep. */ 205 usleep(10000); 206 ATF_REQUIRE(pthread_peekjoin_np(thr, NULL) == EBUSY); 207 208 /* Read some data and re-check, the fd is expected to be returned. */ 209 ATF_REQUIRE(read(sv[1], buf, space) == (ssize_t)space); 210 211 method(sv[0], 1, true); 212 213 /* Now check that thread was successfully woken up and exited. */ 214 ATF_REQUIRE(pthread_join(thr, NULL) == 0); 215 216 close(sv[0]); 217 close(sv[1]); 218 free(buf); 219 } 220 221 /* 222 * Make sure that a full socket is not reported as writable by event APIs. 223 */ 224 ATF_TC_WITHOUT_HEAD(full_writability_select); 225 ATF_TC_BODY(full_writability_select, tc) 226 { 227 int sv[2]; 228 229 full_socketpair(sv); 230 full_writability_check(sv, check_writable_select); 231 close(sv[0]); 232 close(sv[1]); 233 } 234 235 ATF_TC_WITHOUT_HEAD(full_writability_poll); 236 ATF_TC_BODY(full_writability_poll, tc) 237 { 238 int sv[2]; 239 240 full_socketpair(sv); 241 full_writability_check(sv, check_writable_poll); 242 close(sv[0]); 243 close(sv[1]); 244 } 245 246 ATF_TC_WITHOUT_HEAD(full_writability_kevent); 247 ATF_TC_BODY(full_writability_kevent, tc) 248 { 249 int sv[2]; 250 251 full_socketpair(sv); 252 full_writability_check(sv, check_writable_kevent); 253 close(sv[0]); 254 close(sv[1]); 255 } 256 257 ATF_TC_WITHOUT_HEAD(connected_writability); 258 ATF_TC_BODY(connected_writability, tc) 259 { 260 int sv[2]; 261 262 do_socketpair(sv); 263 check_writable_select(sv[0], 1, true); 264 check_writable_poll(sv[0], 1, true); 265 check_writable_kevent(sv[0], 1, true); 266 close(sv[0]); 267 close(sv[1]); 268 } 269 270 ATF_TC_WITHOUT_HEAD(unconnected_writability); 271 ATF_TC_BODY(unconnected_writability, tc) 272 { 273 int s; 274 275 ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_STREAM, 0)) > 0); 276 check_writable_select(s, 0, true); 277 check_writable_poll(s, 0, true); 278 check_writable_kevent(s, 0, true); 279 close(s); 280 } 281 282 ATF_TC_WITHOUT_HEAD(peerclosed_writability); 283 ATF_TC_BODY(peerclosed_writability, tc) 284 { 285 struct kevent kev; 286 int sv[2], kq; 287 288 do_socketpair(sv); 289 close(sv[1]); 290 291 check_writable_select(sv[0], 1, false); 292 check_writable_poll(sv[0], 1, false); 293 294 ATF_REQUIRE(kq = kqueue()); 295 EV_SET(&kev, sv[0], EVFILT_WRITE, EV_ADD, 0, 0, NULL); 296 ATF_REQUIRE(kevent(kq, &kev, 1, &kev, 1, NULL) == 1); 297 ATF_REQUIRE(kev.ident == (uintptr_t)sv[0] && 298 kev.filter == EVFILT_WRITE && 299 kev.flags == EV_EOF); 300 301 close(sv[0]); 302 } 303 304 ATF_TC_WITHOUT_HEAD(peershutdown_writability); 305 ATF_TC_BODY(peershutdown_writability, tc) 306 { 307 int sv[2]; 308 309 do_socketpair(sv); 310 shutdown(sv[1], SHUT_RD); 311 312 check_writable_select(sv[0], 1, false); 313 check_writable_poll(sv[0], 1, false); 314 /* 315 * XXXGL: historically unix(4) sockets were not reporting peer's 316 * shutdown(SHUT_RD) as our EV_EOF. The kevent(2) manual page says 317 * "filter will set EV_EOF when the reader disconnects", which is hard 318 * to interpret unambigously. For now leave the historic behavior, 319 * but we may want to change that in uipc_usrreq.c:uipc_filt_sowrite(), 320 * and then this test will look like the peerclosed_writability test. 321 */ 322 check_writable_kevent(sv[0], 1, false); 323 324 close(sv[0]); 325 close(sv[1]); 326 } 327 328 ATF_TP_ADD_TCS(tp) 329 { 330 ATF_TP_ADD_TC(tp, getpeereid); 331 ATF_TP_ADD_TC(tp, send_0); 332 ATF_TP_ADD_TC(tp, connected_writability); 333 ATF_TP_ADD_TC(tp, unconnected_writability); 334 ATF_TP_ADD_TC(tp, full_writability_select); 335 ATF_TP_ADD_TC(tp, full_writability_poll); 336 ATF_TP_ADD_TC(tp, full_writability_kevent); 337 ATF_TP_ADD_TC(tp, peerclosed_writability); 338 ATF_TP_ADD_TC(tp, peershutdown_writability); 339 340 return atf_no_error(); 341 } 342