Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/capsicum-test/capability-fd.cc
39475 views
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
1361