1 /*- 2 * Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org> 3 * Copyright (c) 2023 The FreeBSD Foundation 4 * 5 * This software was developed by Jake Freeland <jfree@FreeBSD.org> 6 * under sponsorship from the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/capsicum.h> 32 #include <sys/cpuset.h> 33 #include <sys/ktrace.h> 34 #include <sys/mman.h> 35 #include <sys/socket.h> 36 #include <sys/syscall.h> 37 #include <sys/sysent.h> 38 #include <sys/time.h> 39 #include <sys/uio.h> 40 #include <sys/user.h> 41 #include <sys/wait.h> 42 43 #include <machine/sysarch.h> 44 #include <netinet/in.h> 45 46 #include <atf-c.h> 47 #include <capsicum_helpers.h> 48 #include <errno.h> 49 #include <fcntl.h> 50 #include <netdb.h> 51 #include <signal.h> 52 #include <sysdecode.h> 53 54 /* 55 * A variant of ATF_REQUIRE that is suitable for use in child 56 * processes. This only works if the parent process is tripped up by 57 * the early exit and fails some requirement itself. 58 */ 59 #define CHILD_REQUIRE(exp) do { \ 60 if (!(exp)) \ 61 child_fail_require(__FILE__, __LINE__, \ 62 #exp " not met\n"); \ 63 } while (0) 64 #define CHILD_REQUIRE_EQ(actual, expected) do { \ 65 __typeof__(expected) _e = expected; \ 66 __typeof__(actual) _a = actual; \ 67 if (_e != _a) \ 68 child_fail_require(__FILE__, __LINE__, #actual \ 69 " (%jd) == " #expected " (%jd) not met\n", \ 70 (intmax_t)_a, (intmax_t)_e); \ 71 } while (0) 72 73 static __dead2 void 74 child_fail_require(const char *file, int line, const char *fmt, ...) 75 { 76 va_list ap; 77 char buf[1024]; 78 79 /* Use write() not fprintf() to avoid possible duplicate output. */ 80 snprintf(buf, sizeof(buf), "%s:%d: ", file, line); 81 write(STDERR_FILENO, buf, strlen(buf)); 82 va_start(ap, fmt); 83 vsnprintf(buf, sizeof(buf), fmt, ap); 84 write(STDERR_FILENO, buf, strlen(buf)); 85 va_end(ap); 86 87 _exit(32); 88 } 89 90 static void * 91 xmalloc(size_t size) 92 { 93 void *p; 94 95 p = malloc(size); 96 ATF_REQUIRE(p != NULL); 97 return (p); 98 } 99 100 /* 101 * Determine sysdecode ABI based on proc's ABI in sv_flags. 102 */ 103 static enum sysdecode_abi 104 syscallabi(u_int sv_flags) 105 { 106 switch (sv_flags & SV_ABI_MASK) { 107 case SV_ABI_FREEBSD: 108 return (SYSDECODE_ABI_FREEBSD); 109 case SV_ABI_LINUX: 110 #ifdef __LP64__ 111 if ((sv_flags & SV_ILP32) != 0) 112 return (SYSDECODE_ABI_LINUX32); 113 #endif 114 return (SYSDECODE_ABI_LINUX); 115 } 116 return (SYSDECODE_ABI_UNKNOWN); 117 } 118 119 static int 120 trace_child(int cpid, int facility, int status) 121 { 122 int error, fd; 123 124 ATF_REQUIRE((fd = open("ktrace.out", 125 O_RDONLY | O_CREAT | O_TRUNC, 0600)) != -1); 126 ATF_REQUIRE_MSG(ktrace("ktrace.out", KTROP_SET, facility, cpid) != -1, 127 "ktrace failed: %s", strerror(errno)); 128 /* Notify child that we've starting tracing. */ 129 ATF_REQUIRE(kill(cpid, SIGUSR1) != -1); 130 /* Wait for child to raise violation and exit. */ 131 ATF_REQUIRE(waitpid(cpid, &error, 0) != -1); 132 ATF_REQUIRE(WIFEXITED(error)); 133 ATF_REQUIRE_EQ(WEXITSTATUS(error), status); 134 return (fd); 135 } 136 137 /* 138 * Start tracing capability violations and notify child that it can execute. 139 * Return @numv capability violations from child in @v. 140 */ 141 static void 142 cap_trace_child(pid_t cpid, struct ktr_cap_fail *v, int numv) 143 { 144 struct ktr_header header; 145 ssize_t n; 146 int fd; 147 148 fd = trace_child(cpid, KTRFAC_CAPFAIL, 0); 149 150 /* Read ktrace header and ensure violation occurred. */ 151 for (int i = 0; i < numv; ++i) { 152 ATF_REQUIRE((n = read(fd, &header, sizeof(header))) != -1); 153 ATF_REQUIRE_EQ(n, sizeof(header)); 154 ATF_REQUIRE_EQ(header.ktr_len, sizeof(*v)); 155 ATF_REQUIRE_EQ(header.ktr_pid, cpid); 156 /* Read the capability violation. */ 157 ATF_REQUIRE((n = read(fd, v + i, 158 sizeof(*v))) != -1); 159 ATF_REQUIRE_EQ(n, sizeof(*v)); 160 } 161 ATF_REQUIRE(close(fd) != -1); 162 } 163 164 /* 165 * Test if ktrace will record an operation that is done with 166 * insufficient rights. 167 */ 168 ATF_TC_WITHOUT_HEAD(ktrace__cap_not_capable); 169 ATF_TC_BODY(ktrace__cap_not_capable, tc) 170 { 171 struct ktr_cap_fail violation; 172 cap_rights_t rights; 173 sigset_t set = { }; 174 pid_t pid; 175 int error; 176 177 /* Block SIGUSR1 so child does not terminate. */ 178 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 179 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 180 181 ATF_REQUIRE((pid = fork()) != -1); 182 if (pid == 0) { 183 /* Limit fd rights to CAP_READ. */ 184 cap_rights_init(&rights, CAP_READ); 185 CHILD_REQUIRE(caph_rights_limit(STDIN_FILENO, &rights) != -1); 186 CHILD_REQUIRE(caph_enter() != -1); 187 /* Wait until ktrace has started. */ 188 CHILD_REQUIRE(sigwait(&set, &error) != -1); 189 CHILD_REQUIRE_EQ(error, SIGUSR1); 190 /* Write without CAP_WRITE. */ 191 CHILD_REQUIRE(write(STDIN_FILENO, &pid, sizeof(pid)) == -1); 192 CHILD_REQUIRE_EQ(errno, ENOTCAPABLE); 193 exit(0); 194 } 195 196 cap_trace_child(pid, &violation, 1); 197 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_NOTCAPABLE); 198 ATF_REQUIRE(cap_rights_is_set(&violation.cap_data.cap_needed, 199 CAP_WRITE)); 200 } 201 202 /* 203 * Test if ktrace will record an attempt to increase rights. 204 */ 205 ATF_TC_WITHOUT_HEAD(ktrace__cap_increase_rights); 206 ATF_TC_BODY(ktrace__cap_increase_rights, tc) 207 { 208 struct ktr_cap_fail violation; 209 cap_rights_t rights; 210 sigset_t set = { }; 211 pid_t pid; 212 int error; 213 214 /* Block SIGUSR1 so child does not terminate. */ 215 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 216 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 217 218 ATF_REQUIRE((pid = fork()) != -1); 219 if (pid == 0) { 220 /* Limit fd rights to CAP_READ. */ 221 cap_rights_init(&rights, CAP_READ); 222 CHILD_REQUIRE(caph_rights_limit(STDIN_FILENO, &rights) != -1); 223 CHILD_REQUIRE(caph_enter() != -1); 224 /* Wait until ktrace has started. */ 225 CHILD_REQUIRE(sigwait(&set, &error) != -1); 226 CHILD_REQUIRE_EQ(error, SIGUSR1); 227 /* Increase fd rights to include CAP_WRITE. */ 228 cap_rights_set(&rights, CAP_WRITE); 229 CHILD_REQUIRE(caph_rights_limit(STDIN_FILENO, &rights) == -1); 230 CHILD_REQUIRE_EQ(errno, ENOTCAPABLE); 231 exit(0); 232 } 233 234 cap_trace_child(pid, &violation, 1); 235 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_INCREASE); 236 ATF_REQUIRE(cap_rights_is_set(&violation.cap_data.cap_needed, 237 CAP_WRITE)); 238 } 239 240 /* 241 * Test if disallowed syscalls are reported as capability violations. 242 */ 243 ATF_TC_WITHOUT_HEAD(ktrace__cap_syscall); 244 ATF_TC_BODY(ktrace__cap_syscall, tc) 245 { 246 struct kinfo_file kinf; 247 struct ktr_cap_fail violation[2]; 248 sigset_t set = { }; 249 pid_t pid; 250 int error; 251 252 /* Block SIGUSR1 so child does not terminate. */ 253 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 254 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 255 256 ATF_REQUIRE((pid = fork()) != -1); 257 if (pid == 0) { 258 /* Wait until ktrace has started. */ 259 CHILD_REQUIRE(sigwait(&set, &error) != -1); 260 CHILD_REQUIRE_EQ(error, SIGUSR1); 261 /* chdir() is not permitted in capability mode. */ 262 CHILD_REQUIRE(chdir(".") != -1); 263 kinf.kf_structsize = sizeof(struct kinfo_file); 264 /* 265 * fcntl() is permitted in capability mode, 266 * but the F_KINFO cmd is not. 267 */ 268 CHILD_REQUIRE(fcntl(STDIN_FILENO, F_KINFO, &kinf) != -1); 269 exit(0); 270 } 271 272 cap_trace_child(pid, violation, 2); 273 ATF_REQUIRE_EQ(violation[0].cap_type, CAPFAIL_SYSCALL); 274 error = syscallabi(violation[0].cap_svflags); 275 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[0].cap_code), 276 "chdir"); 277 278 ATF_REQUIRE_EQ(violation[1].cap_type, CAPFAIL_SYSCALL); 279 error = syscallabi(violation[1].cap_svflags); 280 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[1].cap_code), 281 "fcntl"); 282 ATF_REQUIRE_EQ(violation[1].cap_data.cap_int, F_KINFO); 283 } 284 285 /* 286 * Test if sending a signal to another process is reported as 287 * a signal violation. 288 */ 289 ATF_TC_WITHOUT_HEAD(ktrace__cap_signal); 290 ATF_TC_BODY(ktrace__cap_signal, tc) 291 { 292 struct ktr_cap_fail violation; 293 sigset_t set = { }; 294 pid_t pid; 295 int error; 296 297 /* Block SIGUSR1 so child does not terminate. */ 298 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 299 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 300 301 ATF_REQUIRE((pid = fork()) != -1); 302 if (pid == 0) { 303 /* Wait until ktrace has started. */ 304 CHILD_REQUIRE(sigwait(&set, &error) != -1); 305 CHILD_REQUIRE_EQ(error, SIGUSR1); 306 /* 307 * Signals may only be sent to ourself. Sending signals 308 * to other processes is not allowed in capability mode. 309 */ 310 CHILD_REQUIRE(kill(getppid(), SIGCONT) != -1); 311 exit(0); 312 } 313 314 cap_trace_child(pid, &violation, 1); 315 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_SIGNAL); 316 error = syscallabi(violation.cap_svflags); 317 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 318 "kill"); 319 ATF_REQUIRE_EQ(violation.cap_data.cap_int, SIGCONT); 320 } 321 322 /* 323 * Test if opening a socket with a restricted protocol is reported 324 * as a protocol violation. 325 */ 326 ATF_TC(ktrace__cap_proto); 327 ATF_TC_HEAD(ktrace__cap_proto, tc) 328 { 329 atf_tc_set_md_var(tc, "require.user", "root"); 330 } 331 ATF_TC_BODY(ktrace__cap_proto, tc) 332 { 333 struct ktr_cap_fail violation; 334 sigset_t set = { }; 335 pid_t pid; 336 int error; 337 338 /* Block SIGUSR1 so child does not terminate. */ 339 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 340 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 341 342 ATF_REQUIRE((pid = fork()) != -1); 343 if (pid == 0) { 344 /* Wait until ktrace has started. */ 345 CHILD_REQUIRE(sigwait(&set, &error) != -1); 346 CHILD_REQUIRE_EQ(error, SIGUSR1); 347 /* 348 * Certain protocols may not be used in capability mode. 349 * ICMP's raw-protocol interface is not allowed. 350 */ 351 CHILD_REQUIRE(close(socket(AF_INET, SOCK_RAW, 352 IPPROTO_ICMP)) != -1); 353 exit(0); 354 } 355 356 cap_trace_child(pid, &violation, 1); 357 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_PROTO); 358 error = syscallabi(violation.cap_svflags); 359 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 360 "socket"); 361 ATF_REQUIRE_EQ(violation.cap_data.cap_int, IPPROTO_ICMP); 362 } 363 364 /* 365 * Test if sending data to an address using a socket is 366 * reported as a sockaddr violation. 367 */ 368 ATF_TC_WITHOUT_HEAD(ktrace__cap_sockaddr); 369 ATF_TC_BODY(ktrace__cap_sockaddr, tc) 370 { 371 struct sockaddr_in addr = { }, *saddr; 372 struct ktr_cap_fail violation; 373 sigset_t set = { }; 374 pid_t pid; 375 int error, sfd; 376 377 /* Block SIGUSR1 so child does not terminate. */ 378 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 379 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 380 381 CHILD_REQUIRE((sfd = socket(AF_INET, SOCK_DGRAM, 382 IPPROTO_UDP)) != -1); 383 addr.sin_family = AF_INET; 384 addr.sin_port = htons(5000); 385 addr.sin_addr.s_addr = INADDR_ANY; 386 CHILD_REQUIRE(bind(sfd, (const struct sockaddr *)&addr, 387 sizeof(addr)) != -1); 388 389 ATF_REQUIRE((pid = fork()) != -1); 390 if (pid == 0) { 391 /* Wait until ktrace has started. */ 392 CHILD_REQUIRE(sigwait(&set, &error) != -1); 393 CHILD_REQUIRE_EQ(error, SIGUSR1); 394 /* 395 * Sending data to an address is not permitted. 396 * In this case, sending data to @addr causes a 397 * violation. 398 */ 399 CHILD_REQUIRE(sendto(sfd, NULL, 0, 0, 400 (const struct sockaddr *)&addr, sizeof(addr)) != -1); 401 exit(0); 402 } 403 404 cap_trace_child(pid, &violation, 1); 405 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_SOCKADDR); 406 error = syscallabi(violation.cap_svflags); 407 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 408 "sendto"); 409 saddr = (struct sockaddr_in *)&violation.cap_data.cap_sockaddr; 410 ATF_REQUIRE_EQ(saddr->sin_family, AF_INET); 411 ATF_REQUIRE_EQ(saddr->sin_port, htons(5000)); 412 ATF_REQUIRE_EQ(saddr->sin_addr.s_addr, INADDR_ANY); 413 close(sfd); 414 } 415 416 /* 417 * Test if openat() with AT_FDCWD and absolute path are reported 418 * as namei violations. 419 */ 420 ATF_TC_WITHOUT_HEAD(ktrace__cap_namei); 421 ATF_TC_BODY(ktrace__cap_namei, tc) 422 { 423 struct ktr_cap_fail violation[2]; 424 sigset_t set = { }; 425 pid_t pid; 426 int error; 427 428 /* Block SIGUSR1 so child does not terminate. */ 429 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 430 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 431 432 ATF_REQUIRE((pid = fork()) != -1); 433 if (pid == 0) { 434 /* Wait until ktrace has started. */ 435 CHILD_REQUIRE(sigwait(&set, &error) != -1); 436 CHILD_REQUIRE_EQ(error, SIGUSR1); 437 /* 438 * The AT_FDCWD file descriptor has not been opened 439 * and will be inaccessible in capability mode. 440 */ 441 CHILD_REQUIRE(close(openat(AT_FDCWD, "ktrace.out", 442 O_RDONLY | O_CREAT)) != -1); 443 /* 444 * Absolute paths are inaccessible in capability mode. 445 */ 446 CHILD_REQUIRE(close(openat(-1, "/", O_RDONLY)) != -1); 447 exit(0); 448 } 449 450 cap_trace_child(pid, violation, 2); 451 ATF_REQUIRE_EQ(violation[0].cap_type, CAPFAIL_NAMEI); 452 error = syscallabi(violation[0].cap_svflags); 453 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[0].cap_code), 454 "openat"); 455 ATF_REQUIRE_STREQ(violation[0].cap_data.cap_path, "AT_FDCWD"); 456 457 ATF_REQUIRE_EQ(violation[1].cap_type, CAPFAIL_NAMEI); 458 error = syscallabi(violation[1].cap_svflags); 459 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[1].cap_code), 460 "openat"); 461 ATF_REQUIRE_STREQ(violation[1].cap_data.cap_path, "/"); 462 } 463 464 /* 465 * Test if changing another process's cpu set is recorded as 466 * a cpuset violation. 467 */ 468 ATF_TC_WITHOUT_HEAD(ktrace__cap_cpuset); 469 ATF_TC_BODY(ktrace__cap_cpuset, tc) 470 { 471 struct ktr_cap_fail violation; 472 cpuset_t cpuset_mask = { }; 473 sigset_t set = { }; 474 pid_t pid; 475 int error; 476 477 /* Block SIGUSR1 so child does not terminate. */ 478 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 479 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 480 481 ATF_REQUIRE((pid = fork()) != -1); 482 if (pid == 0) { 483 /* Wait until ktrace has started. */ 484 CHILD_REQUIRE(sigwait(&set, &error) != -1); 485 CHILD_REQUIRE_EQ(error, SIGUSR1); 486 /* 487 * Set cpu 0 affinity for parent process. 488 * Other process's cpu sets are restricted in capability 489 * mode, so this will raise a violation. 490 */ 491 CPU_SET(0, &cpuset_mask); 492 CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 493 getppid(), sizeof(cpuset_mask), &cpuset_mask) != -1); 494 exit(0); 495 } 496 497 cap_trace_child(pid, &violation, 1); 498 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_CPUSET); 499 error = syscallabi(violation.cap_svflags); 500 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 501 "cpuset_setaffinity"); 502 } 503 504 ATF_TC_WITHOUT_HEAD(ktrace__cap_shm_open); 505 ATF_TC_BODY(ktrace__cap_shm_open, tc) 506 { 507 struct ktr_cap_fail violation; 508 sigset_t set = { }; 509 pid_t pid; 510 int error; 511 512 /* Block SIGUSR1 so child does not terminate. */ 513 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 514 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 515 516 ATF_REQUIRE((pid = fork()) != -1); 517 if (pid == 0) { 518 /* Wait until ktrace has started. */ 519 CHILD_REQUIRE(sigwait(&set, &error) != -1); 520 CHILD_REQUIRE_EQ(error, SIGUSR1); 521 522 CHILD_REQUIRE(shm_open("/ktrace_shm", O_RDWR | O_CREAT, 523 0600) != -1); 524 CHILD_REQUIRE(shm_unlink("/ktrace_shm") != -1); 525 exit(0); 526 } 527 528 cap_trace_child(pid, &violation, 1); 529 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_NAMEI); 530 error = syscallabi(violation.cap_svflags); 531 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 532 "shm_open2"); 533 ATF_REQUIRE_STREQ(violation.cap_data.cap_path, "/ktrace_shm"); 534 } 535 536 /* 537 * Make sure that ktrace is disabled upon exec of a setuid binary. 538 */ 539 ATF_TC(ktrace__setuid_exec); 540 ATF_TC_HEAD(ktrace__setuid_exec, tc) 541 { 542 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 543 } 544 ATF_TC_BODY(ktrace__setuid_exec, tc) 545 { 546 struct ktr_header header; 547 struct ktr_syscall *syscall; 548 sigset_t set = { }; 549 off_t off, off1; 550 ssize_t n; 551 pid_t pid; 552 int error, fd; 553 554 /* Block SIGUSR1 so child does not terminate. */ 555 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 556 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 557 558 ATF_REQUIRE((pid = fork()) != -1); 559 if (pid == 0) { 560 /* Wait until ktrace has started. */ 561 CHILD_REQUIRE(sigwait(&set, &error) != -1); 562 CHILD_REQUIRE_EQ(error, SIGUSR1); 563 564 execve("/usr/bin/su", (char *[]){ "su", "whoami", NULL }, NULL); 565 _exit(0); 566 } 567 568 fd = trace_child(pid, KTRFAC_SYSCALL, 1); 569 570 n = read(fd, &header, sizeof(header)); 571 ATF_REQUIRE(n >= 0); 572 ATF_REQUIRE_EQ((size_t)n, sizeof(header)); 573 ATF_REQUIRE_EQ(header.ktr_pid, pid); 574 ATF_REQUIRE(header.ktr_len >= (int)sizeof(*syscall)); 575 576 syscall = xmalloc(header.ktr_len); 577 n = read(fd, syscall, header.ktr_len); 578 ATF_REQUIRE(n >= 0); 579 ATF_REQUIRE_EQ(n, header.ktr_len); 580 if (syscall->ktr_code == SYS_sigwait) { 581 free(syscall); 582 583 /* Skip the sigwait() syscall. */ 584 n = read(fd, &header, sizeof(header)); 585 ATF_REQUIRE(n >= 0); 586 ATF_REQUIRE_EQ((size_t)n, sizeof(header)); 587 ATF_REQUIRE_EQ(header.ktr_pid, pid); 588 ATF_REQUIRE(header.ktr_len >= (int)sizeof(*syscall)); 589 590 syscall = xmalloc(header.ktr_len); 591 n = read(fd, syscall, header.ktr_len); 592 ATF_REQUIRE(n >= 0); 593 ATF_REQUIRE_EQ(n, header.ktr_len); 594 } 595 ATF_REQUIRE_EQ(syscall->ktr_code, SYS_execve); 596 free(syscall); 597 598 /* su is setuid root, so this should have been the last entry. */ 599 off = lseek(fd, 0, SEEK_CUR); 600 ATF_REQUIRE(off != -1); 601 off1 = lseek(fd, 0, SEEK_END); 602 ATF_REQUIRE(off1 != -1); 603 ATF_REQUIRE_EQ(off, off1); 604 605 ATF_REQUIRE(close(fd) == 0); 606 } 607 608 ATF_TP_ADD_TCS(tp) 609 { 610 ATF_TP_ADD_TC(tp, ktrace__cap_not_capable); 611 ATF_TP_ADD_TC(tp, ktrace__cap_increase_rights); 612 ATF_TP_ADD_TC(tp, ktrace__cap_syscall); 613 ATF_TP_ADD_TC(tp, ktrace__cap_signal); 614 ATF_TP_ADD_TC(tp, ktrace__cap_proto); 615 ATF_TP_ADD_TC(tp, ktrace__cap_sockaddr); 616 ATF_TP_ADD_TC(tp, ktrace__cap_namei); 617 ATF_TP_ADD_TC(tp, ktrace__cap_cpuset); 618 ATF_TP_ADD_TC(tp, ktrace__cap_shm_open); 619 ATF_TP_ADD_TC(tp, ktrace__setuid_exec); 620 return (atf_no_error()); 621 } 622