summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/sentry/syscalls/linux/sys_file.go6
-rw-r--r--test/syscalls/linux/symlink.cc13
2 files changed, 19 insertions, 0 deletions
diff --git a/pkg/sentry/syscalls/linux/sys_file.go b/pkg/sentry/syscalls/linux/sys_file.go
index 3ef7441c2..3410af69c 100644
--- a/pkg/sentry/syscalls/linux/sys_file.go
+++ b/pkg/sentry/syscalls/linux/sys_file.go
@@ -354,6 +354,12 @@ func createAt(t *kernel.Task, dirFD kdefs.FD, addr usermem.Addr, flags uint, mod
break
}
+ // Are we able to resolve further?
+ if remainingTraversals == 0 {
+ found.DecRef()
+ return syscall.ELOOP
+ }
+
// Resolve the symlink to a path via Readlink.
path, err := found.Inode.Readlink(t)
if err != nil {
diff --git a/test/syscalls/linux/symlink.cc b/test/syscalls/linux/symlink.cc
index dce8de9ec..69650a1d3 100644
--- a/test/syscalls/linux/symlink.cc
+++ b/test/syscalls/linux/symlink.cc
@@ -312,6 +312,19 @@ TEST_P(ParamSymlinkTest, OpenLinkCreatesTarget) {
ASSERT_THAT(unlink(target.c_str()), SyscallSucceeds());
}
+// Test that opening a self-symlink with O_CREAT will fail with ELOOP.
+TEST_P(ParamSymlinkTest, CreateExistingSelfLink) {
+ ASSERT_THAT(chdir(GetAbsoluteTestTmpdir().c_str()), SyscallSucceeds());
+
+ const std::string linkpath = GetParam();
+ ASSERT_THAT(symlink(linkpath.c_str(), linkpath.c_str()), SyscallSucceeds());
+
+ EXPECT_THAT(open(linkpath.c_str(), O_CREAT, 0666),
+ SyscallFailsWithErrno(ELOOP));
+
+ ASSERT_THAT(unlink(linkpath.c_str()), SyscallSucceeds());
+}
+
// Test that opening an existing symlink with O_CREAT|O_EXCL will fail with
// EEXIST.
TEST_P(ParamSymlinkTest, OpenLinkExclFails) {