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 39 #include <atf-c.h> 40 41 static void 42 do_socketpair(int *sv) 43 { 44 int s; 45 46 s = socketpair(PF_LOCAL, SOCK_STREAM, 0, sv); 47 ATF_REQUIRE_EQ(0, s); 48 ATF_REQUIRE(sv[0] >= 0); 49 ATF_REQUIRE(sv[1] >= 0); 50 ATF_REQUIRE(sv[0] != sv[1]); 51 } 52 53 static u_long 54 getsendspace(void) 55 { 56 u_long sendspace; 57 58 ATF_REQUIRE_MSG(sysctlbyname("net.local.stream.sendspace", &sendspace, 59 &(size_t){sizeof(u_long)}, NULL, 0) != -1, 60 "sysctl net.local.stream.sendspace failed: %s", strerror(errno)); 61 62 return (sendspace); 63 } 64 65 /* getpeereid(3) should work with stream sockets created via socketpair(2) */ 66 ATF_TC_WITHOUT_HEAD(getpeereid); 67 ATF_TC_BODY(getpeereid, tc) 68 { 69 int sv[2]; 70 uid_t real_euid, euid; 71 gid_t real_egid, egid; 72 73 real_euid = geteuid(); 74 real_egid = getegid(); 75 76 do_socketpair(sv); 77 78 ATF_REQUIRE_EQ(0, getpeereid(sv[0], &euid, &egid)); 79 ATF_CHECK_EQ(real_euid, euid); 80 ATF_CHECK_EQ(real_egid, egid); 81 82 ATF_REQUIRE_EQ(0, getpeereid(sv[1], &euid, &egid)); 83 ATF_CHECK_EQ(real_euid, euid); 84 ATF_CHECK_EQ(real_egid, egid); 85 86 close(sv[0]); 87 close(sv[1]); 88 } 89 90 /* Sending zero bytes should succeed (once regressed in aba79b0f4a3f). */ 91 ATF_TC_WITHOUT_HEAD(send_0); 92 ATF_TC_BODY(send_0, tc) 93 { 94 int sv[2]; 95 96 do_socketpair(sv); 97 ATF_REQUIRE(send(sv[0], sv, 0, 0) == 0); 98 close(sv[0]); 99 close(sv[1]); 100 } 101 102 static void 103 check_writable(int fd, int expect) 104 { 105 fd_set wrfds; 106 struct pollfd pfd[1]; 107 struct kevent kev; 108 int nfds, kq; 109 110 FD_ZERO(&wrfds); 111 FD_SET(fd, &wrfds); 112 nfds = select(fd + 1, NULL, &wrfds, NULL, 113 &(struct timeval){.tv_usec = 1000}); 114 ATF_REQUIRE_MSG(nfds == expect, 115 "select() returns %d errno %d", nfds, errno); 116 117 pfd[0] = (struct pollfd){ 118 .fd = fd, 119 .events = POLLOUT | POLLWRNORM, 120 }; 121 nfds = poll(pfd, 1, 1); 122 ATF_REQUIRE_MSG(nfds == expect, 123 "poll() returns %d errno %d", nfds, errno); 124 125 ATF_REQUIRE(kq = kqueue()); 126 EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); 127 ATF_REQUIRE(kevent(kq, &kev, 1, NULL, 0, NULL) == 0); 128 nfds = kevent(kq, NULL, 0, &kev, 1, 129 &(struct timespec){.tv_nsec = 1000000}); 130 ATF_REQUIRE_MSG(nfds == expect, 131 "kevent() returns %d errno %d", nfds, errno); 132 close(kq); 133 } 134 135 /* 136 * Make sure that a full socket is not reported as writable by event APIs. 137 */ 138 ATF_TC_WITHOUT_HEAD(full_not_writable); 139 ATF_TC_BODY(full_not_writable, tc) 140 { 141 void *buf; 142 u_long sendspace; 143 int sv[2]; 144 145 sendspace = getsendspace(); 146 ATF_REQUIRE((buf = malloc(sendspace)) != NULL); 147 do_socketpair(sv); 148 ATF_REQUIRE(fcntl(sv[0], F_SETFL, O_NONBLOCK) != -1); 149 do {} while (send(sv[0], buf, sendspace, 0) == (ssize_t)sendspace); 150 ATF_REQUIRE(errno == EAGAIN); 151 ATF_REQUIRE(fcntl(sv[0], F_SETFL, 0) != -1); 152 153 check_writable(sv[0], 0); 154 155 /* Read some data and re-check. */ 156 ATF_REQUIRE(read(sv[1], buf, sendspace / 2) == (ssize_t)sendspace / 2); 157 158 check_writable(sv[0], 1); 159 160 free(buf); 161 close(sv[0]); 162 close(sv[1]); 163 } 164 165 ATF_TP_ADD_TCS(tp) 166 { 167 ATF_TP_ADD_TC(tp, getpeereid); 168 ATF_TP_ADD_TC(tp, send_0); 169 ATF_TP_ADD_TC(tp, full_not_writable); 170 171 return atf_no_error(); 172 } 173