diff options
author | Ayush Ranjan <ayushranjan@google.com> | 2021-10-19 16:45:09 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-10-19 16:47:44 -0700 |
commit | 1b494b80f02774ee109ccb7e20d9c2fe59b8cf72 (patch) | |
tree | bac01f38e8c152ace1533cb1c206213cdac83b66 /pkg/sentry/fsimpl/gofer | |
parent | 64aee33ed0e1a422c3e2954de8f1d3f219ed14b8 (diff) |
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
Diffstat (limited to 'pkg/sentry/fsimpl/gofer')
-rw-r--r-- | pkg/sentry/fsimpl/gofer/filesystem.go | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/pkg/sentry/fsimpl/gofer/filesystem.go b/pkg/sentry/fsimpl/gofer/filesystem.go index cf6b34cbf..23c8b8ce3 100644 --- a/pkg/sentry/fsimpl/gofer/filesystem.go +++ b/pkg/sentry/fsimpl/gofer/filesystem.go @@ -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. |