1 // Test that fcntl works in capability mode.
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <sys/mman.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #include <stdint.h>
12
13 #include <string>
14 #include <map>
15
16 #include "capsicum.h"
17 #include "capsicum-test.h"
18 #include "syscalls.h"
19
20 // Ensure that fcntl() works consistently for both regular file descriptors and
21 // capability-wrapped ones.
FORK_TEST(Fcntl,Basic)22 FORK_TEST(Fcntl, Basic) {
23 cap_rights_t rights;
24 cap_rights_init(&rights, CAP_READ, CAP_FCNTL);
25
26 typedef std::map<std::string, int> FileMap;
27
28 // Open some files of different types, and wrap them in capabilities.
29 FileMap files;
30 files["file"] = open("/etc/passwd", O_RDONLY);
31 EXPECT_OK(files["file"]);
32 files["socket"] = socket(PF_LOCAL, SOCK_STREAM, 0);
33 EXPECT_OK(files["socket"]);
34 char shm_name[128];
35 sprintf(shm_name, "/capsicum-test-%d", getuid());
36 files["SHM"] = shm_open(shm_name, (O_CREAT|O_RDWR), 0600);
37 if ((files["SHM"] == -1) && errno == ENOSYS) {
38 // shm_open() is not implemented in user-mode Linux.
39 files.erase("SHM");
40 } else {
41 EXPECT_OK(files["SHM"]);
42 }
43
44 FileMap caps;
45 for (FileMap::iterator ii = files.begin(); ii != files.end(); ++ii) {
46 std::string key = ii->first + " cap";
47 caps[key] = dup(ii->second);
48 EXPECT_OK(cap_rights_limit(caps[key], &rights));
49 EXPECT_OK(caps[key]) << " on " << ii->first;
50 }
51
52 FileMap all(files);
53 all.insert(files.begin(), files.end());
54
55 EXPECT_OK(cap_enter()); // Enter capability mode.
56
57 // Ensure that we can fcntl() all the files that we opened above.
58 cap_rights_t r_ro;
59 cap_rights_init(&r_ro, CAP_READ);
60 for (FileMap::iterator ii = all.begin(); ii != all.end(); ++ii) {
61 EXPECT_OK(fcntl(ii->second, F_GETFL, 0)) << " on " << ii->first;
62 int cap = dup(ii->second);
63 EXPECT_OK(cap) << " on " << ii->first;
64 EXPECT_OK(cap_rights_limit(cap, &r_ro)) << " on " << ii->first;
65 EXPECT_EQ(-1, fcntl(cap, F_GETFL, 0)) << " on " << ii->first;
66 EXPECT_EQ(ENOTCAPABLE, errno) << " on " << ii->first;
67 close(cap);
68 }
69 for (FileMap::iterator ii = all.begin(); ii != all.end(); ++ii) {
70 close(ii->second);
71 }
72 shm_unlink(shm_name);
73 }
74
75 // Supported fcntl(2) operations:
76 // FreeBSD10 FreeBSD9.1: Linux: Rights: Summary:
77 // F_DUPFD F_DUPFD F_DUPFD NONE as dup(2)
78 // F_DUPFD_CLOEXEC F_DUPFD_CLOEXEC NONE as dup(2) with close-on-exec
79 // F_DUP2FD F_DUP2FD NONE as dup2(2)
80 // F_DUP2FD_CLOEXEC NONE as dup2(2) with close-on-exec
81 // F_GETFD F_GETFD F_GETFD NONE get close-on-exec flag
82 // F_SETFD F_SETFD F_SETFD NONE set close-on-exec flag
83 // * F_GETFL F_GETFL F_GETFL FCNTL get file status flag
84 // * F_SETFL F_SETFL F_SETFL FCNTL set file status flag
85 // * F_GETOWN F_GETOWN F_GETOWN FCNTL get pid receiving SIGIO/SIGURG
86 // * F_SETOWN F_SETOWN F_SETOWN FCNTL set pid receiving SIGIO/SIGURG
87 // * F_GETOWN_EX FCNTL get pid/thread receiving SIGIO/SIGURG
88 // * F_SETOWN_EX FCNTL set pid/thread receiving SIGIO/SIGURG
89 // F_GETLK F_GETLK F_GETLK FLOCK get lock info
90 // F_SETLK F_SETLK F_SETLK FLOCK set lock info
91 // F_SETLK_REMOTE FLOCK set lock info
92 // F_SETLKW F_SETLKW F_SETLKW FLOCK set lock info (blocking)
93 // F_READAHEAD F_READAHEAD NONE set or clear readahead amount
94 // F_RDAHEAD F_RDAHEAD NONE set or clear readahead amount to 128KB
95 // F_GETSIG POLL_EVENT+FSIGNAL get signal sent when I/O possible
96 // F_SETSIG POLL_EVENT+FSIGNAL set signal sent when I/O possible
97 // F_GETLEASE FLOCK+FSIGNAL get lease on file descriptor
98 // F_SETLEASE FLOCK+FSIGNAL set new lease on file descriptor
99 // F_NOTIFY NOTIFY generate signal on changes (dnotify)
100 // F_GETPIPE_SZ GETSOCKOPT get pipe size
101 // F_SETPIPE_SZ SETSOCKOPT set pipe size
102 // F_GET_SEAL FSTAT get memfd seals
103 // F_ADD_SEAL FCHMOD set memfd seal
104 // If HAVE_CAP_FCNTLS_LIMIT is defined, then fcntl(2) operations that require
105 // CAP_FCNTL (marked with * above) can be further limited with cap_fcntls_limit(2).
106 namespace {
107 #define FCNTL_NUM_RIGHTS 9
108 cap_rights_t fcntl_rights[FCNTL_NUM_RIGHTS];
InitRights()109 void InitRights() {
110 cap_rights_init(&(fcntl_rights[0]), 0); // Later code assumes this is at [0]
111 cap_rights_init(&(fcntl_rights[1]), CAP_READ, CAP_WRITE);
112 cap_rights_init(&(fcntl_rights[2]), CAP_FCNTL);
113 cap_rights_init(&(fcntl_rights[3]), CAP_FLOCK);
114 cap_rights_init(&(fcntl_rights[4]), 0);
115 cap_rights_init(&(fcntl_rights[5]), 0);
116 #ifdef CAP_NOTIFY
117 cap_rights_init(&(fcntl_rights[6]), CAP_NOTIFY);
118 #else
119 cap_rights_init(&(fcntl_rights[6]), 0);
120 #endif
121 cap_rights_init(&(fcntl_rights[7]), CAP_SETSOCKOPT);
122 cap_rights_init(&(fcntl_rights[8]), CAP_GETSOCKOPT);
123 }
124
CheckFcntl(unsigned long long right,int caps[FCNTL_NUM_RIGHTS],int cmd,long arg,const char * context)125 int CheckFcntl(unsigned long long right, int caps[FCNTL_NUM_RIGHTS], int cmd, long arg, const char* context) {
126 SCOPED_TRACE(context);
127 cap_rights_t rights;
128 cap_rights_init(&rights, right);
129 int ok_index = -1;
130 for (int ii = 0; ii < FCNTL_NUM_RIGHTS; ++ii) {
131 if (cap_rights_contains(&(fcntl_rights[ii]), &rights)) {
132 if (ok_index == -1) ok_index = ii;
133 continue;
134 }
135 EXPECT_NOTCAPABLE(fcntl(caps[ii], cmd, arg));
136 }
137 EXPECT_NE(-1, ok_index);
138 int rc = fcntl(caps[ok_index], cmd, arg);
139 EXPECT_OK(rc);
140 return rc;
141 }
142 } // namespace
143
144 #define CHECK_FCNTL(right, caps, cmd, arg) \
145 CheckFcntl(right, caps, cmd, arg, "fcntl(" #cmd ") expect " #right)
146
TEST(Fcntl,Commands)147 TEST(Fcntl, Commands) {
148 InitRights();
149 int fd = open(TmpFile("cap_fcntl_cmds"), O_RDWR|O_CREAT, 0644);
150 EXPECT_OK(fd);
151 write(fd, "TEST", 4);
152 int sock = socket(PF_LOCAL, SOCK_STREAM, 0);
153 EXPECT_OK(sock);
154 int caps[FCNTL_NUM_RIGHTS];
155 int sock_caps[FCNTL_NUM_RIGHTS];
156 for (int ii = 0; ii < FCNTL_NUM_RIGHTS; ++ii) {
157 caps[ii] = dup(fd);
158 EXPECT_OK(caps[ii]);
159 EXPECT_OK(cap_rights_limit(caps[ii], &(fcntl_rights[ii])));
160 sock_caps[ii] = dup(sock);
161 EXPECT_OK(sock_caps[ii]);
162 EXPECT_OK(cap_rights_limit(sock_caps[ii], &(fcntl_rights[ii])));
163 }
164
165 // Check the things that need no rights against caps[0].
166 int newfd = fcntl(caps[0], F_DUPFD, 0);
167 EXPECT_OK(newfd);
168 // dup()'ed FD should have same rights.
169 cap_rights_t rights;
170 cap_rights_init(&rights, 0);
171 EXPECT_OK(cap_rights_get(newfd, &rights));
172 EXPECT_RIGHTS_EQ(&(fcntl_rights[0]), &rights);
173 close(newfd);
174 EXPECT_OK(fcntl(caps[0], F_DUP2FD, newfd));
175 // dup2()'ed FD should have same rights.
176 EXPECT_OK(cap_rights_get(newfd, &rights));
177 EXPECT_RIGHTS_EQ(&(fcntl_rights[0]), &rights);
178 close(newfd);
179
180 EXPECT_OK(fcntl(caps[0], F_GETFD, 0));
181 EXPECT_OK(fcntl(caps[0], F_SETFD, 0));
182
183 // Check operations that need CAP_FCNTL.
184 int fd_flag = CHECK_FCNTL(CAP_FCNTL, caps, F_GETFL, 0);
185 EXPECT_EQ(0, CHECK_FCNTL(CAP_FCNTL, caps, F_SETFL, fd_flag));
186 int owner = CHECK_FCNTL(CAP_FCNTL, sock_caps, F_GETOWN, 0);
187 EXPECT_EQ(0, CHECK_FCNTL(CAP_FCNTL, sock_caps, F_SETOWN, owner));
188
189 // Check an operation needing CAP_FLOCK.
190 struct flock fl;
191 memset(&fl, 0, sizeof(fl));
192 fl.l_type = F_RDLCK;
193 fl.l_whence = SEEK_SET;
194 fl.l_start = 0;
195 fl.l_len = 1;
196 EXPECT_EQ(0, CHECK_FCNTL(CAP_FLOCK, caps, F_GETLK, (long)&fl));
197
198 for (int ii = 0; ii < FCNTL_NUM_RIGHTS; ++ii) {
199 close(sock_caps[ii]);
200 close(caps[ii]);
201 }
202 close(sock);
203 close(fd);
204 unlink(TmpFile("cap_fcntl_cmds"));
205 }
206
TEST(Fcntl,WriteLock)207 TEST(Fcntl, WriteLock) {
208 int fd = open(TmpFile("cap_fcntl_readlock"), O_RDWR|O_CREAT, 0644);
209 EXPECT_OK(fd);
210 write(fd, "TEST", 4);
211
212 int cap = dup(fd);
213 cap_rights_t rights;
214 cap_rights_init(&rights, CAP_FCNTL, CAP_READ, CAP_WRITE, CAP_FLOCK);
215 EXPECT_OK(cap_rights_limit(cap, &rights));
216
217 struct flock fl;
218 memset(&fl, 0, sizeof(fl));
219 fl.l_type = F_WRLCK;
220 fl.l_whence = SEEK_SET;
221 fl.l_start = 0;
222 fl.l_len = 1;
223 // Write-Lock
224 EXPECT_OK(fcntl(cap, F_SETLK, (long)&fl));
225
226 // Check write-locked (from another process).
227 pid_t child = fork();
228 if (child == 0) {
229 fl.l_type = F_WRLCK;
230 fl.l_whence = SEEK_SET;
231 fl.l_start = 0;
232 fl.l_len = 1;
233 EXPECT_OK(fcntl(fd, F_GETLK, (long)&fl));
234 EXPECT_NE(F_UNLCK, fl.l_type);
235 exit(HasFailure());
236 }
237 int status;
238 EXPECT_EQ(child, waitpid(child, &status, 0));
239 int rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
240 EXPECT_EQ(0, rc);
241
242 // Unlock
243 fl.l_type = F_UNLCK;
244 fl.l_whence = SEEK_SET;
245 fl.l_start = 0;
246 fl.l_len = 1;
247 EXPECT_OK(fcntl(cap, F_SETLK, (long)&fl));
248
249 close(cap);
250 close(fd);
251 unlink(TmpFile("cap_fcntl_readlock"));
252 }
253
TEST(Fcntl,SubRightNormalFD)254 TEST(Fcntl, SubRightNormalFD) {
255 int fd = open(TmpFile("cap_fcntl_subrightnorm"), O_RDWR|O_CREAT, 0644);
256 EXPECT_OK(fd);
257
258 // Restrict the fcntl(2) subrights of a normal FD.
259 EXPECT_OK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL));
260 int fd_flag = fcntl(fd, F_GETFL, 0);
261 EXPECT_OK(fd_flag);
262 EXPECT_NOTCAPABLE(fcntl(fd, F_SETFL, fd_flag));
263
264 // Expect to have all capabilities.
265 cap_rights_t rights;
266 EXPECT_OK(cap_rights_get(fd, &rights));
267 cap_rights_t all;
268 CAP_ALL(&all);
269 EXPECT_RIGHTS_EQ(&all, &rights);
270 cap_fcntl_t fcntls;
271 EXPECT_OK(cap_fcntls_get(fd, &fcntls));
272 EXPECT_EQ((cap_fcntl_t)CAP_FCNTL_GETFL, fcntls);
273
274 // Can't widen the subrights.
275 EXPECT_NOTCAPABLE(cap_fcntls_limit(fd, CAP_FCNTL_GETFL|CAP_FCNTL_SETFL));
276
277 close(fd);
278 unlink(TmpFile("cap_fcntl_subrightnorm"));
279 }
280
TEST(Fcntl,PreserveSubRights)281 TEST(Fcntl, PreserveSubRights) {
282 int fd = open(TmpFile("cap_fcntl_subrightpreserve"), O_RDWR|O_CREAT, 0644);
283 EXPECT_OK(fd);
284
285 cap_rights_t rights;
286 cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_FCNTL);
287 EXPECT_OK(cap_rights_limit(fd, &rights));
288 EXPECT_OK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL));
289
290 cap_rights_t cur_rights;
291 cap_fcntl_t fcntls;
292 EXPECT_OK(cap_rights_get(fd, &cur_rights));
293 EXPECT_RIGHTS_EQ(&rights, &cur_rights);
294 EXPECT_OK(cap_fcntls_get(fd, &fcntls));
295 EXPECT_EQ((cap_fcntl_t)CAP_FCNTL_GETFL, fcntls);
296
297 // Limiting the top-level rights leaves the subrights unaffected...
298 cap_rights_clear(&rights, CAP_READ);
299 EXPECT_OK(cap_rights_limit(fd, &rights));
300 EXPECT_OK(cap_fcntls_get(fd, &fcntls));
301 EXPECT_EQ((cap_fcntl_t)CAP_FCNTL_GETFL, fcntls);
302
303 // ... until we remove CAP_FCNTL.
304 cap_rights_clear(&rights, CAP_FCNTL);
305 EXPECT_OK(cap_rights_limit(fd, &rights));
306 EXPECT_OK(cap_fcntls_get(fd, &fcntls));
307 EXPECT_EQ((cap_fcntl_t)0, fcntls);
308 EXPECT_EQ(-1, cap_fcntls_limit(fd, CAP_FCNTL_GETFL));
309
310 close(fd);
311 unlink(TmpFile("cap_fcntl_subrightpreserve"));
312 }
313
TEST(Fcntl,FLSubRights)314 TEST(Fcntl, FLSubRights) {
315 int fd = open(TmpFile("cap_fcntl_subrights"), O_RDWR|O_CREAT, 0644);
316 EXPECT_OK(fd);
317 write(fd, "TEST", 4);
318 cap_rights_t rights;
319 cap_rights_init(&rights, CAP_FCNTL);
320 EXPECT_OK(cap_rights_limit(fd, &rights));
321
322 // Check operations that need CAP_FCNTL with subrights pristine => OK.
323 int fd_flag = fcntl(fd, F_GETFL, 0);
324 EXPECT_OK(fd_flag);
325 EXPECT_OK(fcntl(fd, F_SETFL, fd_flag));
326
327 // Check operations that need CAP_FCNTL with all subrights => OK.
328 EXPECT_OK(cap_fcntls_limit(fd, CAP_FCNTL_ALL));
329 fd_flag = fcntl(fd, F_GETFL, 0);
330 EXPECT_OK(fd_flag);
331 EXPECT_OK(fcntl(fd, F_SETFL, fd_flag));
332
333 // Check operations that need CAP_FCNTL with specific subrights.
334 int fd_get = dup(fd);
335 int fd_set = dup(fd);
336 EXPECT_OK(cap_fcntls_limit(fd_get, CAP_FCNTL_GETFL));
337 EXPECT_OK(cap_fcntls_limit(fd_set, CAP_FCNTL_SETFL));
338
339 fd_flag = fcntl(fd_get, F_GETFL, 0);
340 EXPECT_OK(fd_flag);
341 EXPECT_NOTCAPABLE(fcntl(fd_set, F_GETFL, 0));
342 EXPECT_OK(fcntl(fd_set, F_SETFL, fd_flag));
343 EXPECT_NOTCAPABLE(fcntl(fd_get, F_SETFL, fd_flag));
344 close(fd_get);
345 close(fd_set);
346
347 // Check operations that need CAP_FCNTL with no subrights => ENOTCAPABLE.
348 EXPECT_OK(cap_fcntls_limit(fd, 0));
349 EXPECT_NOTCAPABLE(fcntl(fd, F_GETFL, 0));
350 EXPECT_NOTCAPABLE(fcntl(fd, F_SETFL, fd_flag));
351
352 close(fd);
353 unlink(TmpFile("cap_fcntl_subrights"));
354 }
355
TEST(Fcntl,OWNSubRights)356 TEST(Fcntl, OWNSubRights) {
357 int sock = socket(PF_LOCAL, SOCK_STREAM, 0);
358 EXPECT_OK(sock);
359 cap_rights_t rights;
360 cap_rights_init(&rights, CAP_FCNTL);
361 EXPECT_OK(cap_rights_limit(sock, &rights));
362
363 // Check operations that need CAP_FCNTL with no subrights => OK.
364 int owner = fcntl(sock, F_GETOWN, 0);
365 EXPECT_OK(owner);
366 EXPECT_OK(fcntl(sock, F_SETOWN, owner));
367
368 // Check operations that need CAP_FCNTL with all subrights => OK.
369 EXPECT_OK(cap_fcntls_limit(sock, CAP_FCNTL_ALL));
370 owner = fcntl(sock, F_GETOWN, 0);
371 EXPECT_OK(owner);
372 EXPECT_OK(fcntl(sock, F_SETOWN, owner));
373
374 // Check operations that need CAP_FCNTL with specific subrights.
375 int sock_get = dup(sock);
376 int sock_set = dup(sock);
377 EXPECT_OK(cap_fcntls_limit(sock_get, CAP_FCNTL_GETOWN));
378 EXPECT_OK(cap_fcntls_limit(sock_set, CAP_FCNTL_SETOWN));
379 owner = fcntl(sock_get, F_GETOWN, 0);
380 EXPECT_OK(owner);
381 EXPECT_NOTCAPABLE(fcntl(sock_set, F_GETOWN, 0));
382 EXPECT_OK(fcntl(sock_set, F_SETOWN, owner));
383 EXPECT_NOTCAPABLE(fcntl(sock_get, F_SETOWN, owner));
384 // Also check we can retrieve the subrights.
385 cap_fcntl_t fcntls;
386 EXPECT_OK(cap_fcntls_get(sock_get, &fcntls));
387 EXPECT_EQ((cap_fcntl_t)CAP_FCNTL_GETOWN, fcntls);
388 EXPECT_OK(cap_fcntls_get(sock_set, &fcntls));
389 EXPECT_EQ((cap_fcntl_t)CAP_FCNTL_SETOWN, fcntls);
390 // And that we can't widen the subrights.
391 EXPECT_NOTCAPABLE(cap_fcntls_limit(sock_get, CAP_FCNTL_GETOWN|CAP_FCNTL_SETOWN));
392 EXPECT_NOTCAPABLE(cap_fcntls_limit(sock_set, CAP_FCNTL_GETOWN|CAP_FCNTL_SETOWN));
393 close(sock_get);
394 close(sock_set);
395
396 // Check operations that need CAP_FCNTL with no subrights => ENOTCAPABLE.
397 EXPECT_OK(cap_fcntls_limit(sock, 0));
398 EXPECT_NOTCAPABLE(fcntl(sock, F_GETOWN, 0));
399 EXPECT_NOTCAPABLE(fcntl(sock, F_SETOWN, owner));
400
401 close(sock);
402 }
403