diff options
author | Nicolas Lacasse <nlacasse@google.com> | 2019-07-01 15:24:18 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2019-07-01 15:25:22 -0700 |
commit | 06537129a67cbdced394f514a7d2399c19082f47 (patch) | |
tree | 2c925f789c745f661c4000c4084309144ea576ad | |
parent | 3446f4e29bd547e5576caf16d8c2bb45560439e9 (diff) |
Check remaining traversal limit when creating a file through a symlink.
This fixes the case when an app tries to create a file that already exists, and
is a symlink to itself. A test was added.
PiperOrigin-RevId: 256044811
-rw-r--r-- | pkg/sentry/syscalls/linux/sys_file.go | 6 | ||||
-rw-r--r-- | test/syscalls/linux/symlink.cc | 13 |
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) { |