xref: /freebsd/tests/sys/kern/unix_stream.c (revision 9b37d84c87e69dabc69d818aa4d2fea718bd8b74)
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