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