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 #ifdef CAP_FSIGNAL
115 cap_rights_init(&(fcntl_rights[4]), CAP_EVENT, CAP_FSIGNAL);
116 cap_rights_init(&(fcntl_rights[5]), CAP_FLOCK, CAP_FSIGNAL);
117 #else
118 cap_rights_init(&(fcntl_rights[4]), 0);
119 cap_rights_init(&(fcntl_rights[5]), 0);
120 #endif
121 #ifdef CAP_NOTIFY
122 cap_rights_init(&(fcntl_rights[6]), CAP_NOTIFY);
123 #else
124 cap_rights_init(&(fcntl_rights[6]), 0);
125 #endif
126 cap_rights_init(&(fcntl_rights[7]), CAP_SETSOCKOPT);
127 cap_rights_init(&(fcntl_rights[8]), CAP_GETSOCKOPT);
128 }
129
CheckFcntl(unsigned long long right,int caps[FCNTL_NUM_RIGHTS],int cmd,long arg,const char * context)130 int CheckFcntl(unsigned long long right, int caps[FCNTL_NUM_RIGHTS], int cmd, long arg, const char* context) {
131 SCOPED_TRACE(context);
132 cap_rights_t rights;
133 cap_rights_init(&rights, right);
134 int ok_index = -1;
135 for (int ii = 0; ii < FCNTL_NUM_RIGHTS; ++ii) {
136 if (cap_rights_contains(&(fcntl_rights[ii]), &rights)) {
137 if (ok_index == -1) ok_index = ii;
138 continue;
139 }
140 EXPECT_NOTCAPABLE(fcntl(caps[ii], cmd, arg));
141 }
142 EXPECT_NE(-1, ok_index);
143 int rc = fcntl(caps[ok_index], cmd, arg);
144 EXPECT_OK(rc);
145 return rc;
146 }
147 } // namespace
148
149 #define CHECK_FCNTL(right, caps, cmd, arg) \
150 CheckFcntl(right, caps, cmd, arg, "fcntl(" #cmd ") expect " #right)
151
TEST(Fcntl,Commands)152 TEST(Fcntl, Commands) {
153 InitRights();
154 int fd = open(TmpFile("cap_fcntl_cmds"), O_RDWR|O_CREAT, 0644);
155 EXPECT_OK(fd);
156 write(fd, "TEST", 4);
157 int sock = socket(PF_LOCAL, SOCK_STREAM, 0);
158 EXPECT_OK(sock);
159 int caps[FCNTL_NUM_RIGHTS];
160 int sock_caps[FCNTL_NUM_RIGHTS];
161 for (int ii = 0; ii < FCNTL_NUM_RIGHTS; ++ii) {
162 caps[ii] = dup(fd);
163 EXPECT_OK(caps[ii]);
164 EXPECT_OK(cap_rights_limit(caps[ii], &(fcntl_rights[ii])));
165 sock_caps[ii] = dup(sock);
166 EXPECT_OK(sock_caps[ii]);
167 EXPECT_OK(cap_rights_limit(sock_caps[ii], &(fcntl_rights[ii])));
168 }
169
170 // Check the things that need no rights against caps[0].
171 int newfd = fcntl(caps[0], F_DUPFD, 0);
172 EXPECT_OK(newfd);
173 // dup()'ed FD should have same rights.
174 cap_rights_t rights;
175 cap_rights_init(&rights, 0);
176 EXPECT_OK(cap_rights_get(newfd, &rights));
177 EXPECT_RIGHTS_EQ(&(fcntl_rights[0]), &rights);
178 close(newfd);
179 #ifdef HAVE_F_DUP2FD
180 EXPECT_OK(fcntl(caps[0], F_DUP2FD, newfd));
181 // dup2()'ed FD should have same rights.
182 EXPECT_OK(cap_rights_get(newfd, &rights));
183 EXPECT_RIGHTS_EQ(&(fcntl_rights[0]), &rights);
184 close(newfd);
185 #endif
186
187 EXPECT_OK(fcntl(caps[0], F_GETFD, 0));
188 EXPECT_OK(fcntl(caps[0], F_SETFD, 0));
189
190 // Check operations that need CAP_FCNTL.
191 int fd_flag = CHECK_FCNTL(CAP_FCNTL, caps, F_GETFL, 0);
192 EXPECT_EQ(0, CHECK_FCNTL(CAP_FCNTL, caps, F_SETFL, fd_flag));
193 int owner = CHECK_FCNTL(CAP_FCNTL, sock_caps, F_GETOWN, 0);
194 EXPECT_EQ(0, CHECK_FCNTL(CAP_FCNTL, sock_caps, F_SETOWN, owner));
195
196 // Check an operation needing CAP_FLOCK.
197 struct flock fl;
198 memset(&fl, 0, sizeof(fl));
199 fl.l_type = F_RDLCK;
200 fl.l_whence = SEEK_SET;
201 fl.l_start = 0;
202 fl.l_len = 1;
203 EXPECT_EQ(0, CHECK_FCNTL(CAP_FLOCK, caps, F_GETLK, (long)&fl));
204
205 for (int ii = 0; ii < FCNTL_NUM_RIGHTS; ++ii) {
206 close(sock_caps[ii]);
207 close(caps[ii]);
208 }
209 close(sock);
210 close(fd);
211 unlink(TmpFile("cap_fcntl_cmds"));
212 }
213
TEST(Fcntl,WriteLock)214 TEST(Fcntl, WriteLock) {
215 int fd = open(TmpFile("cap_fcntl_readlock"), O_RDWR|O_CREAT, 0644);
216 EXPECT_OK(fd);
217 write(fd, "TEST", 4);
218
219 int cap = dup(fd);
220 cap_rights_t rights;
221 cap_rights_init(&rights, CAP_FCNTL, CAP_READ, CAP_WRITE, CAP_FLOCK);
222 EXPECT_OK(cap_rights_limit(cap, &rights));
223
224 struct flock fl;
225 memset(&fl, 0, sizeof(fl));
226 fl.l_type = F_WRLCK;
227 fl.l_whence = SEEK_SET;
228 fl.l_start = 0;
229 fl.l_len = 1;
230 // Write-Lock
231 EXPECT_OK(fcntl(cap, F_SETLK, (long)&fl));
232
233 // Check write-locked (from another process).
234 pid_t child = fork();
235 if (child == 0) {
236 fl.l_type = F_WRLCK;
237 fl.l_whence = SEEK_SET;
238 fl.l_start = 0;
239 fl.l_len = 1;
240 EXPECT_OK(fcntl(fd, F_GETLK, (long)&fl));
241 EXPECT_NE(F_UNLCK, fl.l_type);
242 exit(HasFailure());
243 }
244 int status;
245 EXPECT_EQ(child, waitpid(child, &status, 0));
246 int rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
247 EXPECT_EQ(0, rc);
248
249 // Unlock
250 fl.l_type = F_UNLCK;
251 fl.l_whence = SEEK_SET;
252 fl.l_start = 0;
253 fl.l_len = 1;
254 EXPECT_OK(fcntl(cap, F_SETLK, (long)&fl));
255
256 close(cap);
257 close(fd);
258 unlink(TmpFile("cap_fcntl_readlock"));
259 }
260
261 #ifdef HAVE_CAP_FCNTLS_LIMIT
TEST(Fcntl,SubRightNormalFD)262 TEST(Fcntl, SubRightNormalFD) {
263 int fd = open(TmpFile("cap_fcntl_subrightnorm"), O_RDWR|O_CREAT, 0644);
264 EXPECT_OK(fd);
265
266 // Restrict the fcntl(2) subrights of a normal FD.
267 EXPECT_OK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL));
268 int fd_flag = fcntl(fd, F_GETFL, 0);
269 EXPECT_OK(fd_flag);
270 EXPECT_NOTCAPABLE(fcntl(fd, F_SETFL, fd_flag));
271
272 // Expect to have all capabilities.
273 cap_rights_t rights;
274 EXPECT_OK(cap_rights_get(fd, &rights));
275 cap_rights_t all;
276 CAP_SET_ALL(&all);
277 EXPECT_RIGHTS_EQ(&all, &rights);
278 cap_fcntl_t fcntls;
279 EXPECT_OK(cap_fcntls_get(fd, &fcntls));
280 EXPECT_EQ((cap_fcntl_t)CAP_FCNTL_GETFL, fcntls);
281
282 // Can't widen the subrights.
283 EXPECT_NOTCAPABLE(cap_fcntls_limit(fd, CAP_FCNTL_GETFL|CAP_FCNTL_SETFL));
284
285 close(fd);
286 unlink(TmpFile("cap_fcntl_subrightnorm"));
287 }
288
TEST(Fcntl,PreserveSubRights)289 TEST(Fcntl, PreserveSubRights) {
290 int fd = open(TmpFile("cap_fcntl_subrightpreserve"), O_RDWR|O_CREAT, 0644);
291 EXPECT_OK(fd);
292
293 cap_rights_t rights;
294 cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_FCNTL);
295 EXPECT_OK(cap_rights_limit(fd, &rights));
296 EXPECT_OK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL));
297
298 cap_rights_t cur_rights;
299 cap_fcntl_t fcntls;
300 EXPECT_OK(cap_rights_get(fd, &cur_rights));
301 EXPECT_RIGHTS_EQ(&rights, &cur_rights);
302 EXPECT_OK(cap_fcntls_get(fd, &fcntls));
303 EXPECT_EQ((cap_fcntl_t)CAP_FCNTL_GETFL, fcntls);
304
305 // Limiting the top-level rights leaves the subrights unaffected...
306 cap_rights_clear(&rights, CAP_READ);
307 EXPECT_OK(cap_rights_limit(fd, &rights));
308 EXPECT_OK(cap_fcntls_get(fd, &fcntls));
309 EXPECT_EQ((cap_fcntl_t)CAP_FCNTL_GETFL, fcntls);
310
311 // ... until we remove CAP_FCNTL.
312 cap_rights_clear(&rights, CAP_FCNTL);
313 EXPECT_OK(cap_rights_limit(fd, &rights));
314 EXPECT_OK(cap_fcntls_get(fd, &fcntls));
315 EXPECT_EQ((cap_fcntl_t)0, fcntls);
316 EXPECT_EQ(-1, cap_fcntls_limit(fd, CAP_FCNTL_GETFL));
317
318 close(fd);
319 unlink(TmpFile("cap_fcntl_subrightpreserve"));
320 }
321
TEST(Fcntl,FLSubRights)322 TEST(Fcntl, FLSubRights) {
323 int fd = open(TmpFile("cap_fcntl_subrights"), O_RDWR|O_CREAT, 0644);
324 EXPECT_OK(fd);
325 write(fd, "TEST", 4);
326 cap_rights_t rights;
327 cap_rights_init(&rights, CAP_FCNTL);
328 EXPECT_OK(cap_rights_limit(fd, &rights));
329
330 // Check operations that need CAP_FCNTL with subrights pristine => OK.
331 int fd_flag = fcntl(fd, F_GETFL, 0);
332 EXPECT_OK(fd_flag);
333 EXPECT_OK(fcntl(fd, F_SETFL, fd_flag));
334
335 // Check operations that need CAP_FCNTL with all subrights => OK.
336 EXPECT_OK(cap_fcntls_limit(fd, CAP_FCNTL_ALL));
337 fd_flag = fcntl(fd, F_GETFL, 0);
338 EXPECT_OK(fd_flag);
339 EXPECT_OK(fcntl(fd, F_SETFL, fd_flag));
340
341 // Check operations that need CAP_FCNTL with specific subrights.
342 int fd_get = dup(fd);
343 int fd_set = dup(fd);
344 EXPECT_OK(cap_fcntls_limit(fd_get, CAP_FCNTL_GETFL));
345 EXPECT_OK(cap_fcntls_limit(fd_set, CAP_FCNTL_SETFL));
346
347 fd_flag = fcntl(fd_get, F_GETFL, 0);
348 EXPECT_OK(fd_flag);
349 EXPECT_NOTCAPABLE(fcntl(fd_set, F_GETFL, 0));
350 EXPECT_OK(fcntl(fd_set, F_SETFL, fd_flag));
351 EXPECT_NOTCAPABLE(fcntl(fd_get, F_SETFL, fd_flag));
352 close(fd_get);
353 close(fd_set);
354
355 // Check operations that need CAP_FCNTL with no subrights => ENOTCAPABLE.
356 EXPECT_OK(cap_fcntls_limit(fd, 0));
357 EXPECT_NOTCAPABLE(fcntl(fd, F_GETFL, 0));
358 EXPECT_NOTCAPABLE(fcntl(fd, F_SETFL, fd_flag));
359
360 close(fd);
361 unlink(TmpFile("cap_fcntl_subrights"));
362 }
363
TEST(Fcntl,OWNSubRights)364 TEST(Fcntl, OWNSubRights) {
365 int sock = socket(PF_LOCAL, SOCK_STREAM, 0);
366 EXPECT_OK(sock);
367 cap_rights_t rights;
368 cap_rights_init(&rights, CAP_FCNTL);
369 EXPECT_OK(cap_rights_limit(sock, &rights));
370
371 // Check operations that need CAP_FCNTL with no subrights => OK.
372 int owner = fcntl(sock, F_GETOWN, 0);
373 EXPECT_OK(owner);
374 EXPECT_OK(fcntl(sock, F_SETOWN, owner));
375
376 // Check operations that need CAP_FCNTL with all subrights => OK.
377 EXPECT_OK(cap_fcntls_limit(sock, CAP_FCNTL_ALL));
378 owner = fcntl(sock, F_GETOWN, 0);
379 EXPECT_OK(owner);
380 EXPECT_OK(fcntl(sock, F_SETOWN, owner));
381
382 // Check operations that need CAP_FCNTL with specific subrights.
383 int sock_get = dup(sock);
384 int sock_set = dup(sock);
385 EXPECT_OK(cap_fcntls_limit(sock_get, CAP_FCNTL_GETOWN));
386 EXPECT_OK(cap_fcntls_limit(sock_set, CAP_FCNTL_SETOWN));
387 owner = fcntl(sock_get, F_GETOWN, 0);
388 EXPECT_OK(owner);
389 EXPECT_NOTCAPABLE(fcntl(sock_set, F_GETOWN, 0));
390 EXPECT_OK(fcntl(sock_set, F_SETOWN, owner));
391 EXPECT_NOTCAPABLE(fcntl(sock_get, F_SETOWN, owner));
392 // Also check we can retrieve the subrights.
393 cap_fcntl_t fcntls;
394 EXPECT_OK(cap_fcntls_get(sock_get, &fcntls));
395 EXPECT_EQ((cap_fcntl_t)CAP_FCNTL_GETOWN, fcntls);
396 EXPECT_OK(cap_fcntls_get(sock_set, &fcntls));
397 EXPECT_EQ((cap_fcntl_t)CAP_FCNTL_SETOWN, fcntls);
398 // And that we can't widen the subrights.
399 EXPECT_NOTCAPABLE(cap_fcntls_limit(sock_get, CAP_FCNTL_GETOWN|CAP_FCNTL_SETOWN));
400 EXPECT_NOTCAPABLE(cap_fcntls_limit(sock_set, CAP_FCNTL_GETOWN|CAP_FCNTL_SETOWN));
401 close(sock_get);
402 close(sock_set);
403
404 // Check operations that need CAP_FCNTL with no subrights => ENOTCAPABLE.
405 EXPECT_OK(cap_fcntls_limit(sock, 0));
406 EXPECT_NOTCAPABLE(fcntl(sock, F_GETOWN, 0));
407 EXPECT_NOTCAPABLE(fcntl(sock, F_SETOWN, owner));
408
409 close(sock);
410 }
411 #endif
412