Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/capsicum-test/capmode.cc
39475 views
1
// Test routines to make sure a variety of system calls are or are not
2
// available in capability mode. The goal is not to see if they work, just
3
// whether or not they return the expected ECAPMODE.
4
#include <sys/types.h>
5
#include <sys/socket.h>
6
#ifdef __FreeBSD__
7
#include <sys/sockio.h>
8
#endif
9
#include <sys/stat.h>
10
#include <sys/mount.h>
11
#include <sys/mman.h>
12
#include <sys/wait.h>
13
#include <sys/time.h>
14
#include <sys/resource.h>
15
#include <sys/ptrace.h>
16
#include <dirent.h>
17
#include <net/if.h>
18
#include <netinet/in.h>
19
#include <fcntl.h>
20
#include <sched.h>
21
#include <time.h>
22
#include <unistd.h>
23
#include <pthread.h>
24
25
#include "capsicum.h"
26
#include "syscalls.h"
27
#include "capsicum-test.h"
28
29
// Test fixture that opens (and closes) a bunch of files.
30
class WithFiles : public ::testing::Test {
31
public:
32
WithFiles() :
33
fd_file_(open(TmpFile("cap_capmode"), O_RDWR|O_CREAT, 0644)),
34
fd_close_(open("/dev/null", O_RDWR)),
35
fd_dir_(open(tmpdir.c_str(), O_RDONLY)),
36
fd_socket_(socket(PF_INET, SOCK_DGRAM, 0)),
37
fd_tcp_socket_(socket(PF_INET, SOCK_STREAM, 0)) {
38
EXPECT_OK(fd_file_);
39
EXPECT_OK(fd_close_);
40
EXPECT_OK(fd_dir_);
41
EXPECT_OK(fd_socket_);
42
EXPECT_OK(fd_tcp_socket_);
43
}
44
~WithFiles() {
45
if (fd_tcp_socket_ >= 0) close(fd_tcp_socket_);
46
if (fd_socket_ >= 0) close(fd_socket_);
47
if (fd_dir_ >= 0) close(fd_dir_);
48
if (fd_close_ >= 0) close(fd_close_);
49
if (fd_file_ >= 0) close(fd_file_);
50
unlink(TmpFile("cap_capmode"));
51
}
52
protected:
53
int fd_file_;
54
int fd_close_;
55
int fd_dir_;
56
int fd_socket_;
57
int fd_tcp_socket_;
58
};
59
60
FORK_TEST_F(WithFiles, DisallowedFileSyscalls) {
61
unsigned int mode = -1;
62
EXPECT_OK(cap_getmode(&mode));
63
EXPECT_EQ(0, (int)mode);
64
EXPECT_OK(cap_enter()); // Enter capability mode.
65
EXPECT_OK(cap_getmode(&mode));
66
EXPECT_EQ(1, (int)mode);
67
68
// System calls that are not permitted in capability mode.
69
EXPECT_CAPMODE(access(TmpFile("cap_capmode_access"), F_OK));
70
EXPECT_CAPMODE(acct(TmpFile("cap_capmode_acct")));
71
EXPECT_CAPMODE(chdir(TmpFile("cap_capmode_chdir")));
72
#ifdef HAVE_CHFLAGS
73
EXPECT_CAPMODE(chflags(TmpFile("cap_capmode_chflags"), UF_NODUMP));
74
#endif
75
EXPECT_CAPMODE(chmod(TmpFile("cap_capmode_chmod"), 0644));
76
EXPECT_CAPMODE(chown(TmpFile("cap_capmode_chown"), -1, -1));
77
EXPECT_CAPMODE(chroot(TmpFile("cap_capmode_chroot")));
78
EXPECT_CAPMODE(creat(TmpFile("cap_capmode_creat"), 0644));
79
EXPECT_CAPMODE(fchdir(fd_dir_));
80
#ifdef HAVE_GETFSSTAT
81
struct statfs statfs;
82
EXPECT_CAPMODE(getfsstat(&statfs, sizeof(statfs), MNT_NOWAIT));
83
#endif
84
EXPECT_CAPMODE(link(TmpFile("foo"), TmpFile("bar")));
85
struct stat sb;
86
EXPECT_CAPMODE(lstat(TmpFile("cap_capmode_lstat"), &sb));
87
EXPECT_CAPMODE(mknod(TmpFile("capmode_mknod"), 0644 | S_IFIFO, 0));
88
EXPECT_CAPMODE(bogus_mount_());
89
EXPECT_CAPMODE(open("/dev/null", O_RDWR));
90
char buf[64];
91
EXPECT_CAPMODE(readlink(TmpFile("cap_capmode_readlink"), buf, sizeof(buf)));
92
#ifdef HAVE_REVOKE
93
EXPECT_CAPMODE(revoke(TmpFile("cap_capmode_revoke")));
94
#endif
95
EXPECT_CAPMODE(stat(TmpFile("cap_capmode_stat"), &sb));
96
EXPECT_CAPMODE(symlink(TmpFile("cap_capmode_symlink_from"), TmpFile("cap_capmode_symlink_to")));
97
EXPECT_CAPMODE(unlink(TmpFile("cap_capmode_unlink")));
98
EXPECT_CAPMODE(umount2("/not_mounted", 0));
99
}
100
101
FORK_TEST_F(WithFiles, DisallowedSocketSyscalls) {
102
EXPECT_OK(cap_enter()); // Enter capability mode.
103
104
// System calls that are not permitted in capability mode.
105
struct sockaddr_in addr;
106
addr.sin_family = AF_INET;
107
addr.sin_port = 0;
108
addr.sin_addr.s_addr = htonl(INADDR_ANY);
109
EXPECT_CAPMODE(bind_(fd_socket_, (sockaddr*)&addr, sizeof(addr)));
110
addr.sin_family = AF_INET;
111
addr.sin_port = 53;
112
addr.sin_addr.s_addr = htonl(0x08080808);
113
EXPECT_CAPMODE(connect_(fd_tcp_socket_, (sockaddr*)&addr, sizeof(addr)));
114
}
115
116
FORK_TEST_F(WithFiles, AllowedFileSyscalls) {
117
int rc;
118
EXPECT_OK(cap_enter()); // Enter capability mode.
119
120
EXPECT_OK(close(fd_close_));
121
fd_close_ = -1;
122
int fd_dup = dup(fd_file_);
123
EXPECT_OK(fd_dup);
124
EXPECT_OK(dup2(fd_file_, fd_dup));
125
#ifdef HAVE_DUP3
126
EXPECT_OK(dup3(fd_file_, fd_dup, 0));
127
#endif
128
if (fd_dup >= 0) close(fd_dup);
129
130
struct stat sb;
131
EXPECT_OK(fstat(fd_file_, &sb));
132
EXPECT_OK(lseek(fd_file_, 0, SEEK_SET));
133
char ch;
134
EXPECT_OK(read(fd_file_, &ch, sizeof(ch)));
135
EXPECT_OK(write(fd_file_, &ch, sizeof(ch)));
136
137
#ifdef HAVE_CHFLAGS
138
rc = fchflags(fd_file_, UF_NODUMP);
139
if (rc < 0) {
140
EXPECT_NE(ECAPMODE, errno);
141
}
142
#endif
143
144
char buf[1024];
145
rc = getdents_(fd_dir_, (void*)buf, sizeof(buf));
146
EXPECT_OK(rc);
147
148
char data[] = "123";
149
EXPECT_OK(pwrite(fd_file_, data, 1, 0));
150
EXPECT_OK(pread(fd_file_, data, 1, 0));
151
152
struct iovec io;
153
io.iov_base = data;
154
io.iov_len = 2;
155
#if !defined(__i386__) && !defined(__linux__)
156
// TODO(drysdale): reinstate these tests for 32-bit runs when possible
157
// libc bug is fixed.
158
EXPECT_OK(pwritev(fd_file_, &io, 1, 0));
159
EXPECT_OK(preadv(fd_file_, &io, 1, 0));
160
#endif
161
EXPECT_OK(writev(fd_file_, &io, 1));
162
EXPECT_OK(readv(fd_file_, &io, 1));
163
164
#ifdef HAVE_SYNCFS
165
EXPECT_OK(syncfs(fd_file_));
166
#endif
167
#ifdef HAVE_SYNC_FILE_RANGE
168
EXPECT_OK(sync_file_range(fd_file_, 0, 1, 0));
169
#endif
170
#ifdef HAVE_READAHEAD
171
if (!tmpdir_on_tmpfs) { // tmpfs doesn't support readahead(2)
172
EXPECT_OK(readahead(fd_file_, 0, 1));
173
}
174
#endif
175
}
176
177
FORK_TEST_F(WithFiles, AllowedSocketSyscalls) {
178
EXPECT_OK(cap_enter()); // Enter capability mode.
179
180
// recvfrom() either returns -1 with EAGAIN, or 0.
181
int rc = recvfrom(fd_socket_, NULL, 0, MSG_DONTWAIT, NULL, NULL);
182
if (rc < 0) {
183
EXPECT_EQ(EAGAIN, errno);
184
}
185
char ch;
186
EXPECT_OK(write(fd_file_, &ch, sizeof(ch)));
187
188
// These calls will fail for lack of e.g. a proper name to send to,
189
// but they are allowed in capability mode, so errno != ECAPMODE.
190
EXPECT_FAIL_NOT_CAPMODE(accept(fd_socket_, NULL, NULL));
191
EXPECT_FAIL_NOT_CAPMODE(getpeername(fd_socket_, NULL, NULL));
192
EXPECT_FAIL_NOT_CAPMODE(getsockname(fd_socket_, NULL, NULL));
193
EXPECT_FAIL_NOT_CAPMODE(recvmsg(fd_socket_, NULL, 0));
194
EXPECT_FAIL_NOT_CAPMODE(sendmsg(fd_socket_, NULL, 0));
195
EXPECT_FAIL_NOT_CAPMODE(sendto(fd_socket_, NULL, 0, 0, NULL, 0));
196
off_t offset = 0;
197
EXPECT_FAIL_NOT_CAPMODE(sendfile_(fd_socket_, fd_file_, &offset, 1));
198
199
// The socket/socketpair syscalls are allowed, but they don't give
200
// anything externally useful (can't call bind/connect on them).
201
int fd_socket2 = socket(PF_INET, SOCK_DGRAM, 0);
202
EXPECT_OK(fd_socket2);
203
if (fd_socket2 >= 0) close(fd_socket2);
204
int fd_pair[2] = {-1, -1};
205
EXPECT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, fd_pair));
206
if (fd_pair[0] >= 0) close(fd_pair[0]);
207
if (fd_pair[1] >= 0) close(fd_pair[1]);
208
}
209
210
FORK_TEST_F(WithFiles, AllowedSocketSyscallsIfRoot) {
211
GTEST_SKIP_IF_NOT_ROOT();
212
213
EXPECT_OK(cap_enter()); // Enter capability mode.
214
215
// Creation of raw sockets is not permitted in capability mode.
216
EXPECT_CAPMODE(socket(AF_INET, SOCK_RAW, 0));
217
EXPECT_CAPMODE(socket(AF_INET, SOCK_RAW, IPPROTO_ICMP));
218
EXPECT_CAPMODE(socket(AF_INET, SOCK_RAW, IPPROTO_TCP));
219
EXPECT_CAPMODE(socket(AF_INET, SOCK_RAW, IPPROTO_UDP));
220
221
EXPECT_CAPMODE(socket(AF_INET6, SOCK_RAW, IPPROTO_ICMP));
222
EXPECT_CAPMODE(socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6));
223
EXPECT_CAPMODE(socket(AF_INET6, SOCK_RAW, IPPROTO_TCP));
224
EXPECT_CAPMODE(socket(AF_INET6, SOCK_RAW, IPPROTO_UDP));
225
226
EXPECT_CAPMODE(socket(AF_ROUTE, SOCK_RAW, 0));
227
228
// Interface configuration ioctls are not permitted in capability
229
// mode.
230
//
231
// This test is disabled for now as the corresponding kernel change was
232
// disabled.
233
#if 0
234
#ifdef __FreeBSD__
235
struct if_clonereq req;
236
237
req.ifcr_total = 0;
238
req.ifcr_count = 1;
239
req.ifcr_buffer = static_cast<char *>(malloc(IFNAMSIZ));
240
241
EXPECT_CAPMODE(ioctl(fd_socket_, SIOCIFGCLONERS, &req));
242
243
free(req.ifcr_buffer);
244
#endif
245
#endif
246
}
247
248
#ifdef HAVE_SEND_RECV_MMSG
249
FORK_TEST(Capmode, AllowedMmsgSendRecv) {
250
int fd_socket = socket(PF_INET, SOCK_DGRAM, 0);
251
252
struct sockaddr_in addr;
253
addr.sin_family = AF_INET;
254
addr.sin_port = htons(0);
255
addr.sin_addr.s_addr = htonl(INADDR_ANY);
256
EXPECT_OK(bind(fd_socket, (sockaddr*)&addr, sizeof(addr)));
257
258
EXPECT_OK(cap_enter()); // Enter capability mode.
259
260
char buffer[256] = {0};
261
struct iovec iov;
262
iov.iov_base = buffer;
263
iov.iov_len = sizeof(buffer);
264
struct mmsghdr mm;
265
memset(&mm, 0, sizeof(mm));
266
mm.msg_hdr.msg_iov = &iov;
267
mm.msg_hdr.msg_iovlen = 1;
268
struct timespec ts;
269
ts.tv_sec = 1;
270
ts.tv_nsec = 100;
271
EXPECT_FAIL_NOT_CAPMODE(recvmmsg(fd_socket, &mm, 1, MSG_DONTWAIT, &ts));
272
EXPECT_FAIL_NOT_CAPMODE(sendmmsg(fd_socket, &mm, 1, 0));
273
close(fd_socket);
274
}
275
#endif
276
277
FORK_TEST(Capmode, AllowedIdentifierSyscalls) {
278
// Record some identifiers
279
gid_t my_gid = getgid();
280
pid_t my_pid = getpid();
281
pid_t my_ppid = getppid();
282
uid_t my_uid = getuid();
283
pid_t my_sid = getsid(my_pid);
284
285
EXPECT_OK(cap_enter()); // Enter capability mode.
286
287
EXPECT_EQ(my_gid, getegid_());
288
EXPECT_EQ(my_uid, geteuid_());
289
EXPECT_EQ(my_gid, getgid_());
290
EXPECT_EQ(my_pid, getpid());
291
EXPECT_EQ(my_ppid, getppid());
292
EXPECT_EQ(my_uid, getuid_());
293
EXPECT_EQ(my_sid, getsid(my_pid));
294
gid_t grps[128];
295
EXPECT_OK(getgroups_(128, grps));
296
uid_t ruid;
297
uid_t euid;
298
uid_t suid;
299
EXPECT_OK(getresuid(&ruid, &euid, &suid));
300
gid_t rgid;
301
gid_t egid;
302
gid_t sgid;
303
EXPECT_OK(getresgid(&rgid, &egid, &sgid));
304
#ifdef HAVE_GETLOGIN
305
EXPECT_TRUE(getlogin() != NULL);
306
#endif
307
308
// Set various identifiers (to their existing values).
309
EXPECT_OK(setgid(my_gid));
310
#ifdef HAVE_SETFSGID
311
EXPECT_OK(setfsgid(my_gid));
312
#endif
313
EXPECT_OK(setuid(my_uid));
314
#ifdef HAVE_SETFSUID
315
EXPECT_OK(setfsuid(my_uid));
316
#endif
317
EXPECT_OK(setregid(my_gid, my_gid));
318
EXPECT_OK(setresgid(my_gid, my_gid, my_gid));
319
EXPECT_OK(setreuid(my_uid, my_uid));
320
EXPECT_OK(setresuid(my_uid, my_uid, my_uid));
321
EXPECT_OK(setsid());
322
}
323
324
FORK_TEST(Capmode, AllowedSchedSyscalls) {
325
EXPECT_OK(cap_enter()); // Enter capability mode.
326
int policy = sched_getscheduler(0);
327
EXPECT_OK(policy);
328
struct sched_param sp;
329
EXPECT_OK(sched_getparam(0, &sp));
330
if (policy >= 0 && (!SCHED_SETSCHEDULER_REQUIRES_ROOT || getuid() == 0)) {
331
EXPECT_OK(sched_setscheduler(0, policy, &sp));
332
}
333
EXPECT_OK(sched_setparam(0, &sp));
334
EXPECT_OK(sched_get_priority_max(policy));
335
EXPECT_OK(sched_get_priority_min(policy));
336
struct timespec ts;
337
EXPECT_OK(sched_rr_get_interval(0, &ts));
338
EXPECT_OK(sched_yield());
339
}
340
341
342
FORK_TEST(Capmode, AllowedTimerSyscalls) {
343
EXPECT_OK(cap_enter()); // Enter capability mode.
344
struct timespec ts;
345
EXPECT_OK(clock_getres(CLOCK_REALTIME, &ts));
346
EXPECT_OK(clock_gettime(CLOCK_REALTIME, &ts));
347
struct itimerval itv;
348
EXPECT_OK(getitimer(ITIMER_REAL, &itv));
349
EXPECT_OK(setitimer(ITIMER_REAL, &itv, NULL));
350
struct timeval tv;
351
struct timezone tz;
352
EXPECT_OK(gettimeofday(&tv, &tz));
353
ts.tv_sec = 0;
354
ts.tv_nsec = 1;
355
EXPECT_OK(nanosleep(&ts, NULL));
356
}
357
358
359
FORK_TEST(Capmode, AllowedProfilSyscall) {
360
EXPECT_OK(cap_enter()); // Enter capability mode.
361
char sbuf[32];
362
EXPECT_OK(profil((profil_arg1_t*)sbuf, sizeof(sbuf), 0, 1));
363
}
364
365
366
FORK_TEST(Capmode, AllowedResourceSyscalls) {
367
EXPECT_OK(cap_enter()); // Enter capability mode.
368
errno = 0;
369
int rc = getpriority(PRIO_PROCESS, 0);
370
EXPECT_EQ(0, errno);
371
EXPECT_OK(setpriority(PRIO_PROCESS, 0, rc));
372
struct rlimit rlim;
373
EXPECT_OK(getrlimit_(RLIMIT_CORE, &rlim));
374
EXPECT_OK(setrlimit(RLIMIT_CORE, &rlim));
375
struct rusage ruse;
376
EXPECT_OK(getrusage(RUSAGE_SELF, &ruse));
377
}
378
379
FORK_TEST(CapMode, AllowedMmapSyscalls) {
380
// mmap() some memory.
381
size_t mem_size = getpagesize();
382
void *mem = mmap(NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
383
EXPECT_TRUE(mem != NULL);
384
EXPECT_OK(cap_enter()); // Enter capability mode.
385
386
EXPECT_OK(msync(mem, mem_size, MS_ASYNC));
387
EXPECT_OK(madvise(mem, mem_size, MADV_NORMAL));
388
unsigned char vec[2];
389
EXPECT_OK(mincore_(mem, mem_size, vec));
390
EXPECT_OK(mprotect(mem, mem_size, PROT_READ|PROT_WRITE));
391
392
if (!MLOCK_REQUIRES_ROOT || getuid() == 0) {
393
EXPECT_OK(mlock(mem, mem_size));
394
EXPECT_OK(munlock(mem, mem_size));
395
int rc = mlockall(MCL_CURRENT);
396
if (rc != 0) {
397
// mlockall may well fail with ENOMEM for non-root users, as the
398
// default RLIMIT_MEMLOCK value isn't that big.
399
EXPECT_NE(ECAPMODE, errno);
400
}
401
EXPECT_OK(munlockall());
402
}
403
// Unmap the memory.
404
EXPECT_OK(munmap(mem, mem_size));
405
}
406
407
FORK_TEST(Capmode, AllowedPipeSyscalls) {
408
EXPECT_OK(cap_enter()); // Enter capability mode
409
int fd2[2];
410
int rc = pipe(fd2);
411
EXPECT_EQ(0, rc);
412
413
#ifdef HAVE_VMSPLICE
414
char buf[11] = "0123456789";
415
struct iovec iov;
416
iov.iov_base = buf;
417
iov.iov_len = sizeof(buf);
418
EXPECT_FAIL_NOT_CAPMODE(vmsplice(fd2[0], &iov, 1, SPLICE_F_NONBLOCK));
419
#endif
420
421
if (rc == 0) {
422
close(fd2[0]);
423
close(fd2[1]);
424
};
425
#ifdef HAVE_PIPE2
426
rc = pipe2(fd2, 0);
427
EXPECT_EQ(0, rc);
428
if (rc == 0) {
429
close(fd2[0]);
430
close(fd2[1]);
431
};
432
#endif
433
}
434
435
TEST(Capmode, AllowedAtSyscalls) {
436
int rc = mkdir(TmpFile("cap_at_syscalls"), 0755);
437
EXPECT_OK(rc);
438
if (rc < 0 && errno != EEXIST) return;
439
int dfd = open(TmpFile("cap_at_syscalls"), O_RDONLY);
440
EXPECT_OK(dfd);
441
442
int file = openat(dfd, "testfile", O_RDONLY|O_CREAT, 0644);
443
EXPECT_OK(file);
444
EXPECT_OK(close(file));
445
446
447
pid_t child = fork();
448
if (child == 0) {
449
// Child: enter cap mode and run tests
450
EXPECT_OK(cap_enter()); // Enter capability mode
451
452
struct stat fs;
453
EXPECT_OK(fstatat(dfd, "testfile", &fs, 0));
454
EXPECT_OK(mkdirat(dfd, "subdir", 0600));
455
EXPECT_OK(fchmodat(dfd, "subdir", 0644, 0));
456
EXPECT_OK(faccessat(dfd, "subdir", F_OK, 0));
457
EXPECT_OK(renameat(dfd, "subdir", dfd, "subdir2"));
458
EXPECT_OK(renameat(dfd, "subdir2", dfd, "subdir"));
459
struct timeval tv[2];
460
struct timezone tz;
461
EXPECT_OK(gettimeofday(&tv[0], &tz));
462
EXPECT_OK(gettimeofday(&tv[1], &tz));
463
EXPECT_OK(futimesat(dfd, "testfile", tv));
464
465
EXPECT_OK(fchownat(dfd, "testfile", fs.st_uid, fs.st_gid, 0));
466
EXPECT_OK(linkat(dfd, "testfile", dfd, "linky", 0));
467
EXPECT_OK(symlinkat("testfile", dfd, "symlink"));
468
char buffer[256];
469
EXPECT_OK(readlinkat(dfd, "symlink", buffer, sizeof(buffer)));
470
EXPECT_OK(unlinkat(dfd, "linky", 0));
471
EXPECT_OK(unlinkat(dfd, "subdir", AT_REMOVEDIR));
472
473
// Check that invalid requests get a non-Capsicum errno.
474
errno = 0;
475
rc = readlinkat(-1, "symlink", buffer, sizeof(buffer));
476
EXPECT_GE(0, rc);
477
EXPECT_NE(ECAPMODE, errno);
478
479
exit(HasFailure());
480
}
481
482
// Wait for the child.
483
int status;
484
EXPECT_EQ(child, waitpid(child, &status, 0));
485
rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
486
EXPECT_EQ(0, rc);
487
488
// Tidy up.
489
close(dfd);
490
rmdir(TmpFile("cap_at_syscalls/subdir"));
491
unlink(TmpFile("cap_at_syscalls/symlink"));
492
unlink(TmpFile("cap_at_syscalls/linky"));
493
unlink(TmpFile("cap_at_syscalls/testfile"));
494
rmdir(TmpFile("cap_at_syscalls"));
495
}
496
497
TEST(Capmode, AllowedAtSyscallsCwd) {
498
int rc = mkdir(TmpFile("cap_at_syscalls_cwd"), 0755);
499
EXPECT_OK(rc);
500
if (rc < 0 && errno != EEXIST) return;
501
int dfd = open(TmpFile("cap_at_syscalls_cwd"), O_RDONLY);
502
EXPECT_OK(dfd);
503
504
int file = openat(dfd, "testfile", O_RDONLY|O_CREAT, 0644);
505
EXPECT_OK(file);
506
EXPECT_OK(close(file));
507
508
pid_t child = fork();
509
if (child == 0) {
510
// Child: move into temp dir, enter cap mode and run tests
511
EXPECT_OK(fchdir(dfd));
512
EXPECT_OK(cap_enter()); // Enter capability mode
513
514
// Test that *at(AT_FDCWD, path,...) is policed with ECAPMODE.
515
EXPECT_CAPMODE(openat(AT_FDCWD, "testfile", O_RDONLY));
516
struct stat fs;
517
EXPECT_CAPMODE(fstatat(AT_FDCWD, "testfile", &fs, 0));
518
EXPECT_CAPMODE(mkdirat(AT_FDCWD, "subdir", 0600));
519
EXPECT_CAPMODE(fchmodat(AT_FDCWD, "subdir", 0644, 0));
520
EXPECT_CAPMODE(faccessat(AT_FDCWD, "subdir", F_OK, 0));
521
EXPECT_CAPMODE(renameat(AT_FDCWD, "subdir", AT_FDCWD, "subdir2"));
522
EXPECT_CAPMODE(renameat(AT_FDCWD, "subdir2", AT_FDCWD, "subdir"));
523
struct timeval tv[2];
524
struct timezone tz;
525
EXPECT_OK(gettimeofday(&tv[0], &tz));
526
EXPECT_OK(gettimeofday(&tv[1], &tz));
527
EXPECT_CAPMODE(futimesat(AT_FDCWD, "testfile", tv));
528
529
EXPECT_CAPMODE(fchownat(AT_FDCWD, "testfile", fs.st_uid, fs.st_gid, 0));
530
EXPECT_CAPMODE(linkat(AT_FDCWD, "testfile", AT_FDCWD, "linky", 0));
531
EXPECT_CAPMODE(symlinkat("testfile", AT_FDCWD, "symlink"));
532
char buffer[256];
533
EXPECT_CAPMODE(readlinkat(AT_FDCWD, "symlink", buffer, sizeof(buffer)));
534
EXPECT_CAPMODE(unlinkat(AT_FDCWD, "linky", 0));
535
536
exit(HasFailure());
537
}
538
539
// Wait for the child.
540
int status;
541
EXPECT_EQ(child, waitpid(child, &status, 0));
542
rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
543
EXPECT_EQ(0, rc);
544
545
// Tidy up.
546
close(dfd);
547
rmdir(TmpFile("cap_at_syscalls_cwd/subdir"));
548
unlink(TmpFile("cap_at_syscalls_cwd/symlink"));
549
unlink(TmpFile("cap_at_syscalls_cwd/linky"));
550
unlink(TmpFile("cap_at_syscalls_cwd/testfile"));
551
rmdir(TmpFile("cap_at_syscalls_cwd"));
552
}
553
554
TEST(Capmode, Abort) {
555
// Check that abort(3) works even in capability mode.
556
pid_t child = fork();
557
if (child == 0) {
558
// Child: enter capability mode and call abort(3).
559
// Triggers something like kill(getpid(), SIGABRT).
560
cap_enter(); // Enter capability mode.
561
abort();
562
exit(99);
563
}
564
int status;
565
EXPECT_EQ(child, waitpid(child, &status, 0));
566
EXPECT_TRUE(WIFSIGNALED(status)) << " status = " << std::hex << status;
567
EXPECT_EQ(SIGABRT, WTERMSIG(status)) << " status = " << std::hex << status;
568
}
569
570
FORK_TEST_F(WithFiles, AllowedMiscSyscalls) {
571
umask(022);
572
mode_t um_before = umask(022);
573
int pipefds[2];
574
EXPECT_OK(pipe(pipefds));
575
EXPECT_OK(cap_enter()); // Enter capability mode.
576
577
mode_t um = umask(022);
578
EXPECT_NE(-ECAPMODE, (int)um);
579
EXPECT_EQ(um_before, um);
580
stack_t ss;
581
EXPECT_OK(sigaltstack(NULL, &ss));
582
583
// Finally, tests for system calls that don't fit the pattern very well.
584
pid_t pid = fork();
585
EXPECT_OK(pid);
586
if (pid == 0) {
587
// Child: wait for an exit message from parent (so we can test waitpid).
588
EXPECT_OK(close(pipefds[0]));
589
SEND_INT_MESSAGE(pipefds[1], MSG_CHILD_STARTED);
590
AWAIT_INT_MESSAGE(pipefds[1], MSG_PARENT_REQUEST_CHILD_EXIT);
591
exit(0);
592
} else if (pid > 0) {
593
EXPECT_OK(close(pipefds[1]));
594
AWAIT_INT_MESSAGE(pipefds[0], MSG_CHILD_STARTED);
595
errno = 0;
596
EXPECT_CAPMODE(ptrace_(PTRACE_PEEKDATA_, pid, &pid, NULL));
597
SEND_INT_MESSAGE(pipefds[0], MSG_PARENT_REQUEST_CHILD_EXIT);
598
if (verbose) fprintf(stderr, " child finished\n");
599
}
600
601
// No error return from sync(2) to test, but check errno remains unset.
602
errno = 0;
603
sync();
604
EXPECT_EQ(0, errno);
605
606
// TODO(FreeBSD): ktrace
607
608
#ifdef HAVE_SYSARCH
609
// sysarch() is, by definition, architecture-dependent
610
#if defined (__amd64__) || defined (__i386__)
611
long sysarch_arg = 0;
612
EXPECT_CAPMODE(sysarch(I386_SET_IOPERM, &sysarch_arg));
613
#else
614
// TOOD(jra): write a test for other architectures, like arm
615
#endif
616
#endif
617
}
618
619
void *thread_fn(void *p) {
620
int fd = (int)(intptr_t)p;
621
if (verbose) fprintf(stderr, " thread waiting to run\n");
622
AWAIT_INT_MESSAGE(fd, MSG_PARENT_CHILD_SHOULD_RUN);
623
EXPECT_OK(getpid_());
624
EXPECT_CAPMODE(open("/dev/null", O_RDWR));
625
// Return whether there have been any failures to the main thread.
626
void *rval = (void *)(intptr_t)testing::Test::HasFailure();
627
if (verbose) fprintf(stderr, " thread finished: %p\n", rval);
628
return rval;
629
}
630
631
// Check that restrictions are the same in subprocesses and threads
632
FORK_TEST(Capmode, NewThread) {
633
// Fire off a new thread before entering capability mode
634
pthread_t early_thread;
635
void *thread_rval;
636
// Create two pipes, one for synchronization with the threads, the other to
637
// synchronize with the children (since we can't use waitpid after cap_enter).
638
// Note: Could use pdfork+pdwait instead, but that is tested in procdesc.cc.
639
int thread_pipe[2];
640
EXPECT_OK(pipe(thread_pipe));
641
int proc_pipe[2];
642
EXPECT_OK(pipe(proc_pipe));
643
EXPECT_OK(pthread_create(&early_thread, NULL, thread_fn,
644
(void *)(intptr_t)thread_pipe[1]));
645
646
// Fire off a new process before entering capability mode.
647
if (verbose) fprintf(stderr, " starting second child (non-capability mode)\n");
648
int early_child = fork();
649
EXPECT_OK(early_child);
650
if (early_child == 0) {
651
if (verbose) fprintf(stderr, " first child started\n");
652
EXPECT_OK(close(proc_pipe[0]));
653
// Child: wait and then confirm this process is unaffected by capability mode in the parent.
654
AWAIT_INT_MESSAGE(proc_pipe[1], MSG_PARENT_CHILD_SHOULD_RUN);
655
int fd = open("/dev/null", O_RDWR);
656
EXPECT_OK(fd);
657
close(fd);
658
// Notify the parent of success/failure.
659
int rval = (int)testing::Test::HasFailure();
660
SEND_INT_MESSAGE(proc_pipe[1], rval);
661
if (verbose) fprintf(stderr, " first child finished: %d\n", rval);
662
exit(rval);
663
}
664
665
EXPECT_OK(cap_enter()); // Enter capability mode.
666
// At this point the current process has both a child process and a
667
// child thread that were created before entering capability mode.
668
// - The child process is unaffected by capability mode.
669
// - The child thread is affected by capability mode.
670
SEND_INT_MESSAGE(proc_pipe[0], MSG_PARENT_CHILD_SHOULD_RUN);
671
672
// Do an allowed syscall.
673
EXPECT_OK(getpid_());
674
// Wait for the first child to exit (should get a zero exit code message).
675
AWAIT_INT_MESSAGE(proc_pipe[0], 0);
676
677
// The child processes/threads return HasFailure(), so we depend on no prior errors.
678
ASSERT_FALSE(testing::Test::HasFailure())
679
<< "Cannot continue test with pre-existing failures.";
680
// Now that we're in capability mode, if we create a second child process
681
// it will be affected by capability mode.
682
if (verbose) fprintf(stderr, " starting second child (in capability mode)\n");
683
int child = fork();
684
EXPECT_OK(child);
685
if (child == 0) {
686
if (verbose) fprintf(stderr, " second child started\n");
687
EXPECT_OK(close(proc_pipe[0]));
688
// Child: do an allowed and a disallowed syscall.
689
EXPECT_OK(getpid_());
690
EXPECT_CAPMODE(open("/dev/null", O_RDWR));
691
// Notify the parent of success/failure.
692
int rval = (int)testing::Test::HasFailure();
693
SEND_INT_MESSAGE(proc_pipe[1], rval);
694
if (verbose) fprintf(stderr, " second child finished: %d\n", rval);
695
exit(rval);
696
}
697
// Now tell the early_started thread that it can run. We expect it to also
698
// be affected by capability mode since it's per-process not per-thread.
699
// Note: it is important that we don't allow the thread to run before fork(),
700
// since that could result in fork() being called while the thread holds one
701
// of the gtest-internal mutexes, so the child process deadlocks.
702
SEND_INT_MESSAGE(thread_pipe[0], MSG_PARENT_CHILD_SHOULD_RUN);
703
// Wait for the early-started thread.
704
EXPECT_OK(pthread_join(early_thread, &thread_rval));
705
EXPECT_FALSE((bool)(intptr_t)thread_rval) << "thread returned failure";
706
707
// Wait for the second child to exit (should get a zero exit code message).
708
AWAIT_INT_MESSAGE(proc_pipe[0], 0);
709
710
// Fire off a new (second) child thread, which is also affected by capability mode.
711
ASSERT_FALSE(testing::Test::HasFailure())
712
<< "Cannot continue test with pre-existing failures.";
713
pthread_t child_thread;
714
EXPECT_OK(pthread_create(&child_thread, NULL, thread_fn,
715
(void *)(intptr_t)thread_pipe[1]));
716
SEND_INT_MESSAGE(thread_pipe[0], MSG_PARENT_CHILD_SHOULD_RUN);
717
EXPECT_OK(pthread_join(child_thread, &thread_rval));
718
EXPECT_FALSE((bool)(intptr_t)thread_rval) << "thread returned failure";
719
720
// Fork a subprocess which fires off a new thread.
721
ASSERT_FALSE(testing::Test::HasFailure())
722
<< "Cannot continue test with pre-existing failures.";
723
if (verbose) fprintf(stderr, " starting third child (in capability mode)\n");
724
child = fork();
725
EXPECT_OK(child);
726
if (child == 0) {
727
if (verbose) fprintf(stderr, " third child started\n");
728
EXPECT_OK(close(proc_pipe[0]));
729
pthread_t child_thread2;
730
EXPECT_OK(pthread_create(&child_thread2, NULL, thread_fn,
731
(void *)(intptr_t)thread_pipe[1]));
732
SEND_INT_MESSAGE(thread_pipe[0], MSG_PARENT_CHILD_SHOULD_RUN);
733
EXPECT_OK(pthread_join(child_thread2, &thread_rval));
734
EXPECT_FALSE((bool)(intptr_t)thread_rval) << "thread returned failure";
735
// Notify the parent of success/failure.
736
int rval = (int)testing::Test::HasFailure();
737
SEND_INT_MESSAGE(proc_pipe[1], rval);
738
if (verbose) fprintf(stderr, " third child finished: %d\n", rval);
739
exit(rval);
740
}
741
// Wait for the third child to exit (should get a zero exit code message).
742
AWAIT_INT_MESSAGE(proc_pipe[0], 0);
743
close(proc_pipe[0]);
744
close(proc_pipe[1]);
745
close(thread_pipe[0]);
746
close(thread_pipe[1]);
747
}
748
749
static volatile sig_atomic_t had_signal = 0;
750
static void handle_signal(int) { had_signal = 1; }
751
752
FORK_TEST(Capmode, SelfKill) {
753
pid_t me = getpid();
754
sighandler_t original = signal(SIGUSR1, handle_signal);
755
756
pid_t child = fork();
757
if (child == 0) {
758
// Child: sleep and exit
759
sleep(1);
760
exit(0);
761
}
762
763
EXPECT_OK(cap_enter()); // Enter capability mode.
764
765
// Can only kill(2) to own pid.
766
EXPECT_CAPMODE(kill(child, SIGUSR1));
767
EXPECT_OK(kill(me, SIGUSR1));
768
EXPECT_EQ(1, had_signal);
769
770
signal(SIGUSR1, original);
771
}
772
773