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 ATF_REQUIRE((sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1); 382 addr.sin_family = AF_INET; 383 addr.sin_port = htons(5000); 384 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 385 ATF_REQUIRE(bind(sfd, (const struct sockaddr *)&addr, 386 sizeof(addr)) != -1); 387 388 ATF_REQUIRE((pid = fork()) != -1); 389 if (pid == 0) { 390 /* Wait until ktrace has started. */ 391 CHILD_REQUIRE(sigwait(&set, &error) != -1); 392 CHILD_REQUIRE_EQ(error, SIGUSR1); 393 /* 394 * Sending data to an address is not permitted. 395 * In this case, sending data to @addr causes a 396 * violation. 397 */ 398 CHILD_REQUIRE(sendto(sfd, NULL, 0, 0, 399 (const struct sockaddr *)&addr, sizeof(addr)) != -1); 400 exit(0); 401 } 402 403 cap_trace_child(pid, &violation, 1); 404 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_SOCKADDR); 405 error = syscallabi(violation.cap_svflags); 406 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 407 "sendto"); 408 saddr = (struct sockaddr_in *)&violation.cap_data.cap_sockaddr; 409 ATF_REQUIRE_EQ(saddr->sin_family, AF_INET); 410 ATF_REQUIRE_EQ(saddr->sin_port, htons(5000)); 411 ATF_REQUIRE_EQ(saddr->sin_addr.s_addr, htonl(INADDR_LOOPBACK)); 412 close(sfd); 413 } 414 415 /* 416 * Test if openat() with AT_FDCWD and absolute path are reported 417 * as namei violations. 418 */ 419 ATF_TC_WITHOUT_HEAD(ktrace__cap_namei); 420 ATF_TC_BODY(ktrace__cap_namei, tc) 421 { 422 struct ktr_cap_fail violation[2]; 423 sigset_t set = { }; 424 pid_t pid; 425 int error; 426 427 /* Block SIGUSR1 so child does not terminate. */ 428 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 429 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 430 431 ATF_REQUIRE((pid = fork()) != -1); 432 if (pid == 0) { 433 /* Wait until ktrace has started. */ 434 CHILD_REQUIRE(sigwait(&set, &error) != -1); 435 CHILD_REQUIRE_EQ(error, SIGUSR1); 436 /* 437 * The AT_FDCWD file descriptor has not been opened 438 * and will be inaccessible in capability mode. 439 */ 440 CHILD_REQUIRE(close(openat(AT_FDCWD, "ktrace.out", 441 O_RDONLY | O_CREAT)) != -1); 442 /* 443 * Absolute paths are inaccessible in capability mode. 444 */ 445 CHILD_REQUIRE(close(openat(-1, "/", O_RDONLY)) != -1); 446 exit(0); 447 } 448 449 cap_trace_child(pid, violation, 2); 450 ATF_REQUIRE_EQ(violation[0].cap_type, CAPFAIL_NAMEI); 451 error = syscallabi(violation[0].cap_svflags); 452 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[0].cap_code), 453 "openat"); 454 ATF_REQUIRE_STREQ(violation[0].cap_data.cap_path, "AT_FDCWD"); 455 456 ATF_REQUIRE_EQ(violation[1].cap_type, CAPFAIL_NAMEI); 457 error = syscallabi(violation[1].cap_svflags); 458 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[1].cap_code), 459 "openat"); 460 ATF_REQUIRE_STREQ(violation[1].cap_data.cap_path, "/"); 461 } 462 463 /* 464 * Test if changing another process's cpu set is recorded as 465 * a cpuset violation. 466 */ 467 ATF_TC_WITHOUT_HEAD(ktrace__cap_cpuset); 468 ATF_TC_BODY(ktrace__cap_cpuset, tc) 469 { 470 struct ktr_cap_fail violation; 471 cpuset_t cpuset_mask = { }; 472 sigset_t set = { }; 473 pid_t pid; 474 int error; 475 476 /* Block SIGUSR1 so child does not terminate. */ 477 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 478 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 479 480 ATF_REQUIRE((pid = fork()) != -1); 481 if (pid == 0) { 482 /* Wait until ktrace has started. */ 483 CHILD_REQUIRE(sigwait(&set, &error) != -1); 484 CHILD_REQUIRE_EQ(error, SIGUSR1); 485 /* 486 * Set cpu 0 affinity for parent process. 487 * Other process's cpu sets are restricted in capability 488 * mode, so this will raise a violation. 489 */ 490 CPU_SET(0, &cpuset_mask); 491 CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 492 getppid(), sizeof(cpuset_mask), &cpuset_mask) != -1); 493 exit(0); 494 } 495 496 cap_trace_child(pid, &violation, 1); 497 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_CPUSET); 498 error = syscallabi(violation.cap_svflags); 499 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 500 "cpuset_setaffinity"); 501 } 502 503 ATF_TC_WITHOUT_HEAD(ktrace__cap_shm_open); 504 ATF_TC_BODY(ktrace__cap_shm_open, tc) 505 { 506 struct ktr_cap_fail violation; 507 sigset_t set = { }; 508 pid_t pid; 509 int error; 510 511 /* Block SIGUSR1 so child does not terminate. */ 512 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 513 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 514 515 ATF_REQUIRE((pid = fork()) != -1); 516 if (pid == 0) { 517 /* Wait until ktrace has started. */ 518 CHILD_REQUIRE(sigwait(&set, &error) != -1); 519 CHILD_REQUIRE_EQ(error, SIGUSR1); 520 521 CHILD_REQUIRE(shm_open("/ktrace_shm", O_RDWR | O_CREAT, 522 0600) != -1); 523 CHILD_REQUIRE(shm_unlink("/ktrace_shm") != -1); 524 exit(0); 525 } 526 527 cap_trace_child(pid, &violation, 1); 528 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_NAMEI); 529 error = syscallabi(violation.cap_svflags); 530 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 531 "shm_open2"); 532 ATF_REQUIRE_STREQ(violation.cap_data.cap_path, "/ktrace_shm"); 533 } 534 535 /* 536 * Make sure that ktrace is disabled upon exec of a setuid binary. 537 */ 538 ATF_TC(ktrace__setuid_exec); 539 ATF_TC_HEAD(ktrace__setuid_exec, tc) 540 { 541 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 542 } 543 ATF_TC_BODY(ktrace__setuid_exec, tc) 544 { 545 struct ktr_header header; 546 struct ktr_syscall *syscall; 547 sigset_t set = { }; 548 off_t off, off1; 549 ssize_t n; 550 pid_t pid; 551 int error, fd; 552 553 /* Block SIGUSR1 so child does not terminate. */ 554 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 555 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 556 557 ATF_REQUIRE((pid = fork()) != -1); 558 if (pid == 0) { 559 /* Wait until ktrace has started. */ 560 CHILD_REQUIRE(sigwait(&set, &error) != -1); 561 CHILD_REQUIRE_EQ(error, SIGUSR1); 562 563 execve("/usr/bin/su", (char *[]){ "su", "whoami", NULL }, NULL); 564 _exit(0); 565 } 566 567 fd = trace_child(pid, KTRFAC_SYSCALL, 1); 568 569 n = read(fd, &header, sizeof(header)); 570 ATF_REQUIRE(n >= 0); 571 ATF_REQUIRE_EQ((size_t)n, sizeof(header)); 572 ATF_REQUIRE_EQ(header.ktr_pid, pid); 573 ATF_REQUIRE(header.ktr_len >= (int)sizeof(*syscall)); 574 575 syscall = xmalloc(header.ktr_len); 576 n = read(fd, syscall, header.ktr_len); 577 ATF_REQUIRE(n >= 0); 578 ATF_REQUIRE_EQ(n, header.ktr_len); 579 if (syscall->ktr_code == SYS_sigwait) { 580 free(syscall); 581 582 /* Skip the sigwait() syscall. */ 583 n = read(fd, &header, sizeof(header)); 584 ATF_REQUIRE(n >= 0); 585 ATF_REQUIRE_EQ((size_t)n, sizeof(header)); 586 ATF_REQUIRE_EQ(header.ktr_pid, pid); 587 ATF_REQUIRE(header.ktr_len >= (int)sizeof(*syscall)); 588 589 syscall = xmalloc(header.ktr_len); 590 n = read(fd, syscall, header.ktr_len); 591 ATF_REQUIRE(n >= 0); 592 ATF_REQUIRE_EQ(n, header.ktr_len); 593 } 594 ATF_REQUIRE_EQ(syscall->ktr_code, SYS_execve); 595 free(syscall); 596 597 /* su is setuid root, so this should have been the last entry. */ 598 off = lseek(fd, 0, SEEK_CUR); 599 ATF_REQUIRE(off != -1); 600 off1 = lseek(fd, 0, SEEK_END); 601 ATF_REQUIRE(off1 != -1); 602 ATF_REQUIRE_EQ(off, off1); 603 604 ATF_REQUIRE(close(fd) == 0); 605 } 606 607 ATF_TP_ADD_TCS(tp) 608 { 609 ATF_TP_ADD_TC(tp, ktrace__cap_not_capable); 610 ATF_TP_ADD_TC(tp, ktrace__cap_increase_rights); 611 ATF_TP_ADD_TC(tp, ktrace__cap_syscall); 612 ATF_TP_ADD_TC(tp, ktrace__cap_signal); 613 ATF_TP_ADD_TC(tp, ktrace__cap_proto); 614 ATF_TP_ADD_TC(tp, ktrace__cap_sockaddr); 615 ATF_TP_ADD_TC(tp, ktrace__cap_namei); 616 ATF_TP_ADD_TC(tp, ktrace__cap_cpuset); 617 ATF_TP_ADD_TC(tp, ktrace__cap_shm_open); 618 ATF_TP_ADD_TC(tp, ktrace__setuid_exec); 619 return (atf_no_error()); 620 } 621