diff options
Diffstat (limited to 'pkg/sentry/vfs')
-rw-r--r-- | pkg/sentry/vfs/file_description_impl_util.go | 2 | ||||
-rw-r--r-- | pkg/sentry/vfs/file_description_refs.go | 5 | ||||
-rw-r--r-- | pkg/sentry/vfs/filesystem_refs.go | 5 | ||||
-rw-r--r-- | pkg/sentry/vfs/mount.go | 70 | ||||
-rw-r--r-- | pkg/sentry/vfs/mount_namespace_refs.go | 5 | ||||
-rw-r--r-- | pkg/sentry/vfs/vfs.go | 24 |
6 files changed, 43 insertions, 68 deletions
diff --git a/pkg/sentry/vfs/file_description_impl_util.go b/pkg/sentry/vfs/file_description_impl_util.go index 68b80a951..2b668fd89 100644 --- a/pkg/sentry/vfs/file_description_impl_util.go +++ b/pkg/sentry/vfs/file_description_impl_util.go @@ -107,7 +107,7 @@ func (FileDescriptionDefaultImpl) Write(ctx context.Context, src usermem.IOSeque // file_operations::iterate == file_operations::iterate_shared == NULL in // Linux. func (FileDescriptionDefaultImpl) IterDirents(ctx context.Context, cb IterDirentsCallback) error { - return syserror.ENOTDIR + return syserror.ENOSYS } // Seek implements FileDescriptionImpl.Seek analogously to diff --git a/pkg/sentry/vfs/file_description_refs.go b/pkg/sentry/vfs/file_description_refs.go index 6c7747259..3953d2396 100644 --- a/pkg/sentry/vfs/file_description_refs.go +++ b/pkg/sentry/vfs/file_description_refs.go @@ -1,11 +1,12 @@ package vfs import ( + "runtime" + "sync/atomic" + "fmt" "gvisor.dev/gvisor/pkg/log" refs_vfs1 "gvisor.dev/gvisor/pkg/refs" - "runtime" - "sync/atomic" ) // ownerType is used to customize logging. Note that we use a pointer to T so diff --git a/pkg/sentry/vfs/filesystem_refs.go b/pkg/sentry/vfs/filesystem_refs.go index 96f681831..c6a390430 100644 --- a/pkg/sentry/vfs/filesystem_refs.go +++ b/pkg/sentry/vfs/filesystem_refs.go @@ -1,11 +1,12 @@ package vfs import ( + "runtime" + "sync/atomic" + "fmt" "gvisor.dev/gvisor/pkg/log" refs_vfs1 "gvisor.dev/gvisor/pkg/refs" - "runtime" - "sync/atomic" ) // ownerType is used to customize logging. Note that we use a pointer to T so diff --git a/pkg/sentry/vfs/mount.go b/pkg/sentry/vfs/mount.go index 9da09d4c1..06ca91989 100644 --- a/pkg/sentry/vfs/mount.go +++ b/pkg/sentry/vfs/mount.go @@ -18,12 +18,14 @@ import ( "bytes" "fmt" "math" + "path" "sort" "strings" "sync/atomic" "gvisor.dev/gvisor/pkg/abi/linux" "gvisor.dev/gvisor/pkg/context" + "gvisor.dev/gvisor/pkg/fspath" "gvisor.dev/gvisor/pkg/sentry/kernel/auth" "gvisor.dev/gvisor/pkg/syserror" ) @@ -738,23 +740,11 @@ func (mntns *MountNamespace) Root() VirtualDentry { // // Preconditions: taskRootDir.Ok(). func (vfs *VirtualFilesystem) GenerateProcMounts(ctx context.Context, taskRootDir VirtualDentry, buf *bytes.Buffer) { - rootMnt := taskRootDir.mount - vfs.mountMu.Lock() + defer vfs.mountMu.Unlock() + rootMnt := taskRootDir.mount mounts := rootMnt.submountsLocked() - // Take a reference on mounts since we need to drop vfs.mountMu before - // calling vfs.PathnameReachable() (=> FilesystemImpl.PrependPath()). - for _, mnt := range mounts { - mnt.IncRef() - } - vfs.mountMu.Unlock() - defer func() { - for _, mnt := range mounts { - mnt.DecRef(ctx) - } - }() sort.Slice(mounts, func(i, j int) bool { return mounts[i].ID < mounts[j].ID }) - for _, mnt := range mounts { // Get the path to this mount relative to task root. mntRootVD := VirtualDentry{ @@ -765,7 +755,7 @@ func (vfs *VirtualFilesystem) GenerateProcMounts(ctx context.Context, taskRootDi if err != nil { // For some reason we didn't get a path. Log a warning // and run with empty path. - ctx.Warningf("VFS.GenerateProcMounts: error getting pathname for mount root %+v: %v", mnt.root, err) + ctx.Warningf("Error getting pathname for mount root %+v: %v", mnt.root, err) path = "" } if path == "" { @@ -799,25 +789,11 @@ func (vfs *VirtualFilesystem) GenerateProcMounts(ctx context.Context, taskRootDi // // Preconditions: taskRootDir.Ok(). func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRootDir VirtualDentry, buf *bytes.Buffer) { - rootMnt := taskRootDir.mount - vfs.mountMu.Lock() + defer vfs.mountMu.Unlock() + rootMnt := taskRootDir.mount mounts := rootMnt.submountsLocked() - // Take a reference on mounts since we need to drop vfs.mountMu before - // calling vfs.PathnameReachable() (=> FilesystemImpl.PrependPath()) or - // vfs.StatAt() (=> FilesystemImpl.StatAt()). - for _, mnt := range mounts { - mnt.IncRef() - } - vfs.mountMu.Unlock() - defer func() { - for _, mnt := range mounts { - mnt.DecRef(ctx) - } - }() sort.Slice(mounts, func(i, j int) bool { return mounts[i].ID < mounts[j].ID }) - - creds := auth.CredentialsFromContext(ctx) for _, mnt := range mounts { // Get the path to this mount relative to task root. mntRootVD := VirtualDentry{ @@ -828,7 +804,7 @@ func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRoo if err != nil { // For some reason we didn't get a path. Log a warning // and run with empty path. - ctx.Warningf("VFS.GenerateProcMountInfo: error getting pathname for mount root %+v: %v", mnt.root, err) + ctx.Warningf("Error getting pathname for mount root %+v: %v", mnt.root, err) path = "" } if path == "" { @@ -841,10 +817,9 @@ func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRoo Root: mntRootVD, Start: mntRootVD, } - statx, err := vfs.StatAt(ctx, creds, pop, &StatOptions{}) + statx, err := vfs.StatAt(ctx, auth.NewAnonymousCredentials(), pop, &StatOptions{}) if err != nil { // Well that's not good. Ignore this mount. - ctx.Warningf("VFS.GenerateProcMountInfo: failed to stat mount root %+v: %v", mnt.root, err) break } @@ -856,9 +831,6 @@ func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRoo fmt.Fprintf(buf, "%d ", mnt.ID) // (2) Parent ID (or this ID if there is no parent). - // Note that even if the call to mnt.parent() races with Mount - // destruction (which is possible since we're not holding vfs.mountMu), - // its Mount.ID will still be valid. pID := mnt.ID if p := mnt.parent(); p != nil { pID = p.ID @@ -907,6 +879,30 @@ func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRoo } } +// MakeSyntheticMountpoint creates parent directories of target if they do not +// exist and attempts to create a directory for the mountpoint. If a +// non-directory file already exists there then we allow it. +func (vfs *VirtualFilesystem) MakeSyntheticMountpoint(ctx context.Context, target string, root VirtualDentry, creds *auth.Credentials) error { + mkdirOpts := &MkdirOptions{Mode: 0777, ForSyntheticMountpoint: true} + + // Make sure the parent directory of target exists. + if err := vfs.MkdirAllAt(ctx, path.Dir(target), root, creds, mkdirOpts); err != nil { + return fmt.Errorf("failed to create parent directory of mountpoint %q: %w", target, err) + } + + // Attempt to mkdir the final component. If a file (of any type) exists + // then we let allow mounting on top of that because we do not require the + // target to be an existing directory, unlike Linux mount(2). + if err := vfs.MkdirAt(ctx, creds, &PathOperation{ + Root: root, + Start: root, + Path: fspath.Parse(target), + }, mkdirOpts); err != nil && err != syserror.EEXIST { + return fmt.Errorf("failed to create mountpoint %q: %w", target, err) + } + return nil +} + // manglePath replaces ' ', '\t', '\n', and '\\' with their octal equivalents. // See Linux fs/seq_file.c:mangle_path. func manglePath(p string) string { diff --git a/pkg/sentry/vfs/mount_namespace_refs.go b/pkg/sentry/vfs/mount_namespace_refs.go index 4c422c81f..ed126cc5e 100644 --- a/pkg/sentry/vfs/mount_namespace_refs.go +++ b/pkg/sentry/vfs/mount_namespace_refs.go @@ -1,11 +1,12 @@ package vfs import ( + "runtime" + "sync/atomic" + "fmt" "gvisor.dev/gvisor/pkg/log" refs_vfs1 "gvisor.dev/gvisor/pkg/refs" - "runtime" - "sync/atomic" ) // ownerType is used to customize logging. Note that we use a pointer to T so diff --git a/pkg/sentry/vfs/vfs.go b/pkg/sentry/vfs/vfs.go index 1ebf355ef..ed1cf99ba 100644 --- a/pkg/sentry/vfs/vfs.go +++ b/pkg/sentry/vfs/vfs.go @@ -819,30 +819,6 @@ func (vfs *VirtualFilesystem) MkdirAllAt(ctx context.Context, currentPath string return nil } -// MakeSyntheticMountpoint creates parent directories of target if they do not -// exist and attempts to create a directory for the mountpoint. If a -// non-directory file already exists there then we allow it. -func (vfs *VirtualFilesystem) MakeSyntheticMountpoint(ctx context.Context, target string, root VirtualDentry, creds *auth.Credentials) error { - mkdirOpts := &MkdirOptions{Mode: 0777, ForSyntheticMountpoint: true} - - // Make sure the parent directory of target exists. - if err := vfs.MkdirAllAt(ctx, path.Dir(target), root, creds, mkdirOpts); err != nil { - return fmt.Errorf("failed to create parent directory of mountpoint %q: %w", target, err) - } - - // Attempt to mkdir the final component. If a file (of any type) exists - // then we let allow mounting on top of that because we do not require the - // target to be an existing directory, unlike Linux mount(2). - if err := vfs.MkdirAt(ctx, creds, &PathOperation{ - Root: root, - Start: root, - Path: fspath.Parse(target), - }, mkdirOpts); err != nil && err != syserror.EEXIST { - return fmt.Errorf("failed to create mountpoint %q: %w", target, err) - } - return nil -} - // A VirtualDentry represents a node in a VFS tree, by combining a Dentry // (which represents a node in a Filesystem's tree) and a Mount (which // represents the Filesystem's position in a VFS mount tree). |