1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2024 Stormshield
5 */
6
7 #include <sys/capsicum.h>
8 #include <sys/event.h>
9 #include <sys/filio.h>
10 #include <sys/socket.h>
11 #include <sys/wait.h>
12
13 #include <netinet/in.h>
14 #include <netinet/tcp.h>
15
16 #include <errno.h>
17 #include <poll.h>
18 #include <pthread.h>
19 #include <signal.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <time.h>
24
25 #include <atf-c.h>
26
27 static void
checked_close(int fd)28 checked_close(int fd)
29 {
30 int error;
31
32 error = close(fd);
33 ATF_REQUIRE_MSG(error == 0, "close failed: %s", strerror(errno));
34 }
35
36 static int
fionread(int fd)37 fionread(int fd)
38 {
39 int data, error;
40
41 data = 0;
42 error = ioctl(fd, FIONREAD, &data);
43 ATF_REQUIRE_MSG(error == 0, "ioctl failed: %s", strerror(errno));
44 ATF_REQUIRE(data >= 0);
45 return (data);
46 }
47
48 static void
noblocking(int fd)49 noblocking(int fd)
50 {
51 int flags, error;
52
53 flags = fcntl(fd, F_GETFL);
54 ATF_REQUIRE_MSG(flags != -1, "fcntl failed: %s", strerror(errno));
55 flags |= O_NONBLOCK;
56 error = fcntl(fd, F_SETFL, flags);
57 ATF_REQUIRE_MSG(error == 0, "fcntl failed: %s", strerror(errno));
58 }
59
60 /*
61 * Create a pair of connected TCP sockets, returned via the "out" array.
62 */
63 static void
tcp_socketpair(int out[2],int domain)64 tcp_socketpair(int out[2], int domain)
65 {
66 struct sockaddr_in sin;
67 struct sockaddr_in6 sin6;
68 struct sockaddr *sinp;
69 int error, sd[2];
70
71 sd[0] = socket(domain, SOCK_STREAM, 0);
72 ATF_REQUIRE_MSG(sd[0] >= 0, "socket failed: %s", strerror(errno));
73 sd[1] = socket(domain, SOCK_STREAM, 0);
74 ATF_REQUIRE_MSG(sd[1] >= 0, "socket failed: %s", strerror(errno));
75
76 error = setsockopt(sd[0], IPPROTO_TCP, TCP_NODELAY, &(int){ 1 },
77 sizeof(int));
78 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
79 error = setsockopt(sd[1], IPPROTO_TCP, TCP_NODELAY, &(int){ 1 },
80 sizeof(int));
81 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
82
83 if (domain == PF_INET) {
84 memset(&sin, 0, sizeof(sin));
85 sin.sin_family = AF_INET;
86 sin.sin_len = sizeof(sin);
87 sin.sin_addr.s_addr = htonl(INADDR_ANY);
88 sin.sin_port = htons(0);
89 sinp = (struct sockaddr *)&sin;
90 } else {
91 ATF_REQUIRE(domain == PF_INET6);
92 memset(&sin6, 0, sizeof(sin6));
93 sin6.sin6_family = AF_INET6;
94 sin6.sin6_len = sizeof(sin6);
95 sin6.sin6_addr = in6addr_any;
96 sin6.sin6_port = htons(0);
97 sinp = (struct sockaddr *)&sin6;
98 }
99
100 error = bind(sd[0], sinp, sinp->sa_len);
101 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
102 error = listen(sd[0], 1);
103 ATF_REQUIRE_MSG(error == 0, "listen failed: %s", strerror(errno));
104
105 error = getsockname(sd[0], sinp, &(socklen_t){ sinp->sa_len });
106 ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", strerror(errno));
107
108 error = connect(sd[1], sinp, sinp->sa_len);
109 ATF_REQUIRE_MSG(error == 0, "connect failed: %s", strerror(errno));
110 out[0] = accept(sd[0], NULL, NULL);
111 ATF_REQUIRE_MSG(out[0] >= 0, "accept failed: %s", strerror(errno));
112 checked_close(sd[0]);
113 out[1] = sd[1];
114 }
115
116 static void
tcp4_socketpair(int out[2])117 tcp4_socketpair(int out[2])
118 {
119 tcp_socketpair(out, PF_INET);
120 }
121
122 static void
tcp6_socketpair(int out[2])123 tcp6_socketpair(int out[2])
124 {
125 tcp_socketpair(out, PF_INET6);
126 }
127
128 static off_t
nspliced(int sd)129 nspliced(int sd)
130 {
131 off_t n;
132 socklen_t len;
133 int error;
134
135 len = sizeof(n);
136 error = getsockopt(sd, SOL_SOCKET, SO_SPLICE, &n, &len);
137 ATF_REQUIRE_MSG(error == 0, "getsockopt failed: %s", strerror(errno));
138 ATF_REQUIRE_MSG(len == sizeof(n), "unexpected length: %d", len);
139 return (n);
140 }
141
142 /*
143 * Use a macro so that ATF_REQUIRE_MSG prints a useful line number.
144 */
145 #define check_nspliced(sd, n) do { \
146 off_t sofar; \
147 \
148 sofar = nspliced(sd); \
149 ATF_REQUIRE_MSG(sofar == (off_t)n, "spliced %jd bytes, expected %jd", \
150 (intmax_t)sofar, (intmax_t)n); \
151 } while (0)
152
153 static void
splice_init(struct splice * sp,int fd,off_t max,struct timeval * tv)154 splice_init(struct splice *sp, int fd, off_t max, struct timeval *tv)
155 {
156 memset(sp, 0, sizeof(*sp));
157 sp->sp_fd = fd;
158 sp->sp_max = max;
159 if (tv != NULL)
160 sp->sp_idle = *tv;
161 else
162 sp->sp_idle.tv_sec = sp->sp_idle.tv_usec = 0;
163 }
164
165 static void
unsplice(int fd)166 unsplice(int fd)
167 {
168 struct splice sp;
169 int error;
170
171 splice_init(&sp, -1, 0, NULL);
172 error = setsockopt(fd, SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
173 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
174 }
175
176 static void
unsplice_pair(int fd1,int fd2)177 unsplice_pair(int fd1, int fd2)
178 {
179 unsplice(fd1);
180 unsplice(fd2);
181 }
182
183 static void
splice_pair(int fd1,int fd2,off_t max,struct timeval * tv)184 splice_pair(int fd1, int fd2, off_t max, struct timeval *tv)
185 {
186 struct splice sp;
187 int error;
188
189 splice_init(&sp, fd1, max, tv);
190 error = setsockopt(fd2, SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
191 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
192
193 splice_init(&sp, fd2, max, tv);
194 error = setsockopt(fd1, SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
195 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
196 }
197
198 /*
199 * A structure representing a spliced pair of connections. left[1] is
200 * bidirectionally spliced with right[0].
201 */
202 struct splice_conn {
203 int left[2];
204 int right[2];
205 };
206
207 /*
208 * Initialize a splice connection with the given maximum number of bytes to
209 * splice and the given idle timeout. For now we're forced to use TCP socket,
210 * but at some point it would be nice (and simpler) to use pairs of PF_LOCAL
211 * sockets.
212 */
213 static void
splice_conn_init_limits(struct splice_conn * sc,off_t max,struct timeval * tv)214 splice_conn_init_limits(struct splice_conn *sc, off_t max, struct timeval *tv)
215 {
216 memset(sc, 0, sizeof(*sc));
217 tcp4_socketpair(sc->left);
218 tcp4_socketpair(sc->right);
219 splice_pair(sc->left[1], sc->right[0], max, tv);
220 }
221
222 static void
splice_conn_init(struct splice_conn * sc)223 splice_conn_init(struct splice_conn *sc)
224 {
225 splice_conn_init_limits(sc, 0, NULL);
226 }
227
228 static void
splice_conn_check_empty(struct splice_conn * sc)229 splice_conn_check_empty(struct splice_conn *sc)
230 {
231 int data;
232
233 data = fionread(sc->left[0]);
234 ATF_REQUIRE_MSG(data == 0, "unexpected data on left[0]: %d", data);
235 data = fionread(sc->left[1]);
236 ATF_REQUIRE_MSG(data == 0, "unexpected data on left[1]: %d", data);
237 data = fionread(sc->right[0]);
238 ATF_REQUIRE_MSG(data == 0, "unexpected data on right[0]: %d", data);
239 data = fionread(sc->right[1]);
240 ATF_REQUIRE_MSG(data == 0, "unexpected data on right[1]: %d", data);
241 }
242
243 static void
splice_conn_fini(struct splice_conn * sc)244 splice_conn_fini(struct splice_conn *sc)
245 {
246 checked_close(sc->left[0]);
247 checked_close(sc->left[1]);
248 checked_close(sc->right[0]);
249 checked_close(sc->right[1]);
250 }
251
252 static void
splice_conn_noblocking(struct splice_conn * sc)253 splice_conn_noblocking(struct splice_conn *sc)
254 {
255 noblocking(sc->left[0]);
256 noblocking(sc->left[1]);
257 noblocking(sc->right[0]);
258 noblocking(sc->right[1]);
259 }
260
261 /* Pass a byte through a pair of spliced connections. */
262 ATF_TC_WITHOUT_HEAD(splice_basic);
ATF_TC_BODY(splice_basic,tc)263 ATF_TC_BODY(splice_basic, tc)
264 {
265 struct splice_conn sc;
266 ssize_t n;
267 char c;
268
269 splice_conn_init(&sc);
270
271 check_nspliced(sc.left[1], 0);
272 check_nspliced(sc.right[0], 0);
273
274 /* Left-to-right. */
275 c = 'M';
276 n = write(sc.left[0], &c, 1);
277 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
278 n = read(sc.right[1], &c, 1);
279 ATF_REQUIRE_MSG(n == 1, "read failed: %s", strerror(errno));
280 ATF_REQUIRE_MSG(c == 'M', "unexpected character: %c", c);
281 check_nspliced(sc.left[1], 1);
282 check_nspliced(sc.right[0], 0);
283
284 /* Right-to-left. */
285 c = 'J';
286 n = write(sc.right[1], &c, 1);
287 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
288 n = read(sc.left[0], &c, 1);
289 ATF_REQUIRE_MSG(n == 1, "read failed: %s", strerror(errno));
290 ATF_REQUIRE_MSG(c == 'J', "unexpected character: %c", c);
291 check_nspliced(sc.left[1], 1);
292 check_nspliced(sc.right[0], 1);
293
294 /* Unsplice and verify that the byte counts haven't changed. */
295 unsplice(sc.left[1]);
296 unsplice(sc.right[0]);
297 check_nspliced(sc.left[1], 1);
298 check_nspliced(sc.right[0], 1);
299
300 splice_conn_fini(&sc);
301 }
302
303 static void
remove_rights(int fd,const cap_rights_t * toremove)304 remove_rights(int fd, const cap_rights_t *toremove)
305 {
306 cap_rights_t rights;
307 int error;
308
309 error = cap_rights_get(fd, &rights);
310 ATF_REQUIRE_MSG(error == 0, "cap_rights_get failed: %s",
311 strerror(errno));
312 cap_rights_remove(&rights, toremove);
313 error = cap_rights_limit(fd, &rights);
314 ATF_REQUIRE_MSG(error == 0, "cap_rights_limit failed: %s",
315 strerror(errno));
316 }
317
318 /*
319 * Verify that splicing fails when the socket is missing the necessary rights.
320 */
321 ATF_TC_WITHOUT_HEAD(splice_capsicum);
ATF_TC_BODY(splice_capsicum,tc)322 ATF_TC_BODY(splice_capsicum, tc)
323 {
324 struct splice sp;
325 cap_rights_t rights;
326 off_t n;
327 int error, left[2], right[2];
328
329 tcp4_socketpair(left);
330 tcp4_socketpair(right);
331
332 /*
333 * Make sure that we can't splice a socket that's missing recv rights.
334 */
335 remove_rights(left[1], cap_rights_init(&rights, CAP_RECV));
336 splice_init(&sp, right[0], 0, NULL);
337 error = setsockopt(left[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
338 ATF_REQUIRE_ERRNO(ENOTCAPABLE, error == -1);
339
340 /* Make sure we can still splice left[1] in the other direction. */
341 splice_init(&sp, left[1], 0, NULL);
342 error = setsockopt(right[0], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
343 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
344 splice_init(&sp, -1, 0, NULL);
345 error = setsockopt(right[0], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
346 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
347
348 /*
349 * Now remove send rights from left[1] and verify that splicing is no
350 * longer possible.
351 */
352 remove_rights(left[1], cap_rights_init(&rights, CAP_SEND));
353 splice_init(&sp, left[1], 0, NULL);
354 error = setsockopt(right[0], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
355 ATF_REQUIRE_ERRNO(ENOTCAPABLE, error == -1);
356
357 /*
358 * It's still ok to query the SO_SPLICE state though.
359 */
360 n = -1;
361 error = getsockopt(left[1], SOL_SOCKET, SO_SPLICE, &n,
362 &(socklen_t){ sizeof(n) });
363 ATF_REQUIRE_MSG(error == 0, "getsockopt failed: %s", strerror(errno));
364 ATF_REQUIRE(n == 0);
365
366 /*
367 * Make sure that we can unsplice a spliced pair without any rights
368 * other than CAP_SETSOCKOPT.
369 */
370 splice_pair(left[0], right[1], 0, NULL);
371 error = cap_rights_limit(left[0],
372 cap_rights_init(&rights, CAP_SETSOCKOPT));
373 ATF_REQUIRE_MSG(error == 0, "cap_rights_limit failed: %s",
374 strerror(errno));
375 unsplice(left[0]);
376
377 checked_close(left[0]);
378 checked_close(left[1]);
379 checked_close(right[0]);
380 checked_close(right[1]);
381 }
382
383 /*
384 * Check various error cases in splice configuration.
385 */
386 ATF_TC_WITHOUT_HEAD(splice_error);
ATF_TC_BODY(splice_error,tc)387 ATF_TC_BODY(splice_error, tc)
388 {
389 struct splice_conn sc;
390 struct splice sp;
391 char path[PATH_MAX];
392 int error, fd, sd, usd[2];
393
394 memset(&sc, 0, sizeof(sc));
395 tcp4_socketpair(sc.left);
396 tcp4_socketpair(sc.right);
397
398 /* A negative byte limit is invalid. */
399 splice_init(&sp, sc.right[0], -3, NULL);
400 error = setsockopt(sc.left[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
401 ATF_REQUIRE_ERRNO(EINVAL, error == -1);
402
403 /* Can't unsplice a never-spliced socket. */
404 splice_init(&sp, -1, 0, NULL);
405 error = setsockopt(sc.left[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
406 ATF_REQUIRE_ERRNO(ENOTCONN, error == -1);
407
408 /* Can't double-unsplice a socket. */
409 splice_init(&sp, sc.right[0], 0, NULL);
410 error = setsockopt(sc.left[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
411 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
412 unsplice(sc.left[1]);
413 splice_init(&sp, -1, 0, NULL);
414 error = setsockopt(sc.left[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
415 ATF_REQUIRE_ERRNO(ENOTCONN, error == -1);
416
417 /* Can't splice a spliced socket */
418 splice_init(&sp, sc.right[0], 0, NULL);
419 error = setsockopt(sc.left[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
420 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
421 splice_init(&sp, sc.right[1], 0, NULL);
422 error = setsockopt(sc.left[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
423 ATF_REQUIRE_ERRNO(EBUSY, error == -1);
424 splice_init(&sp, sc.right[0], 0, NULL);
425 error = setsockopt(sc.left[0], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
426 ATF_REQUIRE_ERRNO(EBUSY, error == -1);
427 splice_init(&sp, -1, 0, NULL);
428 error = setsockopt(sc.left[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
429
430 /* Can't splice to a non-socket. */
431 snprintf(path, sizeof(path), "/tmp/splice_error.XXXXXX");
432 fd = mkstemp(path);
433 ATF_REQUIRE_MSG(fd >= 0, "mkstemp failed: %s", strerror(errno));
434 splice_init(&sp, fd, 0, NULL);
435 error = setsockopt(sc.left[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
436 ATF_REQUIRE_ERRNO(ENOTSOCK, error == -1);
437
438 /* Can't splice to an invalid fd. */
439 checked_close(fd);
440 splice_init(&sp, fd, 0, NULL);
441 error = setsockopt(sc.left[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
442 ATF_REQUIRE_ERRNO(EBADF, error == -1);
443
444 /* Can't splice a unix stream socket. */
445 error = socketpair(AF_UNIX, SOCK_STREAM, 0, usd);
446 ATF_REQUIRE_MSG(error == 0, "socketpair failed: %s", strerror(errno));
447 splice_init(&sp, usd[0], 0, NULL);
448 error = setsockopt(sc.left[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
449 ATF_REQUIRE_ERRNO(EPROTONOSUPPORT, error == -1);
450 error = setsockopt(usd[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
451 ATF_REQUIRE_ERRNO(EPROTONOSUPPORT, error == -1);
452 checked_close(usd[0]);
453 checked_close(usd[1]);
454
455 /* Can't splice an unconnected TCP socket. */
456 sd = socket(PF_INET, SOCK_STREAM, 0);
457 ATF_REQUIRE_MSG(sd >= 0, "socket failed: %s", strerror(errno));
458 splice_init(&sp, sd, 0, NULL);
459 error = setsockopt(sc.left[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
460 ATF_REQUIRE_ERRNO(ENOTCONN, error == -1);
461 splice_init(&sp, sc.right[0], 0, NULL);
462 error = setsockopt(sd, SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
463 ATF_REQUIRE_ERRNO(ENOTCONN, error == -1);
464
465 splice_conn_fini(&sc);
466 }
467
468 /*
469 * Make sure that kevent() doesn't report read I/O events on spliced sockets.
470 */
471 ATF_TC_WITHOUT_HEAD(splice_kevent);
ATF_TC_BODY(splice_kevent,tc)472 ATF_TC_BODY(splice_kevent, tc)
473 {
474 struct splice_conn sc;
475 struct kevent kev;
476 struct timespec ts;
477 ssize_t n;
478 int error, nev, kq;
479 uint8_t b;
480
481 splice_conn_init(&sc);
482
483 kq = kqueue();
484 ATF_REQUIRE_MSG(kq >= 0, "kqueue failed: %s", strerror(errno));
485
486 EV_SET(&kev, sc.left[1], EVFILT_READ, EV_ADD, 0, 0, NULL);
487 error = kevent(kq, &kev, 1, NULL, 0, NULL);
488 ATF_REQUIRE_MSG(error == 0, "kevent failed: %s", strerror(errno));
489
490 memset(&ts, 0, sizeof(ts));
491 nev = kevent(kq, NULL, 0, &kev, 1, &ts);
492 ATF_REQUIRE_MSG(nev >= 0, "kevent failed: %s", strerror(errno));
493 ATF_REQUIRE(nev == 0);
494
495 b = 'M';
496 n = write(sc.left[0], &b, 1);
497 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
498 n = read(sc.right[1], &b, 1);
499 ATF_REQUIRE_MSG(n == 1, "read failed: %s", strerror(errno));
500 ATF_REQUIRE(b == 'M');
501
502 nev = kevent(kq, NULL, 0, &kev, 1, &ts);
503 ATF_REQUIRE_MSG(nev >= 0, "kevent failed: %s", strerror(errno));
504 ATF_REQUIRE(nev == 0);
505
506 b = 'J';
507 n = write(sc.right[1], &b, 1);
508 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
509 n = read(sc.left[0], &b, 1);
510 ATF_REQUIRE_MSG(n == 1, "read failed: %s", strerror(errno));
511 ATF_REQUIRE(b == 'J');
512
513 splice_conn_fini(&sc);
514 checked_close(kq);
515 }
516
517 /*
518 * Verify that a splice byte limit is applied.
519 */
520 ATF_TC_WITHOUT_HEAD(splice_limit_bytes);
ATF_TC_BODY(splice_limit_bytes,tc)521 ATF_TC_BODY(splice_limit_bytes, tc)
522 {
523 struct splice_conn sc;
524 ssize_t n;
525 uint8_t b, buf[128];
526
527 splice_conn_init_limits(&sc, sizeof(buf) + 1, NULL);
528
529 memset(buf, 'A', sizeof(buf));
530 for (size_t total = sizeof(buf); total > 0; total -= n) {
531 n = write(sc.left[0], buf, total);
532 ATF_REQUIRE_MSG(n > 0, "write failed: %s", strerror(errno));
533 }
534 for (size_t total = sizeof(buf); total > 0; total -= n) {
535 n = read(sc.right[1], buf, sizeof(buf));
536 ATF_REQUIRE_MSG(n > 0, "read failed: %s", strerror(errno));
537 }
538
539 check_nspliced(sc.left[1], sizeof(buf));
540 check_nspliced(sc.right[0], 0);
541
542 /* Trigger an unsplice by writing the last byte. */
543 b = 'B';
544 n = write(sc.left[0], &b, 1);
545 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
546 n = read(sc.right[1], &b, 1);
547 ATF_REQUIRE_MSG(n == 1, "read failed: %s", strerror(errno));
548 ATF_REQUIRE(b == 'B');
549
550 /*
551 * The next byte should appear on the other side of the connection
552 * rather than the splice.
553 */
554 b = 'C';
555 n = write(sc.left[0], &b, 1);
556 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
557 n = read(sc.left[1], &b, 1);
558 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
559 ATF_REQUIRE(b == 'C');
560
561 splice_conn_check_empty(&sc);
562
563 splice_conn_fini(&sc);
564 }
565
566 /*
567 * Verify that a splice timeout limit is applied.
568 */
569 ATF_TC_WITHOUT_HEAD(splice_limit_timeout);
ATF_TC_BODY(splice_limit_timeout,tc)570 ATF_TC_BODY(splice_limit_timeout, tc)
571 {
572 struct splice_conn sc;
573 ssize_t n;
574 int error;
575 uint8_t b, buf[128];
576
577 splice_conn_init_limits(&sc, 0,
578 &(struct timeval){ .tv_sec = 0, .tv_usec = 500000 /* 500ms */ });
579
580 /* Write some data through the splice. */
581 memset(buf, 'A', sizeof(buf));
582 for (size_t total = sizeof(buf); total > 0; total -= n) {
583 n = write(sc.left[0], buf, total);
584 ATF_REQUIRE_MSG(n > 0, "write failed: %s", strerror(errno));
585 }
586 for (size_t total = sizeof(buf); total > 0; total -= n) {
587 n = read(sc.right[1], buf, sizeof(buf));
588 ATF_REQUIRE_MSG(n > 0, "read failed: %s", strerror(errno));
589 }
590
591 check_nspliced(sc.left[1], sizeof(buf));
592 check_nspliced(sc.right[0], 0);
593
594 /* Wait for the splice to time out. */
595 error = usleep(550000);
596 ATF_REQUIRE_MSG(error == 0, "usleep failed: %s", strerror(errno));
597
598 /*
599 * The next byte should appear on the other side of the connection
600 * rather than the splice.
601 */
602 b = 'C';
603 n = write(sc.left[0], &b, 1);
604 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
605 n = read(sc.left[1], &b, 1);
606 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
607 ATF_REQUIRE(b == 'C');
608
609 splice_conn_fini(&sc);
610 }
611
612 /*
613 * Make sure that listen() fails on spliced sockets, and that SO_SPLICE can't be
614 * used with listening sockets.
615 */
616 ATF_TC_WITHOUT_HEAD(splice_listen);
ATF_TC_BODY(splice_listen,tc)617 ATF_TC_BODY(splice_listen, tc)
618 {
619 struct splice sp;
620 struct splice_conn sc;
621 int error, sd[3];
622
623 /*
624 * These should fail regardless since the sockets are connected, but it
625 * doesn't hurt to check.
626 */
627 splice_conn_init(&sc);
628 error = listen(sc.left[1], 1);
629 ATF_REQUIRE_ERRNO(EINVAL, error == -1);
630 error = listen(sc.right[0], 1);
631 ATF_REQUIRE_ERRNO(EINVAL, error == -1);
632 splice_conn_fini(&sc);
633
634 tcp4_socketpair(sd);
635 sd[2] = socket(PF_INET, SOCK_STREAM, 0);
636 ATF_REQUIRE_MSG(sd[2] >= 0, "socket failed: %s", strerror(errno));
637 error = listen(sd[2], 1);
638 ATF_REQUIRE_MSG(error == 0, "listen failed: %s", strerror(errno));
639
640 /*
641 * Make sure a listening socket can't be spliced in either direction.
642 */
643 splice_init(&sp, sd[2], 0, NULL);
644 error = setsockopt(sd[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
645 ATF_REQUIRE_ERRNO(EINVAL, error == -1);
646 splice_init(&sp, sd[1], 0, NULL);
647 error = setsockopt(sd[2], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
648 ATF_REQUIRE_ERRNO(EINVAL, error == -1);
649
650 /*
651 * Make sure we can't try to unsplice a listening socket.
652 */
653 splice_init(&sp, -1, 0, NULL);
654 error = setsockopt(sd[2], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
655 ATF_REQUIRE_ERRNO(EINVAL, error == -1);
656
657 checked_close(sd[0]);
658 checked_close(sd[1]);
659 checked_close(sd[2]);
660 }
661
662 static void
sigalarm(int sig __unused)663 sigalarm(int sig __unused)
664 {
665 }
666
667 /*
668 * Our SO_SPLICE implementation doesn't do anything to prevent loops. We should
669 * however make sure that they are interruptible.
670 */
671 ATF_TC_WITHOUT_HEAD(splice_loop);
ATF_TC_BODY(splice_loop,tc)672 ATF_TC_BODY(splice_loop, tc)
673 {
674 ssize_t n;
675 int sd[2], status;
676 pid_t child;
677 char c;
678
679 tcp_socketpair(sd, PF_INET);
680 splice_pair(sd[0], sd[1], 0, NULL);
681
682 /*
683 * Let the child process trigger an infinite loop. It should still be
684 * possible to kill the child with a signal, causing the connection to
685 * be dropped and ending the loop.
686 */
687 child = fork();
688 ATF_REQUIRE_MSG(child >= 0, "fork failed: %s", strerror(errno));
689 if (child == 0) {
690 alarm(2);
691 c = 42;
692 n = write(sd[0], &c, 1);
693 if (n != 1)
694 _exit(2);
695 c = 24;
696 n = write(sd[1], &c, 1);
697 if (n != 1)
698 _exit(3);
699
700 for (;;) {
701 /* Wait for SIGALARM. */
702 sleep(100);
703 }
704
705 _exit(0);
706 } else {
707 checked_close(sd[0]);
708 checked_close(sd[1]);
709
710 child = waitpid(child, &status, 0);
711 ATF_REQUIRE_MSG(child >= 0,
712 "waitpid failed: %s", strerror(errno));
713 ATF_REQUIRE(WIFSIGNALED(status));
714 ATF_REQUIRE(WTERMSIG(status) == SIGALRM);
715 }
716 }
717
718 /*
719 * Simple I/O test.
720 */
721 ATF_TC_WITHOUT_HEAD(splice_nonblock);
ATF_TC_BODY(splice_nonblock,tc)722 ATF_TC_BODY(splice_nonblock, tc)
723 {
724 struct splice_conn sc;
725 char buf[200];
726 size_t sofar;
727 ssize_t n;
728
729 splice_conn_init(&sc);
730 splice_conn_noblocking(&sc);
731
732 memset(buf, 'A', sizeof(buf));
733 for (sofar = 0;;) {
734 n = write(sc.left[0], buf, sizeof(buf));
735 if (n < 0) {
736 ATF_REQUIRE_ERRNO(EAGAIN, n == -1);
737 break;
738 }
739 sofar += n;
740 }
741
742 while (sofar > 0) {
743 n = read(sc.right[1], buf, sizeof(buf));
744 if (n < 0) {
745 ATF_REQUIRE_ERRNO(EAGAIN, n == -1);
746 usleep(100);
747 } else {
748 for (size_t i = 0; i < (size_t)n; i++)
749 ATF_REQUIRE(buf[i] == 'A');
750 sofar -= n;
751 }
752 }
753
754 splice_conn_fini(&sc);
755 }
756
757 ATF_TC_WITHOUT_HEAD(splice_resplice);
ATF_TC_BODY(splice_resplice,tc)758 ATF_TC_BODY(splice_resplice, tc)
759 {
760 struct splice_conn sc;
761 ssize_t n;
762 char c;
763
764 splice_conn_init(&sc);
765
766 /* Left-to-right. */
767 c = 'M';
768 n = write(sc.left[0], &c, 1);
769 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
770 n = read(sc.right[1], &c, 1);
771 ATF_REQUIRE_MSG(n == 1, "read failed: %s", strerror(errno));
772 ATF_REQUIRE_MSG(c == 'M', "unexpected character: %c", c);
773 check_nspliced(sc.left[1], 1);
774 check_nspliced(sc.right[0], 0);
775
776 /* Right-to-left. */
777 c = 'J';
778 n = write(sc.right[1], &c, 1);
779 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
780 n = read(sc.left[0], &c, 1);
781 ATF_REQUIRE_MSG(n == 1, "read failed: %s", strerror(errno));
782 ATF_REQUIRE_MSG(c == 'J', "unexpected character: %c", c);
783 check_nspliced(sc.left[1], 1);
784 check_nspliced(sc.right[0], 1);
785
786 /* Unsplice and verify that the byte counts haven't changed. */
787 unsplice(sc.left[1]);
788 unsplice(sc.right[0]);
789 check_nspliced(sc.left[1], 1);
790 check_nspliced(sc.right[0], 1);
791
792 /* Splice again, check that byte counts are reset. */
793 splice_pair(sc.left[1], sc.right[0], 0, NULL);
794 check_nspliced(sc.left[1], 0);
795 check_nspliced(sc.right[0], 0);
796
797 /* Left-to-right. */
798 c = 'M';
799 n = write(sc.left[0], &c, 1);
800 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
801 n = read(sc.right[1], &c, 1);
802 ATF_REQUIRE_MSG(n == 1, "read failed: %s", strerror(errno));
803 ATF_REQUIRE_MSG(c == 'M', "unexpected character: %c", c);
804 check_nspliced(sc.left[1], 1);
805 check_nspliced(sc.right[0], 0);
806
807 /* Right-to-left. */
808 c = 'J';
809 n = write(sc.right[1], &c, 1);
810 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
811 n = read(sc.left[0], &c, 1);
812 ATF_REQUIRE_MSG(n == 1, "read failed: %s", strerror(errno));
813 ATF_REQUIRE_MSG(c == 'J', "unexpected character: %c", c);
814 check_nspliced(sc.left[1], 1);
815 check_nspliced(sc.right[0], 1);
816
817 splice_conn_fini(&sc);
818 }
819
820 struct xfer_args {
821 pthread_barrier_t *barrier;
822 uint32_t bytes;
823 int fd;
824 };
825
826 static void *
xfer(void * arg)827 xfer(void *arg)
828 {
829 struct xfer_args *xfer;
830 uint8_t *buf;
831 size_t sz;
832 ssize_t n;
833 uint32_t resid;
834 int error;
835
836 xfer = arg;
837
838 error = fcntl(xfer->fd, F_SETFL, O_NONBLOCK);
839 ATF_REQUIRE_MSG(error == 0, "fcntl failed: %s", strerror(errno));
840
841 sz = MIN(xfer->bytes, 1024 * 1024);
842 buf = malloc(sz);
843 ATF_REQUIRE(buf != NULL);
844 arc4random_buf(buf, sz);
845
846 pthread_barrier_wait(xfer->barrier);
847
848 for (resid = xfer->bytes; xfer->bytes > 0 || resid > 0;) {
849 n = write(xfer->fd, buf, MIN(sz, xfer->bytes));
850 if (n < 0) {
851 ATF_REQUIRE_ERRNO(EAGAIN, n == -1);
852 usleep(1000);
853 } else {
854 ATF_REQUIRE(xfer->bytes >= (size_t)n);
855 xfer->bytes -= n;
856 }
857
858 n = read(xfer->fd, buf, sz);
859 if (n < 0) {
860 ATF_REQUIRE_ERRNO(EAGAIN, n == -1);
861 usleep(1000);
862 } else {
863 ATF_REQUIRE(resid >= (size_t)n);
864 resid -= n;
865 }
866 }
867
868 free(buf);
869 return (NULL);
870 }
871
872 /*
873 * Use two threads to transfer data between two spliced connections.
874 */
875 ATF_TC_WITHOUT_HEAD(splice_throughput);
ATF_TC_BODY(splice_throughput,tc)876 ATF_TC_BODY(splice_throughput, tc)
877 {
878 struct xfer_args xfers[2];
879 pthread_t thread[2];
880 pthread_barrier_t barrier;
881 struct splice_conn sc;
882 uint32_t bytes;
883 int error;
884
885 /* Transfer an amount between 1B and 1GB. */
886 bytes = arc4random_uniform(1024 * 1024 * 1024) + 1;
887 splice_conn_init(&sc);
888
889 error = pthread_barrier_init(&barrier, NULL, 2);
890 ATF_REQUIRE(error == 0);
891 xfers[0] = (struct xfer_args){
892 .barrier = &barrier,
893 .bytes = bytes,
894 .fd = sc.left[0]
895 };
896 xfers[1] = (struct xfer_args){
897 .barrier = &barrier,
898 .bytes = bytes,
899 .fd = sc.right[1]
900 };
901
902 error = pthread_create(&thread[0], NULL, xfer, &xfers[0]);
903 ATF_REQUIRE_MSG(error == 0,
904 "pthread_create failed: %s", strerror(errno));
905 error = pthread_create(&thread[1], NULL, xfer, &xfers[1]);
906 ATF_REQUIRE_MSG(error == 0,
907 "pthread_create failed: %s", strerror(errno));
908
909 error = pthread_join(thread[0], NULL);
910 ATF_REQUIRE_MSG(error == 0,
911 "pthread_join failed: %s", strerror(errno));
912 error = pthread_join(thread[1], NULL);
913 ATF_REQUIRE_MSG(error == 0,
914 "pthread_join failed: %s", strerror(errno));
915
916 error = pthread_barrier_destroy(&barrier);
917 ATF_REQUIRE(error == 0);
918 splice_conn_fini(&sc);
919 }
920
921 /*
922 * Make sure it's possible to splice v4 and v6 sockets together.
923 */
924 ATF_TC_WITHOUT_HEAD(splice_v4v6);
ATF_TC_BODY(splice_v4v6,tc)925 ATF_TC_BODY(splice_v4v6, tc)
926 {
927 struct splice sp;
928 ssize_t n;
929 int sd4[2], sd6[2];
930 int error;
931 uint8_t b;
932
933 tcp4_socketpair(sd4);
934 tcp6_socketpair(sd6);
935
936 splice_init(&sp, sd6[0], 0, NULL);
937 error = setsockopt(sd4[1], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
938 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
939
940 splice_init(&sp, sd4[1], 0, NULL);
941 error = setsockopt(sd6[0], SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp));
942 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
943
944 b = 'M';
945 n = write(sd4[0], &b, 1);
946 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
947 n = read(sd6[1], &b, 1);
948 ATF_REQUIRE_MSG(n == 1, "read failed: %s", strerror(errno));
949 ATF_REQUIRE(b == 'M');
950
951 b = 'J';
952 n = write(sd6[1], &b, 1);
953 ATF_REQUIRE_MSG(n == 1, "write failed: %s", strerror(errno));
954 n = read(sd4[0], &b, 1);
955 ATF_REQUIRE_MSG(n == 1, "read failed: %s", strerror(errno));
956 ATF_REQUIRE(b == 'J');
957
958 checked_close(sd4[0]);
959 checked_close(sd4[1]);
960 checked_close(sd6[0]);
961 checked_close(sd6[1]);
962 }
963
ATF_TP_ADD_TCS(tp)964 ATF_TP_ADD_TCS(tp)
965 {
966 ATF_TP_ADD_TC(tp, splice_basic);
967 ATF_TP_ADD_TC(tp, splice_capsicum);
968 ATF_TP_ADD_TC(tp, splice_error);
969 ATF_TP_ADD_TC(tp, splice_kevent);
970 ATF_TP_ADD_TC(tp, splice_limit_bytes);
971 ATF_TP_ADD_TC(tp, splice_limit_timeout);
972 ATF_TP_ADD_TC(tp, splice_listen);
973 ATF_TP_ADD_TC(tp, splice_loop);
974 ATF_TP_ADD_TC(tp, splice_nonblock);
975 ATF_TP_ADD_TC(tp, splice_resplice);
976 ATF_TP_ADD_TC(tp, splice_throughput);
977 ATF_TP_ADD_TC(tp, splice_v4v6);
978 return (atf_no_error());
979 }
980