1 #include <stdio.h> 2 #include <unistd.h> 3 #include <sys/file.h> 4 #include <sys/types.h> 5 #include <sys/wait.h> 6 #include <sys/stat.h> 7 #include <sys/mman.h> 8 #include <sys/select.h> 9 #include <sys/socket.h> 10 #include <sys/time.h> 11 #include <errno.h> 12 #include <fcntl.h> 13 #include <poll.h> 14 #include <stdint.h> 15 16 #include "capsicum.h" 17 #include "syscalls.h" 18 #include "capsicum-test.h" 19 20 /* Utilities for printing rights information */ 21 /* Written in C style to allow for: */ 22 /* TODO(drysdale): migrate these to somewhere in libcaprights/ */ 23 #define RIGHTS_INFO(RR) { (RR), #RR} 24 typedef struct { 25 uint64_t right; 26 const char* name; 27 } right_info; 28 static right_info known_rights[] = { 29 /* Rights that are common to all versions of Capsicum */ 30 RIGHTS_INFO(CAP_READ), 31 RIGHTS_INFO(CAP_WRITE), 32 RIGHTS_INFO(CAP_SEEK_TELL), 33 RIGHTS_INFO(CAP_SEEK), 34 RIGHTS_INFO(CAP_PREAD), 35 RIGHTS_INFO(CAP_PWRITE), 36 RIGHTS_INFO(CAP_MMAP), 37 RIGHTS_INFO(CAP_MMAP_R), 38 RIGHTS_INFO(CAP_MMAP_W), 39 RIGHTS_INFO(CAP_MMAP_X), 40 RIGHTS_INFO(CAP_MMAP_RW), 41 RIGHTS_INFO(CAP_MMAP_RX), 42 RIGHTS_INFO(CAP_MMAP_WX), 43 RIGHTS_INFO(CAP_MMAP_RWX), 44 RIGHTS_INFO(CAP_CREATE), 45 RIGHTS_INFO(CAP_FEXECVE), 46 RIGHTS_INFO(CAP_FSYNC), 47 RIGHTS_INFO(CAP_FTRUNCATE), 48 RIGHTS_INFO(CAP_LOOKUP), 49 RIGHTS_INFO(CAP_FCHDIR), 50 RIGHTS_INFO(CAP_FCHFLAGS), 51 RIGHTS_INFO(CAP_CHFLAGSAT), 52 RIGHTS_INFO(CAP_FCHMOD), 53 RIGHTS_INFO(CAP_FCHMODAT), 54 RIGHTS_INFO(CAP_FCHOWN), 55 RIGHTS_INFO(CAP_FCHOWNAT), 56 RIGHTS_INFO(CAP_FCNTL), 57 RIGHTS_INFO(CAP_FLOCK), 58 RIGHTS_INFO(CAP_FPATHCONF), 59 RIGHTS_INFO(CAP_FSCK), 60 RIGHTS_INFO(CAP_FSTAT), 61 RIGHTS_INFO(CAP_FSTATAT), 62 RIGHTS_INFO(CAP_FSTATFS), 63 RIGHTS_INFO(CAP_FUTIMES), 64 RIGHTS_INFO(CAP_FUTIMESAT), 65 RIGHTS_INFO(CAP_MKDIRAT), 66 RIGHTS_INFO(CAP_MKFIFOAT), 67 RIGHTS_INFO(CAP_MKNODAT), 68 RIGHTS_INFO(CAP_RENAMEAT_SOURCE), 69 RIGHTS_INFO(CAP_SYMLINKAT), 70 RIGHTS_INFO(CAP_UNLINKAT), 71 RIGHTS_INFO(CAP_ACCEPT), 72 RIGHTS_INFO(CAP_BIND), 73 RIGHTS_INFO(CAP_CONNECT), 74 RIGHTS_INFO(CAP_GETPEERNAME), 75 RIGHTS_INFO(CAP_GETSOCKNAME), 76 RIGHTS_INFO(CAP_GETSOCKOPT), 77 RIGHTS_INFO(CAP_LISTEN), 78 RIGHTS_INFO(CAP_PEELOFF), 79 RIGHTS_INFO(CAP_RECV), 80 RIGHTS_INFO(CAP_SEND), 81 RIGHTS_INFO(CAP_SETSOCKOPT), 82 RIGHTS_INFO(CAP_SHUTDOWN), 83 RIGHTS_INFO(CAP_BINDAT), 84 RIGHTS_INFO(CAP_CONNECTAT), 85 RIGHTS_INFO(CAP_LINKAT_SOURCE), 86 RIGHTS_INFO(CAP_RENAMEAT_TARGET), 87 RIGHTS_INFO(CAP_SOCK_CLIENT), 88 RIGHTS_INFO(CAP_SOCK_SERVER), 89 RIGHTS_INFO(CAP_MAC_GET), 90 RIGHTS_INFO(CAP_MAC_SET), 91 RIGHTS_INFO(CAP_SEM_GETVALUE), 92 RIGHTS_INFO(CAP_SEM_POST), 93 RIGHTS_INFO(CAP_SEM_WAIT), 94 RIGHTS_INFO(CAP_EVENT), 95 RIGHTS_INFO(CAP_KQUEUE_EVENT), 96 RIGHTS_INFO(CAP_IOCTL), 97 RIGHTS_INFO(CAP_TTYHOOK), 98 RIGHTS_INFO(CAP_PDWAIT), 99 RIGHTS_INFO(CAP_PDGETPID), 100 RIGHTS_INFO(CAP_PDKILL), 101 RIGHTS_INFO(CAP_EXTATTR_DELETE), 102 RIGHTS_INFO(CAP_EXTATTR_GET), 103 RIGHTS_INFO(CAP_EXTATTR_LIST), 104 RIGHTS_INFO(CAP_EXTATTR_SET), 105 RIGHTS_INFO(CAP_ACL_CHECK), 106 RIGHTS_INFO(CAP_ACL_DELETE), 107 RIGHTS_INFO(CAP_ACL_GET), 108 RIGHTS_INFO(CAP_ACL_SET), 109 RIGHTS_INFO(CAP_KQUEUE_CHANGE), 110 RIGHTS_INFO(CAP_KQUEUE), 111 /* Rights that are only present in some version or some OS, and so are #ifdef'ed */ 112 /* LINKAT got split */ 113 #ifdef CAP_LINKAT 114 RIGHTS_INFO(CAP_LINKAT), 115 #endif 116 #ifdef CAP_LINKAT_SOURCE 117 RIGHTS_INFO(CAP_LINKAT_SOURCE), 118 #endif 119 #ifdef CAP_LINKAT_TARGET 120 RIGHTS_INFO(CAP_LINKAT_TARGET), 121 #endif 122 /* Linux aliased some FD operations for pdgetpid/pdkill */ 123 #ifdef CAP_PDGETPID_FREEBSD 124 RIGHTS_INFO(CAP_PDGETPID_FREEBSD), 125 #endif 126 #ifdef CAP_PDKILL_FREEBSD 127 RIGHTS_INFO(CAP_PDKILL_FREEBSD), 128 #endif 129 /* Linux-specific rights */ 130 #ifdef CAP_FSIGNAL 131 RIGHTS_INFO(CAP_FSIGNAL), 132 #endif 133 #ifdef CAP_EPOLL_CTL 134 RIGHTS_INFO(CAP_EPOLL_CTL), 135 #endif 136 #ifdef CAP_NOTIFY 137 RIGHTS_INFO(CAP_NOTIFY), 138 #endif 139 #ifdef CAP_SETNS 140 RIGHTS_INFO(CAP_SETNS), 141 #endif 142 #ifdef CAP_PERFMON 143 RIGHTS_INFO(CAP_PERFMON), 144 #endif 145 #ifdef CAP_BPF 146 RIGHTS_INFO(CAP_BPF), 147 #endif 148 /* Rights in later versions of FreeBSD (>10.0) */ 149 }; 150 151 void ShowCapRights(FILE *out, int fd) { 152 size_t ii; 153 bool first = true; 154 cap_rights_t rights; 155 CAP_SET_NONE(&rights); 156 if (cap_rights_get(fd, &rights) < 0) { 157 fprintf(out, "Failed to get rights for fd %d: errno %d\n", fd, errno); 158 return; 159 } 160 161 /* First print out all known rights */ 162 size_t num_known = (sizeof(known_rights)/sizeof(known_rights[0])); 163 for (ii = 0; ii < num_known; ii++) { 164 if (cap_rights_is_set(&rights, known_rights[ii].right)) { 165 if (!first) fprintf(out, ","); 166 first = false; 167 fprintf(out, "%s", known_rights[ii].name); 168 } 169 } 170 /* Now repeat the loop, clearing rights we know of; this needs to be 171 * a separate loop because some named rights overlap. 172 */ 173 for (ii = 0; ii < num_known; ii++) { 174 cap_rights_clear(&rights, known_rights[ii].right); 175 } 176 /* The following relies on the internal structure of cap_rights_t to 177 * try to show rights we don't know about. */ 178 for (ii = 0; ii < (size_t)CAPARSIZE(&rights); ii++) { 179 uint64_t bits = (rights.cr_rights[0] & 0x01ffffffffffffffULL); 180 if (bits != 0) { 181 uint64_t which = 1; 182 for (which = 1; which < 0x0200000000000000 ; which <<= 1) { 183 if (bits & which) { 184 if (!first) fprintf(out, ","); 185 fprintf(out, "CAP_RIGHT(%d, 0x%016llxULL)", (int)ii, (long long unsigned)which); 186 } 187 } 188 } 189 } 190 fprintf(out, "\n"); 191 } 192 193 void ShowAllCapRights(FILE *out) { 194 int fd; 195 struct rlimit limits; 196 if (getrlimit(RLIMIT_NOFILE, &limits) != 0) { 197 fprintf(out, "Failed to getrlimit for max FDs: errno %d\n", errno); 198 return; 199 } 200 for (fd = 0; fd < (int)limits.rlim_cur; fd++) { 201 if (fcntl(fd, F_GETFD, 0) != 0) { 202 continue; 203 } 204 fprintf(out, "fd %d: ", fd); 205 ShowCapRights(out, fd); 206 } 207 } 208 209 FORK_TEST(Capability, CapNew) { 210 cap_rights_t r_rws; 211 cap_rights_init(&r_rws, CAP_READ, CAP_WRITE, CAP_SEEK); 212 cap_rights_t r_all; 213 CAP_SET_ALL(&r_all); 214 215 int cap_fd = dup(STDOUT_FILENO); 216 cap_rights_t rights; 217 CAP_SET_NONE(&rights); 218 EXPECT_OK(cap_rights_get(cap_fd, &rights)); 219 EXPECT_RIGHTS_EQ(&r_all, &rights); 220 221 EXPECT_OK(cap_fd); 222 EXPECT_OK(cap_rights_limit(cap_fd, &r_rws)); 223 if (cap_fd < 0) return; 224 int rc = write(cap_fd, "OK!\n", 4); 225 EXPECT_OK(rc); 226 EXPECT_EQ(4, rc); 227 EXPECT_OK(cap_rights_get(cap_fd, &rights)); 228 EXPECT_RIGHTS_EQ(&r_rws, &rights); 229 230 // dup/dup2 should preserve rights. 231 int cap_dup = dup(cap_fd); 232 EXPECT_OK(cap_dup); 233 EXPECT_OK(cap_rights_get(cap_dup, &rights)); 234 EXPECT_RIGHTS_EQ(&r_rws, &rights); 235 close(cap_dup); 236 EXPECT_OK(dup2(cap_fd, cap_dup)); 237 EXPECT_OK(cap_rights_get(cap_dup, &rights)); 238 EXPECT_RIGHTS_EQ(&r_rws, &rights); 239 close(cap_dup); 240 #ifdef HAVE_DUP3 241 EXPECT_OK(dup3(cap_fd, cap_dup, 0)); 242 EXPECT_OK(cap_rights_get(cap_dup, &rights)); 243 EXPECT_RIGHTS_EQ(&r_rws, &rights); 244 close(cap_dup); 245 #endif 246 247 // Try to get a disjoint set of rights in a sub-capability. 248 cap_rights_t r_rs; 249 cap_rights_init(&r_rs, CAP_READ, CAP_SEEK); 250 cap_rights_t r_rsmapchmod; 251 cap_rights_init(&r_rsmapchmod, CAP_READ, CAP_SEEK, CAP_MMAP, CAP_FCHMOD); 252 int cap_cap_fd = dup(cap_fd); 253 EXPECT_OK(cap_cap_fd); 254 EXPECT_NOTCAPABLE(cap_rights_limit(cap_cap_fd, &r_rsmapchmod)); 255 256 // Dump rights info to stderr (mostly to ensure that Show[All]CapRights() 257 // is working. 258 ShowAllCapRights(stderr); 259 260 EXPECT_OK(close(cap_fd)); 261 } 262 263 FORK_TEST(Capability, CapEnter) { 264 EXPECT_EQ(0, cap_enter()); 265 } 266 267 FORK_TEST(Capability, BasicInterception) { 268 cap_rights_t r_0; 269 cap_rights_init(&r_0, 0); 270 int cap_fd = dup(1); 271 EXPECT_OK(cap_fd); 272 EXPECT_OK(cap_rights_limit(cap_fd, &r_0)); 273 274 EXPECT_NOTCAPABLE(write(cap_fd, "", 0)); 275 276 EXPECT_OK(cap_enter()); // Enter capability mode 277 278 EXPECT_NOTCAPABLE(write(cap_fd, "", 0)); 279 280 // Create a new capability which does have write permission 281 cap_rights_t r_ws; 282 cap_rights_init(&r_ws, CAP_WRITE, CAP_SEEK); 283 int cap_fd2 = dup(1); 284 EXPECT_OK(cap_fd2); 285 EXPECT_OK(cap_rights_limit(cap_fd2, &r_ws)); 286 EXPECT_OK(write(cap_fd2, "", 0)); 287 288 // Tidy up. 289 if (cap_fd >= 0) close(cap_fd); 290 if (cap_fd2 >= 0) close(cap_fd2); 291 } 292 293 FORK_TEST_ON(Capability, OpenAtDirectoryTraversal, TmpFile("cap_openat_testfile")) { 294 int dir = open(tmpdir.c_str(), O_RDONLY); 295 EXPECT_OK(dir); 296 297 cap_enter(); 298 299 int file = openat(dir, "cap_openat_testfile", O_RDONLY|O_CREAT, 0644); 300 EXPECT_OK(file); 301 302 // Test that we are confined to /tmp, and cannot 303 // escape using absolute paths or ../. 304 int new_file = openat(dir, "../dev/null", O_RDONLY); 305 EXPECT_EQ(-1, new_file); 306 307 new_file = openat(dir, "..", O_RDONLY); 308 EXPECT_EQ(-1, new_file); 309 310 new_file = openat(dir, "/dev/null", O_RDONLY); 311 EXPECT_EQ(-1, new_file); 312 313 new_file = openat(dir, "/", O_RDONLY); 314 EXPECT_EQ(-1, new_file); 315 316 // Tidy up. 317 close(file); 318 close(dir); 319 } 320 321 FORK_TEST_ON(Capability, FileInSync, TmpFile("cap_file_sync")) { 322 int fd = open(TmpFile("cap_file_sync"), O_RDWR|O_CREAT, 0644); 323 EXPECT_OK(fd); 324 const char* message = "Hello capability world"; 325 EXPECT_OK(write(fd, message, strlen(message))); 326 327 cap_rights_t r_rsstat; 328 cap_rights_init(&r_rsstat, CAP_READ, CAP_SEEK, CAP_FSTAT); 329 330 int cap_fd = dup(fd); 331 EXPECT_OK(cap_fd); 332 EXPECT_OK(cap_rights_limit(cap_fd, &r_rsstat)); 333 int cap_cap_fd = dup(cap_fd); 334 EXPECT_OK(cap_cap_fd); 335 EXPECT_OK(cap_rights_limit(cap_cap_fd, &r_rsstat)); 336 337 EXPECT_OK(cap_enter()); // Enter capability mode. 338 339 // Changes to one file descriptor affect the others. 340 EXPECT_EQ(1, lseek(fd, 1, SEEK_SET)); 341 EXPECT_EQ(1, lseek(fd, 0, SEEK_CUR)); 342 EXPECT_EQ(1, lseek(cap_fd, 0, SEEK_CUR)); 343 EXPECT_EQ(1, lseek(cap_cap_fd, 0, SEEK_CUR)); 344 EXPECT_EQ(3, lseek(cap_fd, 3, SEEK_SET)); 345 EXPECT_EQ(3, lseek(fd, 0, SEEK_CUR)); 346 EXPECT_EQ(3, lseek(cap_fd, 0, SEEK_CUR)); 347 EXPECT_EQ(3, lseek(cap_cap_fd, 0, SEEK_CUR)); 348 EXPECT_EQ(5, lseek(cap_cap_fd, 5, SEEK_SET)); 349 EXPECT_EQ(5, lseek(fd, 0, SEEK_CUR)); 350 EXPECT_EQ(5, lseek(cap_fd, 0, SEEK_CUR)); 351 EXPECT_EQ(5, lseek(cap_cap_fd, 0, SEEK_CUR)); 352 353 close(cap_cap_fd); 354 close(cap_fd); 355 close(fd); 356 } 357 358 // Create a capability on /tmp that does not allow CAP_WRITE, 359 // and check that this restriction is inherited through openat(). 360 FORK_TEST_ON(Capability, Inheritance, TmpFile("cap_openat_write_testfile")) { 361 int dir = open(tmpdir.c_str(), O_RDONLY); 362 EXPECT_OK(dir); 363 364 cap_rights_t r_rl; 365 cap_rights_init(&r_rl, CAP_READ, CAP_LOOKUP); 366 367 int cap_dir = dup(dir); 368 EXPECT_OK(cap_dir); 369 EXPECT_OK(cap_rights_limit(cap_dir, &r_rl)); 370 371 const char *filename = "cap_openat_write_testfile"; 372 int file = openat(dir, filename, O_WRONLY|O_CREAT, 0644); 373 EXPECT_OK(file); 374 EXPECT_EQ(5, write(file, "TEST\n", 5)); 375 if (file >= 0) close(file); 376 377 EXPECT_OK(cap_enter()); 378 file = openat(cap_dir, filename, O_RDONLY); 379 EXPECT_OK(file); 380 381 cap_rights_t rights; 382 cap_rights_init(&rights, 0); 383 EXPECT_OK(cap_rights_get(file, &rights)); 384 EXPECT_RIGHTS_EQ(&r_rl, &rights); 385 if (file >= 0) close(file); 386 387 file = openat(cap_dir, filename, O_WRONLY|O_APPEND); 388 EXPECT_NOTCAPABLE(file); 389 if (file > 0) close(file); 390 391 if (dir > 0) close(dir); 392 if (cap_dir > 0) close(cap_dir); 393 } 394 395 396 // Ensure that, if the capability had enough rights for the system call to 397 // pass, then it did. Otherwise, ensure that the errno is ENOTCAPABLE; 398 // capability restrictions should kick in before any other error logic. 399 #define CHECK_RIGHT_RESULT(result, rights, ...) do { \ 400 cap_rights_t rights_needed; \ 401 cap_rights_init(&rights_needed, __VA_ARGS__); \ 402 if (cap_rights_contains(&rights, &rights_needed)) { \ 403 EXPECT_OK(result) << std::endl \ 404 << " need: " << rights_needed \ 405 << std::endl \ 406 << " got: " << rights; \ 407 } else { \ 408 EXPECT_EQ(-1, result) << " need: " << rights_needed \ 409 << std::endl \ 410 << " got: "<< rights; \ 411 EXPECT_EQ(ENOTCAPABLE, errno); \ 412 } \ 413 } while (0) 414 415 #define EXPECT_MMAP_NOTCAPABLE(result) do { \ 416 void *rv = result; \ 417 EXPECT_EQ(MAP_FAILED, rv); \ 418 EXPECT_EQ(ENOTCAPABLE, errno); \ 419 if (rv != MAP_FAILED) munmap(rv, getpagesize()); \ 420 } while (0) 421 422 #define EXPECT_MMAP_OK(result) do { \ 423 void *rv = result; \ 424 EXPECT_NE(MAP_FAILED, rv) << " with errno " << errno; \ 425 if (rv != MAP_FAILED) munmap(rv, getpagesize()); \ 426 } while (0) 427 428 429 // As above, but for the special mmap() case: unmap after successful mmap(). 430 #define CHECK_RIGHT_MMAP_RESULT(result, rights, ...) do { \ 431 cap_rights_t rights_needed; \ 432 cap_rights_init(&rights_needed, __VA_ARGS__); \ 433 if (cap_rights_contains(&rights, &rights_needed)) { \ 434 EXPECT_MMAP_OK(result); \ 435 } else { \ 436 EXPECT_MMAP_NOTCAPABLE(result); \ 437 } \ 438 } while (0) 439 440 FORK_TEST_ON(Capability, Mmap, TmpFile("cap_mmap_operations")) { 441 int fd = open(TmpFile("cap_mmap_operations"), O_RDWR | O_CREAT, 0644); 442 EXPECT_OK(fd); 443 if (fd < 0) return; 444 445 cap_rights_t r_0; 446 cap_rights_init(&r_0, 0); 447 cap_rights_t r_mmap; 448 cap_rights_init(&r_mmap, CAP_MMAP); 449 cap_rights_t r_r; 450 cap_rights_init(&r_r, CAP_PREAD); 451 cap_rights_t r_rmmap; 452 cap_rights_init(&r_rmmap, CAP_PREAD, CAP_MMAP); 453 454 // If we're missing a capability, it will fail. 455 int cap_none = dup(fd); 456 EXPECT_OK(cap_none); 457 EXPECT_OK(cap_rights_limit(cap_none, &r_0)); 458 int cap_mmap = dup(fd); 459 EXPECT_OK(cap_mmap); 460 EXPECT_OK(cap_rights_limit(cap_mmap, &r_mmap)); 461 int cap_read = dup(fd); 462 EXPECT_OK(cap_read); 463 EXPECT_OK(cap_rights_limit(cap_read, &r_r)); 464 int cap_both = dup(fd); 465 EXPECT_OK(cap_both); 466 EXPECT_OK(cap_rights_limit(cap_both, &r_rmmap)); 467 468 EXPECT_OK(cap_enter()); // Enter capability mode. 469 470 EXPECT_MMAP_NOTCAPABLE(mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE, cap_none, 0)); 471 EXPECT_MMAP_NOTCAPABLE(mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE, cap_mmap, 0)); 472 EXPECT_MMAP_NOTCAPABLE(mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE, cap_read, 0)); 473 474 EXPECT_MMAP_OK(mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE, cap_both, 0)); 475 476 // A call with MAP_ANONYMOUS should succeed without any capability requirements. 477 EXPECT_MMAP_OK(mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)); 478 479 EXPECT_OK(close(cap_both)); 480 EXPECT_OK(close(cap_read)); 481 EXPECT_OK(close(cap_mmap)); 482 EXPECT_OK(close(cap_none)); 483 EXPECT_OK(close(fd)); 484 } 485 486 // Given a file descriptor, create a capability with specific rights and 487 // make sure only those rights work. 488 #define TRY_FILE_OPS(fd, ...) do { \ 489 cap_rights_t rights; \ 490 cap_rights_init(&rights, __VA_ARGS__); \ 491 TryFileOps((fd), rights); \ 492 } while (0) 493 494 static void TryFileOps(int fd, cap_rights_t rights) { 495 int cap_fd = dup(fd); 496 EXPECT_OK(cap_fd); 497 EXPECT_OK(cap_rights_limit(cap_fd, &rights)); 498 if (cap_fd < 0) return; 499 cap_rights_t erights; 500 EXPECT_OK(cap_rights_get(cap_fd, &erights)); 501 EXPECT_RIGHTS_EQ(&rights, &erights); 502 503 // Check creation of a capability from a capability. 504 int cap_cap_fd = dup(cap_fd); 505 EXPECT_OK(cap_cap_fd); 506 EXPECT_OK(cap_rights_limit(cap_cap_fd, &rights)); 507 EXPECT_NE(cap_fd, cap_cap_fd); 508 EXPECT_OK(cap_rights_get(cap_cap_fd, &erights)); 509 EXPECT_RIGHTS_EQ(&rights, &erights); 510 close(cap_cap_fd); 511 512 char ch; 513 CHECK_RIGHT_RESULT(read(cap_fd, &ch, sizeof(ch)), rights, CAP_READ, CAP_SEEK_ASWAS); 514 515 ssize_t len1 = pread(cap_fd, &ch, sizeof(ch), 0); 516 CHECK_RIGHT_RESULT(len1, rights, CAP_PREAD); 517 ssize_t len2 = pread(cap_fd, &ch, sizeof(ch), 0); 518 CHECK_RIGHT_RESULT(len2, rights, CAP_PREAD); 519 EXPECT_EQ(len1, len2); 520 521 CHECK_RIGHT_RESULT(write(cap_fd, &ch, sizeof(ch)), rights, CAP_WRITE, CAP_SEEK_ASWAS); 522 CHECK_RIGHT_RESULT(pwrite(cap_fd, &ch, sizeof(ch), 0), rights, CAP_PWRITE); 523 CHECK_RIGHT_RESULT(lseek(cap_fd, 0, SEEK_SET), rights, CAP_SEEK); 524 525 #ifdef HAVE_CHFLAGS 526 // Note: this is not expected to work over NFS. 527 struct statfs sf; 528 EXPECT_OK(fstatfs(fd, &sf)); 529 bool is_nfs = (strncmp("nfs", sf.f_fstypename, sizeof(sf.f_fstypename)) == 0); 530 if (!is_nfs) { 531 CHECK_RIGHT_RESULT(fchflags(cap_fd, UF_NODUMP), rights, CAP_FCHFLAGS); 532 } 533 #endif 534 535 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_NONE, MAP_SHARED, cap_fd, 0), 536 rights, CAP_MMAP); 537 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, cap_fd, 0), 538 rights, CAP_MMAP_R); 539 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, cap_fd, 0), 540 rights, CAP_MMAP_W); 541 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_EXEC, MAP_SHARED, cap_fd, 0), 542 rights, CAP_MMAP_X); 543 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, cap_fd, 0), 544 rights, CAP_MMAP_RW); 545 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_SHARED, cap_fd, 0), 546 rights, CAP_MMAP_RX); 547 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_EXEC | PROT_WRITE, MAP_SHARED, cap_fd, 0), 548 rights, CAP_MMAP_WX); 549 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, cap_fd, 0), 550 rights, CAP_MMAP_RWX); 551 552 CHECK_RIGHT_RESULT(fsync(cap_fd), rights, CAP_FSYNC); 553 #ifdef HAVE_SYNC_FILE_RANGE 554 CHECK_RIGHT_RESULT(sync_file_range(cap_fd, 0, 1, 0), rights, CAP_FSYNC, CAP_SEEK); 555 #endif 556 557 int rc = fcntl(cap_fd, F_GETFL); 558 CHECK_RIGHT_RESULT(rc, rights, CAP_FCNTL); 559 rc = fcntl(cap_fd, F_SETFL, rc); 560 CHECK_RIGHT_RESULT(rc, rights, CAP_FCNTL); 561 562 CHECK_RIGHT_RESULT(fchown(cap_fd, -1, -1), rights, CAP_FCHOWN); 563 564 CHECK_RIGHT_RESULT(fchmod(cap_fd, 0644), rights, CAP_FCHMOD); 565 566 CHECK_RIGHT_RESULT(flock(cap_fd, LOCK_SH), rights, CAP_FLOCK); 567 CHECK_RIGHT_RESULT(flock(cap_fd, LOCK_UN), rights, CAP_FLOCK); 568 569 CHECK_RIGHT_RESULT(ftruncate(cap_fd, 0), rights, CAP_FTRUNCATE); 570 571 struct stat sb; 572 CHECK_RIGHT_RESULT(fstat(cap_fd, &sb), rights, CAP_FSTAT); 573 574 struct statfs cap_sf; 575 CHECK_RIGHT_RESULT(fstatfs(cap_fd, &cap_sf), rights, CAP_FSTATFS); 576 577 #ifdef HAVE_FPATHCONF 578 CHECK_RIGHT_RESULT(fpathconf(cap_fd, _PC_NAME_MAX), rights, CAP_FPATHCONF); 579 #endif 580 581 CHECK_RIGHT_RESULT(futimes(cap_fd, NULL), rights, CAP_FUTIMES); 582 583 struct pollfd pollfd; 584 pollfd.fd = cap_fd; 585 pollfd.events = POLLIN | POLLERR | POLLHUP; 586 pollfd.revents = 0; 587 int ret = poll(&pollfd, 1, 0); 588 if (cap_rights_is_set(&rights, CAP_EVENT)) { 589 EXPECT_OK(ret); 590 } else { 591 EXPECT_NE(0, (pollfd.revents & POLLNVAL)); 592 } 593 594 struct timeval tv; 595 tv.tv_sec = 0; 596 tv.tv_usec = 100; 597 fd_set rset; 598 FD_ZERO(&rset); 599 FD_SET(cap_fd, &rset); 600 fd_set wset; 601 FD_ZERO(&wset); 602 FD_SET(cap_fd, &wset); 603 ret = select(cap_fd+1, &rset, &wset, NULL, &tv); 604 if (cap_rights_is_set(&rights, CAP_EVENT)) { 605 EXPECT_OK(ret); 606 } else { 607 EXPECT_NOTCAPABLE(ret); 608 } 609 610 // TODO(FreeBSD): kqueue 611 612 EXPECT_OK(close(cap_fd)); 613 } 614 615 FORK_TEST_ON(Capability, Operations, TmpFile("cap_fd_operations")) { 616 int fd = open(TmpFile("cap_fd_operations"), O_RDWR | O_CREAT, 0644); 617 EXPECT_OK(fd); 618 if (fd < 0) return; 619 620 EXPECT_OK(cap_enter()); // Enter capability mode. 621 622 // Try a variety of different combinations of rights - a full 623 // enumeration is too large (2^N with N~30+) to perform. 624 TRY_FILE_OPS(fd, CAP_READ); 625 TRY_FILE_OPS(fd, CAP_PREAD); 626 TRY_FILE_OPS(fd, CAP_WRITE); 627 TRY_FILE_OPS(fd, CAP_PWRITE); 628 TRY_FILE_OPS(fd, CAP_READ, CAP_WRITE); 629 TRY_FILE_OPS(fd, CAP_PREAD, CAP_PWRITE); 630 TRY_FILE_OPS(fd, CAP_SEEK); 631 TRY_FILE_OPS(fd, CAP_FCHFLAGS); 632 TRY_FILE_OPS(fd, CAP_IOCTL); 633 TRY_FILE_OPS(fd, CAP_FSTAT); 634 TRY_FILE_OPS(fd, CAP_MMAP); 635 TRY_FILE_OPS(fd, CAP_MMAP_R); 636 TRY_FILE_OPS(fd, CAP_MMAP_W); 637 TRY_FILE_OPS(fd, CAP_MMAP_X); 638 TRY_FILE_OPS(fd, CAP_MMAP_RW); 639 TRY_FILE_OPS(fd, CAP_MMAP_RX); 640 TRY_FILE_OPS(fd, CAP_MMAP_WX); 641 TRY_FILE_OPS(fd, CAP_MMAP_RWX); 642 TRY_FILE_OPS(fd, CAP_FCNTL); 643 TRY_FILE_OPS(fd, CAP_EVENT); 644 TRY_FILE_OPS(fd, CAP_FSYNC); 645 TRY_FILE_OPS(fd, CAP_FCHOWN); 646 TRY_FILE_OPS(fd, CAP_FCHMOD); 647 TRY_FILE_OPS(fd, CAP_FTRUNCATE); 648 TRY_FILE_OPS(fd, CAP_FLOCK); 649 TRY_FILE_OPS(fd, CAP_FSTATFS); 650 TRY_FILE_OPS(fd, CAP_FPATHCONF); 651 TRY_FILE_OPS(fd, CAP_FUTIMES); 652 TRY_FILE_OPS(fd, CAP_ACL_GET); 653 TRY_FILE_OPS(fd, CAP_ACL_SET); 654 TRY_FILE_OPS(fd, CAP_ACL_DELETE); 655 TRY_FILE_OPS(fd, CAP_ACL_CHECK); 656 TRY_FILE_OPS(fd, CAP_EXTATTR_GET); 657 TRY_FILE_OPS(fd, CAP_EXTATTR_SET); 658 TRY_FILE_OPS(fd, CAP_EXTATTR_DELETE); 659 TRY_FILE_OPS(fd, CAP_EXTATTR_LIST); 660 TRY_FILE_OPS(fd, CAP_MAC_GET); 661 TRY_FILE_OPS(fd, CAP_MAC_SET); 662 663 // Socket-specific. 664 TRY_FILE_OPS(fd, CAP_GETPEERNAME); 665 TRY_FILE_OPS(fd, CAP_GETSOCKNAME); 666 TRY_FILE_OPS(fd, CAP_ACCEPT); 667 668 close(fd); 669 } 670 671 #define TRY_DIR_OPS(dfd, ...) do { \ 672 cap_rights_t rights; \ 673 cap_rights_init(&rights, __VA_ARGS__); \ 674 TryDirOps((dfd), rights); \ 675 } while (0) 676 677 static void TryDirOps(int dirfd, cap_rights_t rights) { 678 cap_rights_t erights; 679 int dfd_cap = dup(dirfd); 680 EXPECT_OK(dfd_cap); 681 EXPECT_OK(cap_rights_limit(dfd_cap, &rights)); 682 EXPECT_OK(cap_rights_get(dfd_cap, &erights)); 683 EXPECT_RIGHTS_EQ(&rights, &erights); 684 685 int rc = openat(dfd_cap, "cap_create", O_CREAT | O_RDONLY, 0600); 686 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_READ, CAP_LOOKUP); 687 if (rc >= 0) { 688 EXPECT_OK(close(rc)); 689 EXPECT_OK(unlinkat(dirfd, "cap_create", 0)); 690 } 691 rc = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY | O_APPEND, 0600); 692 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_WRITE, CAP_LOOKUP); 693 if (rc >= 0) { 694 EXPECT_OK(close(rc)); 695 EXPECT_OK(unlinkat(dirfd, "cap_create", 0)); 696 } 697 rc = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR | O_APPEND, 0600); 698 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_READ, CAP_WRITE, CAP_LOOKUP); 699 if (rc >= 0) { 700 EXPECT_OK(close(rc)); 701 EXPECT_OK(unlinkat(dirfd, "cap_create", 0)); 702 } 703 704 rc = openat(dirfd, "cap_faccess", O_CREAT, 0600); 705 EXPECT_OK(rc); 706 EXPECT_OK(close(rc)); 707 rc = faccessat(dfd_cap, "cap_faccess", F_OK, 0); 708 CHECK_RIGHT_RESULT(rc, rights, CAP_FSTAT, CAP_LOOKUP); 709 EXPECT_OK(unlinkat(dirfd, "cap_faccess", 0)); 710 711 rc = openat(dirfd, "cap_fsync", O_CREAT, 0600); 712 EXPECT_OK(rc); 713 EXPECT_OK(close(rc)); 714 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDONLY); 715 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_LOOKUP); 716 if (rc >= 0) { 717 EXPECT_OK(close(rc)); 718 } 719 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY | O_APPEND); 720 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_WRITE, CAP_LOOKUP); 721 if (rc >= 0) { 722 EXPECT_OK(close(rc)); 723 } 724 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR | O_APPEND); 725 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_LOOKUP); 726 if (rc >= 0) { 727 EXPECT_OK(close(rc)); 728 } 729 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDONLY); 730 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_LOOKUP); 731 if (rc >= 0) { 732 EXPECT_OK(close(rc)); 733 } 734 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY | O_APPEND); 735 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_WRITE, CAP_LOOKUP); 736 if (rc >= 0) { 737 EXPECT_OK(close(rc)); 738 } 739 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR | O_APPEND); 740 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_LOOKUP); 741 if (rc >= 0) { 742 EXPECT_OK(close(rc)); 743 } 744 EXPECT_OK(unlinkat(dirfd, "cap_fsync", 0)); 745 746 rc = openat(dirfd, "cap_ftruncate", O_CREAT, 0600); 747 EXPECT_OK(rc); 748 EXPECT_OK(close(rc)); 749 rc = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDONLY); 750 CHECK_RIGHT_RESULT(rc, rights, CAP_FTRUNCATE, CAP_READ, CAP_LOOKUP); 751 if (rc >= 0) { 752 EXPECT_OK(close(rc)); 753 } 754 rc = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_WRONLY); 755 CHECK_RIGHT_RESULT(rc, rights, CAP_FTRUNCATE, CAP_WRITE, CAP_LOOKUP); 756 if (rc >= 0) { 757 EXPECT_OK(close(rc)); 758 } 759 rc = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDWR); 760 CHECK_RIGHT_RESULT(rc, rights, CAP_FTRUNCATE, CAP_READ, CAP_WRITE, CAP_LOOKUP); 761 if (rc >= 0) { 762 EXPECT_OK(close(rc)); 763 } 764 EXPECT_OK(unlinkat(dirfd, "cap_ftruncate", 0)); 765 766 rc = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY, 0600); 767 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_WRITE, CAP_SEEK, CAP_LOOKUP); 768 if (rc >= 0) { 769 EXPECT_OK(close(rc)); 770 EXPECT_OK(unlinkat(dirfd, "cap_create", 0)); 771 } 772 rc = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR, 0600); 773 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_LOOKUP); 774 if (rc >= 0) { 775 EXPECT_OK(close(rc)); 776 EXPECT_OK(unlinkat(dirfd, "cap_create", 0)); 777 } 778 779 rc = openat(dirfd, "cap_fsync", O_CREAT, 0600); 780 EXPECT_OK(rc); 781 EXPECT_OK(close(rc)); 782 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY); 783 CHECK_RIGHT_RESULT(rc, 784 rights, CAP_FSYNC, CAP_WRITE, CAP_SEEK, CAP_LOOKUP); 785 if (rc >= 0) { 786 EXPECT_OK(close(rc)); 787 } 788 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR); 789 CHECK_RIGHT_RESULT(rc, 790 rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_LOOKUP); 791 if (rc >= 0) { 792 EXPECT_OK(close(rc)); 793 } 794 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY); 795 CHECK_RIGHT_RESULT(rc, 796 rights, CAP_FSYNC, CAP_WRITE, CAP_SEEK, CAP_LOOKUP); 797 if (rc >= 0) { 798 EXPECT_OK(close(rc)); 799 } 800 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR); 801 CHECK_RIGHT_RESULT(rc, 802 rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_LOOKUP); 803 if (rc >= 0) { 804 EXPECT_OK(close(rc)); 805 } 806 EXPECT_OK(unlinkat(dirfd, "cap_fsync", 0)); 807 808 #ifdef HAVE_CHFLAGSAT 809 rc = openat(dirfd, "cap_chflagsat", O_CREAT, 0600); 810 EXPECT_OK(rc); 811 EXPECT_OK(close(rc)); 812 rc = chflagsat(dfd_cap, "cap_chflagsat", UF_NODUMP, 0); 813 CHECK_RIGHT_RESULT(rc, rights, CAP_CHFLAGSAT, CAP_LOOKUP); 814 EXPECT_OK(unlinkat(dirfd, "cap_chflagsat", 0)); 815 #endif 816 817 rc = openat(dirfd, "cap_fchownat", O_CREAT, 0600); 818 EXPECT_OK(rc); 819 EXPECT_OK(close(rc)); 820 rc = fchownat(dfd_cap, "cap_fchownat", -1, -1, 0); 821 CHECK_RIGHT_RESULT(rc, rights, CAP_FCHOWN, CAP_LOOKUP); 822 EXPECT_OK(unlinkat(dirfd, "cap_fchownat", 0)); 823 824 rc = openat(dirfd, "cap_fchmodat", O_CREAT, 0600); 825 EXPECT_OK(rc); 826 EXPECT_OK(close(rc)); 827 rc = fchmodat(dfd_cap, "cap_fchmodat", 0600, 0); 828 CHECK_RIGHT_RESULT(rc, rights, CAP_FCHMOD, CAP_LOOKUP); 829 EXPECT_OK(unlinkat(dirfd, "cap_fchmodat", 0)); 830 831 rc = openat(dirfd, "cap_fstatat", O_CREAT, 0600); 832 EXPECT_OK(rc); 833 EXPECT_OK(close(rc)); 834 struct stat sb; 835 rc = fstatat(dfd_cap, "cap_fstatat", &sb, 0); 836 CHECK_RIGHT_RESULT(rc, rights, CAP_FSTAT, CAP_LOOKUP); 837 EXPECT_OK(unlinkat(dirfd, "cap_fstatat", 0)); 838 839 rc = openat(dirfd, "cap_futimesat", O_CREAT, 0600); 840 EXPECT_OK(rc); 841 EXPECT_OK(close(rc)); 842 rc = futimesat(dfd_cap, "cap_futimesat", NULL); 843 CHECK_RIGHT_RESULT(rc, rights, CAP_FUTIMES, CAP_LOOKUP); 844 EXPECT_OK(unlinkat(dirfd, "cap_futimesat", 0)); 845 846 // For linkat(2), need: 847 // - CAP_LINKAT_SOURCE on source 848 // - CAP_LINKAT_TARGET on destination. 849 rc = openat(dirfd, "cap_linkat_src", O_CREAT, 0600); 850 EXPECT_OK(rc); 851 EXPECT_OK(close(rc)); 852 853 rc = linkat(dirfd, "cap_linkat_src", dfd_cap, "cap_linkat_dst", 0); 854 CHECK_RIGHT_RESULT(rc, rights, CAP_LINKAT_TARGET); 855 if (rc >= 0) { 856 EXPECT_OK(unlinkat(dirfd, "cap_linkat_dst", 0)); 857 } 858 859 rc = linkat(dfd_cap, "cap_linkat_src", dirfd, "cap_linkat_dst", 0); 860 CHECK_RIGHT_RESULT(rc, rights, CAP_LINKAT_SOURCE); 861 if (rc >= 0) { 862 EXPECT_OK(unlinkat(dirfd, "cap_linkat_dst", 0)); 863 } 864 865 EXPECT_OK(unlinkat(dirfd, "cap_linkat_src", 0)); 866 867 rc = mkdirat(dfd_cap, "cap_mkdirat", 0700); 868 CHECK_RIGHT_RESULT(rc, rights, CAP_MKDIRAT, CAP_LOOKUP); 869 if (rc >= 0) { 870 EXPECT_OK(unlinkat(dirfd, "cap_mkdirat", AT_REMOVEDIR)); 871 } 872 873 #ifdef HAVE_MKFIFOAT 874 rc = mkfifoat(dfd_cap, "cap_mkfifoat", 0600); 875 CHECK_RIGHT_RESULT(rc, rights, CAP_MKFIFOAT, CAP_LOOKUP); 876 if (rc >= 0) { 877 EXPECT_OK(unlinkat(dirfd, "cap_mkfifoat", 0)); 878 } 879 #endif 880 881 if (getuid() == 0) { 882 rc = mknodat(dfd_cap, "cap_mknodat", S_IFCHR | 0600, 0); 883 CHECK_RIGHT_RESULT(rc, rights, CAP_MKNODAT, CAP_LOOKUP); 884 if (rc >= 0) { 885 EXPECT_OK(unlinkat(dirfd, "cap_mknodat", 0)); 886 } 887 } 888 889 // For renameat(2), need: 890 // - CAP_RENAMEAT_SOURCE on source 891 // - CAP_RENAMEAT_TARGET on destination. 892 rc = openat(dirfd, "cap_renameat_src", O_CREAT, 0600); 893 EXPECT_OK(rc); 894 EXPECT_OK(close(rc)); 895 896 rc = renameat(dirfd, "cap_renameat_src", dfd_cap, "cap_renameat_dst"); 897 CHECK_RIGHT_RESULT(rc, rights, CAP_RENAMEAT_TARGET); 898 if (rc >= 0) { 899 EXPECT_OK(unlinkat(dirfd, "cap_renameat_dst", 0)); 900 } else { 901 EXPECT_OK(unlinkat(dirfd, "cap_renameat_src", 0)); 902 } 903 904 rc = openat(dirfd, "cap_renameat_src", O_CREAT, 0600); 905 EXPECT_OK(rc); 906 EXPECT_OK(close(rc)); 907 908 rc = renameat(dfd_cap, "cap_renameat_src", dirfd, "cap_renameat_dst"); 909 CHECK_RIGHT_RESULT(rc, rights, CAP_RENAMEAT_SOURCE); 910 911 if (rc >= 0) { 912 EXPECT_OK(unlinkat(dirfd, "cap_renameat_dst", 0)); 913 } else { 914 EXPECT_OK(unlinkat(dirfd, "cap_renameat_src", 0)); 915 } 916 917 rc = symlinkat("test", dfd_cap, "cap_symlinkat"); 918 CHECK_RIGHT_RESULT(rc, rights, CAP_SYMLINKAT, CAP_LOOKUP); 919 if (rc >= 0) { 920 EXPECT_OK(unlinkat(dirfd, "cap_symlinkat", 0)); 921 } 922 923 rc = openat(dirfd, "cap_unlinkat", O_CREAT, 0600); 924 EXPECT_OK(rc); 925 EXPECT_OK(close(rc)); 926 rc = unlinkat(dfd_cap, "cap_unlinkat", 0); 927 CHECK_RIGHT_RESULT(rc, rights, CAP_UNLINKAT, CAP_LOOKUP); 928 unlinkat(dirfd, "cap_unlinkat", 0); 929 EXPECT_OK(mkdirat(dirfd, "cap_unlinkat", 0700)); 930 rc = unlinkat(dfd_cap, "cap_unlinkat", AT_REMOVEDIR); 931 CHECK_RIGHT_RESULT(rc, rights, CAP_UNLINKAT, CAP_LOOKUP); 932 unlinkat(dirfd, "cap_unlinkat", AT_REMOVEDIR); 933 934 EXPECT_OK(close(dfd_cap)); 935 } 936 937 void DirOperationsTest(int extra) { 938 int rc = mkdir(TmpFile("cap_dirops"), 0755); 939 EXPECT_OK(rc); 940 if (rc < 0 && errno != EEXIST) return; 941 int dfd = open(TmpFile("cap_dirops"), O_RDONLY | O_DIRECTORY | extra); 942 EXPECT_OK(dfd); 943 int tmpfd = open(tmpdir.c_str(), O_RDONLY | O_DIRECTORY); 944 EXPECT_OK(tmpfd); 945 946 EXPECT_OK(cap_enter()); // Enter capability mode. 947 948 TRY_DIR_OPS(dfd, CAP_LINKAT_SOURCE); 949 TRY_DIR_OPS(dfd, CAP_LINKAT_TARGET); 950 TRY_DIR_OPS(dfd, CAP_CREATE, CAP_READ, CAP_LOOKUP); 951 TRY_DIR_OPS(dfd, CAP_CREATE, CAP_WRITE, CAP_LOOKUP); 952 TRY_DIR_OPS(dfd, CAP_CREATE, CAP_READ, CAP_WRITE, CAP_LOOKUP); 953 TRY_DIR_OPS(dfd, CAP_FSYNC, CAP_READ, CAP_LOOKUP); 954 TRY_DIR_OPS(dfd, CAP_FSYNC, CAP_WRITE, CAP_LOOKUP); 955 TRY_DIR_OPS(dfd, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_LOOKUP); 956 TRY_DIR_OPS(dfd, CAP_FTRUNCATE, CAP_READ, CAP_LOOKUP); 957 TRY_DIR_OPS(dfd, CAP_FTRUNCATE, CAP_WRITE, CAP_LOOKUP); 958 TRY_DIR_OPS(dfd, CAP_FTRUNCATE, CAP_READ, CAP_WRITE, CAP_LOOKUP); 959 TRY_DIR_OPS(dfd, CAP_FCHOWN, CAP_LOOKUP); 960 TRY_DIR_OPS(dfd, CAP_FCHMOD, CAP_LOOKUP); 961 TRY_DIR_OPS(dfd, CAP_FSTAT, CAP_LOOKUP); 962 TRY_DIR_OPS(dfd, CAP_FUTIMES, CAP_LOOKUP); 963 TRY_DIR_OPS(dfd, CAP_MKDIRAT, CAP_LOOKUP); 964 TRY_DIR_OPS(dfd, CAP_MKFIFOAT, CAP_LOOKUP); 965 TRY_DIR_OPS(dfd, CAP_MKNODAT, CAP_LOOKUP); 966 TRY_DIR_OPS(dfd, CAP_SYMLINKAT, CAP_LOOKUP); 967 TRY_DIR_OPS(dfd, CAP_UNLINKAT, CAP_LOOKUP); 968 // Rename needs CAP_RENAMEAT_SOURCE on source directory and 969 // CAP_RENAMEAT_TARGET on destination directory. 970 TRY_DIR_OPS(dfd, CAP_RENAMEAT_SOURCE, CAP_UNLINKAT, CAP_LOOKUP); 971 TRY_DIR_OPS(dfd, CAP_RENAMEAT_TARGET, CAP_UNLINKAT, CAP_LOOKUP); 972 973 EXPECT_OK(unlinkat(tmpfd, "cap_dirops", AT_REMOVEDIR)); 974 EXPECT_OK(close(tmpfd)); 975 EXPECT_OK(close(dfd)); 976 } 977 978 FORK_TEST(Capability, DirOperations) { 979 DirOperationsTest(0); 980 } 981 982 #ifdef O_PATH 983 FORK_TEST(Capability, PathDirOperations) { 984 // Make the dfd in the test a path-only file descriptor. 985 DirOperationsTest(O_PATH); 986 } 987 #endif 988 989 static void TryReadWrite(int cap_fd) { 990 char buffer[64]; 991 EXPECT_OK(read(cap_fd, buffer, sizeof(buffer))); 992 int rc = write(cap_fd, "", 0); 993 EXPECT_EQ(-1, rc); 994 EXPECT_EQ(ENOTCAPABLE, errno); 995 } 996 997 FORK_TEST_ON(Capability, SocketTransfer, TmpFile("cap_fd_transfer")) { 998 int sock_fds[2]; 999 EXPECT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds)); 1000 1001 struct msghdr mh; 1002 mh.msg_name = NULL; // No address needed 1003 mh.msg_namelen = 0; 1004 char buffer1[1024]; 1005 struct iovec iov[1]; 1006 iov[0].iov_base = buffer1; 1007 iov[0].iov_len = sizeof(buffer1); 1008 mh.msg_iov = iov; 1009 mh.msg_iovlen = 1; 1010 char buffer2[1024]; 1011 mh.msg_control = buffer2; 1012 mh.msg_controllen = sizeof(buffer2); 1013 struct cmsghdr *cmptr; 1014 1015 cap_rights_t r_rs; 1016 cap_rights_init(&r_rs, CAP_READ, CAP_SEEK); 1017 1018 pid_t child = fork(); 1019 if (child == 0) { 1020 // Child: enter cap mode 1021 EXPECT_OK(cap_enter()); 1022 1023 // Child: wait to receive FD over socket 1024 int rc = recvmsg(sock_fds[0], &mh, 0); 1025 EXPECT_OK(rc); 1026 EXPECT_LE(CMSG_LEN(sizeof(int)), mh.msg_controllen); 1027 cmptr = CMSG_FIRSTHDR(&mh); 1028 int cap_fd = *(int*)CMSG_DATA(cmptr); 1029 EXPECT_EQ(CMSG_LEN(sizeof(int)), cmptr->cmsg_len); 1030 cmptr = CMSG_NXTHDR(&mh, cmptr); 1031 EXPECT_TRUE(cmptr == NULL); 1032 1033 // Child: confirm we can do the right operations on the capability 1034 cap_rights_t rights; 1035 EXPECT_OK(cap_rights_get(cap_fd, &rights)); 1036 EXPECT_RIGHTS_EQ(&r_rs, &rights); 1037 TryReadWrite(cap_fd); 1038 1039 // Child: wait for a normal read 1040 int val; 1041 read(sock_fds[0], &val, sizeof(val)); 1042 exit(0); 1043 } 1044 1045 int fd = open(TmpFile("cap_fd_transfer"), O_RDWR | O_CREAT, 0644); 1046 EXPECT_OK(fd); 1047 if (fd < 0) return; 1048 int cap_fd = dup(fd); 1049 EXPECT_OK(cap_fd); 1050 EXPECT_OK(cap_rights_limit(cap_fd, &r_rs)); 1051 1052 EXPECT_OK(cap_enter()); // Enter capability mode. 1053 1054 // Confirm we can do the right operations on the capability 1055 TryReadWrite(cap_fd); 1056 1057 // Send the file descriptor over the pipe to the sub-process 1058 mh.msg_controllen = CMSG_LEN(sizeof(int)); 1059 cmptr = CMSG_FIRSTHDR(&mh); 1060 cmptr->cmsg_level = SOL_SOCKET; 1061 cmptr->cmsg_type = SCM_RIGHTS; 1062 cmptr->cmsg_len = CMSG_LEN(sizeof(int)); 1063 *(int *)CMSG_DATA(cmptr) = cap_fd; 1064 buffer1[0] = 0; 1065 iov[0].iov_len = 1; 1066 sleep(3); 1067 int rc = sendmsg(sock_fds[1], &mh, 0); 1068 EXPECT_OK(rc); 1069 1070 sleep(1); // Ensure subprocess runs 1071 int zero = 0; 1072 write(sock_fds[1], &zero, sizeof(zero)); 1073 } 1074 1075 TEST(Capability, SyscallAt) { 1076 int rc = mkdir(TmpFile("cap_at_topdir"), 0755); 1077 EXPECT_OK(rc); 1078 if (rc < 0 && errno != EEXIST) return; 1079 1080 cap_rights_t r_all; 1081 cap_rights_init(&r_all, CAP_READ, CAP_LOOKUP, CAP_MKNODAT, CAP_UNLINKAT, CAP_MKDIRAT, CAP_MKFIFOAT); 1082 cap_rights_t r_no_unlink; 1083 cap_rights_init(&r_no_unlink, CAP_READ, CAP_LOOKUP, CAP_MKDIRAT, CAP_MKFIFOAT); 1084 cap_rights_t r_no_mkdir; 1085 cap_rights_init(&r_no_mkdir, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKFIFOAT); 1086 cap_rights_t r_no_mkfifo; 1087 cap_rights_init(&r_no_mkfifo, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKDIRAT); 1088 cap_rights_t r_no_mknod; 1089 cap_rights_init(&r_no_mknod, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKDIRAT); 1090 cap_rights_t r_create; 1091 cap_rights_init(&r_create, CAP_READ, CAP_LOOKUP, CAP_CREATE); 1092 cap_rights_t r_bind; 1093 cap_rights_init(&r_bind, CAP_READ, CAP_LOOKUP, CAP_BIND); 1094 1095 int dfd = open(TmpFile("cap_at_topdir"), O_RDONLY); 1096 EXPECT_OK(dfd); 1097 int cap_dfd_all = dup(dfd); 1098 EXPECT_OK(cap_dfd_all); 1099 EXPECT_OK(cap_rights_limit(cap_dfd_all, &r_all)); 1100 int cap_dfd_no_unlink = dup(dfd); 1101 EXPECT_OK(cap_dfd_no_unlink); 1102 EXPECT_OK(cap_rights_limit(cap_dfd_no_unlink, &r_no_unlink)); 1103 int cap_dfd_no_mkdir = dup(dfd); 1104 EXPECT_OK(cap_dfd_no_mkdir); 1105 EXPECT_OK(cap_rights_limit(cap_dfd_no_mkdir, &r_no_mkdir)); 1106 int cap_dfd_no_mkfifo = dup(dfd); 1107 EXPECT_OK(cap_dfd_no_mkfifo); 1108 EXPECT_OK(cap_rights_limit(cap_dfd_no_mkfifo, &r_no_mkfifo)); 1109 int cap_dfd_no_mknod = dup(dfd); 1110 EXPECT_OK(cap_dfd_no_mknod); 1111 EXPECT_OK(cap_rights_limit(cap_dfd_no_mknod, &r_no_mknod)); 1112 int cap_dfd_create = dup(dfd); 1113 EXPECT_OK(cap_dfd_create); 1114 EXPECT_OK(cap_rights_limit(cap_dfd_create, &r_create)); 1115 int cap_dfd_bind = dup(dfd); 1116 EXPECT_OK(cap_dfd_bind); 1117 EXPECT_OK(cap_rights_limit(cap_dfd_bind, &r_bind)); 1118 1119 // Need CAP_MKDIRAT to mkdirat(2). 1120 EXPECT_NOTCAPABLE(mkdirat(cap_dfd_no_mkdir, "cap_subdir", 0755)); 1121 rmdir(TmpFile("cap_at_topdir/cap_subdir")); 1122 EXPECT_OK(mkdirat(cap_dfd_all, "cap_subdir", 0755)); 1123 1124 // Need CAP_UNLINKAT to unlinkat(dfd, name, AT_REMOVEDIR). 1125 EXPECT_NOTCAPABLE(unlinkat(cap_dfd_no_unlink, "cap_subdir", AT_REMOVEDIR)); 1126 EXPECT_OK(unlinkat(cap_dfd_all, "cap_subdir", AT_REMOVEDIR)); 1127 rmdir(TmpFile("cap_at_topdir/cap_subdir")); 1128 1129 // Need CAP_MKFIFOAT to mkfifoat(2). 1130 EXPECT_NOTCAPABLE(mkfifoat(cap_dfd_no_mkfifo, "cap_fifo", 0755)); 1131 unlink(TmpFile("cap_at_topdir/cap_fifo")); 1132 EXPECT_OK(mkfifoat(cap_dfd_all, "cap_fifo", 0755)); 1133 unlink(TmpFile("cap_at_topdir/cap_fifo")); 1134 1135 #ifdef HAVE_MKNOD_REG 1136 // Need CAP_CREATE to create a regular file with mknodat(2). 1137 EXPECT_NOTCAPABLE(mknodat(cap_dfd_all, "cap_regular", S_IFREG|0755, 0)); 1138 unlink(TmpFile("cap_at_topdir/cap_regular")); 1139 EXPECT_OK(mknodat(cap_dfd_create, "cap_regular", S_IFREG|0755, 0)); 1140 unlink(TmpFile("cap_at_topdir/cap_regular")); 1141 #endif 1142 1143 #ifdef HAVE_MKNOD_SOCKET 1144 // Need CAP_BIND to create a UNIX domain socket with mknodat(2). 1145 EXPECT_NOTCAPABLE(mknodat(cap_dfd_all, "cap_socket", S_IFSOCK|0755, 0)); 1146 unlink(TmpFile("cap_at_topdir/cap_socket")); 1147 EXPECT_OK(mknodat(cap_dfd_bind, "cap_socket", S_IFSOCK|0755, 0)); 1148 unlink(TmpFile("cap_at_topdir/cap_socket")); 1149 #endif 1150 1151 if (getuid() == 0) { 1152 // Need CAP_MKNODAT to mknodat(2) a device 1153 EXPECT_NOTCAPABLE(mknodat(cap_dfd_no_mknod, "cap_device", S_IFCHR|0755, makedev(99, 123))); 1154 unlink(TmpFile("cap_at_topdir/cap_device")); 1155 EXPECT_OK(mknodat(cap_dfd_all, "cap_device", S_IFCHR|0755, makedev(99, 123))); 1156 unlink(TmpFile("cap_at_topdir/cap_device")); 1157 1158 // Need CAP_MKFIFOAT to mknodat(2) for a FIFO. 1159 EXPECT_NOTCAPABLE(mknodat(cap_dfd_no_mkfifo, "cap_fifo", S_IFIFO|0755, 0)); 1160 unlink(TmpFile("cap_at_topdir/cap_fifo")); 1161 EXPECT_OK(mknodat(cap_dfd_all, "cap_fifo", S_IFIFO|0755, 0)); 1162 unlink(TmpFile("cap_at_topdir/cap_fifo")); 1163 } else { 1164 TEST_SKIPPED("requires root (partial)"); 1165 } 1166 1167 close(cap_dfd_all); 1168 close(cap_dfd_no_mknod); 1169 close(cap_dfd_no_mkfifo); 1170 close(cap_dfd_no_mkdir); 1171 close(cap_dfd_no_unlink); 1172 close(cap_dfd_create); 1173 close(cap_dfd_bind); 1174 close(dfd); 1175 1176 // Tidy up. 1177 rmdir(TmpFile("cap_at_topdir")); 1178 } 1179 1180 FORK_TEST_ON(Capability, ExtendedAttributes, TmpFile("cap_extattr")) { 1181 int fd = open(TmpFile("cap_extattr"), O_RDONLY|O_CREAT, 0644); 1182 EXPECT_OK(fd); 1183 1184 char buffer[1024]; 1185 int rc = fgetxattr_(fd, "user.capsicumtest", buffer, sizeof(buffer)); 1186 if (rc < 0 && errno == ENOTSUP) { 1187 // Need user_xattr mount option for non-root users on Linux 1188 TEST_SKIPPED("/tmp doesn't support extended attributes"); 1189 close(fd); 1190 return; 1191 } 1192 1193 cap_rights_t r_rws; 1194 cap_rights_init(&r_rws, CAP_READ, CAP_WRITE, CAP_SEEK); 1195 cap_rights_t r_xlist; 1196 cap_rights_init(&r_xlist, CAP_EXTATTR_LIST); 1197 cap_rights_t r_xget; 1198 cap_rights_init(&r_xget, CAP_EXTATTR_GET); 1199 cap_rights_t r_xset; 1200 cap_rights_init(&r_xset, CAP_EXTATTR_SET); 1201 cap_rights_t r_xdel; 1202 cap_rights_init(&r_xdel, CAP_EXTATTR_DELETE); 1203 1204 int cap = dup(fd); 1205 EXPECT_OK(cap); 1206 EXPECT_OK(cap_rights_limit(cap, &r_rws)); 1207 int cap_xlist = dup(fd); 1208 EXPECT_OK(cap_xlist); 1209 EXPECT_OK(cap_rights_limit(cap_xlist, &r_xlist)); 1210 int cap_xget = dup(fd); 1211 EXPECT_OK(cap_xget); 1212 EXPECT_OK(cap_rights_limit(cap_xget, &r_xget)); 1213 int cap_xset = dup(fd); 1214 EXPECT_OK(cap_xset); 1215 EXPECT_OK(cap_rights_limit(cap_xset, &r_xset)); 1216 int cap_xdel = dup(fd); 1217 EXPECT_OK(cap_xdel); 1218 EXPECT_OK(cap_rights_limit(cap_xdel, &r_xdel)); 1219 1220 const char* value = "capsicum"; 1221 int len = strlen(value) + 1; 1222 EXPECT_NOTCAPABLE(fsetxattr_(cap, "user.capsicumtest", value, len, 0)); 1223 EXPECT_NOTCAPABLE(fsetxattr_(cap_xlist, "user.capsicumtest", value, len, 0)); 1224 EXPECT_NOTCAPABLE(fsetxattr_(cap_xget, "user.capsicumtest", value, len, 0)); 1225 EXPECT_NOTCAPABLE(fsetxattr_(cap_xdel, "user.capsicumtest", value, len, 0)); 1226 EXPECT_OK(fsetxattr_(cap_xset, "user.capsicumtest", value, len, 0)); 1227 1228 EXPECT_NOTCAPABLE(flistxattr_(cap, buffer, sizeof(buffer))); 1229 EXPECT_NOTCAPABLE(flistxattr_(cap_xget, buffer, sizeof(buffer))); 1230 EXPECT_NOTCAPABLE(flistxattr_(cap_xset, buffer, sizeof(buffer))); 1231 EXPECT_NOTCAPABLE(flistxattr_(cap_xdel, buffer, sizeof(buffer))); 1232 EXPECT_OK(flistxattr_(cap_xlist, buffer, sizeof(buffer))); 1233 1234 EXPECT_NOTCAPABLE(fgetxattr_(cap, "user.capsicumtest", buffer, sizeof(buffer))); 1235 EXPECT_NOTCAPABLE(fgetxattr_(cap_xlist, "user.capsicumtest", buffer, sizeof(buffer))); 1236 EXPECT_NOTCAPABLE(fgetxattr_(cap_xset, "user.capsicumtest", buffer, sizeof(buffer))); 1237 EXPECT_NOTCAPABLE(fgetxattr_(cap_xdel, "user.capsicumtest", buffer, sizeof(buffer))); 1238 EXPECT_OK(fgetxattr_(cap_xget, "user.capsicumtest", buffer, sizeof(buffer))); 1239 1240 EXPECT_NOTCAPABLE(fremovexattr_(cap, "user.capsicumtest")); 1241 EXPECT_NOTCAPABLE(fremovexattr_(cap_xlist, "user.capsicumtest")); 1242 EXPECT_NOTCAPABLE(fremovexattr_(cap_xget, "user.capsicumtest")); 1243 EXPECT_NOTCAPABLE(fremovexattr_(cap_xset, "user.capsicumtest")); 1244 EXPECT_OK(fremovexattr_(cap_xdel, "user.capsicumtest")); 1245 1246 close(cap_xdel); 1247 close(cap_xset); 1248 close(cap_xget); 1249 close(cap_xlist); 1250 close(cap); 1251 close(fd); 1252 } 1253 1254 TEST(Capability, PipeUnseekable) { 1255 int fds[2]; 1256 EXPECT_OK(pipe(fds)); 1257 1258 // Some programs detect pipes by calling seek() and getting ESPIPE. 1259 EXPECT_EQ(-1, lseek(fds[0], 0, SEEK_SET)); 1260 EXPECT_EQ(ESPIPE, errno); 1261 1262 cap_rights_t rights; 1263 cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_SEEK); 1264 EXPECT_OK(cap_rights_limit(fds[0], &rights)); 1265 1266 EXPECT_EQ(-1, lseek(fds[0], 0, SEEK_SET)); 1267 EXPECT_EQ(ESPIPE, errno); 1268 1269 // Remove CAP_SEEK and see if ENOTCAPABLE trumps ESPIPE. 1270 cap_rights_init(&rights, CAP_READ, CAP_WRITE); 1271 EXPECT_OK(cap_rights_limit(fds[0], &rights)); 1272 EXPECT_EQ(-1, lseek(fds[0], 0, SEEK_SET)); 1273 EXPECT_EQ(ENOTCAPABLE, errno); 1274 // TODO(drysdale): in practical terms it might be nice if ESPIPE trumped ENOTCAPABLE. 1275 // EXPECT_EQ(ESPIPE, errno); 1276 1277 close(fds[0]); 1278 close(fds[1]); 1279 } 1280 1281 TEST(Capability, NoBypassDAC) { 1282 REQUIRE_ROOT(); 1283 int fd = open(TmpFile("cap_root_owned"), O_RDONLY|O_CREAT, 0644); 1284 EXPECT_OK(fd); 1285 cap_rights_t rights; 1286 cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FCHMOD, CAP_FSTAT); 1287 EXPECT_OK(cap_rights_limit(fd, &rights)); 1288 1289 pid_t child = fork(); 1290 if (child == 0) { 1291 // Child: change uid to a lesser being 1292 setuid(other_uid); 1293 // Attempt to fchmod the file, and fail. 1294 // Having CAP_FCHMOD doesn't bypass the need to comply with DAC policy. 1295 int rc = fchmod(fd, 0666); 1296 EXPECT_EQ(-1, rc); 1297 EXPECT_EQ(EPERM, errno); 1298 exit(HasFailure()); 1299 } 1300 int status; 1301 EXPECT_EQ(child, waitpid(child, &status, 0)); 1302 EXPECT_TRUE(WIFEXITED(status)) << "0x" << std::hex << status; 1303 EXPECT_EQ(0, WEXITSTATUS(status)); 1304 struct stat info; 1305 EXPECT_OK(fstat(fd, &info)); 1306 EXPECT_EQ((mode_t)(S_IFREG|0644), info.st_mode); 1307 close(fd); 1308 unlink(TmpFile("cap_root_owned")); 1309 } 1310