summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDean Deng <deandeng@google.com>2020-08-19 08:50:59 -0700
committergVisor bot <gvisor-bot@google.com>2020-08-19 08:53:12 -0700
commit33c60b893fe8a0f039c781091bf96cbcd47ecc2d (patch)
treeac2dec1877b69a47880e0c6316cca1069258c94f
parent35dc7fe7e78faab35b55eaa6f82360cc8b23f3b3 (diff)
Return appropriate errors when file locking is unsuccessful.
test_eintr now passes in the Python runtime tests. Updates #3515. PiperOrigin-RevId: 327441081
-rw-r--r--pkg/sentry/vfs/lock.go16
-rw-r--r--test/syscalls/linux/flock.cc54
2 files changed, 66 insertions, 4 deletions
diff --git a/pkg/sentry/vfs/lock.go b/pkg/sentry/vfs/lock.go
index 6c7583a81..42666eebf 100644
--- a/pkg/sentry/vfs/lock.go
+++ b/pkg/sentry/vfs/lock.go
@@ -46,7 +46,13 @@ func (fl *FileLocks) LockBSD(uid fslock.UniqueID, t fslock.LockType, block fsloc
if fl.bsd.LockRegion(uid, t, fslock.LockRange{0, fslock.LockEOF}, block) {
return nil
}
- return syserror.ErrWouldBlock
+
+ // Return an appropriate error for the unsuccessful lock attempt, depending on
+ // whether this is a blocking or non-blocking operation.
+ if block == nil {
+ return syserror.ErrWouldBlock
+ }
+ return syserror.ERESTARTSYS
}
// UnlockBSD releases a BSD-style lock on the entire file.
@@ -66,7 +72,13 @@ func (fl *FileLocks) LockPOSIX(ctx context.Context, fd *FileDescription, uid fsl
if fl.posix.LockRegion(uid, t, rng, block) {
return nil
}
- return syserror.ErrWouldBlock
+
+ // Return an appropriate error for the unsuccessful lock attempt, depending on
+ // whether this is a blocking or non-blocking operation.
+ if block == nil {
+ return syserror.ErrWouldBlock
+ }
+ return syserror.ERESTARTSYS
}
// UnlockPOSIX releases a POSIX-style lock on a file region.
diff --git a/test/syscalls/linux/flock.cc b/test/syscalls/linux/flock.cc
index 638a93979..549141cbb 100644
--- a/test/syscalls/linux/flock.cc
+++ b/test/syscalls/linux/flock.cc
@@ -185,7 +185,7 @@ TEST_F(FlockTest, TestMultipleHolderSharedExclusive) {
ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
}
-TEST_F(FlockTest, TestSharedLockFailExclusiveHolder) {
+TEST_F(FlockTest, TestSharedLockFailExclusiveHolderNonblocking) {
// This test will verify that a shared lock is denied while
// someone holds an exclusive lock.
ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
@@ -203,7 +203,33 @@ TEST_F(FlockTest, TestSharedLockFailExclusiveHolder) {
ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
}
-TEST_F(FlockTest, TestExclusiveLockFailExclusiveHolder) {
+void trivial_handler(int signum) {}
+
+TEST_F(FlockTest, TestSharedLockFailExclusiveHolderBlocking_NoRandomSave) {
+ const DisableSave ds; // Timing-related.
+
+ // This test will verify that a shared lock is denied while
+ // someone holds an exclusive lock.
+ ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
+ SyscallSucceedsWithValue(0));
+
+ const FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
+
+ // Register a signal handler for SIGALRM and set an alarm that will go off
+ // while blocking in the subsequent flock() call. This will interrupt flock()
+ // and cause it to return EINTR.
+ struct sigaction act = {};
+ act.sa_handler = trivial_handler;
+ ASSERT_THAT(sigaction(SIGALRM, &act, NULL), SyscallSucceeds());
+ ASSERT_THAT(ualarm(10000, 0), SyscallSucceeds());
+ ASSERT_THAT(flock(fd.get(), LOCK_SH), SyscallFailsWithErrno(EINTR));
+
+ // Unlock
+ ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
+}
+
+TEST_F(FlockTest, TestExclusiveLockFailExclusiveHolderNonblocking) {
// This test will verify that an exclusive lock is denied while
// someone already holds an exclsuive lock.
ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
@@ -221,6 +247,30 @@ TEST_F(FlockTest, TestExclusiveLockFailExclusiveHolder) {
ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
}
+TEST_F(FlockTest, TestExclusiveLockFailExclusiveHolderBlocking_NoRandomSave) {
+ const DisableSave ds; // Timing-related.
+
+ // This test will verify that an exclusive lock is denied while
+ // someone already holds an exclsuive lock.
+ ASSERT_THAT(flock(test_file_fd_.get(), LOCK_EX | LOCK_NB),
+ SyscallSucceedsWithValue(0));
+
+ const FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR));
+
+ // Register a signal handler for SIGALRM and set an alarm that will go off
+ // while blocking in the subsequent flock() call. This will interrupt flock()
+ // and cause it to return EINTR.
+ struct sigaction act = {};
+ act.sa_handler = trivial_handler;
+ ASSERT_THAT(sigaction(SIGALRM, &act, NULL), SyscallSucceeds());
+ ASSERT_THAT(ualarm(10000, 0), SyscallSucceeds());
+ ASSERT_THAT(flock(fd.get(), LOCK_EX), SyscallFailsWithErrno(EINTR));
+
+ // Unlock
+ ASSERT_THAT(flock(test_file_fd_.get(), LOCK_UN), SyscallSucceedsWithValue(0));
+}
+
TEST_F(FlockTest, TestMultipleHolderSharedExclusiveUpgrade) {
// This test will verify that we cannot obtain an exclusive lock while
// a shared lock is held by another descriptor, then verify that an upgrade