mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
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
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user