diff options
author | Ayush Ranjan <ayushranjan@google.com> | 2021-10-26 11:56:09 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-10-26 11:59:21 -0700 |
commit | 763d7e6e396d8d4c67d650e02bd2350b22606ada (patch) | |
tree | 690226ef6653e159c485e0cf374560db9952be77 /pkg/sentry/fsimpl | |
parent | 8b2e8caad400fd3e7d3e4e235d26dd2d556bf65c (diff) |
Obtain ref on root dentry in mqfs.GetFilesystem.
As documented in FilesystemType.GetFilesystem, a reference should be taken on
the returned dentry and filesystem by GetFilesystem implementation. mqfs did
not do that.
Additionally cleanup and clarify ref counting of dentry, filesystem and mount
in mqfs.
Reported-by: syzbot+a2c54bfb6e1525228e5f@syzkaller.appspotmail.com
Reported-by: syzbot+ccd305cdab11cfebbfff@syzkaller.appspotmail.com
PiperOrigin-RevId: 405700565
Diffstat (limited to 'pkg/sentry/fsimpl')
-rw-r--r-- | pkg/sentry/fsimpl/mqfs/mqfs.go | 5 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/mqfs/registry.go | 23 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/mqfs/root.go | 9 |
3 files changed, 10 insertions, 27 deletions
diff --git a/pkg/sentry/fsimpl/mqfs/mqfs.go b/pkg/sentry/fsimpl/mqfs/mqfs.go index c2b53c9d0..9b3704217 100644 --- a/pkg/sentry/fsimpl/mqfs/mqfs.go +++ b/pkg/sentry/fsimpl/mqfs/mqfs.go @@ -75,6 +75,7 @@ func (ft FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.VirtualF impl.fs.MaxCachedDentries = maxCachedDentries impl.fs.VFSFilesystem().IncRef() + impl.root.IncRef() return impl.fs.VFSFilesystem(), impl.root.VFSDentry(), nil } @@ -100,10 +101,6 @@ func maxCachedDentries(ctx context.Context, mopts map[string]string) (_ uint64, type filesystem struct { kernfs.Filesystem devMinor uint32 - - // root is the filesystem's root dentry. Since we take a reference on it in - // GetFilesystem, we should release it when the fs is released. - root *kernfs.Dentry } // Release implements vfs.FilesystemImpl.Release. diff --git a/pkg/sentry/fsimpl/mqfs/registry.go b/pkg/sentry/fsimpl/mqfs/registry.go index c8fbe4d33..e470ffadc 100644 --- a/pkg/sentry/fsimpl/mqfs/registry.go +++ b/pkg/sentry/fsimpl/mqfs/registry.go @@ -57,16 +57,19 @@ func NewRegistryImpl(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds * return nil, err } - var dentry kernfs.Dentry fs := &filesystem{ devMinor: devMinor, - root: &dentry, } fs.VFSFilesystem().Init(vfsObj, &FilesystemType{}, fs) vfsfs := fs.VFSFilesystem() + // NewDisconnectedMount will obtain a ref on dentry and vfsfs which is + // transferred to mount. vfsfs was initiated with 1 ref already. So get rid + // of the extra ref. + defer vfsfs.DecRef(ctx) + // dentry is initialized with 1 ref which is transferred to fs. + var dentry kernfs.Dentry dentry.InitRoot(&fs.Filesystem, fs.newRootInode(ctx, creds)) - defer vfsfs.DecRef(ctx) // NewDisconnectedMount will obtain a ref on success. mount, err := vfsObj.NewDisconnectedMount(vfsfs, dentry.VFSDentry(), &vfs.MountOptions{}) if err != nil { @@ -82,7 +85,7 @@ func NewRegistryImpl(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds * // Get implements mq.RegistryImpl.Get. func (r *RegistryImpl) Get(ctx context.Context, name string, access mq.AccessType, block bool, flags uint32) (*vfs.FileDescription, bool, error) { - inode, err := r.lookup(ctx, name) + inode, err := r.root.Inode().(*rootInode).Lookup(ctx, name) if err != nil { return nil, false, nil } @@ -120,7 +123,7 @@ func (r *RegistryImpl) Unlink(ctx context.Context, name string) error { } root := r.root.Inode().(*rootInode) - inode, err := r.lookup(ctx, name) + inode, err := root.Lookup(ctx, name) if err != nil { return err } @@ -133,16 +136,6 @@ func (r *RegistryImpl) Destroy(ctx context.Context) { r.mount.DecRef(ctx) } -// lookup retreives a kernfs.Inode using a name. -func (r *RegistryImpl) lookup(ctx context.Context, name string) (kernfs.Inode, error) { - inode := r.root.Inode().(*rootInode) - lookup, err := inode.Lookup(ctx, name) - if err != nil { - return nil, err - } - return lookup, nil -} - // newFD returns a new file description created using the given queue and inode. func (r *RegistryImpl) newFD(q *mq.Queue, inode *queueInode, access mq.AccessType, block bool, flags uint32) (*vfs.FileDescription, error) { view, err := mq.NewView(q, access, block) diff --git a/pkg/sentry/fsimpl/mqfs/root.go b/pkg/sentry/fsimpl/mqfs/root.go index 37b5749fb..922e669e2 100644 --- a/pkg/sentry/fsimpl/mqfs/root.go +++ b/pkg/sentry/fsimpl/mqfs/root.go @@ -34,7 +34,6 @@ type rootInode struct { kernfs.InodeNotSymlink kernfs.InodeTemporary kernfs.OrderedChildren - implStatFS locks vfs.FileLocks } @@ -77,13 +76,7 @@ func (*rootInode) SetStat(context.Context, *vfs.Filesystem, *auth.Credentials, v return linuxerr.EPERM } -// implStatFS provides an implementation of kernfs.Inode.StatFS for message -// queues to be embedded in inodes. -// -// +stateify savable -type implStatFS struct{} - // StatFS implements kernfs.Inode.StatFS. -func (*implStatFS) StatFS(context.Context, *vfs.Filesystem) (linux.Statfs, error) { +func (*rootInode) StatFS(context.Context, *vfs.Filesystem) (linux.Statfs, error) { return vfs.GenericStatFS(linux.MQUEUE_MAGIC), nil } |