mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add FileExec flag to OpenOptions
This allow callers to say whether the file is being opened to be executed, so that the proper checks can be done from FilesystemImpl.OpenAt() Updates #1623 PiperOrigin-RevId: 295042595
This commit is contained in:
@@ -296,7 +296,7 @@ func (fs *filesystem) OpenAt(ctx context.Context, rp *vfs.ResolvingPath, opts vf
|
||||
if vfs.MayWriteFileWithOpenFlags(opts.Flags) || opts.Flags&(linux.O_CREAT|linux.O_EXCL|linux.O_TMPFILE) != 0 {
|
||||
return nil, syserror.EROFS
|
||||
}
|
||||
return inode.open(rp, vfsd, opts.Flags)
|
||||
return inode.open(rp, vfsd, &opts)
|
||||
}
|
||||
|
||||
// ReadlinkAt implements vfs.FilesystemImpl.ReadlinkAt.
|
||||
|
||||
@@ -148,8 +148,8 @@ func newInode(fs *filesystem, inodeNum uint32) (*inode, error) {
|
||||
}
|
||||
|
||||
// open creates and returns a file description for the dentry passed in.
|
||||
func (in *inode) open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) {
|
||||
ats := vfs.AccessTypesForOpenFlags(flags)
|
||||
func (in *inode) open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts *vfs.OpenOptions) (*vfs.FileDescription, error) {
|
||||
ats := vfs.AccessTypesForOpenFlags(opts)
|
||||
if err := in.checkPermissions(rp.Credentials(), ats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -157,7 +157,7 @@ func (in *inode) open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*v
|
||||
switch in.impl.(type) {
|
||||
case *regularFile:
|
||||
var fd regularFileFD
|
||||
if err := fd.vfsfd.Init(&fd, flags, mnt, vfsd, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
if err := fd.vfsfd.Init(&fd, opts.Flags, mnt, vfsd, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fd.vfsfd, nil
|
||||
@@ -168,17 +168,17 @@ func (in *inode) open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*v
|
||||
return nil, syserror.EISDIR
|
||||
}
|
||||
var fd directoryFD
|
||||
if err := fd.vfsfd.Init(&fd, flags, mnt, vfsd, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
if err := fd.vfsfd.Init(&fd, opts.Flags, mnt, vfsd, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fd.vfsfd, nil
|
||||
case *symlink:
|
||||
if flags&linux.O_PATH == 0 {
|
||||
if opts.Flags&linux.O_PATH == 0 {
|
||||
// Can't open symlinks without O_PATH.
|
||||
return nil, syserror.ELOOP
|
||||
}
|
||||
var fd symlinkFD
|
||||
fd.vfsfd.Init(&fd, flags, mnt, vfsd, &vfs.FileDescriptionOptions{})
|
||||
fd.vfsfd.Init(&fd, opts.Flags, mnt, vfsd, &vfs.FileDescriptionOptions{})
|
||||
return &fd.vfsfd, nil
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown inode type: %T", in.impl))
|
||||
|
||||
@@ -593,7 +593,7 @@ func (fs *filesystem) OpenAt(ctx context.Context, rp *vfs.ResolvingPath, opts vf
|
||||
}
|
||||
}
|
||||
if rp.Done() {
|
||||
return start.openLocked(ctx, rp, opts.Flags)
|
||||
return start.openLocked(ctx, rp, &opts)
|
||||
}
|
||||
|
||||
afterTrailingSymlink:
|
||||
@@ -633,12 +633,12 @@ afterTrailingSymlink:
|
||||
start = parent
|
||||
goto afterTrailingSymlink
|
||||
}
|
||||
return child.openLocked(ctx, rp, opts.Flags)
|
||||
return child.openLocked(ctx, rp, &opts)
|
||||
}
|
||||
|
||||
// Preconditions: fs.renameMu must be locked.
|
||||
func (d *dentry) openLocked(ctx context.Context, rp *vfs.ResolvingPath, flags uint32) (*vfs.FileDescription, error) {
|
||||
ats := vfs.AccessTypesForOpenFlags(flags)
|
||||
func (d *dentry) openLocked(ctx context.Context, rp *vfs.ResolvingPath, opts *vfs.OpenOptions) (*vfs.FileDescription, error) {
|
||||
ats := vfs.AccessTypesForOpenFlags(opts)
|
||||
if err := d.checkPermissions(rp.Credentials(), ats, d.isDir()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -646,11 +646,11 @@ func (d *dentry) openLocked(ctx context.Context, rp *vfs.ResolvingPath, flags ui
|
||||
filetype := d.fileType()
|
||||
switch {
|
||||
case filetype == linux.S_IFREG && !d.fs.opts.regularFilesUseSpecialFileFD:
|
||||
if err := d.ensureSharedHandle(ctx, ats&vfs.MayRead != 0, ats&vfs.MayWrite != 0, flags&linux.O_TRUNC != 0); err != nil {
|
||||
if err := d.ensureSharedHandle(ctx, ats&vfs.MayRead != 0, ats&vfs.MayWrite != 0, opts.Flags&linux.O_TRUNC != 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fd := ®ularFileFD{}
|
||||
if err := fd.vfsfd.Init(fd, flags, mnt, &d.vfsd, &vfs.FileDescriptionOptions{
|
||||
if err := fd.vfsfd.Init(fd, opts.Flags, mnt, &d.vfsd, &vfs.FileDescriptionOptions{
|
||||
AllowDirectIO: true,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
@@ -658,21 +658,21 @@ func (d *dentry) openLocked(ctx context.Context, rp *vfs.ResolvingPath, flags ui
|
||||
return &fd.vfsfd, nil
|
||||
case filetype == linux.S_IFDIR:
|
||||
// Can't open directories with O_CREAT.
|
||||
if flags&linux.O_CREAT != 0 {
|
||||
if opts.Flags&linux.O_CREAT != 0 {
|
||||
return nil, syserror.EISDIR
|
||||
}
|
||||
// Can't open directories writably.
|
||||
if ats&vfs.MayWrite != 0 {
|
||||
return nil, syserror.EISDIR
|
||||
}
|
||||
if flags&linux.O_DIRECT != 0 {
|
||||
if opts.Flags&linux.O_DIRECT != 0 {
|
||||
return nil, syserror.EINVAL
|
||||
}
|
||||
if err := d.ensureSharedHandle(ctx, ats&vfs.MayRead != 0, false /* write */, false /* trunc */); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fd := &directoryFD{}
|
||||
if err := fd.vfsfd.Init(fd, flags, mnt, &d.vfsd, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
if err := fd.vfsfd.Init(fd, opts.Flags, mnt, &d.vfsd, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fd.vfsfd, nil
|
||||
@@ -680,17 +680,17 @@ func (d *dentry) openLocked(ctx context.Context, rp *vfs.ResolvingPath, flags ui
|
||||
// Can't open symlinks without O_PATH (which is unimplemented).
|
||||
return nil, syserror.ELOOP
|
||||
default:
|
||||
if flags&linux.O_DIRECT != 0 {
|
||||
if opts.Flags&linux.O_DIRECT != 0 {
|
||||
return nil, syserror.EINVAL
|
||||
}
|
||||
h, err := openHandle(ctx, d.file, ats&vfs.MayRead != 0, ats&vfs.MayWrite != 0, flags&linux.O_TRUNC != 0)
|
||||
h, err := openHandle(ctx, d.file, ats&vfs.MayRead != 0, ats&vfs.MayWrite != 0, opts.Flags&linux.O_TRUNC != 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fd := &specialFileFD{
|
||||
handle: h,
|
||||
}
|
||||
if err := fd.vfsfd.Init(fd, flags, mnt, &d.vfsd, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
if err := fd.vfsfd.Init(fd, opts.Flags, mnt, &d.vfsd, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
h.close(ctx)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -53,9 +53,9 @@ func (f *DynamicBytesFile) Init(creds *auth.Credentials, ino uint64, data vfs.Dy
|
||||
}
|
||||
|
||||
// Open implements Inode.Open.
|
||||
func (f *DynamicBytesFile) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) {
|
||||
func (f *DynamicBytesFile) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
|
||||
fd := &DynamicBytesFD{}
|
||||
if err := fd.Init(rp.Mount(), vfsd, f.data, flags); err != nil {
|
||||
if err := fd.Init(rp.Mount(), vfsd, f.data, opts.Flags); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fd.vfsfd, nil
|
||||
|
||||
@@ -43,12 +43,12 @@ type GenericDirectoryFD struct {
|
||||
}
|
||||
|
||||
// Init initializes a GenericDirectoryFD.
|
||||
func (fd *GenericDirectoryFD) Init(m *vfs.Mount, d *vfs.Dentry, children *OrderedChildren, flags uint32) error {
|
||||
if vfs.AccessTypesForOpenFlags(flags)&vfs.MayWrite != 0 {
|
||||
func (fd *GenericDirectoryFD) Init(m *vfs.Mount, d *vfs.Dentry, 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, flags, m, d, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
if err := fd.vfsfd.Init(fd, opts.Flags, m, d, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
fd.children = children
|
||||
|
||||
@@ -365,7 +365,7 @@ func (fs *Filesystem) OpenAt(ctx context.Context, rp *vfs.ResolvingPath, opts vf
|
||||
// appropriate bits in rp), but are returned by
|
||||
// FileDescriptionImpl.StatusFlags().
|
||||
opts.Flags &= linux.O_ACCMODE | linux.O_CREAT | linux.O_EXCL | linux.O_TRUNC | linux.O_DIRECTORY | linux.O_NOFOLLOW
|
||||
ats := vfs.AccessTypesForOpenFlags(opts.Flags)
|
||||
ats := vfs.AccessTypesForOpenFlags(&opts)
|
||||
|
||||
// Do not create new file.
|
||||
if opts.Flags&linux.O_CREAT == 0 {
|
||||
@@ -379,7 +379,7 @@ func (fs *Filesystem) OpenAt(ctx context.Context, rp *vfs.ResolvingPath, opts vf
|
||||
if err := inode.CheckPermissions(ctx, rp.Credentials(), ats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return inode.Open(rp, vfsd, opts.Flags)
|
||||
return inode.Open(rp, vfsd, opts)
|
||||
}
|
||||
|
||||
// May create new file.
|
||||
@@ -398,7 +398,7 @@ func (fs *Filesystem) OpenAt(ctx context.Context, rp *vfs.ResolvingPath, opts vf
|
||||
if err := inode.CheckPermissions(ctx, rp.Credentials(), ats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return inode.Open(rp, vfsd, opts.Flags)
|
||||
return inode.Open(rp, vfsd, opts)
|
||||
}
|
||||
afterTrailingSymlink:
|
||||
parentVFSD, parentInode, err := fs.walkParentDirLocked(ctx, rp)
|
||||
@@ -438,7 +438,7 @@ afterTrailingSymlink:
|
||||
return nil, err
|
||||
}
|
||||
parentVFSD.Impl().(*Dentry).InsertChild(pc, child)
|
||||
return child.Impl().(*Dentry).inode.Open(rp, child, opts.Flags)
|
||||
return child.Impl().(*Dentry).inode.Open(rp, child, opts)
|
||||
}
|
||||
// Open existing file or follow symlink.
|
||||
if mustCreate {
|
||||
@@ -463,7 +463,7 @@ afterTrailingSymlink:
|
||||
if err := childInode.CheckPermissions(ctx, rp.Credentials(), ats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return childInode.Open(rp, childVFSD, opts.Flags)
|
||||
return childInode.Open(rp, childVFSD, opts)
|
||||
}
|
||||
|
||||
// ReadlinkAt implements vfs.FilesystemImpl.ReadlinkAt.
|
||||
|
||||
@@ -507,7 +507,7 @@ type InodeSymlink struct {
|
||||
}
|
||||
|
||||
// Open implements Inode.Open.
|
||||
func (InodeSymlink) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) {
|
||||
func (InodeSymlink) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
|
||||
return nil, syserror.ELOOP
|
||||
}
|
||||
|
||||
@@ -549,8 +549,8 @@ 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, flags uint32) (*vfs.FileDescription, error) {
|
||||
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, flags)
|
||||
fd.Init(rp.Mount(), vfsd, &s.OrderedChildren, &opts)
|
||||
return fd.VFSFileDescription(), nil
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ type Inode interface {
|
||||
// inode for its lifetime.
|
||||
//
|
||||
// Precondition: !rp.Done(). vfsd.Impl() must be a kernfs Dentry.
|
||||
Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error)
|
||||
Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error)
|
||||
}
|
||||
|
||||
type inodeRefs interface {
|
||||
|
||||
@@ -113,9 +113,9 @@ func (fs *filesystem) newReadonlyDir(creds *auth.Credentials, mode linux.FileMod
|
||||
return &dir.dentry
|
||||
}
|
||||
|
||||
func (d *readonlyDir) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) {
|
||||
func (d *readonlyDir) 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, flags); err != nil {
|
||||
if err := fd.Init(rp.Mount(), vfsd, &d.OrderedChildren, &opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fd.VFSFileDescription(), nil
|
||||
@@ -143,9 +143,9 @@ func (fs *filesystem) newDir(creds *auth.Credentials, mode linux.FileMode, conte
|
||||
return &dir.dentry
|
||||
}
|
||||
|
||||
func (d *dir) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) {
|
||||
func (d *dir) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
|
||||
fd := &kernfs.GenericDirectoryFD{}
|
||||
fd.Init(rp.Mount(), vfsd, &d.OrderedChildren, flags)
|
||||
fd.Init(rp.Mount(), vfsd, &d.OrderedChildren, &opts)
|
||||
return fd.VFSFileDescription(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -114,9 +114,9 @@ func (i *subtasksInode) IterDirents(ctx context.Context, cb vfs.IterDirentsCallb
|
||||
}
|
||||
|
||||
// Open implements kernfs.Inode.
|
||||
func (i *subtasksInode) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) {
|
||||
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, flags)
|
||||
fd.Init(rp.Mount(), vfsd, &i.OrderedChildren, &opts)
|
||||
return fd.VFSFileDescription(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -98,9 +98,9 @@ func (i *taskInode) Valid(ctx context.Context) bool {
|
||||
}
|
||||
|
||||
// Open implements kernfs.Inode.
|
||||
func (i *taskInode) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) {
|
||||
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, flags)
|
||||
fd.Init(rp.Mount(), vfsd, &i.OrderedChildren, &opts)
|
||||
return fd.VFSFileDescription(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -205,9 +205,9 @@ func (i *tasksInode) IterDirents(ctx context.Context, cb vfs.IterDirentsCallback
|
||||
}
|
||||
|
||||
// Open implements kernfs.Inode.
|
||||
func (i *tasksInode) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) {
|
||||
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, flags)
|
||||
fd.Init(rp.Mount(), vfsd, &i.OrderedChildren, &opts)
|
||||
return fd.VFSFileDescription(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -97,9 +97,9 @@ func (d *dir) SetStat(fs *vfs.Filesystem, opts vfs.SetStatOptions) error {
|
||||
}
|
||||
|
||||
// Open implements kernfs.Inode.Open.
|
||||
func (d *dir) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) {
|
||||
func (d *dir) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
|
||||
fd := &kernfs.GenericDirectoryFD{}
|
||||
fd.Init(rp.Mount(), vfsd, &d.OrderedChildren, flags)
|
||||
fd.Init(rp.Mount(), vfsd, &d.OrderedChildren, &opts)
|
||||
return fd.VFSFileDescription(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -334,7 +334,7 @@ afterTrailingSymlink:
|
||||
}
|
||||
|
||||
func (d *dentry) open(ctx context.Context, rp *vfs.ResolvingPath, opts *vfs.OpenOptions, afterCreate bool) (*vfs.FileDescription, error) {
|
||||
ats := vfs.AccessTypesForOpenFlags(opts.Flags)
|
||||
ats := vfs.AccessTypesForOpenFlags(opts)
|
||||
if !afterCreate {
|
||||
if err := d.inode.checkPermissions(rp.Credentials(), ats, d.inode.isDir()); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -72,6 +72,11 @@ type OpenOptions struct {
|
||||
// If FilesystemImpl.OpenAt() creates a file, Mode is the file mode for the
|
||||
// created file.
|
||||
Mode linux.FileMode
|
||||
|
||||
// FileExec is set when the file is being opened to be executed.
|
||||
// VirtualFilesystem.OpenAt() checks that the caller has execute permissions
|
||||
// on the file, and that the file is a regular file.
|
||||
FileExec bool
|
||||
}
|
||||
|
||||
// ReadOptions contains options to FileDescription.PRead(),
|
||||
|
||||
@@ -103,17 +103,22 @@ func GenericCheckPermissions(creds *auth.Credentials, ats AccessTypes, isDir boo
|
||||
// AccessTypesForOpenFlags returns MayRead|MayWrite in this case.
|
||||
//
|
||||
// Use May{Read,Write}FileWithOpenFlags() for these checks instead.
|
||||
func AccessTypesForOpenFlags(flags uint32) AccessTypes {
|
||||
switch flags & linux.O_ACCMODE {
|
||||
func AccessTypesForOpenFlags(opts *OpenOptions) AccessTypes {
|
||||
ats := AccessTypes(0)
|
||||
if opts.FileExec {
|
||||
ats |= MayExec
|
||||
}
|
||||
|
||||
switch opts.Flags & linux.O_ACCMODE {
|
||||
case linux.O_RDONLY:
|
||||
if flags&linux.O_TRUNC != 0 {
|
||||
return MayRead | MayWrite
|
||||
if opts.Flags&linux.O_TRUNC != 0 {
|
||||
return ats | MayRead | MayWrite
|
||||
}
|
||||
return MayRead
|
||||
return ats | MayRead
|
||||
case linux.O_WRONLY:
|
||||
return MayWrite
|
||||
return ats | MayWrite
|
||||
default:
|
||||
return MayRead | MayWrite
|
||||
return ats | MayRead | MayWrite
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -379,6 +379,25 @@ func (vfs *VirtualFilesystem) OpenAt(ctx context.Context, creds *auth.Credential
|
||||
fd, err := rp.mount.fs.impl.OpenAt(ctx, rp, *opts)
|
||||
if err == nil {
|
||||
vfs.putResolvingPath(rp)
|
||||
|
||||
// TODO(gvisor.dev/issue/1193): Move inside fsimpl to avoid another call
|
||||
// to FileDescription.Stat().
|
||||
if opts.FileExec {
|
||||
// Only a regular file can be executed.
|
||||
stat, err := fd.Stat(ctx, StatOptions{Mask: linux.STATX_TYPE})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if stat.Mask&linux.STATX_TYPE != 0 {
|
||||
// This shouldn't happen, but if type can't be retrieved, file can't
|
||||
// be executed.
|
||||
return nil, syserror.EACCES
|
||||
}
|
||||
if linux.FileMode(stat.Mode).FileType() != linux.ModeRegular {
|
||||
return nil, syserror.EACCES
|
||||
}
|
||||
}
|
||||
|
||||
return fd, nil
|
||||
}
|
||||
if !rp.handleError(err) {
|
||||
|
||||
Reference in New Issue
Block a user