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
ShowCapRights(FILE * out,int fd)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
ShowAllCapRights(FILE * out)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
FORK_TEST(Capability,CapNew)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
FORK_TEST(Capability,CapEnter)234 FORK_TEST(Capability, CapEnter) {
235 EXPECT_EQ(0, cap_enter());
236 }
237
FORK_TEST(Capability,BasicInterception)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
TryFileOps(int fd,cap_rights_t rights)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
TryDirOps(int dirfd,cap_rights_t rights)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
DirOperationsTest(int extra)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
FORK_TEST(Capability,DirOperations)937 FORK_TEST(Capability, DirOperations) {
938 DirOperationsTest(0);
939 }
940
FORK_TEST(Capability,PathDirOperations)941 FORK_TEST(Capability, PathDirOperations) {
942 // Make the dfd in the test a path-only file descriptor.
943 DirOperationsTest(O_PATH);
944 }
945
TryReadWrite(int cap_fd)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
TEST(Capability,SyscallAt)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
TEST(Capability,SyscallAtIfRoot)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
TEST(Capability,PipeUnseekable)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
TEST(Capability,NoBypassDACIfRoot)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
TEST(Capability,CheckIsEmpty)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