Do not return non-nil *lisafs.Inode to doCreateAt on error.

lisafs.ClientFile.MkdirAt is allowed to return a non-nil Inode and a non-nil
error on an RPC error. The caller must not use the returned (invalid) Inode on
error. But a code path in the gofer client does end up using it.

More specifically, when the Mkdir RPC fails and we end up creating a synthetic
dentry for a mountpoint, we end up returning the (invalid) non-nil Inode to
filesystem.doCreateAt implementation which thinks that a remote file was
created. But that non-nil Inode is actually invalid because the RPC failed.
Things go downhill from there.

Update client to not use childDirInode if RPC failed.

PiperOrigin-RevId: 404396573
This commit is contained in:
Ayush Ranjan
2021-10-19 16:47:44 -07:00
committed by gVisor bot
parent 64aee33ed0
commit 1b494b80f0
+17 -12
View File
@@ -887,23 +887,28 @@ func (fs *filesystem) MkdirAt(ctx context.Context, rp *vfs.ResolvingPath, opts v
} else {
_, err = parent.file.mkdir(ctx, name, p9.FileMode(mode), (p9.UID)(creds.EffectiveKUID), p9.GID(kgid))
}
if err != nil {
if !opts.ForSyntheticMountpoint || linuxerr.Equals(linuxerr.EEXIST, err) {
return nil, err
if err == nil {
if fs.opts.interop != InteropModeShared {
parent.incLinks()
}
ctx.Infof("Failed to create remote directory %q: %v; falling back to synthetic directory", name, err)
parent.createSyntheticChildLocked(&createSyntheticOpts{
name: name,
mode: linux.S_IFDIR | opts.Mode,
kuid: creds.EffectiveKUID,
kgid: creds.EffectiveKGID,
})
*ds = appendDentry(*ds, parent)
return childDirInode, nil
}
if !opts.ForSyntheticMountpoint || linuxerr.Equals(linuxerr.EEXIST, err) {
return nil, err
}
ctx.Infof("Failed to create remote directory %q: %v; falling back to synthetic directory", name, err)
parent.createSyntheticChildLocked(&createSyntheticOpts{
name: name,
mode: linux.S_IFDIR | opts.Mode,
kuid: creds.EffectiveKUID,
kgid: creds.EffectiveKGID,
})
*ds = appendDentry(*ds, parent)
if fs.opts.interop != InteropModeShared {
parent.incLinks()
}
return childDirInode, nil
return nil, nil
}, func(parent *dentry, name string) error {
if !opts.ForSyntheticMountpoint {
// Can't create non-synthetic files in synthetic directories.