1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2020-2021 Kyle Evans <kevans@FreeBSD.org> 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/param.h> 29 #include <sys/cpuset.h> 30 #include <sys/jail.h> 31 #include <sys/procdesc.h> 32 #include <sys/select.h> 33 #include <sys/socket.h> 34 #include <sys/uio.h> 35 #include <sys/wait.h> 36 37 #include <errno.h> 38 #include <stdio.h> 39 #include <unistd.h> 40 41 #include <atf-c.h> 42 43 #define SP_PARENT 0 44 #define SP_CHILD 1 45 46 struct jail_test_info { 47 cpuset_t jail_tidmask; 48 cpusetid_t jail_cpuset; 49 cpusetid_t jail_child_cpuset; 50 }; 51 52 struct jail_test_cb_params { 53 struct jail_test_info info; 54 cpuset_t mask; 55 cpusetid_t rootid; 56 cpusetid_t setid; 57 }; 58 59 typedef void (*jail_test_cb)(struct jail_test_cb_params *); 60 61 #define FAILURE_JAIL 42 62 #define FAILURE_MASK 43 63 #define FAILURE_JAILSET 44 64 #define FAILURE_PIDSET 45 65 #define FAILURE_SEND 46 66 #define FAILURE_DEADLK 47 67 #define FAILURE_ATTACH 48 68 #define FAILURE_BADAFFIN 49 69 #define FAILURE_SUCCESS 50 70 71 static const char * 72 do_jail_errstr(int error) 73 { 74 75 switch (error) { 76 case FAILURE_JAIL: 77 return ("jail_set(2) failed"); 78 case FAILURE_MASK: 79 return ("Failed to get the thread cpuset mask"); 80 case FAILURE_JAILSET: 81 return ("Failed to get the jail setid"); 82 case FAILURE_PIDSET: 83 return ("Failed to get the pid setid"); 84 case FAILURE_SEND: 85 return ("Failed to send(2) cpuset information"); 86 case FAILURE_DEADLK: 87 return ("Deadlock hit trying to attach to jail"); 88 case FAILURE_ATTACH: 89 return ("jail_attach(2) failed"); 90 case FAILURE_BADAFFIN: 91 return ("Unexpected post-attach affinity"); 92 case FAILURE_SUCCESS: 93 return ("jail_attach(2) succeeded, but should have failed."); 94 default: 95 return (NULL); 96 } 97 } 98 99 static void 100 skip_ltncpu(int ncpu, cpuset_t *mask) 101 { 102 103 CPU_ZERO(mask); 104 ATF_REQUIRE_EQ(0, cpuset_getaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID, 105 -1, sizeof(*mask), mask)); 106 if (CPU_COUNT(mask) < ncpu) 107 atf_tc_skip("Test requires %d or more cores.", ncpu); 108 } 109 110 ATF_TC(newset); 111 ATF_TC_HEAD(newset, tc) 112 { 113 atf_tc_set_md_var(tc, "descr", "Test cpuset(2)"); 114 } 115 ATF_TC_BODY(newset, tc) 116 { 117 cpusetid_t nsetid, setid, qsetid; 118 119 /* Obtain our initial set id. */ 120 ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID, -1, 121 &setid)); 122 123 /* Create a new one. */ 124 ATF_REQUIRE_EQ(0, cpuset(&nsetid)); 125 ATF_CHECK(nsetid != setid); 126 127 /* Query id again, make sure it's equal to the one we just got. */ 128 ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID, -1, 129 &qsetid)); 130 ATF_CHECK_EQ(nsetid, qsetid); 131 } 132 133 ATF_TC(transient); 134 ATF_TC_HEAD(transient, tc) 135 { 136 atf_tc_set_md_var(tc, "descr", 137 "Test that transient cpusets are freed."); 138 } 139 ATF_TC_BODY(transient, tc) 140 { 141 cpusetid_t isetid, scratch, setid; 142 143 ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, 144 &isetid)); 145 146 ATF_REQUIRE_EQ(0, cpuset(&setid)); 147 ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_CPUSET, 148 setid, &scratch)); 149 150 /* 151 * Return back to our initial cpuset; the kernel should free the cpuset 152 * we just created. 153 */ 154 ATF_REQUIRE_EQ(0, cpuset_setid(CPU_WHICH_PID, -1, isetid)); 155 ATF_REQUIRE_EQ(-1, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_CPUSET, 156 setid, &scratch)); 157 ATF_CHECK_EQ(ESRCH, errno); 158 } 159 160 ATF_TC(deadlk); 161 ATF_TC_HEAD(deadlk, tc) 162 { 163 atf_tc_set_md_var(tc, "descr", "Test against disjoint cpusets."); 164 atf_tc_set_md_var(tc, "require.user", "root"); 165 } 166 ATF_TC_BODY(deadlk, tc) 167 { 168 cpusetid_t setid; 169 cpuset_t dismask, mask, omask; 170 int fcpu, i, found, ncpu, second; 171 172 /* Make sure we have 3 cpus, so we test partial overlap. */ 173 skip_ltncpu(3, &omask); 174 175 ATF_REQUIRE_EQ(0, cpuset(&setid)); 176 CPU_ZERO(&mask); 177 CPU_ZERO(&dismask); 178 CPU_COPY(&omask, &mask); 179 CPU_COPY(&omask, &dismask); 180 fcpu = CPU_FFS(&mask); 181 ncpu = CPU_COUNT(&mask); 182 183 /* 184 * Turn off all but the first two for mask, turn off the first for 185 * dismask and turn them all off for both after the third. 186 */ 187 for (i = fcpu - 1, found = 0; i < CPU_MAXSIZE && found != ncpu; i++) { 188 if (CPU_ISSET(i, &omask)) { 189 found++; 190 if (found == 1) { 191 CPU_CLR(i, &dismask); 192 } else if (found == 2) { 193 second = i; 194 } else if (found >= 3) { 195 CPU_CLR(i, &mask); 196 if (found > 3) 197 CPU_CLR(i, &dismask); 198 } 199 } 200 } 201 202 ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID, 203 -1, sizeof(mask), &mask)); 204 205 /* Must be a strict subset! */ 206 ATF_REQUIRE_EQ(-1, cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, 207 -1, sizeof(dismask), &dismask)); 208 ATF_REQUIRE_EQ(EINVAL, errno); 209 210 /* 211 * We'll set our anonymous set to the 0,1 set that currently matches 212 * the process. If we then set the process to the 1,2 set that's in 213 * dismask, we should then personally be restricted down to the single 214 * overlapping CPOU. 215 */ 216 ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, 217 -1, sizeof(mask), &mask)); 218 ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID, 219 -1, sizeof(dismask), &dismask)); 220 ATF_REQUIRE_EQ(0, cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, 221 -1, sizeof(mask), &mask)); 222 ATF_REQUIRE_EQ(1, CPU_COUNT(&mask)); 223 ATF_REQUIRE(CPU_ISSET(second, &mask)); 224 225 /* 226 * Finally, clearing the overlap and attempting to set the process 227 * cpuset to a completely disjoint mask should fail, because this 228 * process will then not have anything to run on. 229 */ 230 CPU_CLR(second, &dismask); 231 ATF_REQUIRE_EQ(-1, cpuset_setaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID, 232 -1, sizeof(dismask), &dismask)); 233 ATF_REQUIRE_EQ(EDEADLK, errno); 234 } 235 236 static int 237 do_jail(int sock) 238 { 239 struct jail_test_info info; 240 struct iovec iov[2]; 241 char *name; 242 int error; 243 244 if (asprintf(&name, "cpuset_%d", getpid()) == -1) 245 _exit(42); 246 247 iov[0].iov_base = "name"; 248 iov[0].iov_len = 5; 249 250 iov[1].iov_base = name; 251 iov[1].iov_len = strlen(name) + 1; 252 253 if (jail_set(iov, 2, JAIL_CREATE | JAIL_ATTACH) < 0) 254 return (FAILURE_JAIL); 255 256 /* Record parameters, kick them over, then make a swift exit. */ 257 CPU_ZERO(&info.jail_tidmask); 258 error = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, 259 -1, sizeof(info.jail_tidmask), &info.jail_tidmask); 260 if (error != 0) 261 return (FAILURE_MASK); 262 263 error = cpuset_getid(CPU_LEVEL_ROOT, CPU_WHICH_TID, -1, 264 &info.jail_cpuset); 265 if (error != 0) 266 return (FAILURE_JAILSET); 267 error = cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID, -1, 268 &info.jail_child_cpuset); 269 if (error != 0) 270 return (FAILURE_PIDSET); 271 if (send(sock, &info, sizeof(info), 0) != sizeof(info)) 272 return (FAILURE_SEND); 273 return (0); 274 } 275 276 static void 277 do_jail_test(int ncpu, bool newset, jail_test_cb prologue, 278 jail_test_cb epilogue) 279 { 280 struct jail_test_cb_params cbp; 281 const char *errstr; 282 pid_t pid; 283 int error, sock, sockpair[2], status; 284 285 memset(&cbp.info, '\0', sizeof(cbp.info)); 286 287 skip_ltncpu(ncpu, &cbp.mask); 288 289 ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1, 290 &cbp.rootid)); 291 if (newset) 292 ATF_REQUIRE_EQ(0, cpuset(&cbp.setid)); 293 else 294 ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_PID, 295 -1, &cbp.setid)); 296 /* Special hack for prison0; it uses cpuset 1 as the root. */ 297 if (cbp.rootid == 0) 298 cbp.rootid = 1; 299 300 /* Not every test needs early setup. */ 301 if (prologue != NULL) 302 (*prologue)(&cbp); 303 304 ATF_REQUIRE_EQ(0, socketpair(PF_UNIX, SOCK_STREAM, 0, sockpair)); 305 ATF_REQUIRE((pid = fork()) != -1); 306 307 if (pid == 0) { 308 /* Child */ 309 close(sockpair[SP_PARENT]); 310 sock = sockpair[SP_CHILD]; 311 312 _exit(do_jail(sock)); 313 } else { 314 /* Parent */ 315 sock = sockpair[SP_PARENT]; 316 close(sockpair[SP_CHILD]); 317 318 while ((error = waitpid(pid, &status, 0)) == -1 && 319 errno == EINTR) { 320 } 321 322 ATF_REQUIRE_EQ(sizeof(cbp.info), recv(sock, &cbp.info, 323 sizeof(cbp.info), 0)); 324 325 /* Sanity check the exit info. */ 326 ATF_REQUIRE_EQ(pid, error); 327 ATF_REQUIRE(WIFEXITED(status)); 328 if (WEXITSTATUS(status) != 0) { 329 errstr = do_jail_errstr(WEXITSTATUS(status)); 330 if (errstr != NULL) 331 atf_tc_fail("%s", errstr); 332 else 333 atf_tc_fail("Unknown error '%d'", 334 WEXITSTATUS(status)); 335 } 336 337 epilogue(&cbp); 338 } 339 } 340 341 static void 342 jail_attach_mutate_pro(struct jail_test_cb_params *cbp) 343 { 344 cpuset_t *mask; 345 int count; 346 347 mask = &cbp->mask; 348 349 /* Knock out the first cpu. */ 350 count = CPU_COUNT(mask); 351 CPU_CLR(CPU_FFS(mask) - 1, mask); 352 ATF_REQUIRE_EQ(count - 1, CPU_COUNT(mask)); 353 ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, 354 -1, sizeof(*mask), mask)); 355 } 356 357 static void 358 jail_attach_newbase_epi(struct jail_test_cb_params *cbp) 359 { 360 struct jail_test_info *info; 361 cpuset_t *mask; 362 363 info = &cbp->info; 364 mask = &cbp->mask; 365 366 /* 367 * The rootid test has been thrown in because a bug was discovered 368 * where any newly derived cpuset during attach would be parented to 369 * the wrong cpuset. Otherwise, we should observe that a new cpuset 370 * has been created for this process. 371 */ 372 ATF_REQUIRE(info->jail_cpuset != cbp->rootid); 373 ATF_REQUIRE(info->jail_cpuset != cbp->setid); 374 ATF_REQUIRE(info->jail_cpuset != info->jail_child_cpuset); 375 ATF_REQUIRE_EQ(0, CPU_CMP(mask, &info->jail_tidmask)); 376 } 377 378 ATF_TC(jail_attach_newbase); 379 ATF_TC_HEAD(jail_attach_newbase, tc) 380 { 381 atf_tc_set_md_var(tc, "descr", 382 "Test jail attachment effect on affinity with a new base cpuset."); 383 atf_tc_set_md_var(tc, "require.user", "root"); 384 } 385 ATF_TC_BODY(jail_attach_newbase, tc) 386 { 387 388 /* Need >= 2 cpus to test restriction. */ 389 do_jail_test(2, true, &jail_attach_mutate_pro, 390 &jail_attach_newbase_epi); 391 } 392 393 ATF_TC(jail_attach_newbase_plain); 394 ATF_TC_HEAD(jail_attach_newbase_plain, tc) 395 { 396 atf_tc_set_md_var(tc, "descr", 397 "Test jail attachment effect on affinity with a new, unmodified base cpuset."); 398 atf_tc_set_md_var(tc, "require.user", "root"); 399 } 400 ATF_TC_BODY(jail_attach_newbase_plain, tc) 401 { 402 403 do_jail_test(2, true, NULL, &jail_attach_newbase_epi); 404 } 405 406 /* 407 * Generic epilogue for tests that are expecting to use the jail's root cpuset 408 * with their own mask, whether that's been modified or not. 409 */ 410 static void 411 jail_attach_jset_epi(struct jail_test_cb_params *cbp) 412 { 413 struct jail_test_info *info; 414 cpuset_t *mask; 415 416 info = &cbp->info; 417 mask = &cbp->mask; 418 419 ATF_REQUIRE(info->jail_cpuset != cbp->setid); 420 ATF_REQUIRE_EQ(info->jail_cpuset, info->jail_child_cpuset); 421 ATF_REQUIRE_EQ(0, CPU_CMP(mask, &info->jail_tidmask)); 422 } 423 424 ATF_TC(jail_attach_prevbase); 425 ATF_TC_HEAD(jail_attach_prevbase, tc) 426 { 427 atf_tc_set_md_var(tc, "descr", 428 "Test jail attachment effect on affinity without a new base."); 429 atf_tc_set_md_var(tc, "require.user", "root"); 430 } 431 ATF_TC_BODY(jail_attach_prevbase, tc) 432 { 433 434 do_jail_test(2, false, &jail_attach_mutate_pro, &jail_attach_jset_epi); 435 } 436 437 static void 438 jail_attach_plain_pro(struct jail_test_cb_params *cbp) 439 { 440 441 if (cbp->setid != cbp->rootid) 442 atf_tc_skip("Must be running with the root cpuset."); 443 } 444 445 ATF_TC(jail_attach_plain); 446 ATF_TC_HEAD(jail_attach_plain, tc) 447 { 448 atf_tc_set_md_var(tc, "descr", 449 "Test jail attachment effect on affinity without specialization."); 450 atf_tc_set_md_var(tc, "require.user", "root"); 451 } 452 ATF_TC_BODY(jail_attach_plain, tc) 453 { 454 455 do_jail_test(1, false, &jail_attach_plain_pro, &jail_attach_jset_epi); 456 } 457 458 static int 459 jail_attach_disjoint_newjail(int fd) 460 { 461 struct iovec iov[2]; 462 char *name; 463 int jid; 464 465 if (asprintf(&name, "cpuset_%d", getpid()) == -1) 466 _exit(42); 467 468 iov[0].iov_base = "name"; 469 iov[0].iov_len = sizeof("name"); 470 471 iov[1].iov_base = name; 472 iov[1].iov_len = strlen(name) + 1; 473 474 if ((jid = jail_set(iov, 2, JAIL_CREATE | JAIL_ATTACH)) < 0) 475 return (FAILURE_JAIL); 476 477 /* Signal that we're ready. */ 478 write(fd, &jid, sizeof(jid)); 479 for (;;) { 480 /* Spin */ 481 } 482 } 483 484 static int 485 wait_jail(int fd, int pfd) 486 { 487 fd_set lset; 488 struct timeval tv; 489 int error, jid, maxfd; 490 491 FD_ZERO(&lset); 492 FD_SET(fd, &lset); 493 FD_SET(pfd, &lset); 494 495 maxfd = MAX(fd, pfd); 496 497 tv.tv_sec = 5; 498 tv.tv_usec = 0; 499 500 /* Wait for jid to be written. */ 501 do { 502 error = select(maxfd + 1, &lset, NULL, NULL, &tv); 503 } while (error == -1 && errno == EINTR); 504 505 if (error == 0) { 506 atf_tc_fail("Jail creator did not respond in time."); 507 } 508 509 ATF_REQUIRE_MSG(error > 0, "Unexpected error %d from select()", errno); 510 511 if (FD_ISSET(pfd, &lset)) { 512 /* Process died */ 513 atf_tc_fail("Jail creator died unexpectedly."); 514 } 515 516 ATF_REQUIRE(FD_ISSET(fd, &lset)); 517 ATF_REQUIRE_EQ(sizeof(jid), recv(fd, &jid, sizeof(jid), 0)); 518 519 return (jid); 520 } 521 522 static int 523 try_attach_child(int jid, cpuset_t *expected_mask) 524 { 525 cpuset_t mask; 526 527 if (jail_attach(jid) == -1) { 528 if (errno == EDEADLK) 529 return (FAILURE_DEADLK); 530 return (FAILURE_ATTACH); 531 } 532 533 if (expected_mask == NULL) 534 return (FAILURE_SUCCESS); 535 536 /* If we had an expected mask, check it against the new process mask. */ 537 CPU_ZERO(&mask); 538 if (cpuset_getaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID, 539 -1, sizeof(mask), &mask) != 0) { 540 return (FAILURE_MASK); 541 } 542 543 if (CPU_CMP(expected_mask, &mask) != 0) 544 return (FAILURE_BADAFFIN); 545 546 return (0); 547 } 548 549 static void 550 try_attach(int jid, cpuset_t *expected_mask) 551 { 552 const char *errstr; 553 pid_t pid; 554 int error, fail, status; 555 556 ATF_REQUIRE(expected_mask != NULL); 557 ATF_REQUIRE((pid = fork()) != -1); 558 if (pid == 0) 559 _exit(try_attach_child(jid, expected_mask)); 560 561 while ((error = waitpid(pid, &status, 0)) == -1 && errno == EINTR) { 562 /* Try again. */ 563 } 564 565 /* Sanity check the exit info. */ 566 ATF_REQUIRE_EQ(pid, error); 567 ATF_REQUIRE(WIFEXITED(status)); 568 if ((fail = WEXITSTATUS(status)) != 0) { 569 errstr = do_jail_errstr(fail); 570 if (errstr != NULL) 571 atf_tc_fail("%s", errstr); 572 else 573 atf_tc_fail("Unknown error '%d'", WEXITSTATUS(status)); 574 } 575 } 576 577 ATF_TC(jail_attach_disjoint); 578 ATF_TC_HEAD(jail_attach_disjoint, tc) 579 { 580 atf_tc_set_md_var(tc, "descr", 581 "Test root attachment into completely disjoint jail cpuset."); 582 atf_tc_set_md_var(tc, "require.user", "root"); 583 } 584 ATF_TC_BODY(jail_attach_disjoint, tc) 585 { 586 cpuset_t smask, jmask; 587 int sockpair[2]; 588 cpusetid_t setid; 589 pid_t pid; 590 int fcpu, jid, pfd, sock, scpu; 591 592 ATF_REQUIRE_EQ(0, cpuset(&setid)); 593 594 skip_ltncpu(2, &jmask); 595 fcpu = CPU_FFS(&jmask) - 1; 596 ATF_REQUIRE_EQ(0, socketpair(PF_UNIX, SOCK_STREAM, 0, sockpair)); 597 598 /* We'll wait on the procdesc, too, so we can fail faster if it dies. */ 599 ATF_REQUIRE((pid = pdfork(&pfd, 0)) != -1); 600 601 if (pid == 0) { 602 /* First child sets up the jail. */ 603 sock = sockpair[SP_CHILD]; 604 close(sockpair[SP_PARENT]); 605 606 _exit(jail_attach_disjoint_newjail(sock)); 607 } 608 609 close(sockpair[SP_CHILD]); 610 sock = sockpair[SP_PARENT]; 611 612 ATF_REQUIRE((jid = wait_jail(sock, pfd)) > 0); 613 614 /* 615 * This process will be clamped down to the first cpu, while the jail 616 * will simply have the first CPU removed to make it a completely 617 * disjoint operation. 618 */ 619 CPU_ZERO(&smask); 620 CPU_SET(fcpu, &smask); 621 CPU_CLR(fcpu, &jmask); 622 623 /* 624 * We'll test with the first and second cpu set as well. Only the 625 * second cpu should be used. 626 */ 627 scpu = CPU_FFS(&jmask) - 1; 628 629 ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_ROOT, CPU_WHICH_JAIL, 630 jid, sizeof(jmask), &jmask)); 631 ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_CPUSET, 632 setid, sizeof(smask), &smask)); 633 634 try_attach(jid, &jmask); 635 636 CPU_SET(scpu, &smask); 637 ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_CPUSET, 638 setid, sizeof(smask), &smask)); 639 640 CPU_CLR(fcpu, &smask); 641 try_attach(jid, &smask); 642 } 643 644 ATF_TC(badparent); 645 ATF_TC_HEAD(badparent, tc) 646 { 647 atf_tc_set_md_var(tc, "descr", 648 "Test parent assignment when assigning a new cpuset."); 649 } 650 ATF_TC_BODY(badparent, tc) 651 { 652 cpuset_t mask; 653 cpusetid_t finalsetid, origsetid, setid; 654 655 /* Need to mask off at least one CPU. */ 656 skip_ltncpu(2, &mask); 657 658 ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID, -1, 659 &origsetid)); 660 661 ATF_REQUIRE_EQ(0, cpuset(&setid)); 662 663 /* 664 * Mask off the first CPU, then we'll reparent ourselves to our original 665 * set. 666 */ 667 CPU_CLR(CPU_FFS(&mask) - 1, &mask); 668 ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, 669 -1, sizeof(mask), &mask)); 670 671 ATF_REQUIRE_EQ(0, cpuset_setid(CPU_WHICH_PID, -1, origsetid)); 672 ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID, -1, 673 &finalsetid)); 674 675 ATF_REQUIRE_EQ(finalsetid, origsetid); 676 } 677 678 ATF_TP_ADD_TCS(tp) 679 { 680 681 ATF_TP_ADD_TC(tp, newset); 682 ATF_TP_ADD_TC(tp, transient); 683 ATF_TP_ADD_TC(tp, deadlk); 684 ATF_TP_ADD_TC(tp, jail_attach_newbase); 685 ATF_TP_ADD_TC(tp, jail_attach_newbase_plain); 686 ATF_TP_ADD_TC(tp, jail_attach_prevbase); 687 ATF_TP_ADD_TC(tp, jail_attach_plain); 688 ATF_TP_ADD_TC(tp, jail_attach_disjoint); 689 ATF_TP_ADD_TC(tp, badparent); 690 return (atf_no_error()); 691 } 692