diff options
author | Jamie Liu <jamieliu@google.com> | 2020-05-08 11:34:15 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-05-08 11:35:41 -0700 |
commit | 21b71395a6aa2eafbc4c59222574d56c2db2e23b (patch) | |
tree | 39298c15bf0366caeb75fd348f646800d16fac6e /pkg | |
parent | 5d7d5ed7d6ffd8d420f042a22b22e0527e78d441 (diff) |
Pass flags to fsimpl/host.inode.open().
This has two effects: It makes flags passed to open("/proc/[pid]/fd/[hostfd]")
effective, and it prevents imported pipes/sockets/character devices from being
opened with O_NONBLOCK unconditionally (because the underlying host FD was set
to non-blocking in ImportFD()).
PiperOrigin-RevId: 310596062
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/sentry/fsimpl/host/host.go | 35 |
1 files changed, 14 insertions, 21 deletions
diff --git a/pkg/sentry/fsimpl/host/host.go b/pkg/sentry/fsimpl/host/host.go index 55de9c438..36bceeaa4 100644 --- a/pkg/sentry/fsimpl/host/host.go +++ b/pkg/sentry/fsimpl/host/host.go @@ -53,13 +53,19 @@ func ImportFD(ctx context.Context, mnt *vfs.Mount, hostFD int, isTTY bool) (*vfs return nil, err } + // Get flags for the imported FD. + flags, err := unix.FcntlInt(uintptr(hostFD), syscall.F_GETFL, 0) + if err != nil { + return nil, err + } + fileMode := linux.FileMode(s.Mode) fileType := fileMode.FileType() // Determine if hostFD is seekable. If not, this syscall will return ESPIPE // (see fs/read_write.c:llseek), e.g. for pipes, sockets, and some character // devices. - _, err := unix.Seek(hostFD, 0, linux.SEEK_CUR) + _, err = unix.Seek(hostFD, 0, linux.SEEK_CUR) seekable := err != syserror.ESPIPE i := &inode{ @@ -95,7 +101,7 @@ func ImportFD(ctx context.Context, mnt *vfs.Mount, hostFD int, isTTY bool) (*vfs // i.open will take a reference on d. defer d.DecRef() - return i.open(ctx, d.VFSDentry(), mnt) + return i.open(ctx, d.VFSDentry(), mnt, uint32(flags)) } // filesystemType implements vfs.FilesystemType. @@ -198,19 +204,6 @@ type inode struct { queue waiter.Queue } -// Note that these flags may become out of date, since they can be modified -// on the host, e.g. with fcntl. -func fileFlagsFromHostFD(fd int) (uint32, error) { - flags, err := unix.FcntlInt(uintptr(fd), syscall.F_GETFL, 0) - if err != nil { - log.Warningf("Failed to get file flags for donated FD %d: %v", fd, err) - return 0, err - } - // TODO(gvisor.dev/issue/1672): implement behavior corresponding to these allowed flags. - flags &= syscall.O_ACCMODE | syscall.O_DIRECT | syscall.O_NONBLOCK | syscall.O_DSYNC | syscall.O_SYNC | syscall.O_APPEND - return uint32(flags), nil -} - // CheckPermissions implements kernfs.Inode. func (i *inode) CheckPermissions(ctx context.Context, creds *auth.Credentials, ats vfs.AccessTypes) error { var s syscall.Stat_t @@ -406,19 +399,19 @@ func (i *inode) Open(ctx context.Context, rp *vfs.ResolvingPath, vfsd *vfs.Dentr if i.Mode().FileType() == linux.S_IFSOCK { return nil, syserror.ENXIO } - return i.open(ctx, vfsd, rp.Mount()) + return i.open(ctx, vfsd, rp.Mount(), opts.Flags) } -func (i *inode) open(ctx context.Context, d *vfs.Dentry, mnt *vfs.Mount) (*vfs.FileDescription, error) { +func (i *inode) open(ctx context.Context, d *vfs.Dentry, mnt *vfs.Mount, flags uint32) (*vfs.FileDescription, error) { var s syscall.Stat_t if err := syscall.Fstat(i.hostFD, &s); err != nil { return nil, err } fileType := s.Mode & linux.FileTypeMask - flags, err := fileFlagsFromHostFD(i.hostFD) - if err != nil { - return nil, err - } + + // Constrain flags to a subset we can handle. + // TODO(gvisor.dev/issue/1672): implement behavior corresponding to these allowed flags. + flags &= syscall.O_ACCMODE | syscall.O_DIRECT | syscall.O_NONBLOCK | syscall.O_DSYNC | syscall.O_SYNC | syscall.O_APPEND if fileType == syscall.S_IFSOCK { if i.isTTY { |