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/sysent.h> 37 #include <sys/time.h> 38 #include <sys/uio.h> 39 #include <sys/user.h> 40 #include <sys/wait.h> 41 42 #include <machine/sysarch.h> 43 #include <netinet/in.h> 44 45 #include <atf-c.h> 46 #include <capsicum_helpers.h> 47 #include <errno.h> 48 #include <fcntl.h> 49 #include <netdb.h> 50 #include <signal.h> 51 #include <sysdecode.h> 52 53 /* 54 * A variant of ATF_REQUIRE that is suitable for use in child 55 * processes. This only works if the parent process is tripped up by 56 * the early exit and fails some requirement itself. 57 */ 58 #define CHILD_REQUIRE(exp) do { \ 59 if (!(exp)) \ 60 child_fail_require(__FILE__, __LINE__, \ 61 #exp " not met\n"); \ 62 } while (0) 63 #define CHILD_REQUIRE_EQ(actual, expected) do { \ 64 __typeof__(expected) _e = expected; \ 65 __typeof__(actual) _a = actual; \ 66 if (_e != _a) \ 67 child_fail_require(__FILE__, __LINE__, #actual \ 68 " (%jd) == " #expected " (%jd) not met\n", \ 69 (intmax_t)_a, (intmax_t)_e); \ 70 } while (0) 71 72 static __dead2 void 73 child_fail_require(const char *file, int line, const char *fmt, ...) 74 { 75 va_list ap; 76 char buf[1024]; 77 78 /* Use write() not fprintf() to avoid possible duplicate output. */ 79 snprintf(buf, sizeof(buf), "%s:%d: ", file, line); 80 write(STDERR_FILENO, buf, strlen(buf)); 81 va_start(ap, fmt); 82 vsnprintf(buf, sizeof(buf), fmt, ap); 83 write(STDERR_FILENO, buf, strlen(buf)); 84 va_end(ap); 85 86 _exit(32); 87 } 88 89 /* 90 * Determine sysdecode ABI based on proc's ABI in sv_flags. 91 */ 92 static enum sysdecode_abi 93 syscallabi(u_int sv_flags) 94 { 95 switch (sv_flags & SV_ABI_MASK) { 96 case SV_ABI_FREEBSD: 97 return (SYSDECODE_ABI_FREEBSD); 98 case SV_ABI_LINUX: 99 #ifdef __LP64__ 100 if ((sv_flags & SV_ILP32) != 0) 101 return (SYSDECODE_ABI_LINUX32); 102 #endif 103 return (SYSDECODE_ABI_LINUX); 104 } 105 return (SYSDECODE_ABI_UNKNOWN); 106 } 107 108 /* 109 * Start tracing capability violations and notify child that it can execute. 110 * Return @numv capability violations from child in @v. 111 */ 112 static void 113 cap_trace_child(int cpid, struct ktr_cap_fail *v, int numv) 114 { 115 struct ktr_header header; 116 int error, fd, i; 117 118 ATF_REQUIRE((fd = open("ktrace.out", 119 O_RDONLY | O_CREAT | O_TRUNC)) != -1); 120 ATF_REQUIRE(ktrace("ktrace.out", KTROP_SET, 121 KTRFAC_CAPFAIL, cpid) != -1); 122 /* Notify child that we've starting tracing. */ 123 ATF_REQUIRE(kill(cpid, SIGUSR1) != -1); 124 /* Wait for child to raise violation and exit. */ 125 ATF_REQUIRE(waitpid(cpid, &error, 0) != -1); 126 ATF_REQUIRE(WIFEXITED(error)); 127 ATF_REQUIRE_EQ(WEXITSTATUS(error), 0); 128 /* Read ktrace header and ensure violation occurred. */ 129 for (i = 0; i < numv; ++i) { 130 ATF_REQUIRE((error = read(fd, &header, sizeof(header))) != -1); 131 ATF_REQUIRE_EQ(error, sizeof(header)); 132 ATF_REQUIRE_EQ(header.ktr_len, sizeof(*v)); 133 ATF_REQUIRE_EQ(header.ktr_pid, cpid); 134 /* Read the capability violation. */ 135 ATF_REQUIRE((error = read(fd, v + i, 136 sizeof(*v))) != -1); 137 ATF_REQUIRE_EQ(error, sizeof(*v)); 138 } 139 ATF_REQUIRE(close(fd) != -1); 140 } 141 142 /* 143 * Test if ktrace will record an operation that is done with 144 * insufficient rights. 145 */ 146 ATF_TC_WITHOUT_HEAD(ktrace__cap_not_capable); 147 ATF_TC_BODY(ktrace__cap_not_capable, tc) 148 { 149 struct ktr_cap_fail violation; 150 cap_rights_t rights; 151 sigset_t set = { }; 152 pid_t pid; 153 int error; 154 155 /* Block SIGUSR1 so child does not terminate. */ 156 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 157 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 158 159 ATF_REQUIRE((pid = fork()) != -1); 160 if (pid == 0) { 161 /* Limit fd rights to CAP_READ. */ 162 cap_rights_init(&rights, CAP_READ); 163 CHILD_REQUIRE(caph_rights_limit(STDIN_FILENO, &rights) != -1); 164 CHILD_REQUIRE(caph_enter() != -1); 165 /* Wait until ktrace has started. */ 166 CHILD_REQUIRE(sigwait(&set, &error) != -1); 167 CHILD_REQUIRE_EQ(error, SIGUSR1); 168 /* Write without CAP_WRITE. */ 169 CHILD_REQUIRE(write(STDIN_FILENO, &pid, sizeof(pid)) == -1); 170 CHILD_REQUIRE_EQ(errno, ENOTCAPABLE); 171 exit(0); 172 } 173 174 cap_trace_child(pid, &violation, 1); 175 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_NOTCAPABLE); 176 ATF_REQUIRE(cap_rights_is_set(&violation.cap_data.cap_needed, 177 CAP_WRITE)); 178 } 179 180 /* 181 * Test if ktrace will record an attempt to increase rights. 182 */ 183 ATF_TC_WITHOUT_HEAD(ktrace__cap_increase_rights); 184 ATF_TC_BODY(ktrace__cap_increase_rights, tc) 185 { 186 struct ktr_cap_fail violation; 187 cap_rights_t rights; 188 sigset_t set = { }; 189 pid_t pid; 190 int error; 191 192 /* Block SIGUSR1 so child does not terminate. */ 193 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 194 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 195 196 ATF_REQUIRE((pid = fork()) != -1); 197 if (pid == 0) { 198 /* Limit fd rights to CAP_READ. */ 199 cap_rights_init(&rights, CAP_READ); 200 CHILD_REQUIRE(caph_rights_limit(STDIN_FILENO, &rights) != -1); 201 CHILD_REQUIRE(caph_enter() != -1); 202 /* Wait until ktrace has started. */ 203 CHILD_REQUIRE(sigwait(&set, &error) != -1); 204 CHILD_REQUIRE_EQ(error, SIGUSR1); 205 /* Increase fd rights to include CAP_WRITE. */ 206 cap_rights_set(&rights, CAP_WRITE); 207 CHILD_REQUIRE(caph_rights_limit(STDIN_FILENO, &rights) == -1); 208 CHILD_REQUIRE_EQ(errno, ENOTCAPABLE); 209 exit(0); 210 } 211 212 cap_trace_child(pid, &violation, 1); 213 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_INCREASE); 214 ATF_REQUIRE(cap_rights_is_set(&violation.cap_data.cap_needed, 215 CAP_WRITE)); 216 } 217 218 /* 219 * Test if disallowed syscalls are reported as capability violations. 220 */ 221 ATF_TC_WITHOUT_HEAD(ktrace__cap_syscall); 222 ATF_TC_BODY(ktrace__cap_syscall, tc) 223 { 224 struct kinfo_file kinf; 225 struct ktr_cap_fail violation[2]; 226 sigset_t set = { }; 227 pid_t pid; 228 int error; 229 230 /* Block SIGUSR1 so child does not terminate. */ 231 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 232 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 233 234 ATF_REQUIRE((pid = fork()) != -1); 235 if (pid == 0) { 236 /* Wait until ktrace has started. */ 237 CHILD_REQUIRE(sigwait(&set, &error) != -1); 238 CHILD_REQUIRE_EQ(error, SIGUSR1); 239 /* chdir() is not permitted in capability mode. */ 240 CHILD_REQUIRE(chdir(".") != -1); 241 kinf.kf_structsize = sizeof(struct kinfo_file); 242 /* 243 * fcntl() is permitted in capability mode, 244 * but the F_KINFO cmd is not. 245 */ 246 CHILD_REQUIRE(fcntl(STDIN_FILENO, F_KINFO, &kinf) != -1); 247 exit(0); 248 } 249 250 cap_trace_child(pid, violation, 2); 251 ATF_REQUIRE_EQ(violation[0].cap_type, CAPFAIL_SYSCALL); 252 error = syscallabi(violation[0].cap_svflags); 253 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[0].cap_code), 254 "chdir"); 255 256 ATF_REQUIRE_EQ(violation[1].cap_type, CAPFAIL_SYSCALL); 257 error = syscallabi(violation[1].cap_svflags); 258 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[1].cap_code), 259 "fcntl"); 260 ATF_REQUIRE_EQ(violation[1].cap_data.cap_int, F_KINFO); 261 } 262 263 /* 264 * Test if sending a signal to another process is reported as 265 * a signal violation. 266 */ 267 ATF_TC_WITHOUT_HEAD(ktrace__cap_signal); 268 ATF_TC_BODY(ktrace__cap_signal, tc) 269 { 270 struct ktr_cap_fail violation; 271 sigset_t set = { }; 272 pid_t pid; 273 int error; 274 275 /* Block SIGUSR1 so child does not terminate. */ 276 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 277 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 278 279 ATF_REQUIRE((pid = fork()) != -1); 280 if (pid == 0) { 281 /* Wait until ktrace has started. */ 282 CHILD_REQUIRE(sigwait(&set, &error) != -1); 283 CHILD_REQUIRE_EQ(error, SIGUSR1); 284 /* 285 * Signals may only be sent to ourself. Sending signals 286 * to other processes is not allowed in capability mode. 287 */ 288 CHILD_REQUIRE(kill(getppid(), SIGCONT) != -1); 289 exit(0); 290 } 291 292 cap_trace_child(pid, &violation, 1); 293 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_SIGNAL); 294 error = syscallabi(violation.cap_svflags); 295 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 296 "kill"); 297 ATF_REQUIRE_EQ(violation.cap_data.cap_int, SIGCONT); 298 } 299 300 /* 301 * Test if opening a socket with a restricted protocol is reported 302 * as a protocol violation. 303 */ 304 ATF_TC_WITHOUT_HEAD(ktrace__cap_proto); 305 ATF_TC_BODY(ktrace__cap_proto, tc) 306 { 307 struct ktr_cap_fail violation; 308 sigset_t set = { }; 309 pid_t pid; 310 int error; 311 312 /* Block SIGUSR1 so child does not terminate. */ 313 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 314 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 315 316 ATF_REQUIRE((pid = fork()) != -1); 317 if (pid == 0) { 318 /* Wait until ktrace has started. */ 319 CHILD_REQUIRE(sigwait(&set, &error) != -1); 320 CHILD_REQUIRE_EQ(error, SIGUSR1); 321 /* 322 * Certain protocols may not be used in capability mode. 323 * ICMP's raw-protocol interface is not allowed. 324 */ 325 CHILD_REQUIRE(close(socket(AF_INET, SOCK_RAW, 326 IPPROTO_ICMP)) != -1); 327 exit(0); 328 } 329 330 cap_trace_child(pid, &violation, 1); 331 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_PROTO); 332 error = syscallabi(violation.cap_svflags); 333 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 334 "socket"); 335 ATF_REQUIRE_EQ(violation.cap_data.cap_int, IPPROTO_ICMP); 336 } 337 338 /* 339 * Test if sending data to an address using a socket is 340 * reported as a sockaddr violation. 341 */ 342 ATF_TC_WITHOUT_HEAD(ktrace__cap_sockaddr); 343 ATF_TC_BODY(ktrace__cap_sockaddr, tc) 344 { 345 struct sockaddr_in addr = { }, *saddr; 346 struct ktr_cap_fail violation; 347 sigset_t set = { }; 348 pid_t pid; 349 int error, sfd; 350 351 /* Block SIGUSR1 so child does not terminate. */ 352 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 353 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 354 355 CHILD_REQUIRE((sfd = socket(AF_INET, SOCK_DGRAM, 356 IPPROTO_UDP)) != -1); 357 addr.sin_family = AF_INET; 358 addr.sin_port = htons(5000); 359 addr.sin_addr.s_addr = INADDR_ANY; 360 CHILD_REQUIRE(bind(sfd, (const struct sockaddr *)&addr, 361 sizeof(addr)) != -1); 362 363 ATF_REQUIRE((pid = fork()) != -1); 364 if (pid == 0) { 365 /* Wait until ktrace has started. */ 366 CHILD_REQUIRE(sigwait(&set, &error) != -1); 367 CHILD_REQUIRE_EQ(error, SIGUSR1); 368 /* 369 * Sending data to an address is not permitted. 370 * In this case, sending data to @addr causes a 371 * violation. 372 */ 373 CHILD_REQUIRE(sendto(sfd, NULL, 0, 0, 374 (const struct sockaddr *)&addr, sizeof(addr)) != -1); 375 exit(0); 376 } 377 378 cap_trace_child(pid, &violation, 1); 379 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_SOCKADDR); 380 error = syscallabi(violation.cap_svflags); 381 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 382 "sendto"); 383 saddr = (struct sockaddr_in *)&violation.cap_data.cap_sockaddr; 384 ATF_REQUIRE_EQ(saddr->sin_family, AF_INET); 385 ATF_REQUIRE_EQ(saddr->sin_port, htons(5000)); 386 ATF_REQUIRE_EQ(saddr->sin_addr.s_addr, INADDR_ANY); 387 close(sfd); 388 } 389 390 /* 391 * Test if openat() with AT_FDCWD and absolute path are reported 392 * as namei violations. 393 */ 394 ATF_TC_WITHOUT_HEAD(ktrace__cap_namei); 395 ATF_TC_BODY(ktrace__cap_namei, tc) 396 { 397 struct ktr_cap_fail violation[2]; 398 sigset_t set = { }; 399 pid_t pid; 400 int error; 401 402 /* Block SIGUSR1 so child does not terminate. */ 403 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 404 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 405 406 ATF_REQUIRE((pid = fork()) != -1); 407 if (pid == 0) { 408 /* Wait until ktrace has started. */ 409 CHILD_REQUIRE(sigwait(&set, &error) != -1); 410 CHILD_REQUIRE_EQ(error, SIGUSR1); 411 /* 412 * The AT_FDCWD file descriptor has not been opened 413 * and will be inaccessible in capability mode. 414 */ 415 CHILD_REQUIRE(close(openat(AT_FDCWD, "ktrace.out", 416 O_RDONLY | O_CREAT)) != -1); 417 /* 418 * Absolute paths are inaccessible in capability mode. 419 */ 420 CHILD_REQUIRE(close(openat(-1, "/", O_RDONLY)) != -1); 421 exit(0); 422 } 423 424 cap_trace_child(pid, violation, 2); 425 ATF_REQUIRE_EQ(violation[0].cap_type, CAPFAIL_NAMEI); 426 error = syscallabi(violation[0].cap_svflags); 427 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[0].cap_code), 428 "openat"); 429 ATF_REQUIRE_STREQ(violation[0].cap_data.cap_path, "AT_FDCWD"); 430 431 ATF_REQUIRE_EQ(violation[1].cap_type, CAPFAIL_NAMEI); 432 error = syscallabi(violation[1].cap_svflags); 433 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[1].cap_code), 434 "openat"); 435 ATF_REQUIRE_STREQ(violation[1].cap_data.cap_path, "/"); 436 } 437 438 /* 439 * Test if changing another process's cpu set is recorded as 440 * a cpuset violation. 441 */ 442 ATF_TC_WITHOUT_HEAD(ktrace__cap_cpuset); 443 ATF_TC_BODY(ktrace__cap_cpuset, tc) 444 { 445 struct ktr_cap_fail violation; 446 cpuset_t cpuset_mask = { }; 447 sigset_t set = { }; 448 pid_t pid; 449 int error; 450 451 /* Block SIGUSR1 so child does not terminate. */ 452 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 453 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 454 455 ATF_REQUIRE((pid = fork()) != -1); 456 if (pid == 0) { 457 /* Wait until ktrace has started. */ 458 CHILD_REQUIRE(sigwait(&set, &error) != -1); 459 CHILD_REQUIRE_EQ(error, SIGUSR1); 460 /* 461 * Set cpu 0 affinity for parent process. 462 * Other process's cpu sets are restricted in capability 463 * mode, so this will raise a violation. 464 */ 465 CPU_SET(0, &cpuset_mask); 466 CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 467 getppid(), sizeof(cpuset_mask), &cpuset_mask) != -1); 468 exit(0); 469 } 470 471 cap_trace_child(pid, &violation, 1); 472 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_CPUSET); 473 error = syscallabi(violation.cap_svflags); 474 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 475 "cpuset_setaffinity"); 476 } 477 478 ATF_TC_WITHOUT_HEAD(ktrace__cap_shm_open); 479 ATF_TC_BODY(ktrace__cap_shm_open, tc) 480 { 481 struct ktr_cap_fail violation; 482 sigset_t set = { }; 483 pid_t pid; 484 int error; 485 486 /* Block SIGUSR1 so child does not terminate. */ 487 ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1); 488 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 489 490 ATF_REQUIRE((pid = fork()) != -1); 491 if (pid == 0) { 492 /* Wait until ktrace has started. */ 493 CHILD_REQUIRE(sigwait(&set, &error) != -1); 494 CHILD_REQUIRE_EQ(error, SIGUSR1); 495 496 CHILD_REQUIRE(shm_open("/ktrace_shm", O_RDWR | O_CREAT, 497 0600) != -1); 498 CHILD_REQUIRE(shm_unlink("/ktrace_shm") != -1); 499 exit(0); 500 } 501 502 cap_trace_child(pid, &violation, 1); 503 ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_NAMEI); 504 error = syscallabi(violation.cap_svflags); 505 ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code), 506 "shm_open2"); 507 ATF_REQUIRE_STREQ(violation.cap_data.cap_path, "/ktrace_shm"); 508 } 509 510 ATF_TP_ADD_TCS(tp) 511 { 512 ATF_TP_ADD_TC(tp, ktrace__cap_not_capable); 513 ATF_TP_ADD_TC(tp, ktrace__cap_increase_rights); 514 ATF_TP_ADD_TC(tp, ktrace__cap_syscall); 515 ATF_TP_ADD_TC(tp, ktrace__cap_signal); 516 ATF_TP_ADD_TC(tp, ktrace__cap_proto); 517 ATF_TP_ADD_TC(tp, ktrace__cap_sockaddr); 518 ATF_TP_ADD_TC(tp, ktrace__cap_namei); 519 ATF_TP_ADD_TC(tp, ktrace__cap_cpuset); 520 ATF_TP_ADD_TC(tp, ktrace__cap_shm_open); 521 return (atf_no_error()); 522 } 523