gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/flock.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 <errno.h>
    16  #include <sys/file.h>
    17  
    18  #include <string>
    19  
    20  #include "gtest/gtest.h"
    21  #include "absl/time/clock.h"
    22  #include "absl/time/time.h"
    23  #include "test/syscalls/linux/file_base.h"
    24  #include "test/util/file_descriptor.h"
    25  #include "test/util/socket_util.h"
    26  #include "test/util/temp_path.h"
    27  #include "test/util/test_util.h"
    28  #include "test/util/thread_util.h"
    29  #include "test/util/timer_util.h"
    30  
    31  namespace gvisor {
    32  namespace testing {
    33  
    34  namespace {
    35  
    36  class FlockTest : public FileTest {};
    37  
    38  TEST_F(FlockTest, InvalidOpCombinations) {
    39    // The operation cannot be both exclusive and shared.
    40    EXPECT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_SH | LOCK_NB),
    41                SyscallFailsWithErrno(EINVAL));
    42  
    43    // Locking and Unlocking doesn't make sense.
    44    EXPECT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_UN | LOCK_NB),
    45                SyscallFailsWithErrno(EINVAL));
    46    EXPECT_THAT(flock(test_file_fd_.get(), LOCK_SH | LOCK_UN | LOCK_NB),
    47                SyscallFailsWithErrno(EINVAL));
    48  }
    49  
    50  TEST_F(FlockTest, NoOperationSpecified) {
    51    // Not specifying an operation is invalid.
    52    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_NB),
    53                SyscallFailsWithErrno(EINVAL));
    54  }
    55  
    56  TEST_F(FlockTest, TestSimpleExLock) {
    57    // Test that we can obtain an exclusive lock (no other holders)
    58    // and that we can unlock it.
    59    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
    60                SyscallSucceedsWithValue(0));
    61    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
    62  }
    63  
    64  TEST_F(FlockTest, TestSimpleShLock) {
    65    // Test that we can obtain a shared lock (no other holders)
    66    // and that we can unlock it.
    67    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_SH | LOCK_NB),
    68                SyscallSucceedsWithValue(0));
    69    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
    70  }
    71  
    72  TEST_F(FlockTest, TestLockableAnyMode) {
    73    // flock(2): A shared or exclusive lock can be placed on a file
    74    // regardless of the mode in which the file was opened.
    75    const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(
    76        Open(test_file_name_, O_RDONLY));  // open read only to test
    77  
    78    // Mode shouldn't prevent us from taking an exclusive lock.
    79    ASSERT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB), SyscallSucceedsWithValue(0));
    80  
    81    // Unlock
    82    ASSERT_THAT(flock(fd.get(), LOCK_UN), SyscallSucceedsWithValue(0));
    83  }
    84  
    85  TEST_F(FlockTest, TestUnlockWithNoHolders) {
    86    // Test that unlocking when no one holds a lock succeeeds.
    87    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
    88  }
    89  
    90  TEST_F(FlockTest, TestRepeatedExLockingBySameHolder) {
    91    // Test that repeated locking by the same holder for the
    92    // same type of lock works correctly.
    93    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_NB | LOCK_EX),
    94                SyscallSucceedsWithValue(0));
    95    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_NB | LOCK_EX),
    96                SyscallSucceedsWithValue(0));
    97    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
    98  }
    99  
   100  TEST_F(FlockTest, TestRepeatedExLockingSingleUnlock) {
   101    // Test that repeated locking by the same holder for the
   102    // same type of lock works correctly and that a single unlock is required.
   103    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_NB | LOCK_EX),
   104                SyscallSucceedsWithValue(0));
   105    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_NB | LOCK_EX),
   106                SyscallSucceedsWithValue(0));
   107    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   108  
   109    const FileDescriptor fd =
   110        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDONLY));
   111  
   112    // Should be unlocked at this point
   113    ASSERT_THAT(flock(fd.get(), LOCK_NB | LOCK_EX), SyscallSucceedsWithValue(0));
   114  
   115    ASSERT_THAT(flock(fd.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   116  }
   117  
   118  TEST_F(FlockTest, TestRepeatedShLockingBySameHolder) {
   119    // Test that repeated locking by the same holder for the
   120    // same type of lock works correctly.
   121    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_NB | LOCK_SH),
   122                SyscallSucceedsWithValue(0));
   123    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_NB | LOCK_SH),
   124                SyscallSucceedsWithValue(0));
   125    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   126  }
   127  
   128  TEST_F(FlockTest, TestSingleHolderUpgrade) {
   129    // Test that a shared lock is upgradable when no one else holds a lock.
   130    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_NB | LOCK_SH),
   131                SyscallSucceedsWithValue(0));
   132    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_NB | LOCK_EX),
   133                SyscallSucceedsWithValue(0));
   134    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   135  }
   136  
   137  TEST_F(FlockTest, TestSingleHolderDowngrade) {
   138    // Test single holder lock downgrade case.
   139    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
   140                SyscallSucceedsWithValue(0));
   141    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_SH | LOCK_NB),
   142                SyscallSucceedsWithValue(0));
   143    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   144  }
   145  
   146  TEST_F(FlockTest, TestMultipleShared) {
   147    // This is a simple test to verify that multiple independent shared
   148    // locks will be granted.
   149    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_SH | LOCK_NB),
   150                SyscallSucceedsWithValue(0));
   151  
   152    const FileDescriptor fd =
   153        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   154  
   155    // A shared lock should be granted as there only exists other shared locks.
   156    ASSERT_THAT(flock(fd.get(), LOCK_SH | LOCK_NB), SyscallSucceedsWithValue(0));
   157  
   158    // Unlock both.
   159    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   160    ASSERT_THAT(flock(fd.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   161  }
   162  
   163  /*
   164   * flock(2): If a process uses open(2) (or similar) to obtain more than one
   165   * descriptor for the same file, these descriptors are treated
   166   * independently by flock(). An attempt to lock the file using one of
   167   * these file descriptors may be denied by a lock that the calling process
   168   * has already placed via another descriptor.
   169   */
   170  TEST_F(FlockTest, TestMultipleHolderSharedExclusive) {
   171    // This test will verify that an exclusive lock will not be granted
   172    // while a shared is held.
   173    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_SH | LOCK_NB),
   174                SyscallSucceedsWithValue(0));
   175  
   176    const FileDescriptor fd =
   177        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   178  
   179    // Verify We're unable to get an exlcusive lock via the second FD.
   180    // because someone is holding a shared lock.
   181    ASSERT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB),
   182                SyscallFailsWithErrno(EWOULDBLOCK));
   183  
   184    // Unlock
   185    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   186  }
   187  
   188  TEST_F(FlockTest, TestSharedLockFailExclusiveHolderNonblocking) {
   189    // This test will verify that a shared lock is denied while
   190    // someone holds an exclusive lock.
   191    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
   192                SyscallSucceedsWithValue(0));
   193  
   194    const FileDescriptor fd =
   195        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   196  
   197    // Verify we're unable to get an shared lock via the second FD.
   198    // because someone is holding an exclusive lock.
   199    ASSERT_THAT(flock(fd.get(), LOCK_SH | LOCK_NB),
   200                SyscallFailsWithErrno(EWOULDBLOCK));
   201  
   202    // Unlock
   203    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   204  }
   205  
   206  void trivial_handler(int signum) {}
   207  
   208  TEST_F(FlockTest, TestSharedLockFailExclusiveHolderBlocking) {
   209    const DisableSave ds;  // Timing-related.
   210  
   211    // This test will verify that a shared lock is denied while
   212    // someone holds an exclusive lock.
   213    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
   214                SyscallSucceedsWithValue(0));
   215  
   216    const FileDescriptor fd =
   217        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   218  
   219    // Make sure that a blocking flock() call will return EINTR when interrupted
   220    // by a signal. Create a timer that will go off while blocking on flock(), and
   221    // register the corresponding signal handler.
   222    auto timer = ASSERT_NO_ERRNO_AND_VALUE(
   223        TimerCreate(CLOCK_MONOTONIC, sigevent_t{
   224                                         .sigev_signo = SIGALRM,
   225                                         .sigev_notify = SIGEV_SIGNAL,
   226                                     }));
   227  
   228    struct sigaction act = {};
   229    act.sa_handler = trivial_handler;
   230    ASSERT_THAT(sigaction(SIGALRM, &act, NULL), SyscallSucceeds());
   231  
   232    // Now that the signal handler is registered, set the timer. Set an interval
   233    // so that it's ok if the timer goes off before we call flock.
   234    ASSERT_NO_ERRNO(
   235        timer.Set(0, itimerspec{
   236                         .it_interval = absl::ToTimespec(absl::Milliseconds(10)),
   237                         .it_value = absl::ToTimespec(absl::Milliseconds(10)),
   238                     }));
   239  
   240    ASSERT_THAT(flock(fd.get(), LOCK_SH), SyscallFailsWithErrno(EINTR));
   241    timer.reset();
   242  
   243    // Unlock
   244    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   245  }
   246  
   247  TEST_F(FlockTest, TestExclusiveLockFailExclusiveHolderNonblocking) {
   248    // This test will verify that an exclusive lock is denied while
   249    // someone already holds an exclsuive lock.
   250    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
   251                SyscallSucceedsWithValue(0));
   252  
   253    const FileDescriptor fd =
   254        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   255  
   256    // Verify we're unable to get an exclusive lock via the second FD
   257    // because someone is already holding an exclusive lock.
   258    ASSERT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB),
   259                SyscallFailsWithErrno(EWOULDBLOCK));
   260  
   261    // Unlock
   262    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   263  }
   264  
   265  TEST_F(FlockTest, TestExclusiveLockFailExclusiveHolderBlocking) {
   266    const DisableSave ds;  // Timing-related.
   267  
   268    // This test will verify that an exclusive lock is denied while
   269    // someone already holds an exclsuive lock.
   270    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
   271                SyscallSucceedsWithValue(0));
   272  
   273    const FileDescriptor fd =
   274        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   275  
   276    // Make sure that a blocking flock() call will return EINTR when interrupted
   277    // by a signal. Create a timer that will go off while blocking on flock(), and
   278    // register the corresponding signal handler.
   279    auto timer = ASSERT_NO_ERRNO_AND_VALUE(
   280        TimerCreate(CLOCK_MONOTONIC, sigevent_t{
   281                                         .sigev_signo = SIGALRM,
   282                                         .sigev_notify = SIGEV_SIGNAL,
   283                                     }));
   284  
   285    struct sigaction act = {};
   286    act.sa_handler = trivial_handler;
   287    ASSERT_THAT(sigaction(SIGALRM, &act, NULL), SyscallSucceeds());
   288  
   289    // Now that the signal handler is registered, set the timer. Set an interval
   290    // so that it's ok if the timer goes off before we call flock.
   291    ASSERT_NO_ERRNO(
   292        timer.Set(0, itimerspec{
   293                         .it_interval = absl::ToTimespec(absl::Milliseconds(10)),
   294                         .it_value = absl::ToTimespec(absl::Milliseconds(10)),
   295                     }));
   296  
   297    ASSERT_THAT(flock(fd.get(), LOCK_EX), SyscallFailsWithErrno(EINTR));
   298    timer.reset();
   299  
   300    // Unlock
   301    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   302  }
   303  
   304  TEST_F(FlockTest, TestMultipleHolderSharedExclusiveUpgrade) {
   305    // This test will verify that we cannot obtain an exclusive lock while
   306    // a shared lock is held by another descriptor, then verify that an upgrade
   307    // is possible on a shared lock once all other shared locks have closed.
   308    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_SH | LOCK_NB),
   309                SyscallSucceedsWithValue(0));
   310  
   311    const FileDescriptor fd =
   312        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   313  
   314    // Verify we're unable to get an exclusive lock via the second FD because
   315    // a shared lock is held.
   316    ASSERT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB),
   317                SyscallFailsWithErrno(EWOULDBLOCK));
   318  
   319    // Verify that we can get a shared lock via the second descriptor instead
   320    ASSERT_THAT(flock(fd.get(), LOCK_SH | LOCK_NB), SyscallSucceedsWithValue(0));
   321  
   322    // Unlock the first and there will only be one shared lock remaining.
   323    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   324  
   325    // Upgrade 2nd fd.
   326    ASSERT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB), SyscallSucceedsWithValue(0));
   327  
   328    // Finally unlock the second
   329    ASSERT_THAT(flock(fd.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   330  }
   331  
   332  TEST_F(FlockTest, TestMultipleHolderSharedExclusiveDowngrade) {
   333    // This test will verify that a shared lock is not obtainable while an
   334    // exclusive lock is held but that once the first is downgraded that
   335    // the second independent file descriptor can also get a shared lock.
   336    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
   337                SyscallSucceedsWithValue(0));
   338  
   339    const FileDescriptor fd =
   340        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   341  
   342    // Verify We're unable to get a shared lock via the second FD because
   343    // an exclusive lock is held.
   344    ASSERT_THAT(flock(fd.get(), LOCK_SH | LOCK_NB),
   345                SyscallFailsWithErrno(EWOULDBLOCK));
   346  
   347    // Verify that we can downgrade the first.
   348    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_SH | LOCK_NB),
   349                SyscallSucceedsWithValue(0));
   350  
   351    // Now verify that we can obtain a shared lock since the first was downgraded.
   352    ASSERT_THAT(flock(fd.get(), LOCK_SH | LOCK_NB), SyscallSucceedsWithValue(0));
   353  
   354    // Finally unlock both.
   355    ASSERT_THAT(flock(fd.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   356    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   357  }
   358  
   359  /*
   360   * flock(2): Locks created by flock() are associated with an open file table
   361   * entry. This means that duplicate file descriptors (created by, for example,
   362   * fork(2) or dup(2)) refer to the same lock, and this lock may be modified or
   363   * released using any of these descriptors. Furthermore, the lock is released
   364   * either by an explicit LOCK_UN operation on any of these duplicate descriptors
   365   * or when all such descriptors have been closed.
   366   */
   367  TEST_F(FlockTest, TestDupFdUpgrade) {
   368    // This test will verify that a shared lock is upgradeable via a dupped
   369    // file descriptor, if the FD wasn't dupped this would fail.
   370    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_SH | LOCK_NB),
   371                SyscallSucceedsWithValue(0));
   372  
   373    const FileDescriptor dup_fd = ASSERT_NO_ERRNO_AND_VALUE(test_file_fd_.Dup());
   374  
   375    // Now we should be able to upgrade via the dupped fd.
   376    ASSERT_THAT(flock(dup_fd.get(), LOCK_EX | LOCK_NB),
   377                SyscallSucceedsWithValue(0));
   378  
   379    // Validate unlock via dupped fd.
   380    ASSERT_THAT(flock(dup_fd.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   381  }
   382  
   383  TEST_F(FlockTest, TestDupFdDowngrade) {
   384    // This test will verify that a exclusive lock is downgradable via a dupped
   385    // file descriptor, if the FD wasn't dupped this would fail.
   386    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
   387                SyscallSucceedsWithValue(0));
   388  
   389    const FileDescriptor dup_fd = ASSERT_NO_ERRNO_AND_VALUE(test_file_fd_.Dup());
   390  
   391    // Now we should be able to downgrade via the dupped fd.
   392    ASSERT_THAT(flock(dup_fd.get(), LOCK_SH | LOCK_NB),
   393                SyscallSucceedsWithValue(0));
   394  
   395    // Validate unlock via dupped fd
   396    ASSERT_THAT(flock(dup_fd.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   397  }
   398  
   399  TEST_F(FlockTest, TestDupFdCloseRelease) {
   400    // flock(2): Furthermore, the lock is released either by an explicit LOCK_UN
   401    // operation on any of these duplicate descriptors, or when all such
   402    // descriptors have been closed.
   403    //
   404    // This test will verify that a dupped fd closing will not release the
   405    // underlying lock until all such dupped fds have closed.
   406    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
   407                SyscallSucceedsWithValue(0));
   408  
   409    FileDescriptor dup_fd = ASSERT_NO_ERRNO_AND_VALUE(test_file_fd_.Dup());
   410  
   411    // At this point we have ONE exclusive locked referenced by two different fds.
   412    const FileDescriptor fd =
   413        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   414  
   415    // Validate that we cannot get a lock on a new unrelated FD.
   416    ASSERT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB),
   417                SyscallFailsWithErrno(EWOULDBLOCK));
   418  
   419    // Closing the dupped fd shouldn't affect the lock until all are closed.
   420    dup_fd.reset();  // Closed the duped fd.
   421  
   422    // Validate that we still cannot get a lock on a new unrelated FD.
   423    ASSERT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB),
   424                SyscallFailsWithErrno(EWOULDBLOCK));
   425  
   426    // Closing the first fd
   427    CloseFile();  // Will validate the syscall succeeds.
   428  
   429    // Now we should actually be able to get a lock since all fds related to
   430    // the first lock are closed.
   431    ASSERT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB), SyscallSucceedsWithValue(0));
   432  
   433    // Unlock.
   434    ASSERT_THAT(flock(fd.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   435  }
   436  
   437  TEST_F(FlockTest, TestDupFdUnlockRelease) {
   438    /* flock(2): Furthermore, the lock is released either by an explicit LOCK_UN
   439     * operation on any of these duplicate descriptors, or when all such
   440     * descriptors have been closed.
   441     */
   442    // This test will verify that an explict unlock on a dupped FD will release
   443    // the underlying lock unlike the previous case where close on a dup was
   444    // not enough to release the lock.
   445    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
   446                SyscallSucceedsWithValue(0));
   447  
   448    const FileDescriptor dup_fd = ASSERT_NO_ERRNO_AND_VALUE(test_file_fd_.Dup());
   449  
   450    // At this point we have ONE exclusive locked referenced by two different fds.
   451    const FileDescriptor fd =
   452        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   453  
   454    // Validate that we cannot get a lock on a new unrelated FD.
   455    ASSERT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB),
   456                SyscallFailsWithErrno(EWOULDBLOCK));
   457  
   458    // Explicitly unlock via the dupped descriptor.
   459    ASSERT_THAT(flock(dup_fd.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   460  
   461    // Validate that we can now get the lock since we explicitly unlocked.
   462    ASSERT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB), SyscallSucceedsWithValue(0));
   463  
   464    // Unlock
   465    ASSERT_THAT(flock(fd.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   466  }
   467  
   468  TEST_F(FlockTest, TestDupFdFollowedByLock) {
   469    // This test will verify that taking a lock on a file descriptor that has
   470    // already been dupped means that the lock is shared between both. This is
   471    // slightly different than than duping on an already locked FD.
   472    FileDescriptor dup_fd = ASSERT_NO_ERRNO_AND_VALUE(test_file_fd_.Dup());
   473  
   474    // Take a lock.
   475    ASSERT_THAT(flock(dup_fd.get(), LOCK_EX | LOCK_NB), SyscallSucceeds());
   476  
   477    // Now dup_fd and test_file_ should both reference the same lock.
   478    // We shouldn't be able to obtain a lock until both are closed.
   479    const FileDescriptor fd =
   480        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   481  
   482    // Closing the first fd
   483    dup_fd.reset();  // Close the duped fd.
   484  
   485    // Validate that we cannot get a lock yet because the dupped descriptor.
   486    ASSERT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB),
   487                SyscallFailsWithErrno(EWOULDBLOCK));
   488  
   489    // Closing the second fd.
   490    CloseFile();  // CloseFile() will validate the syscall succeeds.
   491  
   492    // Now we should be able to get the lock.
   493    ASSERT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB), SyscallSucceeds());
   494  
   495    // Unlock.
   496    ASSERT_THAT(flock(fd.get(), LOCK_UN), SyscallSucceedsWithValue(0));
   497  }
   498  
   499  // NOTE: These blocking tests are not perfect. Unfortunately it's very hard to
   500  // determine if a thread was actually blocked in the kernel so we're forced
   501  // to use timing.
   502  TEST_F(FlockTest, BlockingLockNoBlockingForSharedLocks) {
   503    // This test will verify that although LOCK_NB isn't specified
   504    // two different fds can obtain shared locks without blocking.
   505    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_SH), SyscallSucceeds());
   506  
   507    // kHoldLockTime is the amount of time we will hold the lock before releasing.
   508    constexpr absl::Duration kHoldLockTime = absl::Seconds(30);
   509  
   510    const DisableSave ds;  // Timing-related.
   511  
   512    // We do this in another thread so we can determine if it was actually
   513    // blocked by timing the amount of time it took for the syscall to complete.
   514    ScopedThread t([&] {
   515      MonotonicTimer timer;
   516      const FileDescriptor fd =
   517          ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   518  
   519      // Only a single shared lock is held, the lock will be granted immediately.
   520      // This should be granted without any blocking. Don't save here to avoid
   521      // wild discrepencies on timing.
   522      timer.Start();
   523      ASSERT_THAT(flock(fd.get(), LOCK_SH), SyscallSucceeds());
   524  
   525      // We held the lock for 30 seconds but this thread should not have
   526      // blocked at all so we expect a very small duration on syscall completion.
   527      ASSERT_LT(timer.Duration(),
   528                absl::Seconds(1));  // 1000ms is much less than 30s.
   529  
   530      // We can release our second shared lock
   531      ASSERT_THAT(flock(fd.get(), LOCK_UN), SyscallSucceeds());
   532    });
   533  
   534    // Sleep before unlocking.
   535    absl::SleepFor(kHoldLockTime);
   536  
   537    // Release the first shared lock. Don't save in this situation to avoid
   538    // discrepencies in timing.
   539    EXPECT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceeds());
   540  }
   541  
   542  TEST_F(FlockTest, BlockingLockFirstSharedSecondExclusive) {
   543    // This test will verify that if someone holds a shared lock any attempt to
   544    // obtain an exclusive lock will result in blocking.
   545    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_SH), SyscallSucceeds());
   546  
   547    // kHoldLockTime is the amount of time we will hold the lock before releasing.
   548    constexpr absl::Duration kHoldLockTime = absl::Seconds(2);
   549  
   550    const DisableSave ds;  // Timing-related.
   551  
   552    // We do this in another thread so we can determine if it was actually
   553    // blocked by timing the amount of time it took for the syscall to complete.
   554    ScopedThread t([&] {
   555      MonotonicTimer timer;
   556      const FileDescriptor fd =
   557          ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   558  
   559      // This exclusive lock should block because someone is already holding a
   560      // shared lock. We don't save here to avoid wild discrepencies on timing.
   561      timer.Start();
   562      ASSERT_THAT(RetryEINTR(flock)(fd.get(), LOCK_EX), SyscallSucceeds());
   563  
   564      // We should be blocked, we will expect to be blocked for more than 1.0s.
   565      ASSERT_GT(timer.Duration(), absl::Seconds(1));
   566  
   567      // We can release our exclusive lock.
   568      ASSERT_THAT(flock(fd.get(), LOCK_UN), SyscallSucceeds());
   569    });
   570  
   571    // Sleep before unlocking.
   572    absl::SleepFor(kHoldLockTime);
   573  
   574    // Release the shared lock allowing the thread to proceed.
   575    // We don't save here to avoid wild discrepencies in timing.
   576    EXPECT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceeds());
   577  }
   578  
   579  TEST_F(FlockTest, BlockingLockFirstExclusiveSecondShared) {
   580    // This test will verify that if someone holds an exclusive lock any attempt
   581    // to obtain a shared lock will result in blocking.
   582    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX), SyscallSucceeds());
   583  
   584    // kHoldLockTime is the amount of time we will hold the lock before releasing.
   585    constexpr absl::Duration kHoldLockTime = absl::Seconds(2);
   586  
   587    const DisableSave ds;  // Timing-related.
   588  
   589    // We do this in another thread so we can determine if it was actually
   590    // blocked by timing the amount of time it took for the syscall to complete.
   591    ScopedThread t([&] {
   592      MonotonicTimer timer;
   593      const FileDescriptor fd =
   594          ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   595  
   596      // This shared lock should block because someone is already holding an
   597      // exclusive lock. We don't save here to avoid wild discrepencies on timing.
   598      timer.Start();
   599      ASSERT_THAT(RetryEINTR(flock)(fd.get(), LOCK_SH), SyscallSucceeds());
   600  
   601      // We should be blocked, we will expect to be blocked for more than 1.0s.
   602      ASSERT_GT(timer.Duration(), absl::Seconds(1));
   603  
   604      // We can release our shared lock.
   605      ASSERT_THAT(flock(fd.get(), LOCK_UN), SyscallSucceeds());
   606    });
   607  
   608    // Sleep before unlocking.
   609    absl::SleepFor(kHoldLockTime);
   610  
   611    // Release the exclusive lock allowing the blocked thread to proceed.
   612    // We don't save here to avoid wild discrepencies in timing.
   613    EXPECT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceeds());
   614  }
   615  
   616  TEST_F(FlockTest, BlockingLockFirstExclusiveSecondExclusive) {
   617    // This test will verify that if someone holds an exclusive lock any attempt
   618    // to obtain another exclusive lock will result in blocking.
   619    ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX), SyscallSucceeds());
   620  
   621    // kHoldLockTime is the amount of time we will hold the lock before releasing.
   622    constexpr absl::Duration kHoldLockTime = absl::Seconds(2);
   623  
   624    const DisableSave ds;  // Timing-related.
   625  
   626    // We do this in another thread so we can determine if it was actually
   627    // blocked by timing the amount of time it took for the syscall to complete.
   628    ScopedThread t([&] {
   629      MonotonicTimer timer;
   630      const FileDescriptor fd =
   631          ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
   632  
   633      // This exclusive lock should block because someone is already holding an
   634      // exclusive lock.
   635      timer.Start();
   636      ASSERT_THAT(RetryEINTR(flock)(fd.get(), LOCK_EX), SyscallSucceeds());
   637  
   638      // We should be blocked, we will expect to be blocked for more than 1.0s.
   639      ASSERT_GT(timer.Duration(), absl::Seconds(1));
   640  
   641      // We can release our exclusive lock.
   642      ASSERT_THAT(flock(fd.get(), LOCK_UN), SyscallSucceeds());
   643    });
   644  
   645    // Sleep before unlocking.
   646    absl::SleepFor(kHoldLockTime);
   647  
   648    // Release the exclusive lock allowing the blocked thread to proceed.
   649    // We don't save to avoid wild discrepencies in timing.
   650    EXPECT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceeds());
   651  }
   652  
   653  TEST(FlockTestNoFixture, BadFD) {
   654    // EBADF: fd is not an open file descriptor.
   655    ASSERT_THAT(flock(-1, LOCK_UN), SyscallFailsWithErrno(EBADF));
   656  }
   657  
   658  TEST(FlockTestNoFixture, FlockDir) {
   659    auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   660    auto fd = ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path(), O_RDONLY, 0000));
   661    EXPECT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB), SyscallSucceeds());
   662  }
   663  
   664  TEST(FlockTestNoFixture, FlockSymlink) {
   665    auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   666    auto symlink = ASSERT_NO_ERRNO_AND_VALUE(
   667        TempPath::CreateSymlinkTo(GetAbsoluteTestTmpdir(), file.path()));
   668  
   669    auto fd =
   670        ASSERT_NO_ERRNO_AND_VALUE(Open(symlink.path(), O_RDONLY | O_PATH, 0000));
   671    EXPECT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB), SyscallFailsWithErrno(EBADF));
   672  }
   673  
   674  TEST(FlockTestNoFixture, FlockProc) {
   675    auto fd =
   676        ASSERT_NO_ERRNO_AND_VALUE(Open("/proc/self/status", O_RDONLY, 0000));
   677    EXPECT_THAT(flock(fd.get(), LOCK_EX | LOCK_NB), SyscallSucceeds());
   678  }
   679  
   680  TEST(FlockTestNoFixture, FlockPipe) {
   681    int fds[2];
   682    ASSERT_THAT(pipe(fds), SyscallSucceeds());
   683  
   684    EXPECT_THAT(flock(fds[0], LOCK_EX | LOCK_NB), SyscallSucceeds());
   685    // Check that the pipe was locked above.
   686    EXPECT_THAT(flock(fds[1], LOCK_EX | LOCK_NB), SyscallFailsWithErrno(EAGAIN));
   687  
   688    EXPECT_THAT(flock(fds[0], LOCK_UN), SyscallSucceeds());
   689    EXPECT_THAT(flock(fds[1], LOCK_EX | LOCK_NB), SyscallSucceeds());
   690  
   691    EXPECT_THAT(close(fds[0]), SyscallSucceeds());
   692    EXPECT_THAT(close(fds[1]), SyscallSucceeds());
   693  }
   694  
   695  TEST(FlockTestNoFixture, FlockSocket) {
   696    int sock = socket(AF_UNIX, SOCK_STREAM, 0);
   697    ASSERT_THAT(sock, SyscallSucceeds());
   698  
   699    struct sockaddr_un addr =
   700        ASSERT_NO_ERRNO_AND_VALUE(UniqueUnixAddr(true /* abstract */, AF_UNIX));
   701    ASSERT_THAT(
   702        bind(sock, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)),
   703        SyscallSucceeds());
   704  
   705    EXPECT_THAT(flock(sock, LOCK_EX | LOCK_NB), SyscallSucceeds());
   706    EXPECT_THAT(close(sock), SyscallSucceeds());
   707  }
   708  
   709  }  // namespace
   710  
   711  }  // namespace testing
   712  }  // namespace gvisor