summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fsimpl
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2020-04-24 18:49:57 +0000
committergVisor bot <gvisor-bot@google.com>2020-04-24 18:49:57 +0000
commitada068d683c1f6be72ecbeda436659ba6ecd1e9a (patch)
treea23dd4061907427c2d1e289a45651dc6b102e44f /pkg/sentry/fsimpl
parent57f05062f655eb7b1d9a43b407b82b97449195ee (diff)
parent2cc0fd42f462f3942230c4b33ca2825e2a28765d (diff)
Merge release-20200323.0-235-g2cc0fd4 (automated)
Diffstat (limited to 'pkg/sentry/fsimpl')
-rwxr-xr-xpkg/sentry/fsimpl/kernfs/fd_impl_util.go28
-rwxr-xr-xpkg/sentry/fsimpl/kernfs/filesystem.go4
-rwxr-xr-xpkg/sentry/fsimpl/kernfs/inode_impl_util.go8
-rwxr-xr-xpkg/sentry/fsimpl/kernfs/kernfs.go2
-rwxr-xr-xpkg/sentry/fsimpl/kernfs/symlink.go2
-rwxr-xr-xpkg/sentry/fsimpl/proc/subtasks.go49
-rwxr-xr-xpkg/sentry/fsimpl/proc/task.go7
-rwxr-xr-xpkg/sentry/fsimpl/proc/task_fds.go14
-rwxr-xr-xpkg/sentry/fsimpl/proc/task_files.go76
-rwxr-xr-xpkg/sentry/fsimpl/proc/tasks.go6
-rwxr-xr-xpkg/sentry/fsimpl/proc/tasks_files.go4
-rwxr-xr-xpkg/sentry/fsimpl/sys/sys.go4
12 files changed, 174 insertions, 30 deletions
diff --git a/pkg/sentry/fsimpl/kernfs/fd_impl_util.go b/pkg/sentry/fsimpl/kernfs/fd_impl_util.go
index e8a4670b8..dd5806301 100755
--- a/pkg/sentry/fsimpl/kernfs/fd_impl_util.go
+++ b/pkg/sentry/fsimpl/kernfs/fd_impl_util.go
@@ -15,6 +15,8 @@
package kernfs
import (
+ "math"
+
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -43,15 +45,27 @@ type GenericDirectoryFD struct {
off int64
}
-// Init initializes a GenericDirectoryFD.
-func (fd *GenericDirectoryFD) Init(m *vfs.Mount, d *vfs.Dentry, children *OrderedChildren, opts *vfs.OpenOptions) error {
+// NewGenericDirectoryFD creates a new GenericDirectoryFD and returns its
+// dentry.
+func NewGenericDirectoryFD(m *vfs.Mount, d *vfs.Dentry, children *OrderedChildren, opts *vfs.OpenOptions) (*GenericDirectoryFD, error) {
+ fd := &GenericDirectoryFD{}
+ if err := fd.Init(children, opts); err != nil {
+ return nil, err
+ }
+ if err := fd.vfsfd.Init(fd, opts.Flags, m, d, &vfs.FileDescriptionOptions{}); err != nil {
+ return nil, err
+ }
+ return fd, nil
+}
+
+// Init initializes a GenericDirectoryFD. Use it when overriding
+// GenericDirectoryFD. Caller must call fd.VFSFileDescription.Init() with the
+// correct implementation.
+func (fd *GenericDirectoryFD) Init(children *OrderedChildren, opts *vfs.OpenOptions) error {
if vfs.AccessTypesForOpenFlags(opts)&vfs.MayWrite != 0 {
// Can't open directories for writing.
return syserror.EISDIR
}
- if err := fd.vfsfd.Init(fd, opts.Flags, m, d, &vfs.FileDescriptionOptions{}); err != nil {
- return err
- }
fd.children = children
return nil
}
@@ -187,6 +201,10 @@ func (fd *GenericDirectoryFD) Seek(ctx context.Context, offset int64, whence int
// Use offset as given.
case linux.SEEK_CUR:
offset += fd.off
+ case linux.SEEK_END:
+ // TODO(gvisor.dev/issue/1193): This can prevent new files from showing up
+ // if they are added after SEEK_END.
+ offset = math.MaxInt64
default:
return 0, syserror.EINVAL
}
diff --git a/pkg/sentry/fsimpl/kernfs/filesystem.go b/pkg/sentry/fsimpl/kernfs/filesystem.go
index 1d46dba25..3ccd92fc5 100755
--- a/pkg/sentry/fsimpl/kernfs/filesystem.go
+++ b/pkg/sentry/fsimpl/kernfs/filesystem.go
@@ -82,7 +82,7 @@ afterSymlink:
}
// Resolve any symlink at current path component.
if rp.ShouldFollowSymlink() && next.isSymlink() {
- targetVD, targetPathname, err := next.inode.Getlink(ctx)
+ targetVD, targetPathname, err := next.inode.Getlink(ctx, rp.Mount())
if err != nil {
return nil, err
}
@@ -477,7 +477,7 @@ afterTrailingSymlink:
}
child := childVFSD.Impl().(*Dentry)
if rp.ShouldFollowSymlink() && child.isSymlink() {
- targetVD, targetPathname, err := child.inode.Getlink(ctx)
+ targetVD, targetPathname, err := child.inode.Getlink(ctx, rp.Mount())
if err != nil {
return nil, err
}
diff --git a/pkg/sentry/fsimpl/kernfs/inode_impl_util.go b/pkg/sentry/fsimpl/kernfs/inode_impl_util.go
index a946645f6..02f35a675 100755
--- a/pkg/sentry/fsimpl/kernfs/inode_impl_util.go
+++ b/pkg/sentry/fsimpl/kernfs/inode_impl_util.go
@@ -182,7 +182,7 @@ func (InodeNotSymlink) Readlink(context.Context) (string, error) {
}
// Getlink implements Inode.Getlink.
-func (InodeNotSymlink) Getlink(context.Context) (vfs.VirtualDentry, string, error) {
+func (InodeNotSymlink) Getlink(context.Context, *vfs.Mount) (vfs.VirtualDentry, string, error) {
return vfs.VirtualDentry{}, "", syserror.EINVAL
}
@@ -568,8 +568,10 @@ func (s *StaticDirectory) Init(creds *auth.Credentials, ino uint64, perm linux.F
// Open implements kernfs.Inode.
func (s *StaticDirectory) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
- fd := &GenericDirectoryFD{}
- fd.Init(rp.Mount(), vfsd, &s.OrderedChildren, &opts)
+ fd, err := NewGenericDirectoryFD(rp.Mount(), vfsd, &s.OrderedChildren, &opts)
+ if err != nil {
+ return nil, err
+ }
return fd.VFSFileDescription(), nil
}
diff --git a/pkg/sentry/fsimpl/kernfs/kernfs.go b/pkg/sentry/fsimpl/kernfs/kernfs.go
index f5041824f..95cf6dc24 100755
--- a/pkg/sentry/fsimpl/kernfs/kernfs.go
+++ b/pkg/sentry/fsimpl/kernfs/kernfs.go
@@ -439,5 +439,5 @@ type inodeSymlink interface {
//
// - If the inode is not a symlink, Getlink returns (zero-value
// VirtualDentry, "", EINVAL).
- Getlink(ctx context.Context) (vfs.VirtualDentry, string, error)
+ Getlink(ctx context.Context, mnt *vfs.Mount) (vfs.VirtualDentry, string, error)
}
diff --git a/pkg/sentry/fsimpl/kernfs/symlink.go b/pkg/sentry/fsimpl/kernfs/symlink.go
index 018aa503c..0aa6dc979 100755
--- a/pkg/sentry/fsimpl/kernfs/symlink.go
+++ b/pkg/sentry/fsimpl/kernfs/symlink.go
@@ -56,7 +56,7 @@ func (s *StaticSymlink) Readlink(_ context.Context) (string, error) {
}
// Getlink implements Inode.Getlink.
-func (s *StaticSymlink) Getlink(_ context.Context) (vfs.VirtualDentry, string, error) {
+func (s *StaticSymlink) Getlink(context.Context, *vfs.Mount) (vfs.VirtualDentry, string, error) {
return vfs.VirtualDentry{}, s.target, nil
}
diff --git a/pkg/sentry/fsimpl/proc/subtasks.go b/pkg/sentry/fsimpl/proc/subtasks.go
index a21313666..28ec2484a 100755
--- a/pkg/sentry/fsimpl/proc/subtasks.go
+++ b/pkg/sentry/fsimpl/proc/subtasks.go
@@ -88,6 +88,9 @@ func (i *subtasksInode) IterDirents(ctx context.Context, cb vfs.IterDirentsCallb
if len(tasks) == 0 {
return offset, syserror.ENOENT
}
+ if relOffset >= int64(len(tasks)) {
+ return offset, nil
+ }
tids := make([]int, 0, len(tasks))
for _, tid := range tasks {
@@ -110,10 +113,52 @@ func (i *subtasksInode) IterDirents(ctx context.Context, cb vfs.IterDirentsCallb
return offset, nil
}
+type subtasksFD struct {
+ kernfs.GenericDirectoryFD
+
+ task *kernel.Task
+}
+
+func (fd *subtasksFD) IterDirents(ctx context.Context, cb vfs.IterDirentsCallback) error {
+ if fd.task.ExitState() >= kernel.TaskExitZombie {
+ return syserror.ENOENT
+ }
+ return fd.GenericDirectoryFD.IterDirents(ctx, cb)
+}
+
+// Seek implements vfs.FileDecriptionImpl.Seek.
+func (fd *subtasksFD) Seek(ctx context.Context, offset int64, whence int32) (int64, error) {
+ if fd.task.ExitState() >= kernel.TaskExitZombie {
+ return 0, syserror.ENOENT
+ }
+ return fd.GenericDirectoryFD.Seek(ctx, offset, whence)
+}
+
+// Stat implements vfs.FileDescriptionImpl.Stat.
+func (fd *subtasksFD) Stat(ctx context.Context, opts vfs.StatOptions) (linux.Statx, error) {
+ if fd.task.ExitState() >= kernel.TaskExitZombie {
+ return linux.Statx{}, syserror.ENOENT
+ }
+ return fd.GenericDirectoryFD.Stat(ctx, opts)
+}
+
+// SetStat implements vfs.FileDescriptionImpl.SetStat.
+func (fd *subtasksFD) SetStat(ctx context.Context, opts vfs.SetStatOptions) error {
+ if fd.task.ExitState() >= kernel.TaskExitZombie {
+ return syserror.ENOENT
+ }
+ return fd.GenericDirectoryFD.SetStat(ctx, opts)
+}
+
// Open implements kernfs.Inode.
func (i *subtasksInode) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
- fd := &kernfs.GenericDirectoryFD{}
- fd.Init(rp.Mount(), vfsd, &i.OrderedChildren, &opts)
+ fd := &subtasksFD{task: i.task}
+ if err := fd.Init(&i.OrderedChildren, &opts); err != nil {
+ return nil, err
+ }
+ if err := fd.VFSFileDescription().Init(fd, opts.Flags, rp.Mount(), vfsd, &vfs.FileDescriptionOptions{}); err != nil {
+ return nil, err
+ }
return fd.VFSFileDescription(), nil
}
diff --git a/pkg/sentry/fsimpl/proc/task.go b/pkg/sentry/fsimpl/proc/task.go
index 888afc0fd..e2790d35b 100755
--- a/pkg/sentry/fsimpl/proc/task.go
+++ b/pkg/sentry/fsimpl/proc/task.go
@@ -44,6 +44,7 @@ type taskInode struct {
var _ kernfs.Inode = (*taskInode)(nil)
func newTaskInode(inoGen InoGenerator, task *kernel.Task, pidns *kernel.PIDNamespace, isThreadGroup bool, cgroupControllers map[string]string) *kernfs.Dentry {
+ // TODO(gvisor.dev/issue/164): Fail with ESRCH if task exited.
contents := map[string]*kernfs.Dentry{
"auxv": newTaskOwnedFile(task, inoGen.NextIno(), 0444, &auxvData{task: task}),
"cmdline": newTaskOwnedFile(task, inoGen.NextIno(), 0444, &cmdlineData{task: task, arg: cmdlineDataArg}),
@@ -102,8 +103,10 @@ func (i *taskInode) Valid(ctx context.Context) bool {
// Open implements kernfs.Inode.
func (i *taskInode) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
- fd := &kernfs.GenericDirectoryFD{}
- fd.Init(rp.Mount(), vfsd, &i.OrderedChildren, &opts)
+ fd, err := kernfs.NewGenericDirectoryFD(rp.Mount(), vfsd, &i.OrderedChildren, &opts)
+ if err != nil {
+ return nil, err
+ }
return fd.VFSFileDescription(), nil
}
diff --git a/pkg/sentry/fsimpl/proc/task_fds.go b/pkg/sentry/fsimpl/proc/task_fds.go
index 046265eca..a7622f1b6 100755
--- a/pkg/sentry/fsimpl/proc/task_fds.go
+++ b/pkg/sentry/fsimpl/proc/task_fds.go
@@ -143,8 +143,10 @@ func (i *fdDirInode) Lookup(ctx context.Context, name string) (*vfs.Dentry, erro
// Open implements kernfs.Inode.
func (i *fdDirInode) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
- fd := &kernfs.GenericDirectoryFD{}
- fd.Init(rp.Mount(), vfsd, &i.OrderedChildren, &opts)
+ fd, err := kernfs.NewGenericDirectoryFD(rp.Mount(), vfsd, &i.OrderedChildren, &opts)
+ if err != nil {
+ return nil, err
+ }
return fd.VFSFileDescription(), nil
}
@@ -207,7 +209,7 @@ func (s *fdSymlink) Readlink(ctx context.Context) (string, error) {
return s.task.Kernel().VFS().PathnameWithDeleted(ctx, root, file.VirtualDentry())
}
-func (s *fdSymlink) Getlink(ctx context.Context) (vfs.VirtualDentry, string, error) {
+func (s *fdSymlink) Getlink(ctx context.Context, mnt *vfs.Mount) (vfs.VirtualDentry, string, error) {
file, _ := getTaskFD(s.task, s.fd)
if file == nil {
return vfs.VirtualDentry{}, "", syserror.ENOENT
@@ -268,8 +270,10 @@ func (i *fdInfoDirInode) Lookup(ctx context.Context, name string) (*vfs.Dentry,
// Open implements kernfs.Inode.
func (i *fdInfoDirInode) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
- fd := &kernfs.GenericDirectoryFD{}
- fd.Init(rp.Mount(), vfsd, &i.OrderedChildren, &opts)
+ fd, err := kernfs.NewGenericDirectoryFD(rp.Mount(), vfsd, &i.OrderedChildren, &opts)
+ if err != nil {
+ return nil, err
+ }
return fd.VFSFileDescription(), nil
}
diff --git a/pkg/sentry/fsimpl/proc/task_files.go b/pkg/sentry/fsimpl/proc/task_files.go
index f3173e197..410cc3552 100755
--- a/pkg/sentry/fsimpl/proc/task_files.go
+++ b/pkg/sentry/fsimpl/proc/task_files.go
@@ -622,7 +622,7 @@ func (s *exeSymlink) Readlink(ctx context.Context) (string, error) {
}
// Getlink implements kernfs.Inode.Getlink.
-func (s *exeSymlink) Getlink(ctx context.Context) (vfs.VirtualDentry, string, error) {
+func (s *exeSymlink) Getlink(ctx context.Context, _ *vfs.Mount) (vfs.VirtualDentry, string, error) {
if !kernel.ContextCanTrace(ctx, s.task, false) {
return vfs.VirtualDentry{}, "", syserror.EACCES
}
@@ -754,9 +754,79 @@ func (s *namespaceSymlink) Readlink(ctx context.Context) (string, error) {
}
// Getlink implements Inode.Getlink.
-func (s *namespaceSymlink) Getlink(ctx context.Context) (vfs.VirtualDentry, string, error) {
+func (s *namespaceSymlink) Getlink(ctx context.Context, mnt *vfs.Mount) (vfs.VirtualDentry, string, error) {
if err := checkTaskState(s.task); err != nil {
return vfs.VirtualDentry{}, "", err
}
- return s.StaticSymlink.Getlink(ctx)
+
+ // Create a synthetic inode to represent the namespace.
+ dentry := &kernfs.Dentry{}
+ dentry.Init(&namespaceInode{})
+ vd := vfs.MakeVirtualDentry(mnt, dentry.VFSDentry())
+ vd.IncRef()
+ dentry.DecRef()
+ return vd, "", nil
+}
+
+// namespaceInode is a synthetic inode created to represent a namespace in
+// /proc/[pid]/ns/*.
+type namespaceInode struct {
+ kernfs.InodeAttrs
+ kernfs.InodeNoopRefCount
+ kernfs.InodeNotDirectory
+ kernfs.InodeNotSymlink
+}
+
+var _ kernfs.Inode = (*namespaceInode)(nil)
+
+// Init initializes a namespace inode.
+func (i *namespaceInode) Init(creds *auth.Credentials, ino uint64, perm linux.FileMode) {
+ if perm&^linux.PermissionsMask != 0 {
+ panic(fmt.Sprintf("Only permission mask must be set: %x", perm&linux.PermissionsMask))
+ }
+ i.InodeAttrs.Init(creds, ino, linux.ModeRegular|perm)
+}
+
+// Open implements Inode.Open.
+func (i *namespaceInode) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
+ fd := &namespaceFD{inode: i}
+ i.IncRef()
+ if err := fd.vfsfd.Init(fd, opts.Flags, rp.Mount(), vfsd, &vfs.FileDescriptionOptions{}); err != nil {
+ return nil, err
+ }
+ return &fd.vfsfd, nil
+}
+
+// namespace FD is a synthetic file that represents a namespace in
+// /proc/[pid]/ns/*.
+type namespaceFD struct {
+ vfs.FileDescriptionDefaultImpl
+
+ vfsfd vfs.FileDescription
+ inode *namespaceInode
+}
+
+var _ vfs.FileDescriptionImpl = (*namespaceFD)(nil)
+
+// Stat implements FileDescriptionImpl.
+func (fd *namespaceFD) Stat(ctx context.Context, opts vfs.StatOptions) (linux.Statx, error) {
+ vfs := fd.vfsfd.VirtualDentry().Mount().Filesystem()
+ return fd.inode.Stat(vfs, opts)
+}
+
+// SetStat implements FileDescriptionImpl.
+func (fd *namespaceFD) SetStat(ctx context.Context, opts vfs.SetStatOptions) error {
+ vfs := fd.vfsfd.VirtualDentry().Mount().Filesystem()
+ creds := auth.CredentialsFromContext(ctx)
+ return fd.inode.SetStat(ctx, vfs, creds, opts)
+}
+
+// Release implements FileDescriptionImpl.
+func (fd *namespaceFD) Release() {
+ fd.inode.DecRef()
+}
+
+// OnClose implements FileDescriptionImpl.
+func (*namespaceFD) OnClose(context.Context) error {
+ return nil
}
diff --git a/pkg/sentry/fsimpl/proc/tasks.go b/pkg/sentry/fsimpl/proc/tasks.go
index 9f2ef8200..26518ed03 100755
--- a/pkg/sentry/fsimpl/proc/tasks.go
+++ b/pkg/sentry/fsimpl/proc/tasks.go
@@ -202,8 +202,10 @@ func (i *tasksInode) IterDirents(ctx context.Context, cb vfs.IterDirentsCallback
// Open implements kernfs.Inode.
func (i *tasksInode) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
- fd := &kernfs.GenericDirectoryFD{}
- fd.Init(rp.Mount(), vfsd, &i.OrderedChildren, &opts)
+ fd, err := kernfs.NewGenericDirectoryFD(rp.Mount(), vfsd, &i.OrderedChildren, &opts)
+ if err != nil {
+ return nil, err
+ }
return fd.VFSFileDescription(), nil
}
diff --git a/pkg/sentry/fsimpl/proc/tasks_files.go b/pkg/sentry/fsimpl/proc/tasks_files.go
index 4621e2de0..92007df81 100755
--- a/pkg/sentry/fsimpl/proc/tasks_files.go
+++ b/pkg/sentry/fsimpl/proc/tasks_files.go
@@ -63,7 +63,7 @@ func (s *selfSymlink) Readlink(ctx context.Context) (string, error) {
return strconv.FormatUint(uint64(tgid), 10), nil
}
-func (s *selfSymlink) Getlink(ctx context.Context) (vfs.VirtualDentry, string, error) {
+func (s *selfSymlink) Getlink(ctx context.Context, _ *vfs.Mount) (vfs.VirtualDentry, string, error) {
target, err := s.Readlink(ctx)
return vfs.VirtualDentry{}, target, err
}
@@ -106,7 +106,7 @@ func (s *threadSelfSymlink) Readlink(ctx context.Context) (string, error) {
return fmt.Sprintf("%d/task/%d", tgid, tid), nil
}
-func (s *threadSelfSymlink) Getlink(ctx context.Context) (vfs.VirtualDentry, string, error) {
+func (s *threadSelfSymlink) Getlink(ctx context.Context, _ *vfs.Mount) (vfs.VirtualDentry, string, error) {
target, err := s.Readlink(ctx)
return vfs.VirtualDentry{}, target, err
}
diff --git a/pkg/sentry/fsimpl/sys/sys.go b/pkg/sentry/fsimpl/sys/sys.go
index 5c617270e..34e8e0cbe 100755
--- a/pkg/sentry/fsimpl/sys/sys.go
+++ b/pkg/sentry/fsimpl/sys/sys.go
@@ -106,8 +106,8 @@ func (*dir) SetStat(context.Context, *vfs.Filesystem, *auth.Credentials, vfs.Set
// Open implements kernfs.Inode.Open.
func (d *dir) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
- fd := &kernfs.GenericDirectoryFD{}
- if err := fd.Init(rp.Mount(), vfsd, &d.OrderedChildren, &opts); err != nil {
+ fd, err := kernfs.NewGenericDirectoryFD(rp.Mount(), vfsd, &d.OrderedChildren, &opts)
+ if err != nil {
return nil, err
}
return fd.VFSFileDescription(), nil