summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorJamie Liu <jamieliu@google.com>2020-05-08 11:34:15 -0700
committergVisor bot <gvisor-bot@google.com>2020-05-08 11:35:41 -0700
commit21b71395a6aa2eafbc4c59222574d56c2db2e23b (patch)
tree39298c15bf0366caeb75fd348f646800d16fac6e /pkg
parent5d7d5ed7d6ffd8d420f042a22b22e0527e78d441 (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.go35
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 {