diff options
-rw-r--r-- | pkg/sentry/syscalls/linux/sys_file.go | 9 | ||||
-rw-r--r-- | test/syscalls/linux/symlink.cc | 15 |
2 files changed, 21 insertions, 3 deletions
diff --git a/pkg/sentry/syscalls/linux/sys_file.go b/pkg/sentry/syscalls/linux/sys_file.go index eb6f5648f..40722abc2 100644 --- a/pkg/sentry/syscalls/linux/sys_file.go +++ b/pkg/sentry/syscalls/linux/sys_file.go @@ -353,7 +353,8 @@ func createAt(t *kernel.Task, dirFD int32, addr usermem.Addr, flags uint, mode l // No more resolution necessary. defer resolved.DecRef() break - } else if err != fs.ErrResolveViaReadlink { + } + if err != fs.ErrResolveViaReadlink { return err } @@ -363,15 +364,17 @@ func createAt(t *kernel.Task, dirFD int32, addr usermem.Addr, flags uint, mode l } // Resolve the symlink to a path via Readlink. - path, err := found.Inode.Readlink(t) + var path string + path, err = found.Inode.Readlink(t) if err != nil { break } remainingTraversals-- // Get the new parent from the target path. + var newParent *fs.Dirent newParentPath, newName := fs.SplitLast(path) - newParent, err := t.MountNamespace().FindInode(t, root, parent, newParentPath, &remainingTraversals) + newParent, err = t.MountNamespace().FindInode(t, root, parent, newParentPath, &remainingTraversals) if err != nil { break } diff --git a/test/syscalls/linux/symlink.cc b/test/syscalls/linux/symlink.cc index 69650a1d3..b249ff91f 100644 --- a/test/syscalls/linux/symlink.cc +++ b/test/syscalls/linux/symlink.cc @@ -325,6 +325,21 @@ TEST_P(ParamSymlinkTest, CreateExistingSelfLink) { ASSERT_THAT(unlink(linkpath.c_str()), SyscallSucceeds()); } +// Test that opening a file that is a symlink to its parent directory fails +// with ELOOP. +TEST_P(ParamSymlinkTest, CreateExistingParentLink) { + ASSERT_THAT(chdir(GetAbsoluteTestTmpdir().c_str()), SyscallSucceeds()); + + const std::string linkpath = GetParam(); + const std::string target = JoinPath(linkpath, "child"); + ASSERT_THAT(symlink(target.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) { |