xref: /src/lib/libnv/tests/nvlist_send_recv_test.c (revision fbe6da7f7592169ad7c26aa563f4c6305de1e345)
1 /*-
2  * Copyright (c) 2013 The FreeBSD Foundation
3  *
4  * This software was developed by Pawel Jakub Dawidek under sponsorship from
5  * the FreeBSD Foundation.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/socket.h>
31 #include <sys/sysctl.h>
32 #include <sys/wait.h>
33 #include <sys/nv.h>
34 
35 #include <stdlib.h>
36 #include <err.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <paths.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <unistd.h>
43 
44 #include <atf-c.h>
45 
46 #include <nv_impl.h>
47 #include <msgio.h>
48 
49 #define	ALPHABET	"abcdefghijklmnopqrstuvwxyz"
50 #define	fd_is_valid(fd)	(fcntl((fd), F_GETFL) != -1 || errno != EBADF)
51 
52 static void
send_nvlist_child(int sock)53 send_nvlist_child(int sock)
54 {
55 	nvlist_t *nvl;
56 	nvlist_t *empty;
57 	int pfd[2];
58 
59 	nvl = nvlist_create(0);
60 	empty = nvlist_create(0);
61 
62 	nvlist_add_bool(nvl, "nvlist/bool/true", true);
63 	nvlist_add_bool(nvl, "nvlist/bool/false", false);
64 	nvlist_add_number(nvl, "nvlist/number/0", 0);
65 	nvlist_add_number(nvl, "nvlist/number/1", 1);
66 	nvlist_add_number(nvl, "nvlist/number/-1", -1);
67 	nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX);
68 	nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN);
69 	nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX);
70 	nvlist_add_string(nvl, "nvlist/string/", "");
71 	nvlist_add_string(nvl, "nvlist/string/x", "x");
72 	nvlist_add_string(nvl, "nvlist/string/" ALPHABET, ALPHABET);
73 
74 	nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO",
75 	    STDERR_FILENO);
76 	if (pipe(pfd) == -1)
77 		err(EXIT_FAILURE, "pipe");
78 	if (write(pfd[1], "test", 4) != 4)
79 		err(EXIT_FAILURE, "write");
80 	close(pfd[1]);
81 	nvlist_add_descriptor(nvl, "nvlist/descriptor/pipe_rd", pfd[0]);
82 	close(pfd[0]);
83 
84 	nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1);
85 	nvlist_add_binary(nvl, "nvlist/binary/" ALPHABET, ALPHABET,
86 	    sizeof(ALPHABET));
87 	nvlist_move_nvlist(nvl, "nvlist/nvlist/empty", empty);
88 	nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
89 
90 	nvlist_send(sock, nvl);
91 
92 	nvlist_destroy(nvl);
93 }
94 
95 static void
send_nvlist_parent(int sock)96 send_nvlist_parent(int sock)
97 {
98 	nvlist_t *nvl;
99 	const nvlist_t *cnvl, *empty;
100 	const char *name, *cname;
101 	void *cookie, *ccookie;
102 	int type, ctype, fd;
103 	size_t size;
104 	char buf[4];
105 
106 	nvl = nvlist_recv(sock, 0);
107 	ATF_REQUIRE(nvlist_error(nvl) == 0);
108 	if (nvlist_error(nvl) != 0)
109 		err(1, "nvlist_recv() failed");
110 
111 	cookie = NULL;
112 
113 	name = nvlist_next(nvl, &type, &cookie);
114 	ATF_REQUIRE(name != NULL);
115 	ATF_REQUIRE(type == NV_TYPE_BOOL);
116 	ATF_REQUIRE(strcmp(name, "nvlist/bool/true") == 0);
117 	ATF_REQUIRE(nvlist_get_bool(nvl, name) == true);
118 
119 	name = nvlist_next(nvl, &type, &cookie);
120 	ATF_REQUIRE(name != NULL);
121 	ATF_REQUIRE(type == NV_TYPE_BOOL);
122 	ATF_REQUIRE(strcmp(name, "nvlist/bool/false") == 0);
123 	ATF_REQUIRE(nvlist_get_bool(nvl, name) == false);
124 
125 	name = nvlist_next(nvl, &type, &cookie);
126 	ATF_REQUIRE(name != NULL);
127 	ATF_REQUIRE(type == NV_TYPE_NUMBER);
128 	ATF_REQUIRE(strcmp(name, "nvlist/number/0") == 0);
129 	ATF_REQUIRE(nvlist_get_number(nvl, name) == 0);
130 
131 	name = nvlist_next(nvl, &type, &cookie);
132 	ATF_REQUIRE(name != NULL);
133 	ATF_REQUIRE(type == NV_TYPE_NUMBER);
134 	ATF_REQUIRE(strcmp(name, "nvlist/number/1") == 0);
135 	ATF_REQUIRE(nvlist_get_number(nvl, name) == 1);
136 
137 	name = nvlist_next(nvl, &type, &cookie);
138 	ATF_REQUIRE(name != NULL);
139 	ATF_REQUIRE(type == NV_TYPE_NUMBER);
140 	ATF_REQUIRE(strcmp(name, "nvlist/number/-1") == 0);
141 	ATF_REQUIRE((int)nvlist_get_number(nvl, name) == -1);
142 
143 	name = nvlist_next(nvl, &type, &cookie);
144 	ATF_REQUIRE(name != NULL);
145 	ATF_REQUIRE(type == NV_TYPE_NUMBER);
146 	ATF_REQUIRE(strcmp(name, "nvlist/number/UINT64_MAX") == 0);
147 	ATF_REQUIRE(nvlist_get_number(nvl, name) == UINT64_MAX);
148 
149 	name = nvlist_next(nvl, &type, &cookie);
150 	ATF_REQUIRE(name != NULL);
151 	ATF_REQUIRE(type == NV_TYPE_NUMBER);
152 	ATF_REQUIRE(strcmp(name, "nvlist/number/INT64_MIN") == 0);
153 	ATF_REQUIRE((int64_t)nvlist_get_number(nvl, name) == INT64_MIN);
154 
155 	name = nvlist_next(nvl, &type, &cookie);
156 	ATF_REQUIRE(name != NULL);
157 	ATF_REQUIRE(type == NV_TYPE_NUMBER);
158 	ATF_REQUIRE(strcmp(name, "nvlist/number/INT64_MAX") == 0);
159 	ATF_REQUIRE((int64_t)nvlist_get_number(nvl, name) == INT64_MAX);
160 
161 	name = nvlist_next(nvl, &type, &cookie);
162 	ATF_REQUIRE(name != NULL);
163 	ATF_REQUIRE(type == NV_TYPE_STRING);
164 	ATF_REQUIRE(strcmp(name, "nvlist/string/") == 0);
165 	ATF_REQUIRE(strcmp(nvlist_get_string(nvl, name), "") == 0);
166 
167 	name = nvlist_next(nvl, &type, &cookie);
168 	ATF_REQUIRE(name != NULL);
169 	ATF_REQUIRE(type == NV_TYPE_STRING);
170 	ATF_REQUIRE(strcmp(name, "nvlist/string/x") == 0);
171 	ATF_REQUIRE(strcmp(nvlist_get_string(nvl, name), "x") == 0);
172 
173 	name = nvlist_next(nvl, &type, &cookie);
174 	ATF_REQUIRE(name != NULL);
175 	ATF_REQUIRE(type == NV_TYPE_STRING);
176 	ATF_REQUIRE(strcmp(name, "nvlist/string/" ALPHABET) == 0);
177 	ATF_REQUIRE(strcmp(nvlist_get_string(nvl, name), ALPHABET) == 0);
178 
179 	name = nvlist_next(nvl, &type, &cookie);
180 	ATF_REQUIRE(name != NULL);
181 	ATF_REQUIRE(type == NV_TYPE_DESCRIPTOR);
182 	ATF_REQUIRE(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0);
183 	ATF_REQUIRE(fd_is_valid(nvlist_get_descriptor(nvl, name)));
184 
185 	name = nvlist_next(nvl, &type, &cookie);
186 	ATF_REQUIRE(name != NULL);
187 	ATF_REQUIRE(type == NV_TYPE_DESCRIPTOR);
188 	ATF_REQUIRE(strcmp(name, "nvlist/descriptor/pipe_rd") == 0);
189 	fd = nvlist_get_descriptor(nvl, name);
190 	ATF_REQUIRE(fd_is_valid(fd));
191 	ATF_REQUIRE(read(fd, buf, sizeof(buf)) == 4);
192 	ATF_REQUIRE(strncmp(buf, "test", sizeof(buf)) == 0);
193 
194 	name = nvlist_next(nvl, &type, &cookie);
195 	ATF_REQUIRE(name != NULL);
196 	ATF_REQUIRE(type == NV_TYPE_BINARY);
197 	ATF_REQUIRE(strcmp(name, "nvlist/binary/x") == 0);
198 	ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0);
199 	ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0);
200 	ATF_REQUIRE(size == 1);
201 
202 	name = nvlist_next(nvl, &type, &cookie);
203 	ATF_REQUIRE(name != NULL);
204 	ATF_REQUIRE(type == NV_TYPE_BINARY);
205 	ATF_REQUIRE(strcmp(name, "nvlist/binary/" ALPHABET) == 0);
206 	ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, NULL), ALPHABET,
207 	    sizeof(ALPHABET)) == 0);
208 	ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, &size), ALPHABET,
209 	    sizeof(ALPHABET)) == 0);
210 	ATF_REQUIRE(size == sizeof(ALPHABET));
211 
212 	name = nvlist_next(nvl, &type, &cookie);
213 	ATF_REQUIRE(name != NULL);
214 	ATF_REQUIRE(type == NV_TYPE_NVLIST);
215 	ATF_REQUIRE(strcmp(name, "nvlist/nvlist/empty") == 0);
216 	cnvl = nvlist_get_nvlist(nvl, name);
217 	ATF_REQUIRE(nvlist_empty(cnvl));
218 
219 	name = nvlist_next(nvl, &type, &cookie);
220 	ATF_REQUIRE(name != NULL);
221 	ATF_REQUIRE(type == NV_TYPE_NVLIST);
222 	ATF_REQUIRE(strcmp(name, "nvlist/nvlist") == 0);
223 	cnvl = nvlist_get_nvlist(nvl, name);
224 
225 	ccookie = NULL;
226 
227 	cname = nvlist_next(cnvl, &ctype, &ccookie);
228 	ATF_REQUIRE(cname != NULL);
229 	ATF_REQUIRE(ctype == NV_TYPE_BOOL);
230 	ATF_REQUIRE(strcmp(cname, "nvlist/bool/true") == 0);
231 	ATF_REQUIRE(nvlist_get_bool(cnvl, cname) == true);
232 
233 	cname = nvlist_next(cnvl, &ctype, &ccookie);
234 	ATF_REQUIRE(cname != NULL);
235 	ATF_REQUIRE(ctype == NV_TYPE_BOOL);
236 	ATF_REQUIRE(strcmp(cname, "nvlist/bool/false") == 0);
237 	ATF_REQUIRE(nvlist_get_bool(cnvl, cname) == false);
238 
239 	cname = nvlist_next(cnvl, &ctype, &ccookie);
240 	ATF_REQUIRE(cname != NULL);
241 	ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
242 	ATF_REQUIRE(strcmp(cname, "nvlist/number/0") == 0);
243 	ATF_REQUIRE(nvlist_get_number(cnvl, cname) == 0);
244 
245 	cname = nvlist_next(cnvl, &ctype, &ccookie);
246 	ATF_REQUIRE(cname != NULL);
247 	ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
248 	ATF_REQUIRE(strcmp(cname, "nvlist/number/1") == 0);
249 	ATF_REQUIRE(nvlist_get_number(cnvl, cname) == 1);
250 
251 	cname = nvlist_next(cnvl, &ctype, &ccookie);
252 	ATF_REQUIRE(cname != NULL);
253 	ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
254 	ATF_REQUIRE(strcmp(cname, "nvlist/number/-1") == 0);
255 	ATF_REQUIRE((int)nvlist_get_number(cnvl, cname) == -1);
256 
257 	cname = nvlist_next(cnvl, &ctype, &ccookie);
258 	ATF_REQUIRE(cname != NULL);
259 	ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
260 	ATF_REQUIRE(strcmp(cname, "nvlist/number/UINT64_MAX") == 0);
261 	ATF_REQUIRE(nvlist_get_number(cnvl, cname) == UINT64_MAX);
262 
263 	cname = nvlist_next(cnvl, &ctype, &ccookie);
264 	ATF_REQUIRE(cname != NULL);
265 	ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
266 	ATF_REQUIRE(strcmp(cname, "nvlist/number/INT64_MIN") == 0);
267 	ATF_REQUIRE((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN);
268 
269 	cname = nvlist_next(cnvl, &ctype, &ccookie);
270 	ATF_REQUIRE(cname != NULL);
271 	ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
272 	ATF_REQUIRE(strcmp(cname, "nvlist/number/INT64_MAX") == 0);
273 	ATF_REQUIRE((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX);
274 
275 	cname = nvlist_next(cnvl, &ctype, &ccookie);
276 	ATF_REQUIRE(cname != NULL);
277 	ATF_REQUIRE(ctype == NV_TYPE_STRING);
278 	ATF_REQUIRE(strcmp(cname, "nvlist/string/") == 0);
279 	ATF_REQUIRE(strcmp(nvlist_get_string(cnvl, cname), "") == 0);
280 
281 	cname = nvlist_next(cnvl, &ctype, &ccookie);
282 	ATF_REQUIRE(cname != NULL);
283 	ATF_REQUIRE(ctype == NV_TYPE_STRING);
284 	ATF_REQUIRE(strcmp(cname, "nvlist/string/x") == 0);
285 	ATF_REQUIRE(strcmp(nvlist_get_string(cnvl, cname), "x") == 0);
286 
287 	cname = nvlist_next(cnvl, &ctype, &ccookie);
288 	ATF_REQUIRE(cname != NULL);
289 	ATF_REQUIRE(ctype == NV_TYPE_STRING);
290 	ATF_REQUIRE(strcmp(cname, "nvlist/string/" ALPHABET) == 0);
291 	ATF_REQUIRE(strcmp(nvlist_get_string(cnvl, cname), ALPHABET) == 0);
292 
293 	cname = nvlist_next(cnvl, &ctype, &ccookie);
294 	ATF_REQUIRE(cname != NULL);
295 	ATF_REQUIRE(ctype == NV_TYPE_DESCRIPTOR);
296 	ATF_REQUIRE(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0);
297 	ATF_REQUIRE(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
298 
299 	cname = nvlist_next(cnvl, &ctype, &ccookie);
300 	ATF_REQUIRE(cname != NULL);
301 	ATF_REQUIRE(ctype == NV_TYPE_DESCRIPTOR);
302 	ATF_REQUIRE(strcmp(cname, "nvlist/descriptor/pipe_rd") == 0);
303 	ATF_REQUIRE(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
304 
305 	cname = nvlist_next(cnvl, &ctype, &ccookie);
306 	ATF_REQUIRE(cname != NULL);
307 	ATF_REQUIRE(ctype == NV_TYPE_BINARY);
308 	ATF_REQUIRE(strcmp(cname, "nvlist/binary/x") == 0);
309 	ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0);
310 	ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0);
311 	ATF_REQUIRE(size == 1);
312 
313 	cname = nvlist_next(cnvl, &ctype, &ccookie);
314 	ATF_REQUIRE(cname != NULL);
315 	ATF_REQUIRE(ctype == NV_TYPE_BINARY);
316 	ATF_REQUIRE(strcmp(cname, "nvlist/binary/" ALPHABET) == 0);
317 	ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, NULL), ALPHABET,
318 	    sizeof(ALPHABET)) == 0);
319 	ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, &size), ALPHABET,
320 	    sizeof(ALPHABET)) == 0);
321 	ATF_REQUIRE(size == sizeof(ALPHABET));
322 
323 	cname = nvlist_next(cnvl, &ctype, &ccookie);
324 	ATF_REQUIRE(cname != NULL);
325 	ATF_REQUIRE(ctype == NV_TYPE_NVLIST);
326 	ATF_REQUIRE(strcmp(cname, "nvlist/nvlist/empty") == 0);
327 	empty = nvlist_get_nvlist(cnvl, cname);
328 	ATF_REQUIRE(nvlist_empty(empty));
329 
330 	cname = nvlist_next(cnvl, &ctype, &ccookie);
331 	ATF_REQUIRE(cname == NULL);
332 
333 	name = nvlist_next(nvl, &type, &cookie);
334 	ATF_REQUIRE(name == NULL);
335 
336 	nvlist_destroy(nvl);
337 }
338 
339 static void
nvlist_send_recv__send_nvlist(short sotype)340 nvlist_send_recv__send_nvlist(short sotype)
341 {
342 	int socks[2], status;
343 	pid_t pid;
344 
345 	ATF_REQUIRE(socketpair(PF_UNIX, sotype, 0, socks) == 0);
346 
347 	pid = fork();
348 	ATF_REQUIRE(pid >= 0);
349 	if (pid == 0) {
350 		/* Child. */
351 		(void)close(socks[0]);
352 		send_nvlist_child(socks[1]);
353 		_exit(0);
354 	}
355 
356 	(void)close(socks[1]);
357 	send_nvlist_parent(socks[0]);
358 
359 	ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
360 	ATF_REQUIRE(status == 0);
361 }
362 
363 static void
nvlist_send_recv__send_closed_fd(short sotype)364 nvlist_send_recv__send_closed_fd(short sotype)
365 {
366 	nvlist_t *nvl;
367 	int socks[2];
368 
369 	ATF_REQUIRE(socketpair(PF_UNIX, sotype, 0, socks) == 0);
370 
371 	nvl = nvlist_create(0);
372 	ATF_REQUIRE(nvl != NULL);
373 	nvlist_add_descriptor(nvl, "fd", 12345);
374 	ATF_REQUIRE(nvlist_error(nvl) == EBADF);
375 
376 	ATF_REQUIRE_ERRNO(EBADF, nvlist_send(socks[1], nvl) != 0);
377 }
378 
379 static int
nopenfds(void)380 nopenfds(void)
381 {
382 	size_t len;
383 	int error, mib[4], n;
384 
385 	mib[0] = CTL_KERN;
386 	mib[1] = KERN_PROC;
387 	mib[2] = KERN_PROC_NFDS;
388 	mib[3] = 0;
389 
390 	len = sizeof(n);
391 	error = sysctl(mib, nitems(mib), &n, &len, NULL, 0);
392 	if (error != 0)
393 		return (-1);
394 	return (n);
395 }
396 
397 #define	NFDS	512
398 
399 static void
send_many_fds_child(int sock)400 send_many_fds_child(int sock)
401 {
402 	char name[16];
403 	nvlist_t *nvl;
404 	int anfds, bnfds, fd, i, j;
405 
406 	fd = open(_PATH_DEVNULL, O_RDONLY);
407 	ATF_REQUIRE(fd >= 0);
408 
409 	for (i = 1; i < NFDS; i++) {
410 		nvl = nvlist_create(0);
411 		bnfds = nopenfds();
412 		if (bnfds == -1)
413 			err(EXIT_FAILURE, "sysctl");
414 
415 		for (j = 0; j < i; j++) {
416 			snprintf(name, sizeof(name), "fd%d", j);
417 			nvlist_add_descriptor(nvl, name, fd);
418 		}
419 		nvlist_send(sock, nvl);
420 		nvlist_destroy(nvl);
421 
422 		anfds = nopenfds();
423 		if (anfds == -1)
424 			err(EXIT_FAILURE, "sysctl");
425 		if (anfds != bnfds)
426 			errx(EXIT_FAILURE, "fd count mismatch");
427 	}
428 }
429 
430 static void
nvlist_send_recv__send_many_fds(short sotype)431 nvlist_send_recv__send_many_fds(short sotype)
432 {
433 	char name[16];
434 	nvlist_t *nvl;
435 	int anfds, bnfds, fd, i, j, socks[2], status;
436 	pid_t pid;
437 
438 	ATF_REQUIRE(socketpair(PF_UNIX, sotype, 0, socks) == 0);
439 
440 	pid = fork();
441 	ATF_REQUIRE(pid >= 0);
442 	if (pid == 0) {
443 		/* Child. */
444 		(void)close(socks[0]);
445 		send_many_fds_child(socks[1]);
446 		_exit(0);
447 	}
448 
449 	(void)close(socks[1]);
450 
451 	for (i = 1; i < NFDS; i++) {
452 		bnfds = nopenfds();
453 		ATF_REQUIRE(bnfds != -1);
454 
455 		nvl = nvlist_recv(socks[0], 0);
456 		ATF_REQUIRE(nvl != NULL);
457 		for (j = 0; j < i; j++) {
458 			snprintf(name, sizeof(name), "fd%d", j);
459 			fd = nvlist_take_descriptor(nvl, name);
460 			ATF_REQUIRE(close(fd) == 0);
461 		}
462 		nvlist_destroy(nvl);
463 
464 		anfds = nopenfds();
465 		ATF_REQUIRE(anfds != -1);
466 		ATF_REQUIRE(anfds == bnfds);
467 	}
468 
469 	ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
470 	ATF_REQUIRE(status == 0);
471 }
472 
473 /*
474  * This test needs to tune the following sysctl's:
475  *      net.local.dgram.maxdgram
476  *      net.local.dgram.recvspace
477  */
478 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_many_fds__dgram);
ATF_TC_BODY(nvlist_send_recv__send_many_fds__dgram,tc)479 ATF_TC_BODY(nvlist_send_recv__send_many_fds__dgram, tc)
480 {
481 	u_long maxdgram, recvspace, temp_maxdgram, temp_recvspace;
482 	size_t len;
483 	int error;
484 
485 	/* size of the largest datagram to send */
486 	temp_maxdgram = 16772;
487 	len = sizeof(maxdgram);
488 	error = sysctlbyname("net.local.dgram.maxdgram", &maxdgram,
489 	    &len, &temp_maxdgram, sizeof(temp_maxdgram));
490 	if (error != 0)
491 		atf_tc_skip("cannot set net.local.dgram.maxdgram: %s", strerror(errno));
492 
493 	/*
494 	 * The receive queue fills up quicker than it's being emptied,
495 	 * bump it to a sufficiently large enough value, 1M.
496 	 */
497 	temp_recvspace = 1048576;
498 	len = sizeof(recvspace);
499 	error = sysctlbyname("net.local.dgram.recvspace", &recvspace,
500 	    &len, &temp_recvspace, sizeof(temp_recvspace));
501 	if (error != 0)
502 		atf_tc_skip("cannot set net.local.dgram.recvspace: %s", strerror(errno));
503 
504 	nvlist_send_recv__send_many_fds(SOCK_DGRAM);
505 
506 	/* restore original values */
507 	error = sysctlbyname("net.local.dgram.maxdgram", NULL, NULL, &maxdgram, sizeof(maxdgram));
508 	if (error != 0)
509 		warn("failed to restore net.local.dgram.maxdgram");
510 
511 	error = sysctlbyname("net.local.dgram.recvspace", NULL, NULL, &recvspace, sizeof(recvspace));
512 	if (error != 0)
513 		warn("failed to restore net.local.dgram.recvspace");
514 }
515 
516 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_many_fds__stream);
ATF_TC_BODY(nvlist_send_recv__send_many_fds__stream,tc)517 ATF_TC_BODY(nvlist_send_recv__send_many_fds__stream, tc)
518 {
519 	nvlist_send_recv__send_many_fds(SOCK_STREAM);
520 }
521 
522 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_nvlist__dgram);
ATF_TC_BODY(nvlist_send_recv__send_nvlist__dgram,tc)523 ATF_TC_BODY(nvlist_send_recv__send_nvlist__dgram, tc)
524 {
525 	nvlist_send_recv__send_nvlist(SOCK_DGRAM);
526 }
527 
528 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_nvlist__stream);
ATF_TC_BODY(nvlist_send_recv__send_nvlist__stream,tc)529 ATF_TC_BODY(nvlist_send_recv__send_nvlist__stream, tc)
530 {
531 	nvlist_send_recv__send_nvlist(SOCK_STREAM);
532 }
533 
534 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__dgram);
ATF_TC_BODY(nvlist_send_recv__send_closed_fd__dgram,tc)535 ATF_TC_BODY(nvlist_send_recv__send_closed_fd__dgram, tc)
536 {
537 	nvlist_send_recv__send_closed_fd(SOCK_DGRAM);
538 }
539 
540 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__stream);
ATF_TC_BODY(nvlist_send_recv__send_closed_fd__stream,tc)541 ATF_TC_BODY(nvlist_send_recv__send_closed_fd__stream, tc)
542 {
543 	nvlist_send_recv__send_closed_fd(SOCK_STREAM);
544 }
545 
546 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_header_size);
ATF_TC_BODY(nvlist_send_recv__overflow_header_size,tc)547 ATF_TC_BODY(nvlist_send_recv__overflow_header_size, tc)
548 {
549 	nvlist_t *nvl;
550 	void *packed;
551 	size_t packed_size;
552 	struct nvlist_header *header;
553 	int fd, socks[2], status;
554 	pid_t pid;
555 
556 #ifdef NO_ASAN
557 	atf_tc_skip("This test requires ASAN");
558 #endif
559 
560 	ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
561 
562 	pid = fork();
563 	ATF_REQUIRE(pid >= 0);
564 
565 	if (pid == 0) {
566 		/* Child. */
567 		fd = socks[0];
568 		close(socks[1]);
569 
570 		nvl = nvlist_create(0);
571 		ATF_REQUIRE(nvl != NULL);
572 		ATF_REQUIRE(nvlist_empty(nvl));
573 
574 		packed = nvlist_pack(nvl, &packed_size);
575 		ATF_REQUIRE(packed != NULL);
576 		ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header));
577 
578 		header = (struct nvlist_header *)packed;
579 		header->nvlh_size = SIZE_MAX - sizeof(struct nvlist_header) + 2;
580 
581 		ATF_REQUIRE_EQ(write(fd, packed, packed_size),
582 		    (ssize_t)sizeof(struct nvlist_header));
583 
584 		nvlist_destroy(nvl);
585 		free(packed);
586 
587 		exit(0);
588 	} else {
589 		/* Parent */
590 		fd = socks[1];
591 		close(socks[0]);
592 
593 		errno = 0;
594 		nvl = nvlist_recv(fd, 0);
595 		ATF_REQUIRE(nvl == NULL);
596 
597 		/*
598 		 * Make sure it has failed on EINVAL, and not on
599 		 * errors returned by malloc or recv.
600 		 */
601 		ATF_REQUIRE(errno == EINVAL);
602 
603 		ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
604 		ATF_REQUIRE(status == 0);
605 		close(fd);
606 	}
607 }
608 
609 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__invalid_fd_size);
ATF_TC_BODY(nvlist_send_recv__invalid_fd_size,tc)610 ATF_TC_BODY(nvlist_send_recv__invalid_fd_size, tc)
611 {
612 	nvlist_t *nvl;
613 	void *packed;
614 	size_t packed_size;
615 	struct nvlist_header *header;
616 	int fd, socks[2], status;
617 	pid_t pid;
618 
619 	ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
620 
621 	pid = fork();
622 	ATF_REQUIRE(pid >= 0);
623 
624 	if (pid == 0) {
625 		/* Child. */
626 		fd = socks[0];
627 		close(socks[1]);
628 
629 		nvl = nvlist_create(0);
630 		ATF_REQUIRE(nvl != NULL);
631 		ATF_REQUIRE(nvlist_empty(nvl));
632 
633 		nvlist_add_string(nvl, "nvl/string", "test");
634 		ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
635 
636 		packed = nvlist_pack(nvl, &packed_size);
637 		ATF_REQUIRE(packed != NULL);
638 		ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header));
639 
640 		header = (struct nvlist_header *)packed;
641 		header->nvlh_descriptors = 0x20;
642 
643 		ATF_REQUIRE_EQ(write(fd, packed, packed_size),
644 		    (ssize_t)packed_size);
645 
646 		nvlist_destroy(nvl);
647 		free(packed);
648 
649 		exit(0);
650 	} else {
651 		/* Parent */
652 		fd = socks[1];
653 		close(socks[0]);
654 
655 		nvl = nvlist_recv(fd, 0);
656 		ATF_REQUIRE(nvl == NULL);
657 
658 		ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
659 		ATF_REQUIRE(status == 0);
660 	}
661 
662 	close(fd);
663 }
664 
665 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_fd_size);
ATF_TC_BODY(nvlist_send_recv__overflow_fd_size,tc)666 ATF_TC_BODY(nvlist_send_recv__overflow_fd_size, tc)
667 {
668 	nvlist_t *nvl;
669 	void *packed;
670 	size_t packed_size;
671 	struct nvlist_header *header;
672 	int fd, socks[2], fds[1], status;
673 	pid_t pid;
674 
675 	ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
676 
677 	pid = fork();
678 	ATF_REQUIRE(pid >= 0);
679 
680 	if (pid == 0) {
681 		/* Child. */
682 		fd = socks[0];
683 		close(socks[1]);
684 
685 		nvl = nvlist_create(0);
686 		ATF_REQUIRE(nvl != NULL);
687 		ATF_REQUIRE(nvlist_empty(nvl));
688 
689 		nvlist_add_string(nvl, "nvl/string", "test");
690 		ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
691 
692 		packed = nvlist_pack(nvl, &packed_size);
693 		ATF_REQUIRE(packed != NULL);
694 		ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header));
695 
696 		header = (struct nvlist_header *)packed;
697 		header->nvlh_descriptors = 0x4000000000000002;
698 
699 		ATF_REQUIRE_EQ(write(fd, packed, packed_size),
700 		    (ssize_t)packed_size);
701 
702 		fds[0] = dup(STDERR_FILENO);
703 		ATF_REQUIRE(fds[0] >= 0);
704 		ATF_REQUIRE_EQ(fd_send(fd, fds, 1), 0);
705 
706 		nvlist_destroy(nvl);
707 		free(packed);
708 
709 		close(fds[0]);
710 		close(fd);
711 
712 		exit(0);
713 	} else {
714 		/* Parent */
715 		fd = socks[1];
716 		close(socks[0]);
717 
718 		nvl = nvlist_recv(fd, 0);
719 		ATF_REQUIRE(nvl == NULL);
720 
721 		/* Make sure that fd was not parsed by nvlist */
722 		ATF_REQUIRE(fd_recv(fd, fds, 1) == 0);
723 
724 		ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
725 		ATF_REQUIRE(status == 0);
726 
727 		close(fds[0]);
728 		close(fd);
729 	}
730 }
731 
ATF_TP_ADD_TCS(tp)732 ATF_TP_ADD_TCS(tp)
733 {
734 
735 	ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__dgram);
736 	ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__stream);
737 	ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__dgram);
738 	ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__stream);
739 	ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__dgram);
740 	ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__stream);
741 
742 	ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_header_size);
743 	ATF_TP_ADD_TC(tp, nvlist_send_recv__invalid_fd_size);
744 	ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_fd_size);
745 
746 	return (atf_no_error());
747 }
748