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 SCOPED_TRACE(#__VA_ARGS__); \ 490 cap_rights_t rights; \ 491 cap_rights_init(&rights, __VA_ARGS__); \ 492 TryFileOps((fd), rights); \ 493 } while (0) 494 495 static void TryFileOps(int fd, cap_rights_t rights) { 496 int cap_fd = dup(fd); 497 EXPECT_OK(cap_fd); 498 EXPECT_OK(cap_rights_limit(cap_fd, &rights)); 499 if (cap_fd < 0) return; 500 cap_rights_t erights; 501 EXPECT_OK(cap_rights_get(cap_fd, &erights)); 502 EXPECT_RIGHTS_EQ(&rights, &erights); 503 504 // Check creation of a capability from a capability. 505 int cap_cap_fd = dup(cap_fd); 506 EXPECT_OK(cap_cap_fd); 507 EXPECT_OK(cap_rights_limit(cap_cap_fd, &rights)); 508 EXPECT_NE(cap_fd, cap_cap_fd); 509 EXPECT_OK(cap_rights_get(cap_cap_fd, &erights)); 510 EXPECT_RIGHTS_EQ(&rights, &erights); 511 close(cap_cap_fd); 512 513 char ch; 514 CHECK_RIGHT_RESULT(read(cap_fd, &ch, sizeof(ch)), rights, CAP_READ, CAP_SEEK_ASWAS); 515 516 ssize_t len1 = pread(cap_fd, &ch, sizeof(ch), 0); 517 CHECK_RIGHT_RESULT(len1, rights, CAP_PREAD); 518 ssize_t len2 = pread(cap_fd, &ch, sizeof(ch), 0); 519 CHECK_RIGHT_RESULT(len2, rights, CAP_PREAD); 520 EXPECT_EQ(len1, len2); 521 522 CHECK_RIGHT_RESULT(write(cap_fd, &ch, sizeof(ch)), rights, CAP_WRITE, CAP_SEEK_ASWAS); 523 CHECK_RIGHT_RESULT(pwrite(cap_fd, &ch, sizeof(ch), 0), rights, CAP_PWRITE); 524 CHECK_RIGHT_RESULT(lseek(cap_fd, 0, SEEK_SET), rights, CAP_SEEK); 525 526 #ifdef HAVE_CHFLAGS 527 // Note: this is not expected to work over NFS. 528 struct statfs sf; 529 EXPECT_OK(fstatfs(fd, &sf)); 530 bool is_nfs = (strncmp("nfs", sf.f_fstypename, sizeof(sf.f_fstypename)) == 0); 531 if (!is_nfs) { 532 CHECK_RIGHT_RESULT(fchflags(cap_fd, UF_NODUMP), rights, CAP_FCHFLAGS); 533 } 534 #endif 535 536 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_NONE, MAP_SHARED, cap_fd, 0), 537 rights, CAP_MMAP); 538 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, cap_fd, 0), 539 rights, CAP_MMAP_R); 540 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, cap_fd, 0), 541 rights, CAP_MMAP_W); 542 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_EXEC, MAP_SHARED, cap_fd, 0), 543 rights, CAP_MMAP_X); 544 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, cap_fd, 0), 545 rights, CAP_MMAP_RW); 546 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_SHARED, cap_fd, 0), 547 rights, CAP_MMAP_RX); 548 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_EXEC | PROT_WRITE, MAP_SHARED, cap_fd, 0), 549 rights, CAP_MMAP_WX); 550 CHECK_RIGHT_MMAP_RESULT(mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, cap_fd, 0), 551 rights, CAP_MMAP_RWX); 552 553 CHECK_RIGHT_RESULT(fsync(cap_fd), rights, CAP_FSYNC); 554 #ifdef HAVE_SYNC_FILE_RANGE 555 CHECK_RIGHT_RESULT(sync_file_range(cap_fd, 0, 1, 0), rights, CAP_FSYNC, CAP_SEEK); 556 #endif 557 558 int rc = fcntl(cap_fd, F_GETFL); 559 CHECK_RIGHT_RESULT(rc, rights, CAP_FCNTL); 560 rc = fcntl(cap_fd, F_SETFL, rc); 561 CHECK_RIGHT_RESULT(rc, rights, CAP_FCNTL); 562 563 CHECK_RIGHT_RESULT(fchown(cap_fd, -1, -1), rights, CAP_FCHOWN); 564 565 CHECK_RIGHT_RESULT(fchmod(cap_fd, 0644), rights, CAP_FCHMOD); 566 567 CHECK_RIGHT_RESULT(flock(cap_fd, LOCK_SH), rights, CAP_FLOCK); 568 CHECK_RIGHT_RESULT(flock(cap_fd, LOCK_UN), rights, CAP_FLOCK); 569 570 CHECK_RIGHT_RESULT(ftruncate(cap_fd, 0), rights, CAP_FTRUNCATE); 571 572 struct stat sb; 573 CHECK_RIGHT_RESULT(fstat(cap_fd, &sb), rights, CAP_FSTAT); 574 575 struct statfs cap_sf; 576 CHECK_RIGHT_RESULT(fstatfs(cap_fd, &cap_sf), rights, CAP_FSTATFS); 577 578 #ifdef HAVE_FPATHCONF 579 CHECK_RIGHT_RESULT(fpathconf(cap_fd, _PC_NAME_MAX), rights, CAP_FPATHCONF); 580 #endif 581 582 CHECK_RIGHT_RESULT(futimes(cap_fd, NULL), rights, CAP_FUTIMES); 583 584 struct pollfd pollfd; 585 pollfd.fd = cap_fd; 586 pollfd.events = POLLIN | POLLERR | POLLHUP; 587 pollfd.revents = 0; 588 int ret = poll(&pollfd, 1, 0); 589 if (cap_rights_is_set(&rights, CAP_EVENT)) { 590 EXPECT_OK(ret); 591 } else { 592 EXPECT_NE(0, (pollfd.revents & POLLNVAL)); 593 } 594 595 struct timeval tv; 596 tv.tv_sec = 0; 597 tv.tv_usec = 100; 598 fd_set rset; 599 FD_ZERO(&rset); 600 FD_SET(cap_fd, &rset); 601 fd_set wset; 602 FD_ZERO(&wset); 603 FD_SET(cap_fd, &wset); 604 ret = select(cap_fd+1, &rset, &wset, NULL, &tv); 605 if (cap_rights_is_set(&rights, CAP_EVENT)) { 606 EXPECT_OK(ret); 607 } else { 608 EXPECT_NOTCAPABLE(ret); 609 } 610 611 // TODO(FreeBSD): kqueue 612 613 EXPECT_OK(close(cap_fd)); 614 } 615 616 FORK_TEST_ON(Capability, Operations, TmpFile("cap_fd_operations")) { 617 int fd = open(TmpFile("cap_fd_operations"), O_RDWR | O_CREAT, 0644); 618 EXPECT_OK(fd); 619 if (fd < 0) return; 620 621 EXPECT_OK(cap_enter()); // Enter capability mode. 622 623 // Try a variety of different combinations of rights - a full 624 // enumeration is too large (2^N with N~30+) to perform. 625 TRY_FILE_OPS(fd, CAP_READ); 626 TRY_FILE_OPS(fd, CAP_PREAD); 627 TRY_FILE_OPS(fd, CAP_WRITE); 628 TRY_FILE_OPS(fd, CAP_PWRITE); 629 TRY_FILE_OPS(fd, CAP_READ, CAP_WRITE); 630 TRY_FILE_OPS(fd, CAP_PREAD, CAP_PWRITE); 631 TRY_FILE_OPS(fd, CAP_SEEK); 632 TRY_FILE_OPS(fd, CAP_FCHFLAGS); 633 TRY_FILE_OPS(fd, CAP_IOCTL); 634 TRY_FILE_OPS(fd, CAP_FSTAT); 635 TRY_FILE_OPS(fd, CAP_MMAP); 636 TRY_FILE_OPS(fd, CAP_MMAP_R); 637 TRY_FILE_OPS(fd, CAP_MMAP_W); 638 TRY_FILE_OPS(fd, CAP_MMAP_X); 639 TRY_FILE_OPS(fd, CAP_MMAP_RW); 640 TRY_FILE_OPS(fd, CAP_MMAP_RX); 641 TRY_FILE_OPS(fd, CAP_MMAP_WX); 642 TRY_FILE_OPS(fd, CAP_MMAP_RWX); 643 TRY_FILE_OPS(fd, CAP_FCNTL); 644 TRY_FILE_OPS(fd, CAP_EVENT); 645 TRY_FILE_OPS(fd, CAP_FSYNC); 646 TRY_FILE_OPS(fd, CAP_FCHOWN); 647 TRY_FILE_OPS(fd, CAP_FCHMOD); 648 TRY_FILE_OPS(fd, CAP_FTRUNCATE); 649 TRY_FILE_OPS(fd, CAP_FLOCK); 650 TRY_FILE_OPS(fd, CAP_FSTATFS); 651 TRY_FILE_OPS(fd, CAP_FPATHCONF); 652 TRY_FILE_OPS(fd, CAP_FUTIMES); 653 TRY_FILE_OPS(fd, CAP_ACL_GET); 654 TRY_FILE_OPS(fd, CAP_ACL_SET); 655 TRY_FILE_OPS(fd, CAP_ACL_DELETE); 656 TRY_FILE_OPS(fd, CAP_ACL_CHECK); 657 TRY_FILE_OPS(fd, CAP_EXTATTR_GET); 658 TRY_FILE_OPS(fd, CAP_EXTATTR_SET); 659 TRY_FILE_OPS(fd, CAP_EXTATTR_DELETE); 660 TRY_FILE_OPS(fd, CAP_EXTATTR_LIST); 661 TRY_FILE_OPS(fd, CAP_MAC_GET); 662 TRY_FILE_OPS(fd, CAP_MAC_SET); 663 664 // Socket-specific. 665 TRY_FILE_OPS(fd, CAP_GETPEERNAME); 666 TRY_FILE_OPS(fd, CAP_GETSOCKNAME); 667 TRY_FILE_OPS(fd, CAP_ACCEPT); 668 669 close(fd); 670 } 671 672 #define TRY_DIR_OPS(dfd, ...) do { \ 673 cap_rights_t rights; \ 674 cap_rights_init(&rights, __VA_ARGS__); \ 675 TryDirOps((dfd), rights); \ 676 } while (0) 677 678 static void TryDirOps(int dirfd, cap_rights_t rights) { 679 cap_rights_t erights; 680 int dfd_cap = dup(dirfd); 681 EXPECT_OK(dfd_cap); 682 EXPECT_OK(cap_rights_limit(dfd_cap, &rights)); 683 EXPECT_OK(cap_rights_get(dfd_cap, &erights)); 684 EXPECT_RIGHTS_EQ(&rights, &erights); 685 686 int rc = openat(dfd_cap, "cap_create", O_CREAT | O_RDONLY, 0600); 687 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_READ, CAP_LOOKUP); 688 if (rc >= 0) { 689 EXPECT_OK(close(rc)); 690 EXPECT_OK(unlinkat(dirfd, "cap_create", 0)); 691 } 692 rc = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY | O_APPEND, 0600); 693 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_WRITE, CAP_LOOKUP); 694 if (rc >= 0) { 695 EXPECT_OK(close(rc)); 696 EXPECT_OK(unlinkat(dirfd, "cap_create", 0)); 697 } 698 rc = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR | O_APPEND, 0600); 699 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_READ, CAP_WRITE, CAP_LOOKUP); 700 if (rc >= 0) { 701 EXPECT_OK(close(rc)); 702 EXPECT_OK(unlinkat(dirfd, "cap_create", 0)); 703 } 704 705 rc = openat(dirfd, "cap_faccess", O_CREAT, 0600); 706 EXPECT_OK(rc); 707 EXPECT_OK(close(rc)); 708 rc = faccessat(dfd_cap, "cap_faccess", F_OK, 0); 709 CHECK_RIGHT_RESULT(rc, rights, CAP_FSTAT, CAP_LOOKUP); 710 EXPECT_OK(unlinkat(dirfd, "cap_faccess", 0)); 711 712 rc = openat(dirfd, "cap_fsync", O_CREAT, 0600); 713 EXPECT_OK(rc); 714 EXPECT_OK(close(rc)); 715 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDONLY); 716 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_LOOKUP); 717 if (rc >= 0) { 718 EXPECT_OK(close(rc)); 719 } 720 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY | O_APPEND); 721 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_WRITE, CAP_LOOKUP); 722 if (rc >= 0) { 723 EXPECT_OK(close(rc)); 724 } 725 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR | O_APPEND); 726 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_LOOKUP); 727 if (rc >= 0) { 728 EXPECT_OK(close(rc)); 729 } 730 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDONLY); 731 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_LOOKUP); 732 if (rc >= 0) { 733 EXPECT_OK(close(rc)); 734 } 735 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY | O_APPEND); 736 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_WRITE, CAP_LOOKUP); 737 if (rc >= 0) { 738 EXPECT_OK(close(rc)); 739 } 740 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR | O_APPEND); 741 CHECK_RIGHT_RESULT(rc, rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_LOOKUP); 742 if (rc >= 0) { 743 EXPECT_OK(close(rc)); 744 } 745 EXPECT_OK(unlinkat(dirfd, "cap_fsync", 0)); 746 747 rc = openat(dirfd, "cap_ftruncate", O_CREAT, 0600); 748 EXPECT_OK(rc); 749 EXPECT_OK(close(rc)); 750 rc = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDONLY); 751 CHECK_RIGHT_RESULT(rc, rights, CAP_FTRUNCATE, CAP_READ, CAP_LOOKUP); 752 if (rc >= 0) { 753 EXPECT_OK(close(rc)); 754 } 755 rc = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_WRONLY); 756 CHECK_RIGHT_RESULT(rc, rights, CAP_FTRUNCATE, CAP_WRITE, CAP_LOOKUP); 757 if (rc >= 0) { 758 EXPECT_OK(close(rc)); 759 } 760 rc = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDWR); 761 CHECK_RIGHT_RESULT(rc, rights, CAP_FTRUNCATE, CAP_READ, CAP_WRITE, CAP_LOOKUP); 762 if (rc >= 0) { 763 EXPECT_OK(close(rc)); 764 } 765 EXPECT_OK(unlinkat(dirfd, "cap_ftruncate", 0)); 766 767 rc = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY, 0600); 768 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_WRITE, CAP_SEEK, CAP_LOOKUP); 769 if (rc >= 0) { 770 EXPECT_OK(close(rc)); 771 EXPECT_OK(unlinkat(dirfd, "cap_create", 0)); 772 } 773 rc = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR, 0600); 774 CHECK_RIGHT_RESULT(rc, rights, CAP_CREATE, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_LOOKUP); 775 if (rc >= 0) { 776 EXPECT_OK(close(rc)); 777 EXPECT_OK(unlinkat(dirfd, "cap_create", 0)); 778 } 779 780 rc = openat(dirfd, "cap_fsync", O_CREAT, 0600); 781 EXPECT_OK(rc); 782 EXPECT_OK(close(rc)); 783 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY); 784 CHECK_RIGHT_RESULT(rc, 785 rights, CAP_FSYNC, CAP_WRITE, CAP_SEEK, CAP_LOOKUP); 786 if (rc >= 0) { 787 EXPECT_OK(close(rc)); 788 } 789 rc = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR); 790 CHECK_RIGHT_RESULT(rc, 791 rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_LOOKUP); 792 if (rc >= 0) { 793 EXPECT_OK(close(rc)); 794 } 795 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY); 796 CHECK_RIGHT_RESULT(rc, 797 rights, CAP_FSYNC, CAP_WRITE, CAP_SEEK, CAP_LOOKUP); 798 if (rc >= 0) { 799 EXPECT_OK(close(rc)); 800 } 801 rc = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR); 802 CHECK_RIGHT_RESULT(rc, 803 rights, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_LOOKUP); 804 if (rc >= 0) { 805 EXPECT_OK(close(rc)); 806 } 807 EXPECT_OK(unlinkat(dirfd, "cap_fsync", 0)); 808 809 #ifdef HAVE_CHFLAGSAT 810 rc = openat(dirfd, "cap_chflagsat", O_CREAT, 0600); 811 EXPECT_OK(rc); 812 EXPECT_OK(close(rc)); 813 rc = chflagsat(dfd_cap, "cap_chflagsat", UF_NODUMP, 0); 814 CHECK_RIGHT_RESULT(rc, rights, CAP_CHFLAGSAT, CAP_LOOKUP); 815 EXPECT_OK(unlinkat(dirfd, "cap_chflagsat", 0)); 816 #endif 817 818 rc = openat(dirfd, "cap_fchownat", O_CREAT, 0600); 819 EXPECT_OK(rc); 820 EXPECT_OK(close(rc)); 821 rc = fchownat(dfd_cap, "cap_fchownat", -1, -1, 0); 822 CHECK_RIGHT_RESULT(rc, rights, CAP_FCHOWN, CAP_LOOKUP); 823 EXPECT_OK(unlinkat(dirfd, "cap_fchownat", 0)); 824 825 rc = openat(dirfd, "cap_fchmodat", O_CREAT, 0600); 826 EXPECT_OK(rc); 827 EXPECT_OK(close(rc)); 828 rc = fchmodat(dfd_cap, "cap_fchmodat", 0600, 0); 829 CHECK_RIGHT_RESULT(rc, rights, CAP_FCHMOD, CAP_LOOKUP); 830 EXPECT_OK(unlinkat(dirfd, "cap_fchmodat", 0)); 831 832 rc = openat(dirfd, "cap_fstatat", O_CREAT, 0600); 833 EXPECT_OK(rc); 834 EXPECT_OK(close(rc)); 835 struct stat sb; 836 rc = fstatat(dfd_cap, "cap_fstatat", &sb, 0); 837 CHECK_RIGHT_RESULT(rc, rights, CAP_FSTAT, CAP_LOOKUP); 838 EXPECT_OK(unlinkat(dirfd, "cap_fstatat", 0)); 839 840 rc = openat(dirfd, "cap_futimesat", O_CREAT, 0600); 841 EXPECT_OK(rc); 842 EXPECT_OK(close(rc)); 843 rc = futimesat(dfd_cap, "cap_futimesat", NULL); 844 CHECK_RIGHT_RESULT(rc, rights, CAP_FUTIMES, CAP_LOOKUP); 845 EXPECT_OK(unlinkat(dirfd, "cap_futimesat", 0)); 846 847 // For linkat(2), need: 848 // - CAP_LINKAT_SOURCE on source 849 // - CAP_LINKAT_TARGET on destination. 850 rc = openat(dirfd, "cap_linkat_src", O_CREAT, 0600); 851 EXPECT_OK(rc); 852 EXPECT_OK(close(rc)); 853 854 rc = linkat(dirfd, "cap_linkat_src", dfd_cap, "cap_linkat_dst", 0); 855 CHECK_RIGHT_RESULT(rc, rights, CAP_LINKAT_TARGET); 856 if (rc >= 0) { 857 EXPECT_OK(unlinkat(dirfd, "cap_linkat_dst", 0)); 858 } 859 860 rc = linkat(dfd_cap, "cap_linkat_src", dirfd, "cap_linkat_dst", 0); 861 CHECK_RIGHT_RESULT(rc, rights, CAP_LINKAT_SOURCE); 862 if (rc >= 0) { 863 EXPECT_OK(unlinkat(dirfd, "cap_linkat_dst", 0)); 864 } 865 866 EXPECT_OK(unlinkat(dirfd, "cap_linkat_src", 0)); 867 868 rc = mkdirat(dfd_cap, "cap_mkdirat", 0700); 869 CHECK_RIGHT_RESULT(rc, rights, CAP_MKDIRAT, CAP_LOOKUP); 870 if (rc >= 0) { 871 EXPECT_OK(unlinkat(dirfd, "cap_mkdirat", AT_REMOVEDIR)); 872 } 873 874 #ifdef HAVE_MKFIFOAT 875 rc = mkfifoat(dfd_cap, "cap_mkfifoat", 0600); 876 CHECK_RIGHT_RESULT(rc, rights, CAP_MKFIFOAT, CAP_LOOKUP); 877 if (rc >= 0) { 878 EXPECT_OK(unlinkat(dirfd, "cap_mkfifoat", 0)); 879 } 880 #endif 881 882 if (getuid() == 0) { 883 rc = mknodat(dfd_cap, "cap_mknodat", S_IFCHR | 0600, 0); 884 CHECK_RIGHT_RESULT(rc, rights, CAP_MKNODAT, CAP_LOOKUP); 885 if (rc >= 0) { 886 EXPECT_OK(unlinkat(dirfd, "cap_mknodat", 0)); 887 } 888 } 889 890 // For renameat(2), need: 891 // - CAP_RENAMEAT_SOURCE on source 892 // - CAP_RENAMEAT_TARGET on destination. 893 rc = openat(dirfd, "cap_renameat_src", O_CREAT, 0600); 894 EXPECT_OK(rc); 895 EXPECT_OK(close(rc)); 896 897 rc = renameat(dirfd, "cap_renameat_src", dfd_cap, "cap_renameat_dst"); 898 CHECK_RIGHT_RESULT(rc, rights, CAP_RENAMEAT_TARGET); 899 if (rc >= 0) { 900 EXPECT_OK(unlinkat(dirfd, "cap_renameat_dst", 0)); 901 } else { 902 EXPECT_OK(unlinkat(dirfd, "cap_renameat_src", 0)); 903 } 904 905 rc = openat(dirfd, "cap_renameat_src", O_CREAT, 0600); 906 EXPECT_OK(rc); 907 EXPECT_OK(close(rc)); 908 909 rc = renameat(dfd_cap, "cap_renameat_src", dirfd, "cap_renameat_dst"); 910 CHECK_RIGHT_RESULT(rc, rights, CAP_RENAMEAT_SOURCE); 911 912 if (rc >= 0) { 913 EXPECT_OK(unlinkat(dirfd, "cap_renameat_dst", 0)); 914 } else { 915 EXPECT_OK(unlinkat(dirfd, "cap_renameat_src", 0)); 916 } 917 918 rc = symlinkat("test", dfd_cap, "cap_symlinkat"); 919 CHECK_RIGHT_RESULT(rc, rights, CAP_SYMLINKAT, CAP_LOOKUP); 920 if (rc >= 0) { 921 EXPECT_OK(unlinkat(dirfd, "cap_symlinkat", 0)); 922 } 923 924 rc = openat(dirfd, "cap_unlinkat", O_CREAT, 0600); 925 EXPECT_OK(rc); 926 EXPECT_OK(close(rc)); 927 rc = unlinkat(dfd_cap, "cap_unlinkat", 0); 928 CHECK_RIGHT_RESULT(rc, rights, CAP_UNLINKAT, CAP_LOOKUP); 929 unlinkat(dirfd, "cap_unlinkat", 0); 930 EXPECT_OK(mkdirat(dirfd, "cap_unlinkat", 0700)); 931 rc = unlinkat(dfd_cap, "cap_unlinkat", AT_REMOVEDIR); 932 CHECK_RIGHT_RESULT(rc, rights, CAP_UNLINKAT, CAP_LOOKUP); 933 unlinkat(dirfd, "cap_unlinkat", AT_REMOVEDIR); 934 935 EXPECT_OK(close(dfd_cap)); 936 } 937 938 void DirOperationsTest(int extra) { 939 int rc = mkdir(TmpFile("cap_dirops"), 0755); 940 EXPECT_OK(rc); 941 if (rc < 0 && errno != EEXIST) return; 942 int dfd = open(TmpFile("cap_dirops"), O_RDONLY | O_DIRECTORY | extra); 943 EXPECT_OK(dfd); 944 int tmpfd = open(tmpdir.c_str(), O_RDONLY | O_DIRECTORY); 945 EXPECT_OK(tmpfd); 946 947 EXPECT_OK(cap_enter()); // Enter capability mode. 948 949 TRY_DIR_OPS(dfd, CAP_LINKAT_SOURCE); 950 TRY_DIR_OPS(dfd, CAP_LINKAT_TARGET); 951 TRY_DIR_OPS(dfd, CAP_CREATE, CAP_READ, CAP_LOOKUP); 952 TRY_DIR_OPS(dfd, CAP_CREATE, CAP_WRITE, CAP_LOOKUP); 953 TRY_DIR_OPS(dfd, CAP_CREATE, CAP_READ, CAP_WRITE, CAP_LOOKUP); 954 TRY_DIR_OPS(dfd, CAP_FSYNC, CAP_READ, CAP_LOOKUP); 955 TRY_DIR_OPS(dfd, CAP_FSYNC, CAP_WRITE, CAP_LOOKUP); 956 TRY_DIR_OPS(dfd, CAP_FSYNC, CAP_READ, CAP_WRITE, CAP_LOOKUP); 957 TRY_DIR_OPS(dfd, CAP_FTRUNCATE, CAP_READ, CAP_LOOKUP); 958 TRY_DIR_OPS(dfd, CAP_FTRUNCATE, CAP_WRITE, CAP_LOOKUP); 959 TRY_DIR_OPS(dfd, CAP_FTRUNCATE, CAP_READ, CAP_WRITE, CAP_LOOKUP); 960 TRY_DIR_OPS(dfd, CAP_FCHOWN, CAP_LOOKUP); 961 TRY_DIR_OPS(dfd, CAP_FCHMOD, CAP_LOOKUP); 962 TRY_DIR_OPS(dfd, CAP_FSTAT, CAP_LOOKUP); 963 TRY_DIR_OPS(dfd, CAP_FUTIMES, CAP_LOOKUP); 964 TRY_DIR_OPS(dfd, CAP_MKDIRAT, CAP_LOOKUP); 965 TRY_DIR_OPS(dfd, CAP_MKFIFOAT, CAP_LOOKUP); 966 TRY_DIR_OPS(dfd, CAP_MKNODAT, CAP_LOOKUP); 967 TRY_DIR_OPS(dfd, CAP_SYMLINKAT, CAP_LOOKUP); 968 TRY_DIR_OPS(dfd, CAP_UNLINKAT, CAP_LOOKUP); 969 // Rename needs CAP_RENAMEAT_SOURCE on source directory and 970 // CAP_RENAMEAT_TARGET on destination directory. 971 TRY_DIR_OPS(dfd, CAP_RENAMEAT_SOURCE, CAP_UNLINKAT, CAP_LOOKUP); 972 TRY_DIR_OPS(dfd, CAP_RENAMEAT_TARGET, CAP_UNLINKAT, CAP_LOOKUP); 973 974 EXPECT_OK(unlinkat(tmpfd, "cap_dirops", AT_REMOVEDIR)); 975 EXPECT_OK(close(tmpfd)); 976 EXPECT_OK(close(dfd)); 977 } 978 979 FORK_TEST(Capability, DirOperations) { 980 DirOperationsTest(0); 981 } 982 983 #ifdef O_PATH 984 FORK_TEST(Capability, PathDirOperations) { 985 // Make the dfd in the test a path-only file descriptor. 986 DirOperationsTest(O_PATH); 987 } 988 #endif 989 990 static void TryReadWrite(int cap_fd) { 991 char buffer[64]; 992 EXPECT_OK(read(cap_fd, buffer, sizeof(buffer))); 993 int rc = write(cap_fd, "", 0); 994 EXPECT_EQ(-1, rc); 995 EXPECT_EQ(ENOTCAPABLE, errno); 996 } 997 998 FORK_TEST_ON(Capability, SocketTransfer, TmpFile("cap_fd_transfer")) { 999 int sock_fds[2]; 1000 EXPECT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds)); 1001 1002 struct msghdr mh; 1003 mh.msg_name = NULL; // No address needed 1004 mh.msg_namelen = 0; 1005 char buffer1[1024]; 1006 struct iovec iov[1]; 1007 iov[0].iov_base = buffer1; 1008 iov[0].iov_len = sizeof(buffer1); 1009 mh.msg_iov = iov; 1010 mh.msg_iovlen = 1; 1011 char buffer2[1024]; 1012 mh.msg_control = buffer2; 1013 mh.msg_controllen = sizeof(buffer2); 1014 struct cmsghdr *cmptr; 1015 1016 cap_rights_t r_rs; 1017 cap_rights_init(&r_rs, CAP_READ, CAP_SEEK); 1018 1019 pid_t child = fork(); 1020 if (child == 0) { 1021 // Child: enter cap mode 1022 EXPECT_OK(cap_enter()); 1023 // Child: send startup notification 1024 SEND_INT_MESSAGE(sock_fds[0], MSG_CHILD_STARTED); 1025 1026 // Child: wait to receive FD over socket 1027 int rc = recvmsg(sock_fds[0], &mh, 0); 1028 EXPECT_OK(rc); 1029 EXPECT_LE(CMSG_LEN(sizeof(int)), mh.msg_controllen); 1030 cmptr = CMSG_FIRSTHDR(&mh); 1031 int cap_fd = *(int*)CMSG_DATA(cmptr); 1032 EXPECT_EQ(CMSG_LEN(sizeof(int)), cmptr->cmsg_len); 1033 cmptr = CMSG_NXTHDR(&mh, cmptr); 1034 EXPECT_TRUE(cmptr == NULL); 1035 1036 // Child: confirm we can do the right operations on the capability 1037 cap_rights_t rights; 1038 EXPECT_OK(cap_rights_get(cap_fd, &rights)); 1039 EXPECT_RIGHTS_EQ(&r_rs, &rights); 1040 TryReadWrite(cap_fd); 1041 1042 // Child: acknowledge that we have received and tested the file descriptor 1043 SEND_INT_MESSAGE(sock_fds[0], MSG_CHILD_FD_RECEIVED); 1044 1045 // Child: wait for a normal read 1046 AWAIT_INT_MESSAGE(sock_fds[0], MSG_PARENT_REQUEST_CHILD_EXIT); 1047 exit(testing::Test::HasFailure()); 1048 } 1049 1050 int fd = open(TmpFile("cap_fd_transfer"), O_RDWR | O_CREAT, 0644); 1051 EXPECT_OK(fd); 1052 if (fd < 0) return; 1053 int cap_fd = dup(fd); 1054 EXPECT_OK(cap_fd); 1055 EXPECT_OK(cap_rights_limit(cap_fd, &r_rs)); 1056 1057 EXPECT_OK(cap_enter()); // Enter capability mode. 1058 1059 // Confirm we can do the right operations on the capability 1060 TryReadWrite(cap_fd); 1061 1062 // Wait for child to start up: 1063 AWAIT_INT_MESSAGE(sock_fds[1], MSG_CHILD_STARTED); 1064 1065 // Send the file descriptor over the pipe to the sub-process 1066 mh.msg_controllen = CMSG_LEN(sizeof(int)); 1067 cmptr = CMSG_FIRSTHDR(&mh); 1068 cmptr->cmsg_level = SOL_SOCKET; 1069 cmptr->cmsg_type = SCM_RIGHTS; 1070 cmptr->cmsg_len = CMSG_LEN(sizeof(int)); 1071 *(int *)CMSG_DATA(cmptr) = cap_fd; 1072 buffer1[0] = 0; 1073 iov[0].iov_len = 1; 1074 int rc = sendmsg(sock_fds[1], &mh, 0); 1075 EXPECT_OK(rc); 1076 1077 // Check that the child received the message 1078 AWAIT_INT_MESSAGE(sock_fds[1], MSG_CHILD_FD_RECEIVED); 1079 1080 // Tell the child to exit 1081 SEND_INT_MESSAGE(sock_fds[1], MSG_PARENT_REQUEST_CHILD_EXIT); 1082 } 1083 1084 TEST(Capability, SyscallAt) { 1085 int rc = mkdir(TmpFile("cap_at_topdir"), 0755); 1086 EXPECT_OK(rc); 1087 if (rc < 0 && errno != EEXIST) return; 1088 1089 cap_rights_t r_all; 1090 cap_rights_init(&r_all, CAP_READ, CAP_LOOKUP, CAP_MKNODAT, CAP_UNLINKAT, CAP_MKDIRAT, CAP_MKFIFOAT); 1091 cap_rights_t r_no_unlink; 1092 cap_rights_init(&r_no_unlink, CAP_READ, CAP_LOOKUP, CAP_MKDIRAT, CAP_MKFIFOAT); 1093 cap_rights_t r_no_mkdir; 1094 cap_rights_init(&r_no_mkdir, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKFIFOAT); 1095 cap_rights_t r_no_mkfifo; 1096 cap_rights_init(&r_no_mkfifo, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKDIRAT); 1097 cap_rights_t r_create; 1098 cap_rights_init(&r_create, CAP_READ, CAP_LOOKUP, CAP_CREATE); 1099 cap_rights_t r_bind; 1100 cap_rights_init(&r_bind, CAP_READ, CAP_LOOKUP, CAP_BIND); 1101 1102 int dfd = open(TmpFile("cap_at_topdir"), O_RDONLY); 1103 EXPECT_OK(dfd); 1104 int cap_dfd_all = dup(dfd); 1105 EXPECT_OK(cap_dfd_all); 1106 EXPECT_OK(cap_rights_limit(cap_dfd_all, &r_all)); 1107 int cap_dfd_no_unlink = dup(dfd); 1108 EXPECT_OK(cap_dfd_no_unlink); 1109 EXPECT_OK(cap_rights_limit(cap_dfd_no_unlink, &r_no_unlink)); 1110 int cap_dfd_no_mkdir = dup(dfd); 1111 EXPECT_OK(cap_dfd_no_mkdir); 1112 EXPECT_OK(cap_rights_limit(cap_dfd_no_mkdir, &r_no_mkdir)); 1113 int cap_dfd_no_mkfifo = dup(dfd); 1114 EXPECT_OK(cap_dfd_no_mkfifo); 1115 EXPECT_OK(cap_rights_limit(cap_dfd_no_mkfifo, &r_no_mkfifo)); 1116 int cap_dfd_create = dup(dfd); 1117 EXPECT_OK(cap_dfd_create); 1118 EXPECT_OK(cap_rights_limit(cap_dfd_create, &r_create)); 1119 int cap_dfd_bind = dup(dfd); 1120 EXPECT_OK(cap_dfd_bind); 1121 EXPECT_OK(cap_rights_limit(cap_dfd_bind, &r_bind)); 1122 1123 // Need CAP_MKDIRAT to mkdirat(2). 1124 EXPECT_NOTCAPABLE(mkdirat(cap_dfd_no_mkdir, "cap_subdir", 0755)); 1125 rmdir(TmpFile("cap_at_topdir/cap_subdir")); 1126 EXPECT_OK(mkdirat(cap_dfd_all, "cap_subdir", 0755)); 1127 1128 // Need CAP_UNLINKAT to unlinkat(dfd, name, AT_REMOVEDIR). 1129 EXPECT_NOTCAPABLE(unlinkat(cap_dfd_no_unlink, "cap_subdir", AT_REMOVEDIR)); 1130 EXPECT_OK(unlinkat(cap_dfd_all, "cap_subdir", AT_REMOVEDIR)); 1131 rmdir(TmpFile("cap_at_topdir/cap_subdir")); 1132 1133 // Need CAP_MKFIFOAT to mkfifoat(2). 1134 EXPECT_NOTCAPABLE(mkfifoat(cap_dfd_no_mkfifo, "cap_fifo", 0755)); 1135 unlink(TmpFile("cap_at_topdir/cap_fifo")); 1136 EXPECT_OK(mkfifoat(cap_dfd_all, "cap_fifo", 0755)); 1137 unlink(TmpFile("cap_at_topdir/cap_fifo")); 1138 1139 #ifdef HAVE_MKNOD_REG 1140 // Need CAP_CREATE to create a regular file with mknodat(2). 1141 EXPECT_NOTCAPABLE(mknodat(cap_dfd_all, "cap_regular", S_IFREG|0755, 0)); 1142 unlink(TmpFile("cap_at_topdir/cap_regular")); 1143 EXPECT_OK(mknodat(cap_dfd_create, "cap_regular", S_IFREG|0755, 0)); 1144 unlink(TmpFile("cap_at_topdir/cap_regular")); 1145 #endif 1146 1147 #ifdef HAVE_MKNOD_SOCKET 1148 // Need CAP_BIND to create a UNIX domain socket with mknodat(2). 1149 EXPECT_NOTCAPABLE(mknodat(cap_dfd_all, "cap_socket", S_IFSOCK|0755, 0)); 1150 unlink(TmpFile("cap_at_topdir/cap_socket")); 1151 EXPECT_OK(mknodat(cap_dfd_bind, "cap_socket", S_IFSOCK|0755, 0)); 1152 unlink(TmpFile("cap_at_topdir/cap_socket")); 1153 #endif 1154 1155 close(cap_dfd_all); 1156 close(cap_dfd_no_mkfifo); 1157 close(cap_dfd_no_mkdir); 1158 close(cap_dfd_no_unlink); 1159 close(cap_dfd_create); 1160 close(cap_dfd_bind); 1161 close(dfd); 1162 1163 // Tidy up. 1164 rmdir(TmpFile("cap_at_topdir")); 1165 } 1166 1167 TEST(Capability, SyscallAtIfRoot) { 1168 GTEST_SKIP_IF_NOT_ROOT(); 1169 int rc = mkdir(TmpFile("cap_at_topdir"), 0755); 1170 EXPECT_OK(rc); 1171 if (rc < 0 && errno != EEXIST) return; 1172 1173 cap_rights_t r_all; 1174 cap_rights_init(&r_all, CAP_READ, CAP_LOOKUP, CAP_MKNODAT, CAP_UNLINKAT, CAP_MKDIRAT, CAP_MKFIFOAT); 1175 cap_rights_t r_no_mkfifo; 1176 cap_rights_init(&r_no_mkfifo, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKDIRAT); 1177 cap_rights_t r_no_mknod; 1178 cap_rights_init(&r_no_mknod, CAP_READ, CAP_LOOKUP, CAP_UNLINKAT, CAP_MKDIRAT); 1179 1180 int dfd = open(TmpFile("cap_at_topdir"), O_RDONLY); 1181 EXPECT_OK(dfd); 1182 int cap_dfd_all = dup(dfd); 1183 EXPECT_OK(cap_dfd_all); 1184 EXPECT_OK(cap_rights_limit(cap_dfd_all, &r_all)); 1185 int cap_dfd_no_mkfifo = dup(dfd); 1186 EXPECT_OK(cap_dfd_no_mkfifo); 1187 EXPECT_OK(cap_rights_limit(cap_dfd_no_mkfifo, &r_no_mkfifo)); 1188 int cap_dfd_no_mknod = dup(dfd); 1189 EXPECT_OK(cap_dfd_no_mknod); 1190 EXPECT_OK(cap_rights_limit(cap_dfd_no_mknod, &r_no_mknod)); 1191 1192 // Need CAP_MKNODAT to mknodat(2) a device 1193 EXPECT_NOTCAPABLE(mknodat(cap_dfd_no_mknod, "cap_device", S_IFCHR|0755, makedev(99, 123))); 1194 unlink(TmpFile("cap_at_topdir/cap_device")); 1195 EXPECT_OK(mknodat(cap_dfd_all, "cap_device", S_IFCHR|0755, makedev(99, 123))); 1196 unlink(TmpFile("cap_at_topdir/cap_device")); 1197 1198 // Need CAP_MKFIFOAT to mknodat(2) for a FIFO. 1199 EXPECT_NOTCAPABLE(mknodat(cap_dfd_no_mkfifo, "cap_fifo", S_IFIFO|0755, 0)); 1200 unlink(TmpFile("cap_at_topdir/cap_fifo")); 1201 EXPECT_OK(mknodat(cap_dfd_all, "cap_fifo", S_IFIFO|0755, 0)); 1202 unlink(TmpFile("cap_at_topdir/cap_fifo")); 1203 1204 close(cap_dfd_all); 1205 close(cap_dfd_no_mknod); 1206 close(cap_dfd_no_mkfifo); 1207 close(dfd); 1208 1209 // Tidy up. 1210 rmdir(TmpFile("cap_at_topdir")); 1211 } 1212 1213 FORK_TEST_ON(Capability, ExtendedAttributesIfAvailable, TmpFile("cap_extattr")) { 1214 int fd = open(TmpFile("cap_extattr"), O_RDONLY|O_CREAT, 0644); 1215 EXPECT_OK(fd); 1216 1217 char buffer[1024]; 1218 int rc = fgetxattr_(fd, "user.capsicumtest", buffer, sizeof(buffer)); 1219 if (rc < 0 && errno == ENOTSUP) { 1220 // Need user_xattr mount option for non-root users on Linux 1221 close(fd); 1222 GTEST_SKIP() << "/tmp doesn't support extended attributes"; 1223 } 1224 1225 cap_rights_t r_rws; 1226 cap_rights_init(&r_rws, CAP_READ, CAP_WRITE, CAP_SEEK); 1227 cap_rights_t r_xlist; 1228 cap_rights_init(&r_xlist, CAP_EXTATTR_LIST); 1229 cap_rights_t r_xget; 1230 cap_rights_init(&r_xget, CAP_EXTATTR_GET); 1231 cap_rights_t r_xset; 1232 cap_rights_init(&r_xset, CAP_EXTATTR_SET); 1233 cap_rights_t r_xdel; 1234 cap_rights_init(&r_xdel, CAP_EXTATTR_DELETE); 1235 1236 int cap = dup(fd); 1237 EXPECT_OK(cap); 1238 EXPECT_OK(cap_rights_limit(cap, &r_rws)); 1239 int cap_xlist = dup(fd); 1240 EXPECT_OK(cap_xlist); 1241 EXPECT_OK(cap_rights_limit(cap_xlist, &r_xlist)); 1242 int cap_xget = dup(fd); 1243 EXPECT_OK(cap_xget); 1244 EXPECT_OK(cap_rights_limit(cap_xget, &r_xget)); 1245 int cap_xset = dup(fd); 1246 EXPECT_OK(cap_xset); 1247 EXPECT_OK(cap_rights_limit(cap_xset, &r_xset)); 1248 int cap_xdel = dup(fd); 1249 EXPECT_OK(cap_xdel); 1250 EXPECT_OK(cap_rights_limit(cap_xdel, &r_xdel)); 1251 1252 const char* value = "capsicum"; 1253 int len = strlen(value) + 1; 1254 EXPECT_NOTCAPABLE(fsetxattr_(cap, "user.capsicumtest", value, len, 0)); 1255 EXPECT_NOTCAPABLE(fsetxattr_(cap_xlist, "user.capsicumtest", value, len, 0)); 1256 EXPECT_NOTCAPABLE(fsetxattr_(cap_xget, "user.capsicumtest", value, len, 0)); 1257 EXPECT_NOTCAPABLE(fsetxattr_(cap_xdel, "user.capsicumtest", value, len, 0)); 1258 EXPECT_OK(fsetxattr_(cap_xset, "user.capsicumtest", value, len, 0)); 1259 1260 EXPECT_NOTCAPABLE(flistxattr_(cap, buffer, sizeof(buffer))); 1261 EXPECT_NOTCAPABLE(flistxattr_(cap_xget, buffer, sizeof(buffer))); 1262 EXPECT_NOTCAPABLE(flistxattr_(cap_xset, buffer, sizeof(buffer))); 1263 EXPECT_NOTCAPABLE(flistxattr_(cap_xdel, buffer, sizeof(buffer))); 1264 EXPECT_OK(flistxattr_(cap_xlist, buffer, sizeof(buffer))); 1265 1266 EXPECT_NOTCAPABLE(fgetxattr_(cap, "user.capsicumtest", buffer, sizeof(buffer))); 1267 EXPECT_NOTCAPABLE(fgetxattr_(cap_xlist, "user.capsicumtest", buffer, sizeof(buffer))); 1268 EXPECT_NOTCAPABLE(fgetxattr_(cap_xset, "user.capsicumtest", buffer, sizeof(buffer))); 1269 EXPECT_NOTCAPABLE(fgetxattr_(cap_xdel, "user.capsicumtest", buffer, sizeof(buffer))); 1270 EXPECT_OK(fgetxattr_(cap_xget, "user.capsicumtest", buffer, sizeof(buffer))); 1271 1272 EXPECT_NOTCAPABLE(fremovexattr_(cap, "user.capsicumtest")); 1273 EXPECT_NOTCAPABLE(fremovexattr_(cap_xlist, "user.capsicumtest")); 1274 EXPECT_NOTCAPABLE(fremovexattr_(cap_xget, "user.capsicumtest")); 1275 EXPECT_NOTCAPABLE(fremovexattr_(cap_xset, "user.capsicumtest")); 1276 EXPECT_OK(fremovexattr_(cap_xdel, "user.capsicumtest")); 1277 1278 close(cap_xdel); 1279 close(cap_xset); 1280 close(cap_xget); 1281 close(cap_xlist); 1282 close(cap); 1283 close(fd); 1284 } 1285 1286 TEST(Capability, PipeUnseekable) { 1287 int fds[2]; 1288 EXPECT_OK(pipe(fds)); 1289 1290 // Some programs detect pipes by calling seek() and getting ESPIPE. 1291 EXPECT_EQ(-1, lseek(fds[0], 0, SEEK_SET)); 1292 EXPECT_EQ(ESPIPE, errno); 1293 1294 cap_rights_t rights; 1295 cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_SEEK); 1296 EXPECT_OK(cap_rights_limit(fds[0], &rights)); 1297 1298 EXPECT_EQ(-1, lseek(fds[0], 0, SEEK_SET)); 1299 EXPECT_EQ(ESPIPE, errno); 1300 1301 // Remove CAP_SEEK and see if ENOTCAPABLE trumps ESPIPE. 1302 cap_rights_init(&rights, CAP_READ, CAP_WRITE); 1303 EXPECT_OK(cap_rights_limit(fds[0], &rights)); 1304 EXPECT_EQ(-1, lseek(fds[0], 0, SEEK_SET)); 1305 EXPECT_EQ(ENOTCAPABLE, errno); 1306 // TODO(drysdale): in practical terms it might be nice if ESPIPE trumped ENOTCAPABLE. 1307 // EXPECT_EQ(ESPIPE, errno); 1308 1309 close(fds[0]); 1310 close(fds[1]); 1311 } 1312 1313 TEST(Capability, NoBypassDACIfRoot) { 1314 GTEST_SKIP_IF_NOT_ROOT(); 1315 int fd = open(TmpFile("cap_root_owned"), O_RDONLY|O_CREAT, 0644); 1316 EXPECT_OK(fd); 1317 cap_rights_t rights; 1318 cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FCHMOD, CAP_FSTAT); 1319 EXPECT_OK(cap_rights_limit(fd, &rights)); 1320 1321 pid_t child = fork(); 1322 if (child == 0) { 1323 // Child: change uid to a lesser being 1324 ASSERT_NE(0u, other_uid) << "other_uid not initialized correctly, " 1325 "please pass the -u <uid> flag."; 1326 EXPECT_EQ(0, setuid(other_uid)); 1327 EXPECT_EQ(other_uid, getuid()); 1328 // Attempt to fchmod the file, and fail. 1329 // Having CAP_FCHMOD doesn't bypass the need to comply with DAC policy. 1330 int rc = fchmod(fd, 0666); 1331 EXPECT_EQ(-1, rc); 1332 EXPECT_EQ(EPERM, errno); 1333 exit(HasFailure()); 1334 } 1335 int status; 1336 EXPECT_EQ(child, waitpid(child, &status, 0)); 1337 EXPECT_TRUE(WIFEXITED(status)) << "0x" << std::hex << status; 1338 EXPECT_EQ(0, WEXITSTATUS(status)); 1339 struct stat info; 1340 EXPECT_OK(fstat(fd, &info)); 1341 EXPECT_EQ((mode_t)(S_IFREG|0644), info.st_mode); 1342 close(fd); 1343 unlink(TmpFile("cap_root_owned")); 1344 } 1345 1346 TEST(Capability, CheckIsEmpty) { 1347 cap_rights_t rights; 1348 1349 cap_rights_init(&rights); 1350 EXPECT_TRUE(cap_rights_is_empty(&rights)); 1351 1352 size_t num_known = (sizeof(known_rights)/sizeof(known_rights[0])); 1353 for (size_t ii = 0; ii < num_known; ii++) { 1354 cap_rights_init(&rights, known_rights[ii].right); 1355 EXPECT_FALSE(cap_rights_is_empty(&rights)); 1356 cap_rights_clear(&rights, known_rights[ii].right); 1357 EXPECT_TRUE(cap_rights_is_empty(&rights)); 1358 } 1359 } 1360