Don't mask errors in createAt loop.

The error set in the loop in createAt was being masked
by other errors declared with ":=". This allowed an
ErrResolveViaReadlink error to escape, which can cause
a sentry panic.

Added test case which repros without the fix.

PiperOrigin-RevId: 257061767
This commit is contained in:
Nicolas Lacasse
2019-07-08 14:57:15 -07:00
committed by gVisor bot
parent e45d724948
commit 6db3f8d54c
2 changed files with 21 additions and 3 deletions
+6 -3
View File
@@ -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
}
+15
View File
@@ -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) {