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 atf_tc_skip("https://bugs.freebsd.org/260891"); 486 487 /* size of the largest datagram to send */ 488 temp_maxdgram = 16772; 489 len = sizeof(maxdgram); 490 error = sysctlbyname("net.local.dgram.maxdgram", &maxdgram, 491 &len, &temp_maxdgram, sizeof(temp_maxdgram)); 492 if (error != 0) 493 atf_tc_skip("cannot set net.local.dgram.maxdgram: %s", strerror(errno)); 494 495 /* 496 * The receive queue fills up quicker than it's being emptied, 497 * bump it to a sufficiently large enough value, 1M. 498 */ 499 temp_recvspace = 1048576; 500 len = sizeof(recvspace); 501 error = sysctlbyname("net.local.dgram.recvspace", &recvspace, 502 &len, &temp_recvspace, sizeof(temp_recvspace)); 503 if (error != 0) 504 atf_tc_skip("cannot set net.local.dgram.recvspace: %s", strerror(errno)); 505 506 nvlist_send_recv__send_many_fds(SOCK_DGRAM); 507 508 /* restore original values */ 509 error = sysctlbyname("net.local.dgram.maxdgram", NULL, NULL, &maxdgram, sizeof(maxdgram)); 510 if (error != 0) 511 warn("failed to restore net.local.dgram.maxdgram"); 512 513 error = sysctlbyname("net.local.dgram.recvspace", NULL, NULL, &recvspace, sizeof(recvspace)); 514 if (error != 0) 515 warn("failed to restore net.local.dgram.recvspace"); 516 } 517 518 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_many_fds__stream); 519 ATF_TC_BODY(nvlist_send_recv__send_many_fds__stream, tc) 520 { 521 nvlist_send_recv__send_many_fds(SOCK_STREAM); 522 } 523 524 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_nvlist__dgram); 525 ATF_TC_BODY(nvlist_send_recv__send_nvlist__dgram, tc) 526 { 527 nvlist_send_recv__send_nvlist(SOCK_DGRAM); 528 } 529 530 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_nvlist__stream); 531 ATF_TC_BODY(nvlist_send_recv__send_nvlist__stream, tc) 532 { 533 nvlist_send_recv__send_nvlist(SOCK_STREAM); 534 } 535 536 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__dgram); 537 ATF_TC_BODY(nvlist_send_recv__send_closed_fd__dgram, tc) 538 { 539 nvlist_send_recv__send_closed_fd(SOCK_DGRAM); 540 } 541 542 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__stream); 543 ATF_TC_BODY(nvlist_send_recv__send_closed_fd__stream, tc) 544 { 545 nvlist_send_recv__send_closed_fd(SOCK_STREAM); 546 } 547 548 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_header_size); 549 ATF_TC_BODY(nvlist_send_recv__overflow_header_size, tc) 550 { 551 nvlist_t *nvl; 552 void *packed; 553 size_t packed_size; 554 struct nvlist_header *header; 555 int fd, socks[2], status; 556 pid_t pid; 557 558 #ifdef NO_ASAN 559 atf_tc_skip("This test requires ASAN"); 560 #endif 561 562 ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); 563 564 pid = fork(); 565 ATF_REQUIRE(pid >= 0); 566 567 if (pid == 0) { 568 /* Child. */ 569 fd = socks[0]; 570 close(socks[1]); 571 572 nvl = nvlist_create(0); 573 ATF_REQUIRE(nvl != NULL); 574 ATF_REQUIRE(nvlist_empty(nvl)); 575 576 packed = nvlist_pack(nvl, &packed_size); 577 ATF_REQUIRE(packed != NULL); 578 ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header)); 579 580 header = (struct nvlist_header *)packed; 581 header->nvlh_size = SIZE_MAX - sizeof(struct nvlist_header) + 2; 582 583 ATF_REQUIRE_EQ(write(fd, packed, packed_size), 584 (ssize_t)sizeof(struct nvlist_header)); 585 586 nvlist_destroy(nvl); 587 free(packed); 588 589 exit(0); 590 } else { 591 /* Parent */ 592 fd = socks[1]; 593 close(socks[0]); 594 595 errno = 0; 596 nvl = nvlist_recv(fd, 0); 597 ATF_REQUIRE(nvl == NULL); 598 599 /* 600 * Make sure it has failed on EINVAL, and not on 601 * errors returned by malloc or recv. 602 */ 603 ATF_REQUIRE(errno == EINVAL); 604 605 ATF_REQUIRE(waitpid(pid, &status, 0) == pid); 606 ATF_REQUIRE(status == 0); 607 close(fd); 608 } 609 } 610 611 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__invalid_fd_size); 612 ATF_TC_BODY(nvlist_send_recv__invalid_fd_size, tc) 613 { 614 nvlist_t *nvl; 615 void *packed; 616 size_t packed_size; 617 struct nvlist_header *header; 618 int fd, socks[2], status; 619 pid_t pid; 620 621 ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); 622 623 pid = fork(); 624 ATF_REQUIRE(pid >= 0); 625 626 if (pid == 0) { 627 /* Child. */ 628 fd = socks[0]; 629 close(socks[1]); 630 631 nvl = nvlist_create(0); 632 ATF_REQUIRE(nvl != NULL); 633 ATF_REQUIRE(nvlist_empty(nvl)); 634 635 nvlist_add_string(nvl, "nvl/string", "test"); 636 ATF_REQUIRE_EQ(nvlist_error(nvl), 0); 637 638 packed = nvlist_pack(nvl, &packed_size); 639 ATF_REQUIRE(packed != NULL); 640 ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header)); 641 642 header = (struct nvlist_header *)packed; 643 header->nvlh_descriptors = 0x20; 644 645 ATF_REQUIRE_EQ(write(fd, packed, packed_size), 646 (ssize_t)packed_size); 647 648 nvlist_destroy(nvl); 649 free(packed); 650 651 exit(0); 652 } else { 653 /* Parent */ 654 fd = socks[1]; 655 close(socks[0]); 656 657 nvl = nvlist_recv(fd, 0); 658 ATF_REQUIRE(nvl == NULL); 659 660 ATF_REQUIRE(waitpid(pid, &status, 0) == pid); 661 ATF_REQUIRE(status == 0); 662 } 663 664 close(fd); 665 } 666 667 ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_fd_size); 668 ATF_TC_BODY(nvlist_send_recv__overflow_fd_size, tc) 669 { 670 nvlist_t *nvl; 671 void *packed; 672 size_t packed_size; 673 struct nvlist_header *header; 674 int fd, socks[2], fds[1], status; 675 pid_t pid; 676 677 ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); 678 679 pid = fork(); 680 ATF_REQUIRE(pid >= 0); 681 682 if (pid == 0) { 683 /* Child. */ 684 fd = socks[0]; 685 close(socks[1]); 686 687 nvl = nvlist_create(0); 688 ATF_REQUIRE(nvl != NULL); 689 ATF_REQUIRE(nvlist_empty(nvl)); 690 691 nvlist_add_string(nvl, "nvl/string", "test"); 692 ATF_REQUIRE_EQ(nvlist_error(nvl), 0); 693 694 packed = nvlist_pack(nvl, &packed_size); 695 ATF_REQUIRE(packed != NULL); 696 ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header)); 697 698 header = (struct nvlist_header *)packed; 699 header->nvlh_descriptors = 0x4000000000000002; 700 701 ATF_REQUIRE_EQ(write(fd, packed, packed_size), 702 (ssize_t)packed_size); 703 704 fds[0] = dup(STDERR_FILENO); 705 ATF_REQUIRE(fds[0] >= 0); 706 ATF_REQUIRE_EQ(fd_send(fd, fds, 1), 0); 707 708 nvlist_destroy(nvl); 709 free(packed); 710 711 close(fds[0]); 712 close(fd); 713 714 exit(0); 715 } else { 716 /* Parent */ 717 fd = socks[1]; 718 close(socks[0]); 719 720 nvl = nvlist_recv(fd, 0); 721 ATF_REQUIRE(nvl == NULL); 722 723 /* Make sure that fd was not parsed by nvlist */ 724 ATF_REQUIRE(fd_recv(fd, fds, 1) == 0); 725 726 ATF_REQUIRE(waitpid(pid, &status, 0) == pid); 727 ATF_REQUIRE(status == 0); 728 729 close(fds[0]); 730 close(fd); 731 } 732 } 733 734 ATF_TP_ADD_TCS(tp) 735 { 736 737 ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__dgram); 738 ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__stream); 739 ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__dgram); 740 ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__stream); 741 ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__dgram); 742 ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__stream); 743 744 ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_header_size); 745 ATF_TP_ADD_TC(tp, nvlist_send_recv__invalid_fd_size); 746 ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_fd_size); 747 748 return (atf_no_error()); 749 } 750