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 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 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 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 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 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 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 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); 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); 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); 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); 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); 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); 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); 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); 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); 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 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