Handle absolute symlink target '/' correctly in VFS layer.

vfs.ResolvingPath.relpathPrepend() has a precondition which was being violated
when handling resolveAbsSymlinkError. This was only happening when
`rp.absSymlinkTarget = "/"` because it has no path components. Added check for
that and also added regression test.

Reported-by: syzbot+48846f91b6252b56382f@syzkaller.appspotmail.com
PiperOrigin-RevId: 503862090
This commit is contained in:
Ayush Ranjan
2023-01-22 18:59:56 -08:00
committed by gVisor bot
parent 212fecc105
commit fe562179fe
4 changed files with 15 additions and 4 deletions
+1 -1
View File
@@ -201,7 +201,7 @@ func (d *dentry) getRemoteChild(ctx context.Context, name string) (*dentry, erro
// - fs.renameMu must be locked.
// - parent.dirMu must be locked.
// - parent.isDir().
// - name is not "." or "..".
// - !rp.Done() && rp.Component() is not "." or "..".
// - dentry at name must not already exist in dentry tree.
//
// Postcondition: The returned dentry is already cached appropriately.
+1 -1
View File
@@ -241,7 +241,7 @@ func (d *lisafsDentry) getRemoteChild(ctx context.Context, name string) (*dentry
// - fs.renameMu must be locked.
// - parent.dirMu must be locked.
// - parent.isDir().
// - name is not "." or "..".
// - !rp.Done().
// - dentry at name must not already exist in dentry tree.
func (d *lisafsDentry) getRemoteChildAndWalkPathLocked(ctx context.Context, rp *vfs.ResolvingPath, ds **[]*dentry) (*dentry, error) {
// Walk as much of the path as possible in 1 RPC.
+4 -2
View File
@@ -438,8 +438,10 @@ func (rp *ResolvingPath) handleError(ctx context.Context, err error) bool {
rp.flags &^= rpflagsHaveMountRef | rpflagsHaveStartRef
// Consume the path component that represented the symlink.
rp.Advance()
// Prepend the symlink target to the relative path.
rp.relpathPrepend(rp.absSymlinkTarget)
if rp.absSymlinkTarget.HasComponents() {
// Prepend the symlink target to the relative path.
rp.relpathPrepend(rp.absSymlinkTarget)
}
// Restart path resolution on the new Mount.
rp.releaseErrorState(ctx)
return true
+9
View File
@@ -365,6 +365,15 @@ TEST(SymlinkTest, SymlinkAtEmptyPath) {
SyscallFailsWithErrno(ENOENT));
}
// NOTE(b/266111750): Regression test.
TEST(SymlinkTest, AbsoluteSymlinkDouble) {
const std::string symlinkPath = NewTempAbsPath();
EXPECT_THAT(symlink("/", symlinkPath.c_str()), SyscallSucceeds());
auto doubleSymlinkPath = symlinkPath + symlinkPath;
EXPECT_THAT(mkdir(doubleSymlinkPath.c_str(), 0777),
SyscallFailsWithErrno(EEXIST));
}
class ParamSymlinkTest : public ::testing::TestWithParam<std::string> {};
// Test that creating an existing symlink with creat will create the target.