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. 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]; 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 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 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 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 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 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 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 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