]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/kern/unix_passfd_test.c
riscv: fix VM_MAXUSER_ADDRESS checks in asm routines
[FreeBSD/FreeBSD.git] / tests / sys / kern / unix_passfd_test.c
1 /*-
2  * Copyright (c) 2005 Robert N. M. Watson
3  * Copyright (c) 2015 Mark Johnston
4  * All rights reserved.
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 THE 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 THE 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 __FBSDID("$FreeBSD$");
30
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <sys/stat.h>
34 #include <sys/sysctl.h>
35 #include <sys/un.h>
36
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <limits.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44
45 #include <atf-c.h>
46
47 /*
48  * UNIX domain sockets allow file descriptors to be passed via "ancillary
49  * data", or control messages.  This regression test is intended to exercise
50  * this facility, both performing some basic tests that it operates, and also
51  * causing some kernel edge cases to execute, such as garbage collection when
52  * there are cyclic file descriptor references.  Right now we test only with
53  * stream sockets, but ideally we'd also test with datagram sockets.
54  */
55
56 static void
57 domainsocketpair(int *fdp)
58 {
59
60         ATF_REQUIRE_MSG(socketpair(PF_UNIX, SOCK_STREAM, 0, fdp) != -1,
61             "socketpair(PF_UNIX, SOCK_STREAM) failed: %s", strerror(errno));
62 }
63
64 static void
65 closesocketpair(int *fdp)
66 {
67
68         close(fdp[0]);
69         close(fdp[1]);
70 }
71
72 static void
73 devnull(int *fdp)
74 {
75         int fd;
76
77         fd = open("/dev/null", O_RDONLY);
78         ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
79         *fdp = fd;
80 }
81
82 static void
83 tempfile(int *fdp)
84 {
85         char path[PATH_MAX];
86         int fd;
87
88         snprintf(path, PATH_MAX, "%s/unix_passfd.XXXXXXXXXXXXXXX",
89             getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR"));
90         fd = mkstemp(path);
91         ATF_REQUIRE_MSG(fd != -1, "mkstemp(%s) failed", path);
92         (void)unlink(path);
93         *fdp = fd;
94 }
95
96 static void
97 dofstat(int fd, struct stat *sb)
98 {
99
100         ATF_REQUIRE_MSG(fstat(fd, sb) == 0,
101             "fstat failed: %s", strerror(errno));
102 }
103
104 static int
105 getnfds(void)
106 {
107         size_t len;
108         int mib[4], n, rc;
109
110         len = sizeof(n);
111         mib[0] = CTL_KERN;
112         mib[1] = KERN_PROC;
113         mib[2] = KERN_PROC_NFDS;
114         mib[3] = 0;
115
116         rc = sysctl(mib, 4, &n, &len, NULL, 0);
117         ATF_REQUIRE_MSG(rc != -1, "sysctl(KERN_PROC_NFDS) failed");
118         return (n);
119 }
120
121 static void
122 putfds(char *buf, int fd, int nfds)
123 {
124         struct cmsghdr *cm;
125         int *fdp, i;
126
127         cm = (struct cmsghdr *)buf;
128         cm->cmsg_len = CMSG_LEN(nfds * sizeof(int));
129         cm->cmsg_level = SOL_SOCKET;
130         cm->cmsg_type = SCM_RIGHTS;
131         for (fdp = (int *)CMSG_DATA(cm), i = 0; i < nfds; i++)
132                 *fdp++ = fd;
133 }
134
135 static void
136 samefile(struct stat *sb1, struct stat *sb2)
137 {
138
139         ATF_REQUIRE_MSG(sb1->st_dev == sb2->st_dev, "different device");
140         ATF_REQUIRE_MSG(sb1->st_ino == sb2->st_ino, "different inode");
141 }
142
143 static size_t
144 sendfd_payload(int sockfd, int send_fd, void *payload, size_t paylen)
145 {
146         struct iovec iovec;
147         char message[CMSG_SPACE(sizeof(int))];
148         struct msghdr msghdr;
149         ssize_t len;
150
151         bzero(&msghdr, sizeof(msghdr));
152         bzero(&message, sizeof(message));
153
154         msghdr.msg_control = message;
155         msghdr.msg_controllen = sizeof(message);
156
157         iovec.iov_base = payload;
158         iovec.iov_len = paylen;
159
160         msghdr.msg_iov = &iovec;
161         msghdr.msg_iovlen = 1;
162
163         putfds(message, send_fd, 1);
164         len = sendmsg(sockfd, &msghdr, 0);
165         ATF_REQUIRE_MSG(len != -1, "sendmsg failed: %s", strerror(errno));
166         return ((size_t)len);
167 }
168
169 static void
170 sendfd(int sockfd, int send_fd)
171 {
172         size_t len;
173         char ch;
174
175         ch = 0;
176         len = sendfd_payload(sockfd, send_fd, &ch, sizeof(ch));
177         ATF_REQUIRE_MSG(len == sizeof(ch),
178             "sendmsg: %zu bytes sent; expected %zu; %s", len, sizeof(ch),
179             strerror(errno));
180 }
181
182 static bool
183 localcreds(int sockfd)
184 {
185         socklen_t sz;
186         int rc, val;
187
188         sz = sizeof(val);
189         rc = getsockopt(sockfd, 0, LOCAL_CREDS, &val, &sz);
190         ATF_REQUIRE_MSG(rc != -1, "getsockopt(LOCAL_CREDS) failed: %s",
191             strerror(errno));
192         return (val != 0);
193 }
194
195 static void
196 recvfd_payload(int sockfd, int *recv_fd, void *buf, size_t buflen,
197     size_t cmsgsz, int recvmsg_flags)
198 {
199         struct cmsghdr *cmsghdr;
200         struct msghdr msghdr;
201         struct iovec iovec;
202         char *message;
203         ssize_t len;
204         bool foundcreds;
205
206         bzero(&msghdr, sizeof(msghdr));
207         message = malloc(cmsgsz);
208         ATF_REQUIRE(message != NULL);
209
210         msghdr.msg_control = message;
211         msghdr.msg_controllen = cmsgsz;
212
213         iovec.iov_base = buf;
214         iovec.iov_len = buflen;
215
216         msghdr.msg_iov = &iovec;
217         msghdr.msg_iovlen = 1;
218
219         len = recvmsg(sockfd, &msghdr, recvmsg_flags);
220         ATF_REQUIRE_MSG(len != -1, "recvmsg failed: %s", strerror(errno));
221         ATF_REQUIRE_MSG((size_t)len == buflen,
222             "recvmsg: %zd bytes received; expected %zd", len, buflen);
223
224         cmsghdr = CMSG_FIRSTHDR(&msghdr);
225         ATF_REQUIRE_MSG(cmsghdr != NULL,
226             "recvmsg: did not receive control message");
227         foundcreds = false;
228         *recv_fd = -1;
229         for (; cmsghdr != NULL; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) {
230                 if (cmsghdr->cmsg_level == SOL_SOCKET &&
231                     cmsghdr->cmsg_type == SCM_RIGHTS &&
232                     cmsghdr->cmsg_len == CMSG_LEN(sizeof(int))) {
233                         memcpy(recv_fd, CMSG_DATA(cmsghdr), sizeof(int));
234                         ATF_REQUIRE(*recv_fd != -1);
235                 } else if (cmsghdr->cmsg_level == SOL_SOCKET &&
236                     cmsghdr->cmsg_type == SCM_CREDS)
237                         foundcreds = true;
238         }
239         ATF_REQUIRE_MSG(*recv_fd != -1,
240             "recvmsg: did not receive single-fd message");
241         ATF_REQUIRE_MSG(!localcreds(sockfd) || foundcreds,
242             "recvmsg: expected credentials were not received");
243 }
244
245 static void
246 recvfd(int sockfd, int *recv_fd, int flags)
247 {
248         char ch = 0;
249
250         recvfd_payload(sockfd, recv_fd, &ch, sizeof(ch),
251             CMSG_SPACE(sizeof(int)), flags);
252 }
253
254 /*
255  * Put a temporary file into a UNIX domain socket, then take it out and make
256  * sure it's the same file.  First time around, don't close the reference
257  * after sending.
258  */
259 ATF_TC_WITHOUT_HEAD(simple_send_fd);
260 ATF_TC_BODY(simple_send_fd, tc)
261 {
262         struct stat getfd_stat, putfd_stat;
263         int fd[2], getfd, putfd;
264
265         domainsocketpair(fd);
266         tempfile(&putfd);
267         dofstat(putfd, &putfd_stat);
268         sendfd(fd[0], putfd);
269         recvfd(fd[1], &getfd, 0);
270         dofstat(getfd, &getfd_stat);
271         samefile(&putfd_stat, &getfd_stat);
272         close(putfd);
273         close(getfd);
274         closesocketpair(fd);
275 }
276
277 /*
278  * Like simple_send_fd but also sets MSG_CMSG_CLOEXEC and checks that the
279  * received file descriptor has the FD_CLOEXEC flag set.
280  */
281 ATF_TC_WITHOUT_HEAD(simple_send_fd_msg_cmsg_cloexec);
282 ATF_TC_BODY(simple_send_fd_msg_cmsg_cloexec, tc)
283 {
284         struct stat getfd_stat, putfd_stat;
285         int fd[2], getfd, putfd;
286
287         domainsocketpair(fd);
288         tempfile(&putfd);
289         dofstat(putfd, &putfd_stat);
290         sendfd(fd[0], putfd);
291         recvfd(fd[1], &getfd, MSG_CMSG_CLOEXEC);
292         dofstat(getfd, &getfd_stat);
293         samefile(&putfd_stat, &getfd_stat);
294         ATF_REQUIRE_EQ_MSG(fcntl(getfd, F_GETFD) & FD_CLOEXEC, FD_CLOEXEC,
295             "FD_CLOEXEC not set on the received file descriptor");
296         close(putfd);
297         close(getfd);
298         closesocketpair(fd);
299 }
300
301 /*
302  * Same as simple_send_fd, only close the file reference after sending, so that
303  * the only reference is the descriptor in the UNIX domain socket buffer.
304  */
305 ATF_TC_WITHOUT_HEAD(send_and_close);
306 ATF_TC_BODY(send_and_close, tc)
307 {
308         struct stat getfd_stat, putfd_stat;
309         int fd[2], getfd, putfd;
310
311         domainsocketpair(fd);
312         tempfile(&putfd);
313         dofstat(putfd, &putfd_stat);
314         sendfd(fd[0], putfd);
315         close(putfd);
316         recvfd(fd[1], &getfd, 0);
317         dofstat(getfd, &getfd_stat);
318         samefile(&putfd_stat, &getfd_stat);
319         close(getfd);
320         closesocketpair(fd);
321 }
322
323 /*
324  * Put a temporary file into a UNIX domain socket, then close both endpoints
325  * causing garbage collection to kick off.
326  */
327 ATF_TC_WITHOUT_HEAD(send_and_cancel);
328 ATF_TC_BODY(send_and_cancel, tc)
329 {
330         int fd[2], putfd;
331
332         domainsocketpair(fd);
333         tempfile(&putfd);
334         sendfd(fd[0], putfd);
335         close(putfd);
336         closesocketpair(fd);
337 }
338
339 /*
340  * Send two files.  Then receive them.  Make sure they are returned in the
341  * right order, and both get there.
342  */
343 ATF_TC_WITHOUT_HEAD(two_files);
344 ATF_TC_BODY(two_files, tc)
345 {
346         struct stat getfd_1_stat, getfd_2_stat, putfd_1_stat, putfd_2_stat;
347         int fd[2], getfd_1, getfd_2, putfd_1, putfd_2;
348
349         domainsocketpair(fd);
350         tempfile(&putfd_1);
351         tempfile(&putfd_2);
352         dofstat(putfd_1, &putfd_1_stat);
353         dofstat(putfd_2, &putfd_2_stat);
354         sendfd(fd[0], putfd_1);
355         sendfd(fd[0], putfd_2);
356         close(putfd_1);
357         close(putfd_2);
358         recvfd(fd[1], &getfd_1, 0);
359         recvfd(fd[1], &getfd_2, 0);
360         dofstat(getfd_1, &getfd_1_stat);
361         dofstat(getfd_2, &getfd_2_stat);
362         samefile(&putfd_1_stat, &getfd_1_stat);
363         samefile(&putfd_2_stat, &getfd_2_stat);
364         close(getfd_1);
365         close(getfd_2);
366         closesocketpair(fd);
367 }
368
369 /*
370  * Big bundling test.  Send an endpoint of the UNIX domain socket over itself,
371  * closing the door behind it.
372  */
373 ATF_TC_WITHOUT_HEAD(bundle);
374 ATF_TC_BODY(bundle, tc)
375 {
376         int fd[2], getfd;
377
378         domainsocketpair(fd);
379
380         sendfd(fd[0], fd[0]);
381         close(fd[0]);
382         recvfd(fd[1], &getfd, 0);
383         close(getfd);
384         close(fd[1]);
385 }
386
387 /*
388  * Big bundling test part two: Send an endpoint of the UNIX domain socket over
389  * itself, close the door behind it, and never remove it from the other end.
390  */
391 ATF_TC_WITHOUT_HEAD(bundle_cancel);
392 ATF_TC_BODY(bundle_cancel, tc)
393 {
394         int fd[2];
395
396         domainsocketpair(fd);
397         sendfd(fd[0], fd[0]);
398         sendfd(fd[1], fd[0]);
399         closesocketpair(fd);
400 }
401
402 /*
403  * Test for PR 151758: Send an character device over the UNIX domain socket
404  * and then close both sockets to orphan the device.
405  */
406 ATF_TC_WITHOUT_HEAD(devfs_orphan);
407 ATF_TC_BODY(devfs_orphan, tc)
408 {
409         int fd[2], putfd;
410
411         domainsocketpair(fd);
412         devnull(&putfd);
413         sendfd(fd[0], putfd);
414         close(putfd);
415         closesocketpair(fd);
416 }
417
418 #define LOCAL_SENDSPACE_SYSCTL  "net.local.stream.sendspace"
419
420 /*
421  * Test for PR 181741. Receiver sets LOCAL_CREDS, and kernel prepends a
422  * control message to the data. Sender sends large payload using a non-blocking
423  * socket. Payload + SCM_RIGHTS + LOCAL_CREDS hit socket buffer limit, and
424  * receiver receives truncated data.
425  */
426 ATF_TC_WITHOUT_HEAD(rights_creds_payload);
427 ATF_TC_BODY(rights_creds_payload, tc)
428 {
429         const int on = 1;
430         u_long sendspace;
431         size_t len;
432         void *buf;
433         int fd[2], getfd, putfd, rc;
434
435         len = sizeof(sendspace);
436         rc = sysctlbyname(LOCAL_SENDSPACE_SYSCTL, &sendspace,
437             &len, NULL, 0);
438         ATF_REQUIRE_MSG(rc != -1,
439             "sysctl %s failed: %s", LOCAL_SENDSPACE_SYSCTL, strerror(errno));
440
441         buf = calloc(1, sendspace);
442         ATF_REQUIRE(buf != NULL);
443
444         domainsocketpair(fd);
445         tempfile(&putfd);
446
447         rc = fcntl(fd[0], F_SETFL, O_NONBLOCK);
448         ATF_REQUIRE_MSG(rc != -1, "fcntl(O_NONBLOCK) failed: %s",
449             strerror(errno));
450         rc = setsockopt(fd[1], 0, LOCAL_CREDS, &on, sizeof(on));
451         ATF_REQUIRE_MSG(rc != -1, "setsockopt(LOCAL_CREDS) failed: %s",
452             strerror(errno));
453
454         len = sendfd_payload(fd[0], putfd, buf, sendspace);
455         ATF_REQUIRE_MSG(len < sendspace, "sendmsg: %zu bytes sent", len);
456         recvfd_payload(fd[1], &getfd, buf, len,
457             CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + CMSG_SPACE(sizeof(int)), 0);
458
459         close(putfd);
460         close(getfd);
461         closesocketpair(fd);
462 }
463
464 static void
465 send_cmsg(int sockfd, void *cmsg, size_t cmsgsz)
466 {
467         struct iovec iov;
468         struct msghdr msghdr;
469         ssize_t len;
470         char ch;
471
472         ch = 0;
473         bzero(&msghdr, sizeof(msghdr));
474
475         iov.iov_base = &ch;
476         iov.iov_len = sizeof(ch);
477         msghdr.msg_control = cmsg;
478         msghdr.msg_controllen = cmsgsz;
479         msghdr.msg_iov = &iov;
480         msghdr.msg_iovlen = 1;
481
482         len = sendmsg(sockfd, &msghdr, 0);
483         ATF_REQUIRE_MSG(len != -1,
484             "sendmsg failed: %s", strerror(errno));
485         ATF_REQUIRE_MSG(len == sizeof(ch),
486             "sendmsg: %zd bytes sent; expected %zu", len, sizeof(ch));
487 }
488
489 static void
490 recv_cmsg(int sockfd, char *cmsg, size_t cmsgsz, int flags)
491 {
492         struct iovec iov;
493         struct msghdr msghdr;
494         ssize_t len;
495         char ch;
496
497         ch = 0;
498         bzero(&msghdr, sizeof(msghdr));
499
500         iov.iov_base = &ch;
501         iov.iov_len = sizeof(ch);
502         msghdr.msg_control = cmsg;
503         msghdr.msg_controllen = cmsgsz;
504         msghdr.msg_iov = &iov;
505         msghdr.msg_iovlen = 1;
506
507         len = recvmsg(sockfd, &msghdr, 0);
508         ATF_REQUIRE_MSG(len != -1,
509             "recvmsg failed: %s", strerror(errno));
510         ATF_REQUIRE_MSG(len == sizeof(ch),
511             "recvmsg: %zd bytes received; expected %zu", len, sizeof(ch));
512         ATF_REQUIRE_MSG((msghdr.msg_flags & flags) == flags,
513             "recvmsg: got flags %#x; expected %#x", msghdr.msg_flags, flags);
514 }
515
516 /*
517  * Test for PR 131876.  Receiver uses a control message buffer that is too
518  * small for the incoming SCM_RIGHTS message, so the message is truncated.
519  * The kernel must not leak the copied right into the receiver's namespace.
520  */
521 ATF_TC_WITHOUT_HEAD(truncated_rights);
522 ATF_TC_BODY(truncated_rights, tc)
523 {
524         char *message;
525         int fd[2], nfds, putfd, rc;
526
527         domainsocketpair(fd);
528         devnull(&putfd);
529         nfds = getnfds();
530
531         /*
532          * Case 1: Send a single descriptor and truncate the message.
533          */
534         message = malloc(CMSG_SPACE(sizeof(int)));
535         ATF_REQUIRE(message != NULL);
536         putfds(message, putfd, 1);
537         send_cmsg(fd[0], message, CMSG_LEN(sizeof(int)));
538         recv_cmsg(fd[1], message, CMSG_LEN(0), MSG_CTRUNC);
539         ATF_REQUIRE(getnfds() == nfds);
540         free(message);
541
542         /*
543          * Case 2a: Send two descriptors in separate messages, and truncate at
544          *          the boundary between the two messages.  We should still
545          *          receive the first message.
546          */
547         message = malloc(CMSG_SPACE(sizeof(int)) * 2);
548         ATF_REQUIRE(message != NULL);
549         putfds(message, putfd, 1);
550         putfds(message + CMSG_SPACE(sizeof(int)), putfd, 1);
551         send_cmsg(fd[0], message, CMSG_SPACE(sizeof(int)) * 2);
552         recv_cmsg(fd[1], message, CMSG_SPACE(sizeof(int)), MSG_CTRUNC);
553         rc = close(*(int *)CMSG_DATA(message));
554         ATF_REQUIRE_MSG(rc == 0, "close failed: %s", strerror(errno));
555         ATF_REQUIRE(getnfds() == nfds);
556         free(message);
557
558         /*
559          * Case 2b: Send two descriptors in separate messages, and truncate
560          *          before the end of the first message.
561          */
562         message = malloc(CMSG_SPACE(sizeof(int)) * 2);
563         ATF_REQUIRE(message != NULL);
564         putfds(message, putfd, 1);
565         putfds(message + CMSG_SPACE(sizeof(int)), putfd, 1);
566         send_cmsg(fd[0], message, CMSG_SPACE(sizeof(int)) * 2);
567         recv_cmsg(fd[1], message, CMSG_SPACE(0), MSG_CTRUNC);
568         ATF_REQUIRE(getnfds() == nfds);
569         free(message);
570
571         /*
572          * Case 2c: Send two descriptors in separate messages, and truncate
573          *          after the end of the first message.  We should still
574          *          receive the first message.
575          */
576         message = malloc(CMSG_SPACE(sizeof(int)) * 2);
577         ATF_REQUIRE(message != NULL);
578         putfds(message, putfd, 1);
579         putfds(message + CMSG_SPACE(sizeof(int)), putfd, 1);
580         send_cmsg(fd[0], message, CMSG_SPACE(sizeof(int)) * 2);
581         recv_cmsg(fd[1], message, CMSG_SPACE(sizeof(int)) + CMSG_SPACE(0),
582             MSG_CTRUNC);
583         rc = close(*(int *)CMSG_DATA(message));
584         ATF_REQUIRE_MSG(rc == 0, "close failed: %s", strerror(errno));
585         ATF_REQUIRE(getnfds() == nfds);
586         free(message);
587
588         /*
589          * Case 3: Send three descriptors in the same message, and leave space
590          *         only for the first when receiving the message.
591          */
592         message = malloc(CMSG_SPACE(sizeof(int) * 3));
593         ATF_REQUIRE(message != NULL);
594         putfds(message, putfd, 3);
595         send_cmsg(fd[0], message, CMSG_SPACE(sizeof(int) * 3));
596         recv_cmsg(fd[1], message, CMSG_SPACE(sizeof(int)), MSG_CTRUNC);
597         ATF_REQUIRE(getnfds() == nfds);
598         free(message);
599
600         close(putfd);
601         closesocketpair(fd);
602 }
603
604 /*
605  * Ensure that an attempt to copy a SCM_RIGHTS message to the recipient
606  * fails.  In this case the kernel must dispose of the externalized rights
607  * rather than leaking them into the recipient's file descriptor table.
608  */
609 ATF_TC_WITHOUT_HEAD(copyout_rights_error);
610 ATF_TC_BODY(copyout_rights_error, tc)
611 {
612         struct iovec iovec;
613         struct msghdr msghdr;
614         char buf[16];
615         ssize_t len;
616         int fd[2], error, nfds, putfd;
617
618         memset(buf, 0, sizeof(buf));
619         domainsocketpair(fd);
620         devnull(&putfd);
621         nfds = getnfds();
622
623         sendfd_payload(fd[0], putfd, buf, sizeof(buf));
624
625         bzero(&msghdr, sizeof(msghdr));
626
627         iovec.iov_base = buf;
628         iovec.iov_len = sizeof(buf);
629         msghdr.msg_control = (char *)-1; /* trigger EFAULT */
630         msghdr.msg_controllen = CMSG_SPACE(sizeof(int));
631         msghdr.msg_iov = &iovec;
632         msghdr.msg_iovlen = 1;
633
634         len = recvmsg(fd[1], &msghdr, 0);
635         error = errno;
636         ATF_REQUIRE_MSG(len == -1, "recvmsg succeeded: %zd", len);
637         ATF_REQUIRE_MSG(errno == EFAULT, "expected EFAULT, got %d (%s)",
638             error, strerror(errno));
639
640         /* Verify that no FDs were leaked. */
641         ATF_REQUIRE(getnfds() == nfds);
642
643         close(putfd);
644         closesocketpair(fd);
645 }
646
647 /*
648  * Verify that we can handle empty rights messages.  Try sending two SCM_RIGHTS
649  * messages with a single call, one empty and one containing a single FD.
650  */
651 ATF_TC_WITHOUT_HEAD(empty_rights_message);
652 ATF_TC_BODY(empty_rights_message, tc)
653 {
654         struct iovec iov;
655         struct msghdr msghdr;
656         char *cm, message[CMSG_SPACE(0) + CMSG_SPACE(sizeof(int))];
657         ssize_t len;
658         int error, fd[2], putfd;
659
660         domainsocketpair(fd);
661         devnull(&putfd);
662
663         /*
664          * First, try sending an empty message followed by a non-empty message.
665          */
666         cm = message;
667         putfds(cm, -1, 0);
668         cm += CMSG_SPACE(0);
669         putfds(cm, putfd, 1);
670
671         memset(&msghdr, 0, sizeof(msghdr));
672         iov.iov_base = NULL;
673         iov.iov_len = 0;
674         msghdr.msg_control = message;
675         msghdr.msg_controllen = sizeof(message);
676         msghdr.msg_iov = &iov;
677         msghdr.msg_iovlen = 1;
678
679         len = sendmsg(fd[0], &msghdr, 0);
680         ATF_REQUIRE_MSG(len == 0, "sendmsg failed: %s", strerror(errno));
681
682         /* Only the non-empty message should be received. */
683         len = recvmsg(fd[1], &msghdr, 0);
684         ATF_REQUIRE_MSG(len == 0, "recvmsg failed: %s", strerror(errno));
685         ATF_REQUIRE(msghdr.msg_controllen = CMSG_SPACE(sizeof(int)));
686         error = close(*(int *)CMSG_DATA(msghdr.msg_control));
687         ATF_REQUIRE_MSG(error == 0, "close failed: %s", strerror(errno));
688
689         /*
690          * Now try sending with the non-empty message before the empty message.
691          */
692         cm = message;
693         putfds(cm, putfd, 1);
694         cm += CMSG_SPACE(sizeof(int));
695         putfds(cm, -1, 0);
696
697         memset(&msghdr, 0, sizeof(msghdr));
698         iov.iov_base = NULL;
699         iov.iov_len = 0;
700         msghdr.msg_control = message;
701         msghdr.msg_controllen = CMSG_SPACE(sizeof(int));
702         msghdr.msg_iov = &iov;
703         msghdr.msg_iovlen = 1;
704
705         len = sendmsg(fd[0], &msghdr, 0);
706         ATF_REQUIRE_MSG(len == 0, "sendmsg failed: %s", strerror(errno));
707
708         /* Only the non-empty message should be received. */
709         len = recvmsg(fd[1], &msghdr, 0);
710         ATF_REQUIRE_MSG(len == 0, "recvmsg failed: %s", strerror(errno));
711         ATF_REQUIRE(msghdr.msg_controllen = CMSG_SPACE(sizeof(int)));
712         error = close(*(int *)CMSG_DATA(msghdr.msg_control));
713         ATF_REQUIRE_MSG(error == 0, "close failed: %s", strerror(errno));
714
715         (void)close(putfd);
716 }
717
718 ATF_TP_ADD_TCS(tp)
719 {
720
721         ATF_TP_ADD_TC(tp, simple_send_fd);
722         ATF_TP_ADD_TC(tp, simple_send_fd_msg_cmsg_cloexec);
723         ATF_TP_ADD_TC(tp, send_and_close);
724         ATF_TP_ADD_TC(tp, send_and_cancel);
725         ATF_TP_ADD_TC(tp, two_files);
726         ATF_TP_ADD_TC(tp, bundle);
727         ATF_TP_ADD_TC(tp, bundle_cancel);
728         ATF_TP_ADD_TC(tp, devfs_orphan);
729         ATF_TP_ADD_TC(tp, rights_creds_payload);
730         ATF_TP_ADD_TC(tp, truncated_rights);
731         ATF_TP_ADD_TC(tp, copyout_rights_error);
732         ATF_TP_ADD_TC(tp, empty_rights_message);
733
734         return (atf_no_error());
735 }