Add fsimpl/gofer.InternalFilesystemOptions.OpenSocketsByConnecting.

PiperOrigin-RevId: 311014995
This commit is contained in:
Jamie Liu 2020-05-11 16:13:14 -07:00 committed by gVisor bot
parent 633e1b89bb
commit 15de8cc9e0
3 changed files with 61 additions and 11 deletions

View File

@ -21,6 +21,8 @@ import (
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/p9"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/host"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/kernel/pipe"
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
@ -835,6 +837,9 @@ func (d *dentry) openLocked(ctx context.Context, rp *vfs.ResolvingPath, opts *vf
if d.isSynthetic() {
return nil, syserror.ENXIO
}
if d.fs.iopts.OpenSocketsByConnecting {
return d.connectSocketLocked(ctx, opts)
}
case linux.S_IFIFO:
if d.isSynthetic() {
return d.pipe.Open(ctx, mnt, &d.vfsd, opts.Flags)
@ -843,10 +848,28 @@ func (d *dentry) openLocked(ctx context.Context, rp *vfs.ResolvingPath, opts *vf
return d.openSpecialFileLocked(ctx, mnt, opts)
}
func (d *dentry) connectSocketLocked(ctx context.Context, opts *vfs.OpenOptions) (*vfs.FileDescription, error) {
if opts.Flags&linux.O_DIRECT != 0 {
return nil, syserror.EINVAL
}
fdObj, err := d.file.connect(ctx, p9.AnonymousSocket)
if err != nil {
return nil, err
}
fd, err := host.NewFD(ctx, kernel.KernelFromContext(ctx).HostMount(), fdObj.FD(), &host.NewFDOptions{
HaveFlags: true,
Flags: opts.Flags,
})
if err != nil {
fdObj.Close()
return nil, err
}
fdObj.Release()
return fd, nil
}
func (d *dentry) openSpecialFileLocked(ctx context.Context, mnt *vfs.Mount, opts *vfs.OpenOptions) (*vfs.FileDescription, error) {
ats := vfs.AccessTypesForOpenFlags(opts)
// Treat as a special file. This is done for non-synthetic pipes as well as
// regular files when d.fs.opts.regularFilesUseSpecialFileFD is true.
if opts.Flags&linux.O_DIRECT != 0 {
return nil, syserror.EINVAL
}

View File

@ -221,6 +221,10 @@ type InternalFilesystemOptions struct {
// which servers can handle only a single client and report failure if that
// client disconnects.
LeakConnection bool
// If OpenSocketsByConnecting is true, silently translate attempts to open
// files identifying as sockets to connect RPCs.
OpenSocketsByConnecting bool
}
// Name implements vfs.FilesystemType.Name.

View File

@ -40,8 +40,20 @@ import (
"gvisor.dev/gvisor/pkg/waiter"
)
// ImportFD sets up and returns a vfs.FileDescription from a donated fd.
func ImportFD(ctx context.Context, mnt *vfs.Mount, hostFD int, isTTY bool) (*vfs.FileDescription, error) {
// NewFDOptions contains options to NewFD.
type NewFDOptions struct {
// If IsTTY is true, the file descriptor is a TTY.
IsTTY bool
// If HaveFlags is true, use Flags for the new file description. Otherwise,
// the new file description will inherit flags from hostFD.
HaveFlags bool
Flags uint32
}
// NewFD returns a vfs.FileDescription representing the given host file
// descriptor. mnt must be Kernel.HostMount().
func NewFD(ctx context.Context, mnt *vfs.Mount, hostFD int, opts *NewFDOptions) (*vfs.FileDescription, error) {
fs, ok := mnt.Filesystem().Impl().(*filesystem)
if !ok {
return nil, fmt.Errorf("can't import host FDs into filesystems of type %T", mnt.Filesystem().Impl())
@ -53,10 +65,14 @@ 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
flags := opts.Flags
if !opts.HaveFlags {
// Get flags for the imported FD.
flagsInt, err := unix.FcntlInt(uintptr(hostFD), syscall.F_GETFL, 0)
if err != nil {
return nil, err
}
flags = uint32(flagsInt)
}
fileMode := linux.FileMode(s.Mode)
@ -65,13 +81,13 @@ func ImportFD(ctx context.Context, mnt *vfs.Mount, hostFD int, isTTY bool) (*vfs
// 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{
hostFD: hostFD,
seekable: seekable,
isTTY: isTTY,
isTTY: opts.IsTTY,
canMap: canMap(uint32(fileType)),
wouldBlock: wouldBlock(uint32(fileType)),
ino: fs.NextIno(),
@ -101,7 +117,14 @@ 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, uint32(flags))
return i.open(ctx, d.VFSDentry(), mnt, flags)
}
// ImportFD sets up and returns a vfs.FileDescription from a donated fd.
func ImportFD(ctx context.Context, mnt *vfs.Mount, hostFD int, isTTY bool) (*vfs.FileDescription, error) {
return NewFD(ctx, mnt, hostFD, &NewFDOptions{
IsTTY: isTTY,
})
}
// filesystemType implements vfs.FilesystemType.