gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/fcntl.cc (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <fcntl.h> 16 #include <signal.h> 17 #include <sys/epoll.h> 18 #include <sys/mman.h> 19 #include <sys/signalfd.h> 20 #include <sys/types.h> 21 #include <syscall.h> 22 #include <unistd.h> 23 24 #include <atomic> 25 #include <cerrno> 26 #include <deque> 27 #include <iostream> 28 #include <list> 29 #include <string> 30 #include <vector> 31 32 #include "gmock/gmock.h" 33 #include "gtest/gtest.h" 34 #include "absl/base/macros.h" 35 #include "absl/base/port.h" 36 #include "absl/flags/flag.h" 37 #include "absl/memory/memory.h" 38 #include "absl/strings/str_cat.h" 39 #include "absl/time/clock.h" 40 #include "absl/time/time.h" 41 #include "test/util/capability_util.h" 42 #include "test/util/cleanup.h" 43 #include "test/util/eventfd_util.h" 44 #include "test/util/file_descriptor.h" 45 #include "test/util/fs_util.h" 46 #include "test/util/memory_util.h" 47 #include "test/util/multiprocess_util.h" 48 #include "test/util/posix_error.h" 49 #include "test/util/save_util.h" 50 #include "test/util/signal_util.h" 51 #include "test/util/socket_util.h" 52 #include "test/util/temp_path.h" 53 #include "test/util/test_util.h" 54 #include "test/util/thread_util.h" 55 #include "test/util/timer_util.h" 56 57 ABSL_FLAG(std::string, child_set_lock_on, "", 58 "Contains the path to try to set a file lock on."); 59 ABSL_FLAG(bool, child_set_lock_write, false, 60 "Whether to set a writable lock (otherwise readable)"); 61 ABSL_FLAG(bool, blocking, false, 62 "Whether to set a blocking lock (otherwise non-blocking)."); 63 ABSL_FLAG(bool, retry_eintr, false, 64 "Whether to retry in the subprocess on EINTR."); 65 ABSL_FLAG(uint64_t, child_set_lock_start, 0, "The value of struct flock start"); 66 ABSL_FLAG(uint64_t, child_set_lock_len, 0, "The value of struct flock len"); 67 ABSL_FLAG(int32_t, socket_fd, -1, 68 "A socket to use for communicating more state back " 69 "to the parent."); 70 71 namespace gvisor { 72 namespace testing { 73 74 std::function<void(int, siginfo_t*, void*)> setsig_signal_handle; 75 void setsig_signal_handler(int signum, siginfo_t* siginfo, void* ucontext) { 76 setsig_signal_handle(signum, siginfo, ucontext); 77 } 78 79 class FcntlLockTest : public ::testing::Test { 80 public: 81 void SetUp() override { 82 // Let's make a socket pair. 83 ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, 0, fds_), SyscallSucceeds()); 84 } 85 86 void TearDown() override { 87 EXPECT_THAT(close(fds_[0]), SyscallSucceeds()); 88 EXPECT_THAT(close(fds_[1]), SyscallSucceeds()); 89 } 90 91 int64_t GetSubprocessFcntlTimeInUsec() { 92 int64_t ret = 0; 93 EXPECT_THAT(ReadFd(fds_[0], reinterpret_cast<void*>(&ret), sizeof(ret)), 94 SyscallSucceedsWithValue(sizeof(ret))); 95 return ret; 96 } 97 98 // The first fd will remain with the process creating the subprocess 99 // and the second will go to the subprocess. 100 int fds_[2] = {}; 101 }; 102 103 struct SignalDelivery { 104 int num; 105 siginfo_t info; 106 }; 107 108 class FcntlSignalTest : public ::testing::Test { 109 public: 110 void SetUp() override { 111 int pipe_fds[2]; 112 ASSERT_THAT(pipe2(pipe_fds, O_NONBLOCK), SyscallSucceeds()); 113 pipe_read_fd_ = pipe_fds[0]; 114 pipe_write_fd_ = pipe_fds[1]; 115 } 116 117 PosixErrorOr<Cleanup> RegisterSignalHandler(int signum) { 118 struct sigaction handler; 119 handler.sa_sigaction = setsig_signal_handler; 120 setsig_signal_handle = [&](int signum, siginfo_t* siginfo, 121 void* unused_ucontext) { 122 SignalDelivery sig; 123 sig.num = signum; 124 sig.info = *siginfo; 125 signals_received_.push_back(sig); 126 num_signals_received_++; 127 }; 128 sigemptyset(&handler.sa_mask); 129 handler.sa_flags = SA_SIGINFO; 130 return ScopedSigaction(signum, handler); 131 } 132 133 void FlushAndCloseFD(int fd) { 134 char buf; 135 int read_bytes; 136 do { 137 read_bytes = read(fd, &buf, 1); 138 } while (read_bytes > 0); 139 // read() can also fail with EWOULDBLOCK since the pipe is open in 140 // non-blocking mode. This is not an error. 141 EXPECT_TRUE(read_bytes == 0 || (read_bytes == -1 && errno == EWOULDBLOCK)); 142 EXPECT_THAT(close(fd), SyscallSucceeds()); 143 } 144 145 void DupReadFD() { 146 ASSERT_THAT(pipe_read_fd_dup_ = dup(pipe_read_fd_), SyscallSucceeds()); 147 max_expected_signals++; 148 } 149 150 void RegisterFD(int fd, int signum) { 151 ASSERT_THAT(fcntl(fd, F_SETOWN, getpid()), SyscallSucceeds()); 152 ASSERT_THAT(fcntl(fd, F_SETSIG, signum), SyscallSucceeds()); 153 int old_flags; 154 ASSERT_THAT(old_flags = fcntl(fd, F_GETFL), SyscallSucceeds()); 155 ASSERT_THAT(fcntl(fd, F_SETFL, old_flags | O_ASYNC), SyscallSucceeds()); 156 } 157 158 void GenerateIOEvent() { 159 ASSERT_THAT(write(pipe_write_fd_, "test", 4), SyscallSucceedsWithValue(4)); 160 } 161 162 void WaitForSignalDelivery(absl::Duration timeout) { 163 absl::Time wait_start = absl::Now(); 164 while (num_signals_received_ < max_expected_signals && 165 absl::Now() - wait_start < timeout) { 166 absl::SleepFor(absl::Milliseconds(10)); 167 } 168 } 169 170 int pipe_read_fd_ = -1; 171 int pipe_read_fd_dup_ = -1; 172 int pipe_write_fd_ = -1; 173 int max_expected_signals = 1; 174 std::deque<SignalDelivery> signals_received_; 175 std::atomic<int> num_signals_received_ = 0; 176 }; 177 178 namespace { 179 180 PosixErrorOr<Cleanup> SubprocessLock(std::string const& path, bool for_write, 181 bool blocking, bool retry_eintr, 182 int* socket_pair, off_t start, 183 off_t length, pid_t* child) { 184 std::vector<std::string> args = { 185 "/proc/self/exe", 186 "--child_set_lock_on", 187 path, 188 "--child_set_lock_start", 189 absl::StrCat(start), 190 "--child_set_lock_len", 191 absl::StrCat(length), 192 "--socket_fd", 193 absl::StrCat(socket_pair ? socket_pair[1] : -1)}; 194 195 if (for_write) { 196 args.push_back("--child_set_lock_write"); 197 } 198 199 if (blocking) { 200 args.push_back("--blocking"); 201 } 202 203 if (retry_eintr) { 204 args.push_back("--retry_eintr"); 205 } 206 207 int execve_errno = 0; 208 ASSIGN_OR_RETURN_ERRNO( 209 auto cleanup, 210 ForkAndExec("/proc/self/exe", ExecveArray(args.begin(), args.end()), {}, 211 nullptr, child, &execve_errno)); 212 213 if (execve_errno != 0) { 214 return PosixError(execve_errno, "execve"); 215 } 216 217 if (socket_pair) { 218 // Wait for when a chill will start. 219 char c; 220 EXPECT_THAT(ReadFd(socket_pair[0], reinterpret_cast<void*>(&c), sizeof(c)), 221 SyscallSucceedsWithValue(sizeof(c))); 222 } 223 return std::move(cleanup); 224 } 225 226 TEST(FcntlTest, FcntlDupWithOpath) { 227 auto f = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 228 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(f.path(), O_PATH)); 229 230 int new_fd; 231 // Dup the descriptor and make sure it's the same file. 232 EXPECT_THAT(new_fd = fcntl(fd.get(), F_DUPFD, 0), SyscallSucceeds()); 233 234 FileDescriptor nfd = FileDescriptor(new_fd); 235 ASSERT_NE(fd.get(), nfd.get()); 236 ASSERT_NO_ERRNO(CheckSameFile(fd, nfd)); 237 EXPECT_THAT(fcntl(nfd.get(), F_GETFL), SyscallSucceedsWithValue(O_PATH)); 238 } 239 240 TEST(FcntlTest, SetFileStatusFlagWithOpath) { 241 TempPath path = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 242 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path.path(), O_PATH)); 243 244 EXPECT_THAT(fcntl(fd.get(), F_SETFL, 0), SyscallFailsWithErrno(EBADF)); 245 } 246 247 TEST(FcntlTest, BadFcntlsWithOpath) { 248 TempPath path = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 249 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path.path(), O_PATH)); 250 251 EXPECT_THAT(fcntl(fd.get(), F_SETOWN, 0), SyscallFailsWithErrno(EBADF)); 252 EXPECT_THAT(fcntl(fd.get(), F_GETOWN, 0), SyscallFailsWithErrno(EBADF)); 253 254 EXPECT_THAT(fcntl(fd.get(), F_SETOWN_EX, 0), SyscallFailsWithErrno(EBADF)); 255 EXPECT_THAT(fcntl(fd.get(), F_GETOWN_EX, 0), SyscallFailsWithErrno(EBADF)); 256 } 257 258 TEST(FcntlTest, SetCloExecBadFD) { 259 // Open an eventfd file descriptor with FD_CLOEXEC descriptor flag not set. 260 FileDescriptor f = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0)); 261 auto fd = f.get(); 262 f.reset(); 263 ASSERT_THAT(fcntl(fd, F_GETFD), SyscallFailsWithErrno(EBADF)); 264 ASSERT_THAT(fcntl(fd, F_SETFD, FD_CLOEXEC), SyscallFailsWithErrno(EBADF)); 265 } 266 267 TEST(FcntlTest, SetCloExec) { 268 // Open an eventfd file descriptor with FD_CLOEXEC descriptor flag not set. 269 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0)); 270 ASSERT_THAT(fcntl(fd.get(), F_GETFD), SyscallSucceedsWithValue(0)); 271 272 // Set the FD_CLOEXEC flag. 273 ASSERT_THAT(fcntl(fd.get(), F_SETFD, FD_CLOEXEC), SyscallSucceeds()); 274 ASSERT_THAT(fcntl(fd.get(), F_GETFD), SyscallSucceedsWithValue(FD_CLOEXEC)); 275 } 276 277 TEST(FcntlTest, SetCloExecWithOpath) { 278 // Open a file descriptor with FD_CLOEXEC descriptor flag not set. 279 TempPath path = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 280 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path.path(), O_PATH)); 281 ASSERT_THAT(fcntl(fd.get(), F_GETFD), SyscallSucceedsWithValue(0)); 282 283 // Set the FD_CLOEXEC flag. 284 ASSERT_THAT(fcntl(fd.get(), F_SETFD, FD_CLOEXEC), SyscallSucceeds()); 285 ASSERT_THAT(fcntl(fd.get(), F_GETFD), SyscallSucceedsWithValue(FD_CLOEXEC)); 286 } 287 288 TEST(FcntlTest, DupFDCloExecWithOpath) { 289 // Open a file descriptor with FD_CLOEXEC descriptor flag not set. 290 TempPath path = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 291 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path.path(), O_PATH)); 292 int nfd; 293 ASSERT_THAT(nfd = fcntl(fd.get(), F_DUPFD_CLOEXEC, 0), SyscallSucceeds()); 294 FileDescriptor dup_fd(nfd); 295 296 // Check for the FD_CLOEXEC flag. 297 ASSERT_THAT(fcntl(dup_fd.get(), F_GETFD), 298 SyscallSucceedsWithValue(FD_CLOEXEC)); 299 } 300 301 TEST(FcntlTest, ClearCloExec) { 302 // Open an eventfd file descriptor with FD_CLOEXEC descriptor flag set. 303 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_CLOEXEC)); 304 ASSERT_THAT(fcntl(fd.get(), F_GETFD), SyscallSucceedsWithValue(FD_CLOEXEC)); 305 306 // Clear the FD_CLOEXEC flag. 307 ASSERT_THAT(fcntl(fd.get(), F_SETFD, 0), SyscallSucceeds()); 308 ASSERT_THAT(fcntl(fd.get(), F_GETFD), SyscallSucceedsWithValue(0)); 309 } 310 311 TEST(FcntlTest, IndependentDescriptorFlags) { 312 // Open an eventfd file descriptor with FD_CLOEXEC descriptor flag not set. 313 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0)); 314 ASSERT_THAT(fcntl(fd.get(), F_GETFD), SyscallSucceedsWithValue(0)); 315 316 // Duplicate the descriptor. Ensure that it also doesn't have FD_CLOEXEC. 317 FileDescriptor newfd = ASSERT_NO_ERRNO_AND_VALUE(fd.Dup()); 318 ASSERT_THAT(fcntl(newfd.get(), F_GETFD), SyscallSucceedsWithValue(0)); 319 320 // Set FD_CLOEXEC on the first FD. 321 ASSERT_THAT(fcntl(fd.get(), F_SETFD, FD_CLOEXEC), SyscallSucceeds()); 322 ASSERT_THAT(fcntl(fd.get(), F_GETFD), SyscallSucceedsWithValue(FD_CLOEXEC)); 323 324 // Ensure that the second FD is unaffected by the change on the first. 325 ASSERT_THAT(fcntl(newfd.get(), F_GETFD), SyscallSucceedsWithValue(0)); 326 } 327 328 // All file description flags passed to open appear in F_GETFL. 329 TEST(FcntlTest, GetAllFlags) { 330 TempPath path = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 331 int flags = O_RDWR | O_DIRECT | O_SYNC | O_NONBLOCK | O_APPEND; 332 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path.path(), flags)); 333 334 // Linux forces O_LARGEFILE on all 64-bit kernels and gVisor's is 64-bit. 335 int expected = flags | kOLargeFile; 336 337 int rflags; 338 EXPECT_THAT(rflags = fcntl(fd.get(), F_GETFL), SyscallSucceeds()); 339 EXPECT_EQ(rflags, expected); 340 } 341 342 // When O_PATH is specified in flags, flag bits other than O_CLOEXEC, 343 // O_DIRECTORY, and O_NOFOLLOW are ignored. 344 TEST(FcntlTest, GetOpathFlag) { 345 TempPath path = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 346 int flags = O_RDWR | O_DIRECT | O_SYNC | O_NONBLOCK | O_APPEND | O_PATH | 347 O_NOFOLLOW | O_DIRECTORY; 348 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path.path(), flags)); 349 350 int expected = O_PATH | O_NOFOLLOW | O_DIRECTORY; 351 352 int rflags; 353 EXPECT_THAT(rflags = fcntl(fd.get(), F_GETFL), SyscallSucceeds()); 354 EXPECT_EQ(rflags, expected); 355 } 356 357 TEST(FcntlTest, SetFlags) { 358 TempPath path = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 359 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path.path(), 0)); 360 361 int const flags = O_RDWR | O_DIRECT | O_SYNC | O_NONBLOCK | O_APPEND; 362 EXPECT_THAT(fcntl(fd.get(), F_SETFL, flags), SyscallSucceeds()); 363 364 // Can't set O_RDWR or O_SYNC. 365 // Linux forces O_LARGEFILE on all 64-bit kernels and gVisor's is 64-bit. 366 int expected = O_DIRECT | O_NONBLOCK | O_APPEND | kOLargeFile; 367 368 int rflags; 369 EXPECT_THAT(rflags = fcntl(fd.get(), F_GETFL), SyscallSucceeds()); 370 EXPECT_EQ(rflags, expected); 371 } 372 373 void TestLock(int fd, short lock_type = F_RDLCK) { // NOLINT, type in flock 374 struct flock fl; 375 fl.l_type = lock_type; 376 fl.l_whence = SEEK_SET; 377 fl.l_start = 0; 378 // len 0 locks all bytes despite how large the file grows. 379 fl.l_len = 0; 380 EXPECT_THAT(fcntl(fd, F_SETLK, &fl), SyscallSucceeds()); 381 } 382 383 void TestLockBadFD(int fd, 384 short lock_type = F_RDLCK) { // NOLINT, type in flock 385 struct flock fl; 386 fl.l_type = lock_type; 387 fl.l_whence = SEEK_SET; 388 fl.l_start = 0; 389 // len 0 locks all bytes despite how large the file grows. 390 fl.l_len = 0; 391 EXPECT_THAT(fcntl(fd, F_SETLK, &fl), SyscallFailsWithErrno(EBADF)); 392 } 393 394 TEST_F(FcntlLockTest, SetLockBadFd) { TestLockBadFD(-1); } 395 396 TEST_F(FcntlLockTest, SetLockDir) { 397 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 398 auto fd = ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path(), O_RDONLY, 0000)); 399 TestLock(fd.get()); 400 } 401 402 TEST_F(FcntlLockTest, SetLockSymlink) { 403 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 404 auto symlink = ASSERT_NO_ERRNO_AND_VALUE( 405 TempPath::CreateSymlinkTo(GetAbsoluteTestTmpdir(), file.path())); 406 407 auto fd = 408 ASSERT_NO_ERRNO_AND_VALUE(Open(symlink.path(), O_RDONLY | O_PATH, 0000)); 409 TestLockBadFD(fd.get()); 410 } 411 412 TEST_F(FcntlLockTest, SetLockProc) { 413 auto fd = 414 ASSERT_NO_ERRNO_AND_VALUE(Open("/proc/self/status", O_RDONLY, 0000)); 415 TestLock(fd.get()); 416 } 417 418 TEST_F(FcntlLockTest, SetLockPipe) { 419 int fds[2]; 420 ASSERT_THAT(pipe(fds), SyscallSucceeds()); 421 422 TestLock(fds[0]); 423 TestLockBadFD(fds[0], F_WRLCK); 424 425 TestLock(fds[1], F_WRLCK); 426 TestLockBadFD(fds[1]); 427 428 EXPECT_THAT(close(fds[0]), SyscallSucceeds()); 429 EXPECT_THAT(close(fds[1]), SyscallSucceeds()); 430 } 431 432 TEST_F(FcntlLockTest, SetLockSocket) { 433 int sock = socket(AF_UNIX, SOCK_STREAM, 0); 434 ASSERT_THAT(sock, SyscallSucceeds()); 435 436 struct sockaddr_un addr = 437 ASSERT_NO_ERRNO_AND_VALUE(UniqueUnixAddr(true /* abstract */, AF_UNIX)); 438 ASSERT_THAT( 439 bind(sock, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)), 440 SyscallSucceeds()); 441 442 TestLock(sock); 443 EXPECT_THAT(close(sock), SyscallSucceeds()); 444 } 445 446 TEST_F(FcntlLockTest, SetLockBadOpenFlagsWrite) { 447 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 448 FileDescriptor fd = 449 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY, 0666)); 450 451 struct flock fl0; 452 fl0.l_type = F_WRLCK; 453 fl0.l_whence = SEEK_SET; 454 fl0.l_start = 0; 455 fl0.l_len = 0; // Lock all file 456 457 // Expect that setting a write lock using a read only file descriptor 458 // won't work. 459 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl0), SyscallFailsWithErrno(EBADF)); 460 } 461 462 TEST_F(FcntlLockTest, SetLockBadOpenFlagsRead) { 463 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 464 FileDescriptor fd = 465 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_WRONLY, 0666)); 466 467 struct flock fl1; 468 fl1.l_type = F_RDLCK; 469 fl1.l_whence = SEEK_SET; 470 fl1.l_start = 0; 471 // Same as SetLockBadFd. 472 fl1.l_len = 0; 473 474 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl1), SyscallFailsWithErrno(EBADF)); 475 } 476 477 TEST_F(FcntlLockTest, SetLockWithOpath) { 478 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 479 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_PATH)); 480 481 struct flock fl0; 482 fl0.l_type = F_WRLCK; 483 fl0.l_whence = SEEK_SET; 484 fl0.l_start = 0; 485 fl0.l_len = 0; // Lock all file 486 487 // Expect that setting a write lock using a Opath file descriptor 488 // won't work. 489 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl0), SyscallFailsWithErrno(EBADF)); 490 } 491 492 TEST_F(FcntlLockTest, SetLockUnlockOnNothing) { 493 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 494 FileDescriptor fd = 495 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 496 497 struct flock fl; 498 fl.l_type = F_UNLCK; 499 fl.l_whence = SEEK_SET; 500 fl.l_start = 0; 501 // Same as SetLockBadFd. 502 fl.l_len = 0; 503 504 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 505 } 506 507 TEST_F(FcntlLockTest, SetWriteLockSingleProc) { 508 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 509 FileDescriptor fd0 = 510 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 511 512 struct flock fl; 513 fl.l_type = F_WRLCK; 514 fl.l_whence = SEEK_SET; 515 fl.l_start = 0; 516 // Same as SetLockBadFd. 517 fl.l_len = 0; 518 519 EXPECT_THAT(fcntl(fd0.get(), F_SETLK, &fl), SyscallSucceeds()); 520 // Expect to be able to take the same lock on the same fd no problem. 521 EXPECT_THAT(fcntl(fd0.get(), F_SETLK, &fl), SyscallSucceeds()); 522 523 FileDescriptor fd1 = 524 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 525 526 // Expect to be able to take the same lock from a different fd but for 527 // the same process. 528 EXPECT_THAT(fcntl(fd1.get(), F_SETLK, &fl), SyscallSucceeds()); 529 } 530 531 TEST_F(FcntlLockTest, SetReadLockMultiProc) { 532 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 533 FileDescriptor fd = 534 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 535 536 struct flock fl; 537 fl.l_type = F_RDLCK; 538 fl.l_whence = SEEK_SET; 539 fl.l_start = 0; 540 // Same as SetLockBadFd. 541 fl.l_len = 0; 542 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 543 544 // spawn a child process to take a read lock on the same file. 545 pid_t child_pid = 0; 546 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 547 file.path(), false /* write lock */, false /* nonblocking */, 548 false /* no eintr retry */, nullptr /* no socket fd */, fl.l_start, 549 fl.l_len, &child_pid)); 550 551 int status = 0; 552 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 553 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 554 << "Exited with code: " << status; 555 } 556 557 TEST_F(FcntlLockTest, SetReadThenWriteLockMultiProc) { 558 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 559 FileDescriptor fd = 560 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 561 562 struct flock fl; 563 fl.l_type = F_RDLCK; 564 fl.l_whence = SEEK_SET; 565 fl.l_start = 0; 566 // Same as SetLockBadFd. 567 fl.l_len = 0; 568 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 569 570 // Assert that another process trying to lock on the same file will fail 571 // with EAGAIN. It's important that we keep the fd above open so that 572 // that the other process will contend with the lock. 573 pid_t child_pid = 0; 574 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 575 file.path(), true /* write lock */, false /* nonblocking */, 576 false /* no eintr retry */, nullptr /* no socket fd */, fl.l_start, 577 fl.l_len, &child_pid)); 578 579 int status = 0; 580 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 581 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == EAGAIN) 582 << "Exited with code: " << status; 583 584 // Close the fd: we want to test that another process can acquire the 585 // lock after this point. 586 fd.reset(); 587 // Assert that another process can now acquire the lock. 588 589 child_pid = 0; 590 auto cleanup2 = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 591 file.path(), true /* write lock */, false /* nonblocking */, 592 false /* no eintr retry */, nullptr /* no socket fd */, fl.l_start, 593 fl.l_len, &child_pid)); 594 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 595 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 596 << "Exited with code: " << status; 597 } 598 599 TEST_F(FcntlLockTest, SetWriteThenReadLockMultiProc) { 600 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 601 602 FileDescriptor fd = 603 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 604 // Same as SetReadThenWriteLockMultiProc. 605 606 struct flock fl; 607 fl.l_type = F_WRLCK; 608 fl.l_whence = SEEK_SET; 609 fl.l_start = 0; 610 // Same as SetLockBadFd. 611 fl.l_len = 0; 612 613 // Same as SetReadThenWriteLockMultiProc. 614 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 615 616 // Same as SetReadThenWriteLockMultiProc. 617 pid_t child_pid = 0; 618 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 619 file.path(), false /* write lock */, false /* nonblocking */, 620 false /* no eintr retry */, nullptr /* no socket fd */, fl.l_start, 621 fl.l_len, &child_pid)); 622 623 int status = 0; 624 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 625 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == EAGAIN) 626 << "Exited with code: " << status; 627 628 // Same as SetReadThenWriteLockMultiProc. 629 fd.reset(); // Close the fd. 630 631 // Same as SetReadThenWriteLockMultiProc. 632 child_pid = 0; 633 auto cleanup2 = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 634 file.path(), false /* write lock */, false /* nonblocking */, 635 false /* no eintr retry */, nullptr /* no socket fd */, fl.l_start, 636 fl.l_len, &child_pid)); 637 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 638 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 639 << "Exited with code: " << status; 640 } 641 642 TEST_F(FcntlLockTest, SetWriteLockMultiProc) { 643 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 644 FileDescriptor fd = 645 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 646 // Same as SetReadThenWriteLockMultiProc. 647 648 struct flock fl; 649 fl.l_type = F_WRLCK; 650 fl.l_whence = SEEK_SET; 651 fl.l_start = 0; 652 // Same as SetLockBadFd. 653 fl.l_len = 0; 654 655 // Same as SetReadWriteLockMultiProc. 656 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 657 658 // Same as SetReadWriteLockMultiProc. 659 pid_t child_pid = 0; 660 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 661 file.path(), true /* write lock */, false /* nonblocking */, 662 false /* no eintr retry */, nullptr /* no socket fd */, fl.l_start, 663 fl.l_len, &child_pid)); 664 int status = 0; 665 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 666 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == EAGAIN) 667 << "Exited with code: " << status; 668 669 fd.reset(); // Close the FD. 670 // Same as SetReadWriteLockMultiProc. 671 child_pid = 0; 672 auto cleanup2 = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 673 file.path(), true /* write lock */, false /* nonblocking */, 674 false /* no eintr retry */, nullptr /* no socket fd */, fl.l_start, 675 fl.l_len, &child_pid)); 676 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 677 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 678 << "Exited with code: " << status; 679 } 680 681 TEST_F(FcntlLockTest, SetLockIsRegional) { 682 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 683 FileDescriptor fd = 684 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 685 686 struct flock fl; 687 fl.l_type = F_WRLCK; 688 fl.l_whence = SEEK_SET; 689 fl.l_start = 0; 690 fl.l_len = 4096; 691 692 // Same as SetReadWriteLockMultiProc. 693 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 694 695 // Same as SetReadWriteLockMultiProc. 696 pid_t child_pid = 0; 697 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 698 SubprocessLock(file.path(), true /* write lock */, 699 false /* nonblocking */, false /* no eintr retry */, 700 nullptr /* no socket fd */, fl.l_len, 0, &child_pid)); 701 int status = 0; 702 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 703 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 704 << "Exited with code: " << status; 705 } 706 707 TEST_F(FcntlLockTest, SetLockUpgradeDowngrade) { 708 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 709 FileDescriptor fd = 710 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 711 712 struct flock fl; 713 fl.l_type = F_RDLCK; 714 fl.l_whence = SEEK_SET; 715 fl.l_start = 0; 716 // Same as SetLockBadFd. 717 fl.l_len = 0; 718 719 // Same as SetReadWriteLockMultiProc. 720 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 721 722 // Upgrade to a write lock. This will prevent anyone else from taking 723 // the lock. 724 fl.l_type = F_WRLCK; 725 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 726 727 // Same as SetReadWriteLockMultiProc., 728 pid_t child_pid = 0; 729 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 730 file.path(), false /* write lock */, false /* nonblocking */, 731 false /* no eintr retry */, nullptr /* no socket fd */, fl.l_start, 732 fl.l_len, &child_pid)); 733 734 int status = 0; 735 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 736 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == EAGAIN) 737 << "Exited with code: " << status; 738 739 // Downgrade back to a read lock. 740 fl.l_type = F_RDLCK; 741 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 742 743 // Do the same stint as before, but this time it should succeed. 744 child_pid = 0; 745 auto cleanup2 = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 746 file.path(), false /* write lock */, false /* nonblocking */, 747 false /* no eintr retry */, nullptr /* no socket fd */, fl.l_start, 748 fl.l_len, &child_pid)); 749 750 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 751 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 752 << "Exited with code: " << status; 753 } 754 755 TEST_F(FcntlLockTest, SetLockDroppedOnClose) { 756 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 757 FileDescriptor fd = 758 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 759 760 // While somewhat surprising, obtaining another fd to the same file and 761 // then closing it in this process drops *all* locks. 762 FileDescriptor other_fd = 763 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 764 // Same as SetReadThenWriteLockMultiProc. 765 766 struct flock fl; 767 fl.l_type = F_WRLCK; 768 fl.l_whence = SEEK_SET; 769 fl.l_start = 0; 770 // Same as SetLockBadFd. 771 fl.l_len = 0; 772 773 // Same as SetReadWriteLockMultiProc. 774 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 775 776 other_fd.reset(); // Close. 777 778 // Expect to be able to get the lock, given that the close above dropped it. 779 pid_t child_pid = 0; 780 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 781 file.path(), true /* write lock */, false /* nonblocking */, 782 false /* no eintr retry */, nullptr /* no socket fd */, fl.l_start, 783 fl.l_len, &child_pid)); 784 785 int status = 0; 786 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 787 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 788 << "Exited with code: " << status; 789 } 790 791 TEST_F(FcntlLockTest, SetLockUnlock) { 792 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 793 FileDescriptor fd = 794 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 795 796 // Setup two regional locks with different permissions. 797 struct flock fl0; 798 fl0.l_type = F_WRLCK; 799 fl0.l_whence = SEEK_SET; 800 fl0.l_start = 0; 801 fl0.l_len = 4096; 802 803 struct flock fl1; 804 fl1.l_type = F_RDLCK; 805 fl1.l_whence = SEEK_SET; 806 fl1.l_start = 4096; 807 // Same as SetLockBadFd. 808 fl1.l_len = 0; 809 810 // Set both region locks. 811 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl0), SyscallSucceeds()); 812 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl1), SyscallSucceeds()); 813 814 // Another process should fail to take a read lock on the entire file 815 // due to the regional write lock. 816 pid_t child_pid = 0; 817 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 818 SubprocessLock(file.path(), false /* write lock */, 819 false /* nonblocking */, false /* no eintr retry */, 820 nullptr /* no socket fd */, 0, 0, &child_pid)); 821 822 int status = 0; 823 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 824 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == EAGAIN) 825 << "Exited with code: " << status; 826 827 // Then only unlock the writable one. This should ensure that other 828 // processes can take any read lock that it wants. 829 fl0.l_type = F_UNLCK; 830 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl0), SyscallSucceeds()); 831 832 // Another process should now succeed to get a read lock on the entire file. 833 child_pid = 0; 834 auto cleanup2 = ASSERT_NO_ERRNO_AND_VALUE( 835 SubprocessLock(file.path(), false /* write lock */, 836 false /* nonblocking */, false /* no eintr retry */, 837 nullptr /* no socket fd */, 0, 0, &child_pid)); 838 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 839 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 840 << "Exited with code: " << status; 841 } 842 843 TEST_F(FcntlLockTest, SetLockAcrossRename) { 844 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 845 FileDescriptor fd = 846 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 847 848 // Setup two regional locks with different permissions. 849 struct flock fl; 850 fl.l_type = F_WRLCK; 851 fl.l_whence = SEEK_SET; 852 fl.l_start = 0; 853 // Same as SetLockBadFd. 854 fl.l_len = 0; 855 856 // Set the region lock. 857 EXPECT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 858 859 // Rename the file to someplace nearby. 860 std::string const newpath = NewTempAbsPath(); 861 EXPECT_THAT(rename(file.path().c_str(), newpath.c_str()), SyscallSucceeds()); 862 863 // Another process should fail to take a read lock on the renamed file 864 // since we still have an open handle to the inode. 865 pid_t child_pid = 0; 866 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 867 SubprocessLock(newpath, false /* write lock */, false /* nonblocking */, 868 false /* no eintr retry */, nullptr /* no socket fd */, 869 fl.l_start, fl.l_len, &child_pid)); 870 871 int status = 0; 872 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 873 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == EAGAIN) 874 << "Exited with code: " << status; 875 } 876 877 // NOTE: The blocking tests below aren't perfect. It's hard to assert exactly 878 // what the kernel did while handling a syscall. These tests are timing based 879 // because there really isn't any other reasonable way to assert that correct 880 // blocking behavior happened. 881 882 // This test will verify that blocking works as expected when another process 883 // holds a write lock when obtaining a write lock. This test will hold the lock 884 // for some amount of time and then wait for the second process to send over the 885 // socket_fd the amount of time it was blocked for before the lock succeeded. 886 TEST_F(FcntlLockTest, SetWriteLockThenBlockingWriteLock) { 887 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 888 FileDescriptor fd = 889 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 890 891 struct flock fl; 892 fl.l_type = F_WRLCK; 893 fl.l_whence = SEEK_SET; 894 fl.l_start = 0; 895 fl.l_len = 0; 896 897 // Take the write lock. 898 ASSERT_THAT(fcntl(fd.get(), F_SETLKW, &fl), SyscallSucceeds()); 899 900 // Attempt to take the read lock in a sub process. This will immediately block 901 // so we will release our lock after some amount of time and then assert the 902 // amount of time the other process was blocked for. 903 pid_t child_pid = 0; 904 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 905 file.path(), true /* write lock */, true /* Blocking Lock */, 906 true /* Retry on EINTR */, fds_ /* Socket fd for timing information */, 907 fl.l_start, fl.l_len, &child_pid)); 908 909 // We will wait kHoldLockForSec before we release our lock allowing the 910 // subprocess to obtain it. 911 constexpr absl::Duration kHoldLockFor = absl::Seconds(5); 912 const int64_t kMinBlockTimeUsec = absl::ToInt64Microseconds(absl::Seconds(1)); 913 914 absl::SleepFor(kHoldLockFor); 915 916 // Unlock our write lock. 917 fl.l_type = F_UNLCK; 918 ASSERT_THAT(fcntl(fd.get(), F_SETLKW, &fl), SyscallSucceeds()); 919 920 // Read the blocked time from the subprocess socket. 921 int64_t subprocess_blocked_time_usec = GetSubprocessFcntlTimeInUsec(); 922 923 // We must have been waiting at least kMinBlockTime. 924 EXPECT_GT(subprocess_blocked_time_usec, kMinBlockTimeUsec); 925 926 // The FCNTL write lock must always succeed as it will simply block until it 927 // can obtain the lock. 928 int status = 0; 929 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 930 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 931 << "Exited with code: " << status; 932 } 933 934 // This test will verify that blocking works as expected when another process 935 // holds a read lock when obtaining a write lock. This test will hold the lock 936 // for some amount of time and then wait for the second process to send over the 937 // socket_fd the amount of time it was blocked for before the lock succeeded. 938 TEST_F(FcntlLockTest, SetReadLockThenBlockingWriteLock) { 939 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 940 FileDescriptor fd = 941 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 942 943 struct flock fl; 944 fl.l_type = F_RDLCK; 945 fl.l_whence = SEEK_SET; 946 fl.l_start = 0; 947 fl.l_len = 0; 948 949 // Take the write lock. 950 ASSERT_THAT(fcntl(fd.get(), F_SETLKW, &fl), SyscallSucceeds()); 951 952 // Attempt to take the read lock in a sub process. This will immediately block 953 // so we will release our lock after some amount of time and then assert the 954 // amount of time the other process was blocked for. 955 pid_t child_pid = 0; 956 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 957 file.path(), true /* write lock */, true /* Blocking Lock */, 958 true /* Retry on EINTR */, fds_ /* Socket fd for timing information */, 959 fl.l_start, fl.l_len, &child_pid)); 960 961 // We will wait kHoldLockForSec before we release our lock allowing the 962 // subprocess to obtain it. 963 constexpr absl::Duration kHoldLockFor = absl::Seconds(5); 964 965 const int64_t kMinBlockTimeUsec = absl::ToInt64Microseconds(absl::Seconds(1)); 966 967 absl::SleepFor(kHoldLockFor); 968 969 // Unlock our READ lock. 970 fl.l_type = F_UNLCK; 971 ASSERT_THAT(fcntl(fd.get(), F_SETLKW, &fl), SyscallSucceeds()); 972 973 // Read the blocked time from the subprocess socket. 974 int64_t subprocess_blocked_time_usec = GetSubprocessFcntlTimeInUsec(); 975 976 // We must have been waiting at least kMinBlockTime. 977 EXPECT_GT(subprocess_blocked_time_usec, kMinBlockTimeUsec); 978 979 // The FCNTL write lock must always succeed as it will simply block until it 980 // can obtain the lock. 981 int status = 0; 982 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 983 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 984 << "Exited with code: " << status; 985 } 986 987 // This test will veirfy that blocking works as expected when another process 988 // holds a write lock when obtaining a read lock. This test will hold the lock 989 // for some amount of time and then wait for the second process to send over the 990 // socket_fd the amount of time it was blocked for before the lock succeeded. 991 TEST_F(FcntlLockTest, SetWriteLockThenBlockingReadLock) { 992 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 993 FileDescriptor fd = 994 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 995 996 struct flock fl; 997 fl.l_type = F_WRLCK; 998 fl.l_whence = SEEK_SET; 999 fl.l_start = 0; 1000 fl.l_len = 0; 1001 1002 // Take the write lock. 1003 ASSERT_THAT(fcntl(fd.get(), F_SETLKW, &fl), SyscallSucceeds()); 1004 1005 // Attempt to take the read lock in a sub process. This will immediately block 1006 // so we will release our lock after some amount of time and then assert the 1007 // amount of time the other process was blocked for. 1008 pid_t child_pid = 0; 1009 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 1010 file.path(), false /* read lock */, true /* Blocking Lock */, 1011 true /* Retry on EINTR */, fds_ /* Socket fd for timing information */, 1012 fl.l_start, fl.l_len, &child_pid)); 1013 1014 // We will wait kHoldLockForSec before we release our lock allowing the 1015 // subprocess to obtain it. 1016 constexpr absl::Duration kHoldLockFor = absl::Seconds(5); 1017 1018 const int64_t kMinBlockTimeUsec = absl::ToInt64Microseconds(absl::Seconds(1)); 1019 1020 absl::SleepFor(kHoldLockFor); 1021 1022 // Unlock our write lock. 1023 fl.l_type = F_UNLCK; 1024 ASSERT_THAT(fcntl(fd.get(), F_SETLKW, &fl), SyscallSucceeds()); 1025 1026 // Read the blocked time from the subprocess socket. 1027 int64_t subprocess_blocked_time_usec = GetSubprocessFcntlTimeInUsec(); 1028 1029 // We must have been waiting at least kMinBlockTime. 1030 EXPECT_GT(subprocess_blocked_time_usec, kMinBlockTimeUsec); 1031 1032 // The FCNTL read lock must always succeed as it will simply block until it 1033 // can obtain the lock. 1034 int status = 0; 1035 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 1036 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 1037 << "Exited with code: " << status; 1038 } 1039 1040 // This test will verify that when one process only holds a read lock that 1041 // another will not block while obtaining a read lock when F_SETLKW is used. 1042 TEST_F(FcntlLockTest, SetReadLockThenBlockingReadLock) { 1043 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 1044 FileDescriptor fd = 1045 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 1046 1047 struct flock fl; 1048 fl.l_type = F_RDLCK; 1049 fl.l_whence = SEEK_SET; 1050 fl.l_start = 0; 1051 fl.l_len = 0; 1052 1053 // Take the READ lock. 1054 ASSERT_THAT(fcntl(fd.get(), F_SETLKW, &fl), SyscallSucceeds()); 1055 1056 // Attempt to take the read lock in a sub process. Since multiple processes 1057 // can hold a read lock this should immediately return without blocking 1058 // even though we used F_SETLKW in the subprocess. 1059 pid_t child_pid = 0; 1060 auto sp = ASSERT_NO_ERRNO_AND_VALUE(SubprocessLock( 1061 file.path(), false /* read lock */, true /* Blocking Lock */, 1062 true /* Retry on EINTR */, nullptr /* No fd, should not block */, 1063 fl.l_start, fl.l_len, &child_pid)); 1064 1065 // We never release the lock and the subprocess should still obtain it without 1066 // blocking for any period of time. 1067 int status = 0; 1068 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 1069 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 1070 << "Exited with code: " << status; 1071 } 1072 1073 TEST(FcntlTest, GetO_ASYNC) { 1074 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1075 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1076 1077 int flag_fl = -1; 1078 ASSERT_THAT(flag_fl = fcntl(s.get(), F_GETFL), SyscallSucceeds()); 1079 EXPECT_EQ(flag_fl & O_ASYNC, 0); 1080 1081 int flag_fd = -1; 1082 ASSERT_THAT(flag_fd = fcntl(s.get(), F_GETFD), SyscallSucceeds()); 1083 EXPECT_EQ(flag_fd & O_ASYNC, 0); 1084 } 1085 1086 TEST(FcntlTest, SetFlO_ASYNC) { 1087 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1088 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1089 1090 int before_fl = -1; 1091 ASSERT_THAT(before_fl = fcntl(s.get(), F_GETFL), SyscallSucceeds()); 1092 1093 int before_fd = -1; 1094 ASSERT_THAT(before_fd = fcntl(s.get(), F_GETFD), SyscallSucceeds()); 1095 1096 ASSERT_THAT(fcntl(s.get(), F_SETFL, before_fl | O_ASYNC), SyscallSucceeds()); 1097 1098 int after_fl = -1; 1099 ASSERT_THAT(after_fl = fcntl(s.get(), F_GETFL), SyscallSucceeds()); 1100 EXPECT_EQ(after_fl, before_fl | O_ASYNC); 1101 1102 int after_fd = -1; 1103 ASSERT_THAT(after_fd = fcntl(s.get(), F_GETFD), SyscallSucceeds()); 1104 EXPECT_EQ(after_fd, before_fd); 1105 } 1106 1107 TEST(FcntlTest, SetFdO_ASYNC) { 1108 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1109 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1110 1111 int before_fl = -1; 1112 ASSERT_THAT(before_fl = fcntl(s.get(), F_GETFL), SyscallSucceeds()); 1113 1114 int before_fd = -1; 1115 ASSERT_THAT(before_fd = fcntl(s.get(), F_GETFD), SyscallSucceeds()); 1116 1117 ASSERT_THAT(fcntl(s.get(), F_SETFD, before_fd | O_ASYNC), SyscallSucceeds()); 1118 1119 int after_fl = -1; 1120 ASSERT_THAT(after_fl = fcntl(s.get(), F_GETFL), SyscallSucceeds()); 1121 EXPECT_EQ(after_fl, before_fl); 1122 1123 int after_fd = -1; 1124 ASSERT_THAT(after_fd = fcntl(s.get(), F_GETFD), SyscallSucceeds()); 1125 EXPECT_EQ(after_fd, before_fd); 1126 } 1127 1128 TEST(FcntlTest, DupAfterO_ASYNC) { 1129 FileDescriptor s1 = ASSERT_NO_ERRNO_AND_VALUE( 1130 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1131 1132 int before = -1; 1133 ASSERT_THAT(before = fcntl(s1.get(), F_GETFL), SyscallSucceeds()); 1134 1135 ASSERT_THAT(fcntl(s1.get(), F_SETFL, before | O_ASYNC), SyscallSucceeds()); 1136 1137 FileDescriptor fd2 = ASSERT_NO_ERRNO_AND_VALUE(s1.Dup()); 1138 1139 int after = -1; 1140 ASSERT_THAT(after = fcntl(fd2.get(), F_GETFL), SyscallSucceeds()); 1141 EXPECT_EQ(after & O_ASYNC, O_ASYNC); 1142 } 1143 1144 TEST(FcntlTest, GetOwnNone) { 1145 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1146 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1147 1148 // Use the raw syscall because the glibc wrapper may convert F_{GET,SET}OWN 1149 // into F_{GET,SET}OWN_EX. 1150 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN), 1151 SyscallSucceedsWithValue(0)); 1152 } 1153 1154 TEST(FcntlTest, GetOwnExNone) { 1155 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1156 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1157 1158 f_owner_ex owner = {}; 1159 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN_EX, &owner), 1160 SyscallSucceedsWithValue(0)); 1161 } 1162 1163 TEST(FcntlTest, SetOwnInvalidPid) { 1164 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1165 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1166 1167 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN, 12345678), 1168 SyscallFailsWithErrno(ESRCH)); 1169 } 1170 1171 TEST(FcntlTest, SetOwnInvalidPgrp) { 1172 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1173 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1174 1175 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN, -12345678), 1176 SyscallFailsWithErrno(ESRCH)); 1177 } 1178 1179 TEST(FcntlTest, SetOwnPid) { 1180 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1181 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1182 1183 pid_t pid; 1184 EXPECT_THAT(pid = getpid(), SyscallSucceeds()); 1185 1186 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN, pid), 1187 SyscallSucceedsWithValue(0)); 1188 1189 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN), 1190 SyscallSucceedsWithValue(pid)); 1191 } 1192 1193 TEST(FcntlTest, SetOwnPgrp) { 1194 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1195 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1196 1197 pid_t pgid; 1198 EXPECT_THAT(pgid = getpgrp(), SyscallSucceeds()); 1199 1200 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN, -pgid), 1201 SyscallSucceedsWithValue(0)); 1202 1203 // Verify with F_GETOWN_EX; using F_GETOWN on Linux may incorrectly treat the 1204 // negative return value as an error, converting the return value to -1 and 1205 // setting errno accordingly. 1206 f_owner_ex got_owner = {}; 1207 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN_EX, &got_owner), 1208 SyscallSucceedsWithValue(0)); 1209 EXPECT_EQ(got_owner.type, F_OWNER_PGRP); 1210 EXPECT_EQ(got_owner.pid, pgid); 1211 } 1212 1213 TEST(FcntlTest, SetOwnUnset) { 1214 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1215 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1216 1217 // Set and unset pid. 1218 pid_t pid; 1219 EXPECT_THAT(pid = getpid(), SyscallSucceeds()); 1220 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN, pid), 1221 SyscallSucceedsWithValue(0)); 1222 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN, 0), 1223 SyscallSucceedsWithValue(0)); 1224 1225 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN), 1226 SyscallSucceedsWithValue(0)); 1227 1228 // Set and unset pgid. 1229 pid_t pgid; 1230 EXPECT_THAT(pgid = getpgrp(), SyscallSucceeds()); 1231 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN, -pgid), 1232 SyscallSucceedsWithValue(0)); 1233 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN, 0), 1234 SyscallSucceedsWithValue(0)); 1235 1236 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN), 1237 SyscallSucceedsWithValue(0)); 1238 } 1239 1240 // F_SETOWN flips the sign of negative values, an operation that is guarded 1241 // against overflow. 1242 TEST(FcntlTest, SetOwnOverflow) { 1243 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1244 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1245 1246 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN, INT_MIN), 1247 SyscallFailsWithErrno(EINVAL)); 1248 } 1249 1250 TEST(FcntlTest, SetOwnExInvalidType) { 1251 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1252 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1253 1254 f_owner_ex owner = {}; 1255 owner.type = static_cast<decltype(owner.type)>(-1); 1256 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &owner), 1257 SyscallFailsWithErrno(EINVAL)); 1258 } 1259 1260 TEST(FcntlTest, SetOwnExInvalidTid) { 1261 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1262 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1263 1264 f_owner_ex owner = {}; 1265 owner.type = F_OWNER_TID; 1266 owner.pid = -1; 1267 1268 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &owner), 1269 SyscallFailsWithErrno(ESRCH)); 1270 } 1271 1272 TEST(FcntlTest, SetOwnExInvalidPid) { 1273 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1274 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1275 1276 f_owner_ex owner = {}; 1277 owner.type = F_OWNER_PID; 1278 owner.pid = -1; 1279 1280 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &owner), 1281 SyscallFailsWithErrno(ESRCH)); 1282 } 1283 1284 TEST(FcntlTest, SetOwnExInvalidPgrp) { 1285 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1286 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1287 1288 f_owner_ex owner = {}; 1289 owner.type = F_OWNER_PGRP; 1290 owner.pid = -1; 1291 1292 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &owner), 1293 SyscallFailsWithErrno(ESRCH)); 1294 } 1295 1296 TEST(FcntlTest, SetOwnExTid) { 1297 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1298 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1299 1300 f_owner_ex owner = {}; 1301 owner.type = F_OWNER_TID; 1302 EXPECT_THAT(owner.pid = syscall(__NR_gettid), SyscallSucceeds()); 1303 1304 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &owner), 1305 SyscallSucceedsWithValue(0)); 1306 1307 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN), 1308 SyscallSucceedsWithValue(owner.pid)); 1309 } 1310 1311 TEST(FcntlTest, SetOwnExPid) { 1312 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1313 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1314 1315 f_owner_ex owner = {}; 1316 owner.type = F_OWNER_PID; 1317 EXPECT_THAT(owner.pid = getpid(), SyscallSucceeds()); 1318 1319 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &owner), 1320 SyscallSucceedsWithValue(0)); 1321 1322 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN), 1323 SyscallSucceedsWithValue(owner.pid)); 1324 } 1325 1326 TEST(FcntlTest, SetOwnExPgrp) { 1327 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1328 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1329 1330 f_owner_ex set_owner = {}; 1331 set_owner.type = F_OWNER_PGRP; 1332 EXPECT_THAT(set_owner.pid = getpgrp(), SyscallSucceeds()); 1333 1334 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &set_owner), 1335 SyscallSucceedsWithValue(0)); 1336 1337 // Verify with F_GETOWN_EX; using F_GETOWN on Linux may incorrectly treat the 1338 // negative return value as an error, converting the return value to -1 and 1339 // setting errno accordingly. 1340 f_owner_ex got_owner = {}; 1341 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN_EX, &got_owner), 1342 SyscallSucceedsWithValue(0)); 1343 EXPECT_EQ(got_owner.type, set_owner.type); 1344 EXPECT_EQ(got_owner.pid, set_owner.pid); 1345 } 1346 1347 TEST(FcntlTest, SetOwnExUnset) { 1348 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1349 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1350 1351 // Set and unset pid. 1352 f_owner_ex owner = {}; 1353 owner.type = F_OWNER_PID; 1354 EXPECT_THAT(owner.pid = getpid(), SyscallSucceeds()); 1355 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &owner), 1356 SyscallSucceedsWithValue(0)); 1357 owner.pid = 0; 1358 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &owner), 1359 SyscallSucceedsWithValue(0)); 1360 1361 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN), 1362 SyscallSucceedsWithValue(0)); 1363 1364 // Set and unset pgid. 1365 owner.type = F_OWNER_PGRP; 1366 EXPECT_THAT(owner.pid = getpgrp(), SyscallSucceeds()); 1367 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &owner), 1368 SyscallSucceedsWithValue(0)); 1369 owner.pid = 0; 1370 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &owner), 1371 SyscallSucceedsWithValue(0)); 1372 1373 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN), 1374 SyscallSucceedsWithValue(0)); 1375 } 1376 1377 TEST(FcntlTest, GetOwnExTid) { 1378 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1379 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1380 1381 f_owner_ex set_owner = {}; 1382 set_owner.type = F_OWNER_TID; 1383 EXPECT_THAT(set_owner.pid = syscall(__NR_gettid), SyscallSucceeds()); 1384 1385 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &set_owner), 1386 SyscallSucceedsWithValue(0)); 1387 1388 f_owner_ex got_owner = {}; 1389 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN_EX, &got_owner), 1390 SyscallSucceedsWithValue(0)); 1391 EXPECT_EQ(got_owner.type, set_owner.type); 1392 EXPECT_EQ(got_owner.pid, set_owner.pid); 1393 } 1394 1395 TEST(FcntlTest, GetOwnExPid) { 1396 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1397 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1398 1399 f_owner_ex set_owner = {}; 1400 set_owner.type = F_OWNER_PID; 1401 EXPECT_THAT(set_owner.pid = getpid(), SyscallSucceeds()); 1402 1403 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &set_owner), 1404 SyscallSucceedsWithValue(0)); 1405 1406 f_owner_ex got_owner = {}; 1407 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN_EX, &got_owner), 1408 SyscallSucceedsWithValue(0)); 1409 EXPECT_EQ(got_owner.type, set_owner.type); 1410 EXPECT_EQ(got_owner.pid, set_owner.pid); 1411 } 1412 1413 TEST(FcntlTest, GetOwnExPgrp) { 1414 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1415 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1416 1417 f_owner_ex set_owner = {}; 1418 set_owner.type = F_OWNER_PGRP; 1419 EXPECT_THAT(set_owner.pid = getpgrp(), SyscallSucceeds()); 1420 1421 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN_EX, &set_owner), 1422 SyscallSucceedsWithValue(0)); 1423 1424 f_owner_ex got_owner = {}; 1425 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_GETOWN_EX, &got_owner), 1426 SyscallSucceedsWithValue(0)); 1427 EXPECT_EQ(got_owner.type, set_owner.type); 1428 EXPECT_EQ(got_owner.pid, set_owner.pid); 1429 } 1430 1431 TEST(FcntlTest, SetSig) { 1432 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1433 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1434 1435 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETSIG, SIGUSR1), 1436 SyscallSucceedsWithValue(0)); 1437 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETSIG), 1438 SyscallSucceedsWithValue(SIGUSR1)); 1439 } 1440 1441 TEST(FcntlTest, SetSigDefaultsToZero) { 1442 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1443 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1444 1445 // Defaults to returning the zero value, indicating default behavior (SIGIO). 1446 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETSIG), 1447 SyscallSucceedsWithValue(0)); 1448 } 1449 1450 TEST(FcntlTest, SetSigToDefault) { 1451 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1452 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1453 1454 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETSIG, SIGIO), 1455 SyscallSucceedsWithValue(0)); 1456 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_GETSIG), 1457 SyscallSucceedsWithValue(SIGIO)); 1458 1459 // Can be reset to the default behavior. 1460 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETSIG, 0), 1461 SyscallSucceedsWithValue(0)); 1462 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETSIG), 1463 SyscallSucceedsWithValue(0)); 1464 } 1465 1466 TEST(FcntlTest, SetSigInvalid) { 1467 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1468 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1469 1470 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETSIG, SIGRTMAX + 1), 1471 SyscallFailsWithErrno(EINVAL)); 1472 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETSIG), 1473 SyscallSucceedsWithValue(0)); 1474 } 1475 1476 TEST(FcntlTest, SetSigInvalidDoesNotResetPreviousChoice) { 1477 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1478 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1479 1480 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETSIG, SIGUSR1), 1481 SyscallSucceedsWithValue(0)); 1482 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETSIG, SIGRTMAX + 1), 1483 SyscallFailsWithErrno(EINVAL)); 1484 EXPECT_THAT(syscall(__NR_fcntl, s.get(), F_GETSIG), 1485 SyscallSucceedsWithValue(SIGUSR1)); 1486 } 1487 1488 TEST_F(FcntlSignalTest, SetSigDefault) { 1489 const auto signal_cleanup = 1490 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGIO)); 1491 RegisterFD(pipe_read_fd_, 0); // Zero = default behavior 1492 GenerateIOEvent(); 1493 WaitForSignalDelivery(absl::Seconds(1)); 1494 ASSERT_EQ(num_signals_received_, 1); 1495 SignalDelivery sig = signals_received_.front(); 1496 signals_received_.pop_front(); 1497 EXPECT_EQ(sig.num, SIGIO); 1498 EXPECT_EQ(sig.info.si_signo, SIGIO); 1499 // siginfo contents is undefined in this case. 1500 } 1501 1502 TEST_F(FcntlSignalTest, SignalFD) { 1503 // Create the signalfd. 1504 sigset_t mask; 1505 sigemptyset(&mask); 1506 sigaddset(&mask, SIGIO); 1507 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask, 0)); 1508 const auto signal_cleanup = 1509 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGIO)); 1510 RegisterFD(fd.get(), 0); 1511 int tid = syscall(SYS_gettid); 1512 syscall(SYS_tkill, tid, SIGIO); 1513 } 1514 1515 TEST_F(FcntlSignalTest, SignalFDSetSigAfterASYNC) { 1516 // Create the signalfd. 1517 sigset_t mask; 1518 sigemptyset(&mask); 1519 sigaddset(&mask, SIGIO); 1520 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask, 0)); 1521 1522 const auto signal_cleanup = 1523 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGIO)); 1524 ASSERT_THAT(fcntl(fd.get(), F_SETOWN, getpid()), SyscallSucceeds()); 1525 int old_flags; 1526 ASSERT_THAT(old_flags = fcntl(fd.get(), F_GETFL), SyscallSucceeds()); 1527 ASSERT_THAT(fcntl(fd.get(), F_SETFL, old_flags | O_ASYNC), SyscallSucceeds()); 1528 ASSERT_THAT(fcntl(fd.get(), F_SETSIG, 0), SyscallSucceeds()); 1529 1530 int tid = syscall(SYS_gettid); 1531 syscall(SYS_tkill, tid, SIGIO); 1532 } 1533 1534 TEST_F(FcntlSignalTest, SetSigCustom) { 1535 const auto signal_cleanup = 1536 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR1)); 1537 RegisterFD(pipe_read_fd_, SIGUSR1); 1538 GenerateIOEvent(); 1539 WaitForSignalDelivery(absl::Seconds(1)); 1540 ASSERT_EQ(num_signals_received_, 1); 1541 SignalDelivery sig = signals_received_.front(); 1542 signals_received_.pop_front(); 1543 EXPECT_EQ(sig.num, SIGUSR1); 1544 EXPECT_EQ(sig.info.si_signo, SIGUSR1); 1545 EXPECT_EQ(sig.info.si_fd, pipe_read_fd_); 1546 EXPECT_EQ(sig.info.si_band, EPOLLIN | EPOLLRDNORM); 1547 } 1548 1549 TEST_F(FcntlSignalTest, SetSigUnregisterStillGetsSigio) { 1550 const auto sigio_cleanup = 1551 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGIO)); 1552 const auto sigusr1_cleanup = 1553 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR1)); 1554 RegisterFD(pipe_read_fd_, SIGUSR1); 1555 RegisterFD(pipe_read_fd_, 0); 1556 GenerateIOEvent(); 1557 WaitForSignalDelivery(absl::Seconds(1)); 1558 ASSERT_EQ(num_signals_received_, 1); 1559 SignalDelivery sig = signals_received_.front(); 1560 signals_received_.pop_front(); 1561 EXPECT_EQ(sig.num, SIGIO); 1562 // siginfo contents is undefined in this case. 1563 } 1564 1565 TEST_F(FcntlSignalTest, SetSigWithSigioStillGetsSiginfo) { 1566 const auto signal_cleanup = 1567 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGIO)); 1568 RegisterFD(pipe_read_fd_, SIGIO); 1569 GenerateIOEvent(); 1570 WaitForSignalDelivery(absl::Seconds(1)); 1571 ASSERT_EQ(num_signals_received_, 1); 1572 SignalDelivery sig = signals_received_.front(); 1573 EXPECT_EQ(sig.num, SIGIO); 1574 EXPECT_EQ(sig.info.si_signo, SIGIO); 1575 EXPECT_EQ(sig.info.si_fd, pipe_read_fd_); 1576 EXPECT_EQ(sig.info.si_band, EPOLLIN | EPOLLRDNORM); 1577 } 1578 1579 TEST_F(FcntlSignalTest, SetSigDupThenCloseOld) { 1580 const auto sigusr1_cleanup = 1581 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR1)); 1582 RegisterFD(pipe_read_fd_, SIGUSR1); 1583 DupReadFD(); 1584 FlushAndCloseFD(pipe_read_fd_); 1585 GenerateIOEvent(); 1586 WaitForSignalDelivery(absl::Seconds(1)); 1587 ASSERT_EQ(num_signals_received_, 1); 1588 SignalDelivery sig = signals_received_.front(); 1589 // We get a signal with the **old** FD (even though it is closed). 1590 EXPECT_EQ(sig.num, SIGUSR1); 1591 EXPECT_EQ(sig.info.si_signo, SIGUSR1); 1592 EXPECT_EQ(sig.info.si_fd, pipe_read_fd_); 1593 EXPECT_EQ(sig.info.si_band, EPOLLIN | EPOLLRDNORM); 1594 } 1595 1596 TEST_F(FcntlSignalTest, SetSigDupThenCloseNew) { 1597 const auto sigusr1_cleanup = 1598 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR1)); 1599 RegisterFD(pipe_read_fd_, SIGUSR1); 1600 DupReadFD(); 1601 FlushAndCloseFD(pipe_read_fd_dup_); 1602 GenerateIOEvent(); 1603 WaitForSignalDelivery(absl::Seconds(1)); 1604 ASSERT_EQ(num_signals_received_, 1); 1605 SignalDelivery sig = signals_received_.front(); 1606 // We get a signal with the old FD. 1607 EXPECT_EQ(sig.num, SIGUSR1); 1608 EXPECT_EQ(sig.info.si_signo, SIGUSR1); 1609 EXPECT_EQ(sig.info.si_fd, pipe_read_fd_); 1610 EXPECT_EQ(sig.info.si_band, EPOLLIN | EPOLLRDNORM); 1611 } 1612 1613 TEST_F(FcntlSignalTest, SetSigDupOldRegistered) { 1614 const auto sigusr1_cleanup = 1615 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR1)); 1616 RegisterFD(pipe_read_fd_, SIGUSR1); 1617 DupReadFD(); 1618 GenerateIOEvent(); 1619 WaitForSignalDelivery(absl::Seconds(1)); 1620 ASSERT_EQ(num_signals_received_, 1); 1621 SignalDelivery sig = signals_received_.front(); 1622 // We get a signal with the old FD. 1623 EXPECT_EQ(sig.num, SIGUSR1); 1624 EXPECT_EQ(sig.info.si_signo, SIGUSR1); 1625 EXPECT_EQ(sig.info.si_fd, pipe_read_fd_); 1626 EXPECT_EQ(sig.info.si_band, EPOLLIN | EPOLLRDNORM); 1627 } 1628 1629 TEST_F(FcntlSignalTest, SetSigDupNewRegistered) { 1630 const auto sigusr2_cleanup = 1631 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR2)); 1632 DupReadFD(); 1633 RegisterFD(pipe_read_fd_dup_, SIGUSR2); 1634 GenerateIOEvent(); 1635 WaitForSignalDelivery(absl::Seconds(1)); 1636 ASSERT_EQ(num_signals_received_, 1); 1637 SignalDelivery sig = signals_received_.front(); 1638 // We get a signal with the new FD. 1639 EXPECT_EQ(sig.num, SIGUSR2); 1640 EXPECT_EQ(sig.info.si_signo, SIGUSR2); 1641 EXPECT_EQ(sig.info.si_fd, pipe_read_fd_dup_); 1642 EXPECT_EQ(sig.info.si_band, EPOLLIN | EPOLLRDNORM); 1643 } 1644 1645 TEST_F(FcntlSignalTest, SetSigDupBothRegistered) { 1646 const auto sigusr1_cleanup = 1647 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR1)); 1648 const auto sigusr2_cleanup = 1649 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR2)); 1650 RegisterFD(pipe_read_fd_, SIGUSR1); 1651 DupReadFD(); 1652 RegisterFD(pipe_read_fd_dup_, SIGUSR2); 1653 GenerateIOEvent(); 1654 WaitForSignalDelivery(absl::Seconds(1)); 1655 ASSERT_EQ(num_signals_received_, 1); 1656 SignalDelivery sig = signals_received_.front(); 1657 // We get a signal with the **new** signal number, but the **old** FD. 1658 EXPECT_EQ(sig.num, SIGUSR2); 1659 EXPECT_EQ(sig.info.si_signo, SIGUSR2); 1660 EXPECT_EQ(sig.info.si_fd, pipe_read_fd_); 1661 EXPECT_EQ(sig.info.si_band, EPOLLIN | EPOLLRDNORM); 1662 } 1663 1664 TEST_F(FcntlSignalTest, SetSigDupBothRegisteredAfterDup) { 1665 const auto sigusr1_cleanup = 1666 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR1)); 1667 const auto sigusr2_cleanup = 1668 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR2)); 1669 DupReadFD(); 1670 RegisterFD(pipe_read_fd_, SIGUSR1); 1671 RegisterFD(pipe_read_fd_dup_, SIGUSR2); 1672 GenerateIOEvent(); 1673 WaitForSignalDelivery(absl::Seconds(1)); 1674 ASSERT_EQ(num_signals_received_, 1); 1675 SignalDelivery sig = signals_received_.front(); 1676 // We get a signal with the **new** signal number, but the **old** FD. 1677 EXPECT_EQ(sig.num, SIGUSR2); 1678 EXPECT_EQ(sig.info.si_signo, SIGUSR2); 1679 EXPECT_EQ(sig.info.si_fd, pipe_read_fd_); 1680 EXPECT_EQ(sig.info.si_band, EPOLLIN | EPOLLRDNORM); 1681 } 1682 1683 TEST_F(FcntlSignalTest, SetSigDupUnregisterOld) { 1684 const auto sigio_cleanup = 1685 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGIO)); 1686 const auto sigusr1_cleanup = 1687 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR1)); 1688 const auto sigusr2_cleanup = 1689 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR2)); 1690 RegisterFD(pipe_read_fd_, SIGUSR1); 1691 DupReadFD(); 1692 RegisterFD(pipe_read_fd_dup_, SIGUSR2); 1693 RegisterFD(pipe_read_fd_, 0); // Should go back to SIGIO behavior. 1694 GenerateIOEvent(); 1695 WaitForSignalDelivery(absl::Seconds(1)); 1696 ASSERT_EQ(num_signals_received_, 1); 1697 SignalDelivery sig = signals_received_.front(); 1698 // We get a signal with SIGIO. 1699 EXPECT_EQ(sig.num, SIGIO); 1700 // siginfo is undefined in this case. 1701 } 1702 1703 TEST_F(FcntlSignalTest, SetSigDupUnregisterNew) { 1704 const auto sigio_cleanup = 1705 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGIO)); 1706 const auto sigusr1_cleanup = 1707 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR1)); 1708 const auto sigusr2_cleanup = 1709 ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR2)); 1710 RegisterFD(pipe_read_fd_, SIGUSR1); 1711 DupReadFD(); 1712 RegisterFD(pipe_read_fd_dup_, SIGUSR2); 1713 RegisterFD(pipe_read_fd_dup_, 0); // Should go back to SIGIO behavior. 1714 GenerateIOEvent(); 1715 WaitForSignalDelivery(absl::Seconds(1)); 1716 ASSERT_EQ(num_signals_received_, 1); 1717 SignalDelivery sig = signals_received_.front(); 1718 // We get a signal with SIGIO. 1719 EXPECT_EQ(sig.num, SIGIO); 1720 // siginfo is undefined in this case. 1721 } 1722 1723 // Make sure that making multiple concurrent changes to async signal generation 1724 // does not cause any race issues. 1725 TEST(FcntlTest, SetFlSetOwnSetSigDoNotRace) { 1726 FileDescriptor s = ASSERT_NO_ERRNO_AND_VALUE( 1727 Socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); 1728 1729 pid_t pid; 1730 EXPECT_THAT(pid = getpid(), SyscallSucceeds()); 1731 1732 constexpr absl::Duration runtime = absl::Milliseconds(300); 1733 auto set_async = [&s, &runtime] { 1734 for (auto start = absl::Now(); absl::Now() - start < runtime;) { 1735 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETFL, O_ASYNC), 1736 SyscallSucceeds()); 1737 sched_yield(); 1738 } 1739 }; 1740 auto reset_async = [&s, &runtime] { 1741 for (auto start = absl::Now(); absl::Now() - start < runtime;) { 1742 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETFL, 0), SyscallSucceeds()); 1743 sched_yield(); 1744 } 1745 }; 1746 auto set_own = [&s, &pid, &runtime] { 1747 for (auto start = absl::Now(); absl::Now() - start < runtime;) { 1748 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETOWN, pid), 1749 SyscallSucceeds()); 1750 sched_yield(); 1751 } 1752 }; 1753 auto set_sig = [&s, &runtime] { 1754 for (auto start = absl::Now(); absl::Now() - start < runtime;) { 1755 ASSERT_THAT(syscall(__NR_fcntl, s.get(), F_SETSIG, SIGUSR1), 1756 SyscallSucceeds()); 1757 sched_yield(); 1758 } 1759 }; 1760 1761 std::list<ScopedThread> threads; 1762 for (int i = 0; i < 10; i++) { 1763 threads.emplace_back(set_async); 1764 threads.emplace_back(reset_async); 1765 threads.emplace_back(set_own); 1766 threads.emplace_back(set_sig); 1767 } 1768 } 1769 1770 TEST_F(FcntlLockTest, GetLockOnNothing) { 1771 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 1772 FileDescriptor fd = 1773 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 1774 1775 struct flock fl; 1776 fl.l_type = F_RDLCK; 1777 fl.l_whence = SEEK_SET; 1778 fl.l_start = 0; 1779 fl.l_len = 40; 1780 ASSERT_THAT(fcntl(fd.get(), F_GETLK, &fl), SyscallSucceeds()); 1781 ASSERT_TRUE(fl.l_type == F_UNLCK); 1782 } 1783 1784 TEST_F(FcntlLockTest, GetLockOnLockSameProcess) { 1785 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 1786 FileDescriptor fd = 1787 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 1788 1789 struct flock fl; 1790 fl.l_type = F_RDLCK; 1791 fl.l_whence = SEEK_SET; 1792 fl.l_start = 0; 1793 fl.l_len = 40; 1794 ASSERT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 1795 ASSERT_THAT(fcntl(fd.get(), F_GETLK, &fl), SyscallSucceeds()); 1796 ASSERT_TRUE(fl.l_type == F_UNLCK); 1797 1798 fl.l_type = F_WRLCK; 1799 ASSERT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 1800 ASSERT_THAT(fcntl(fd.get(), F_GETLK, &fl), SyscallSucceeds()); 1801 ASSERT_TRUE(fl.l_type == F_UNLCK); 1802 } 1803 1804 TEST_F(FcntlLockTest, GetReadLockOnReadLock) { 1805 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 1806 FileDescriptor fd = 1807 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 1808 1809 struct flock fl; 1810 fl.l_type = F_RDLCK; 1811 fl.l_whence = SEEK_SET; 1812 fl.l_start = 0; 1813 fl.l_len = 40; 1814 ASSERT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 1815 1816 pid_t child_pid = fork(); 1817 if (child_pid == 0) { 1818 TEST_CHECK(fcntl(fd.get(), F_GETLK, &fl) >= 0); 1819 TEST_CHECK(fl.l_type == F_UNLCK); 1820 _exit(0); 1821 } 1822 int status; 1823 ASSERT_THAT(waitpid(child_pid, &status, 0), 1824 SyscallSucceedsWithValue(child_pid)); 1825 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0); 1826 } 1827 1828 TEST_F(FcntlLockTest, GetReadLockOnWriteLock) { 1829 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 1830 FileDescriptor fd = 1831 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 1832 1833 struct flock fl; 1834 fl.l_type = F_WRLCK; 1835 fl.l_whence = SEEK_SET; 1836 fl.l_start = 0; 1837 fl.l_len = 40; 1838 ASSERT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 1839 1840 fl.l_type = F_RDLCK; 1841 pid_t child_pid = fork(); 1842 if (child_pid == 0) { 1843 TEST_CHECK(fcntl(fd.get(), F_GETLK, &fl) >= 0); 1844 TEST_CHECK(fl.l_type == F_WRLCK); 1845 TEST_CHECK(fl.l_pid == getppid()); 1846 _exit(0); 1847 } 1848 1849 int status; 1850 ASSERT_THAT(waitpid(child_pid, &status, 0), 1851 SyscallSucceedsWithValue(child_pid)); 1852 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0); 1853 } 1854 1855 TEST_F(FcntlLockTest, GetWriteLockOnReadLock) { 1856 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 1857 FileDescriptor fd = 1858 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 1859 1860 struct flock fl; 1861 fl.l_type = F_RDLCK; 1862 fl.l_whence = SEEK_SET; 1863 fl.l_start = 0; 1864 fl.l_len = 40; 1865 ASSERT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 1866 1867 fl.l_type = F_WRLCK; 1868 pid_t child_pid = fork(); 1869 if (child_pid == 0) { 1870 TEST_CHECK(fcntl(fd.get(), F_GETLK, &fl) >= 0); 1871 TEST_CHECK(fl.l_type == F_RDLCK); 1872 TEST_CHECK(fl.l_pid == getppid()); 1873 _exit(0); 1874 } 1875 1876 int status; 1877 ASSERT_THAT(waitpid(child_pid, &status, 0), 1878 SyscallSucceedsWithValue(child_pid)); 1879 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0); 1880 } 1881 1882 TEST_F(FcntlLockTest, GetWriteLockOnWriteLock) { 1883 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 1884 FileDescriptor fd = 1885 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 1886 1887 struct flock fl; 1888 fl.l_type = F_WRLCK; 1889 fl.l_whence = SEEK_SET; 1890 fl.l_start = 0; 1891 fl.l_len = 40; 1892 ASSERT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 1893 1894 pid_t child_pid = fork(); 1895 if (child_pid == 0) { 1896 TEST_CHECK(fcntl(fd.get(), F_GETLK, &fl) >= 0); 1897 TEST_CHECK(fl.l_type == F_WRLCK); 1898 TEST_CHECK(fl.l_pid == getppid()); 1899 _exit(0); 1900 } 1901 1902 int status; 1903 ASSERT_THAT(waitpid(child_pid, &status, 0), 1904 SyscallSucceedsWithValue(child_pid)); 1905 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0); 1906 } 1907 1908 // Tests that the pid returned from F_GETLK is relative to the caller's PID 1909 // namespace. 1910 TEST_F(FcntlLockTest, GetLockRespectsPIDNamespace) { 1911 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN))); 1912 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 1913 std::string filename = file.path(); 1914 const FileDescriptor fd = 1915 ASSERT_NO_ERRNO_AND_VALUE(Open(filename, O_RDWR, 0666)); 1916 1917 // Lock in the parent process. 1918 struct flock fl; 1919 fl.l_type = F_WRLCK; 1920 fl.l_whence = SEEK_SET; 1921 fl.l_start = 0; 1922 fl.l_len = 40; 1923 ASSERT_THAT(fcntl(fd.get(), F_SETLK, &fl), SyscallSucceeds()); 1924 1925 auto child_getlk = [](void* filename) { 1926 int fd = open((char*)filename, O_RDWR, 0666); 1927 TEST_CHECK(fd >= 0); 1928 1929 struct flock fl; 1930 fl.l_type = F_WRLCK; 1931 fl.l_whence = SEEK_SET; 1932 fl.l_start = 0; 1933 fl.l_len = 40; 1934 TEST_CHECK(fcntl(fd, F_GETLK, &fl) >= 0); 1935 TEST_CHECK(fl.l_type == F_WRLCK); 1936 // Parent PID should be 0 in the child PID namespace. 1937 TEST_CHECK(fl.l_pid == 0); 1938 close(fd); 1939 return 0; 1940 }; 1941 1942 // Set up child process in a new PID namespace. 1943 constexpr int kStackSize = 4096; 1944 Mapping stack = ASSERT_NO_ERRNO_AND_VALUE( 1945 Mmap(nullptr, kStackSize, PROT_READ | PROT_WRITE, 1946 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0)); 1947 pid_t child_pid; 1948 ASSERT_THAT( 1949 child_pid = clone(child_getlk, (char*)stack.ptr() + stack.len(), 1950 CLONE_NEWPID | SIGCHLD, (void*)filename.c_str()), 1951 SyscallSucceeds()); 1952 1953 int status; 1954 ASSERT_THAT(waitpid(child_pid, &status, 0), 1955 SyscallSucceedsWithValue(child_pid)); 1956 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0); 1957 } 1958 1959 TEST_F(FcntlLockTest, TestOFDBasicLock) { 1960 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 1961 FileDescriptor fd1 = 1962 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 1963 1964 struct flock fl = { 1965 .l_type = F_WRLCK, 1966 .l_whence = SEEK_SET, 1967 .l_start = 0, 1968 .l_len = 0, 1969 .l_pid = 0, 1970 }; 1971 ASSERT_THAT(fcntl(fd1.get(), F_OFD_SETLK, &fl), SyscallSucceeds()); 1972 1973 FileDescriptor fd2 = 1974 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 1975 // Locking from a different file descriptor should fail. 1976 ASSERT_THAT(fcntl(fd2.get(), F_OFD_SETLK, &fl), 1977 SyscallFailsWithErrno(EAGAIN)); 1978 1979 fl.l_type = F_UNLCK; 1980 ASSERT_THAT(fcntl(fd1.get(), F_OFD_SETLK, &fl), SyscallSucceeds()); 1981 1982 fl.l_type = F_WRLCK; 1983 ASSERT_THAT(fcntl(fd2.get(), F_OFD_SETLK, &fl), SyscallSucceeds()); 1984 } 1985 1986 TEST_F(FcntlLockTest, TestOFDLockNonZeroPidFails) { 1987 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 1988 FileDescriptor fd1 = 1989 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 1990 1991 struct flock fl = { 1992 .l_type = F_WRLCK, 1993 .l_whence = SEEK_SET, 1994 .l_start = 0, 1995 .l_len = 0, 1996 .l_pid = 1, 1997 }; 1998 ASSERT_THAT(fcntl(fd1.get(), F_OFD_SETLK, &fl), 1999 SyscallFailsWithErrno(EINVAL)); 2000 } 2001 2002 TEST_F(FcntlLockTest, TestOFDNoUnlockOnClose) { 2003 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 2004 struct flock fl = { 2005 .l_type = F_RDLCK, 2006 .l_whence = SEEK_SET, 2007 .l_start = 0, 2008 .l_len = 0, 2009 .l_pid = 0, 2010 }; 2011 FileDescriptor fd1 = 2012 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 2013 FileDescriptor fd2 = 2014 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 2015 2016 ASSERT_THAT(fcntl(fd1.get(), F_OFD_SETLK, &fl), SyscallSucceeds()); 2017 ASSERT_THAT(fcntl(fd2.get(), F_OFD_SETLK, &fl), SyscallSucceeds()); 2018 2019 FileDescriptor fd3 = 2020 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 2021 2022 // Close should not release all locks, just the one associated with the closed 2023 // file descriptor. 2024 ASSERT_THAT(close(fd1.release()), SyscallSucceeds()); 2025 fl.l_type = F_WRLCK; 2026 ASSERT_THAT(fcntl(fd3.get(), F_OFD_GETLK, &fl), SyscallSucceeds()); 2027 ASSERT_EQ(fl.l_type, F_RDLCK); 2028 } 2029 2030 TEST_F(FcntlLockTest, TestOFDUnlocksOnLastClose) { 2031 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 2032 struct flock fl = { 2033 .l_type = F_RDLCK, 2034 .l_whence = SEEK_SET, 2035 .l_start = 0, 2036 .l_len = 0, 2037 .l_pid = 0, 2038 }; 2039 FileDescriptor fd1 = 2040 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 2041 FileDescriptor fd2 = 2042 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 2043 2044 ASSERT_THAT(fcntl(fd1.get(), F_OFD_SETLK, &fl), SyscallSucceeds()); 2045 ASSERT_THAT(fcntl(fd2.get(), F_OFD_SETLK, &fl), SyscallSucceeds()); 2046 ASSERT_THAT(close(fd1.release()), SyscallSucceeds()); 2047 ASSERT_THAT(close(fd2.release()), SyscallSucceeds()); 2048 2049 FileDescriptor fd3 = 2050 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 2051 fl.l_type = F_WRLCK; 2052 ASSERT_THAT(fcntl(fd3.get(), F_OFD_GETLK, &fl), SyscallSucceeds()); 2053 ASSERT_EQ(fl.l_type, F_UNLCK); 2054 } 2055 2056 TEST_F(FcntlLockTest, TestOFDInheritsLockAfterDup) { 2057 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 2058 struct flock fl = { 2059 .l_type = F_WRLCK, 2060 .l_whence = SEEK_SET, 2061 .l_start = 0, 2062 .l_len = 0, 2063 .l_pid = 0, 2064 }; 2065 FileDescriptor fd1 = 2066 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 2067 ASSERT_THAT(fcntl(fd1.get(), F_OFD_SETLK, &fl), SyscallSucceeds()); 2068 FileDescriptor duped = ASSERT_NO_ERRNO_AND_VALUE(fd1.Dup()); 2069 ASSERT_THAT(close(fd1.release()), SyscallSucceeds()); 2070 2071 FileDescriptor fd2 = 2072 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 2073 ASSERT_THAT(fcntl(fd2.get(), F_OFD_SETLK, &fl), 2074 SyscallFailsWithErrno(EAGAIN)); 2075 } 2076 2077 TEST_F(FcntlLockTest, TestOFDLocksHoldAfterExec) { 2078 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 2079 FileDescriptor fd = 2080 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 2081 2082 // Setup two regional locks with different permissions. 2083 struct flock fl0; 2084 fl0.l_type = F_WRLCK; 2085 fl0.l_whence = SEEK_SET; 2086 fl0.l_start = 0; 2087 fl0.l_len = 4096; 2088 fl0.l_pid = 0; 2089 2090 struct flock fl1; 2091 fl1.l_type = F_RDLCK; 2092 fl1.l_whence = SEEK_SET; 2093 fl1.l_start = 4096; 2094 // Same as SetLockBadFd. 2095 fl1.l_len = 0; 2096 fl1.l_pid = 0; 2097 2098 // Set both region locks. 2099 EXPECT_THAT(fcntl(fd.get(), F_OFD_SETLK, &fl0), SyscallSucceeds()); 2100 EXPECT_THAT(fcntl(fd.get(), F_OFD_SETLK, &fl1), SyscallSucceeds()); 2101 2102 // Another process should fail to take a read lock on the entire file 2103 // due to the regional write lock. 2104 pid_t child_pid = 0; 2105 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 2106 SubprocessLock(file.path(), false /* write lock */, 2107 false /* nonblocking */, false /* no eintr retry */, 2108 nullptr /* no socket fd */, 0, 0, &child_pid)); 2109 2110 int status = 0; 2111 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 2112 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == EAGAIN) 2113 << "Exited with code: " << status; 2114 } 2115 2116 TEST_F(FcntlLockTest, TestOFDGetLkReturnsNegPID) { 2117 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 2118 struct flock fl = { 2119 .l_type = F_WRLCK, 2120 .l_whence = SEEK_SET, 2121 .l_start = 0, 2122 .l_len = 0, 2123 .l_pid = 0, 2124 }; 2125 FileDescriptor fd1 = 2126 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 2127 ASSERT_THAT(fcntl(fd1.get(), F_OFD_SETLK, &fl), SyscallSucceeds()); 2128 FileDescriptor fd2 = 2129 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 2130 ASSERT_THAT(fcntl(fd2.get(), F_OFD_GETLK, &fl), SyscallSucceeds()); 2131 ASSERT_EQ(fl.l_pid, -1); 2132 } 2133 2134 TEST_F(FcntlLockTest, TestOFDCanUpgradeLock) { 2135 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 2136 struct flock fl = { 2137 .l_type = F_RDLCK, 2138 .l_whence = SEEK_SET, 2139 .l_start = 0, 2140 .l_len = 0, 2141 .l_pid = 0, 2142 }; 2143 FileDescriptor fd1 = 2144 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR, 0666)); 2145 ASSERT_THAT(fcntl(fd1.get(), F_OFD_SETLK, &fl), SyscallSucceeds()); 2146 2147 fl.l_type = F_WRLCK; 2148 ASSERT_THAT(fcntl(fd1.get(), F_OFD_GETLK, &fl), SyscallSucceeds()); 2149 ASSERT_EQ(fl.l_type, F_UNLCK); 2150 } 2151 2152 } // namespace 2153 2154 } // namespace testing 2155 } // namespace gvisor 2156 2157 int set_lock() { 2158 const std::string set_lock_on = absl::GetFlag(FLAGS_child_set_lock_on); 2159 int socket_fd = absl::GetFlag(FLAGS_socket_fd); 2160 int fd = open(set_lock_on.c_str(), O_RDWR, 0666); 2161 if (fd == -1 && errno != 0) { 2162 int err = errno; 2163 std::cerr << "CHILD open " << set_lock_on << " failed: " << err 2164 << std::endl; 2165 return err; 2166 } 2167 2168 struct flock fl; 2169 if (absl::GetFlag(FLAGS_child_set_lock_write)) { 2170 fl.l_type = F_WRLCK; 2171 } else { 2172 fl.l_type = F_RDLCK; 2173 } 2174 fl.l_whence = SEEK_SET; 2175 fl.l_start = absl::GetFlag(FLAGS_child_set_lock_start); 2176 fl.l_len = absl::GetFlag(FLAGS_child_set_lock_len); 2177 2178 if (socket_fd != -1) { 2179 // Send signal to the parent. 2180 char c = 0; 2181 gvisor::testing::WriteFd(socket_fd, reinterpret_cast<void*>(&c), 2182 sizeof(c)); 2183 } 2184 // Test the fcntl. 2185 int err = 0; 2186 int ret = 0; 2187 2188 gvisor::testing::MonotonicTimer timer; 2189 timer.Start(); 2190 do { 2191 ret = fcntl(fd, absl::GetFlag(FLAGS_blocking) ? F_SETLKW : F_SETLK, &fl); 2192 } while (absl::GetFlag(FLAGS_retry_eintr) && ret == -1 && errno == EINTR); 2193 auto usec = absl::ToInt64Microseconds(timer.Duration()); 2194 2195 if (ret == -1 && errno != 0) { 2196 err = errno; 2197 std::cerr << "CHILD lock " << set_lock_on << " failed " << err << std::endl; 2198 } 2199 2200 // If there is a socket fd let's send back the time in microseconds it took 2201 // to execute this syscall. 2202 if (socket_fd != -1) { 2203 gvisor::testing::WriteFd(socket_fd, reinterpret_cast<void*>(&usec), 2204 sizeof(usec)); 2205 close(socket_fd); 2206 } 2207 2208 close(fd); 2209 return err; 2210 } 2211 2212 int main(int argc, char** argv) { 2213 gvisor::testing::TestInit(&argc, &argv); 2214 2215 if (!absl::GetFlag(FLAGS_child_set_lock_on).empty()) { 2216 exit(set_lock()); 2217 } 2218 2219 return gvisor::testing::RunAllTests(); 2220 }