github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fsimpl/kernfs/dynamic_bytes_file.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package kernfs 16 17 import ( 18 "fmt" 19 20 "github.com/SagerNet/gvisor/pkg/abi/linux" 21 "github.com/SagerNet/gvisor/pkg/context" 22 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 23 "github.com/SagerNet/gvisor/pkg/sentry/kernel/auth" 24 "github.com/SagerNet/gvisor/pkg/sentry/vfs" 25 "github.com/SagerNet/gvisor/pkg/usermem" 26 ) 27 28 // DynamicBytesFile implements kernfs.Inode and represents a read-only file 29 // whose contents are backed by a vfs.DynamicBytesSource. If data additionally 30 // implements vfs.WritableDynamicBytesSource, the file also supports dispatching 31 // writes to the implementer, but note that this will not update the source data. 32 // 33 // Must be instantiated with NewDynamicBytesFile or initialized with Init 34 // before first use. 35 // 36 // +stateify savable 37 type DynamicBytesFile struct { 38 InodeAttrs 39 InodeNoStatFS 40 InodeNoopRefCount 41 InodeNotDirectory 42 InodeNotSymlink 43 44 locks vfs.FileLocks 45 // data can additionally implement vfs.WritableDynamicBytesSource to support 46 // writes. 47 data vfs.DynamicBytesSource 48 } 49 50 var _ Inode = (*DynamicBytesFile)(nil) 51 52 // Init initializes a dynamic bytes file. 53 func (f *DynamicBytesFile) Init(ctx context.Context, creds *auth.Credentials, devMajor, devMinor uint32, ino uint64, data vfs.DynamicBytesSource, perm linux.FileMode) { 54 if perm&^linux.PermissionsMask != 0 { 55 panic(fmt.Sprintf("Only permission mask must be set: %x", perm&linux.PermissionsMask)) 56 } 57 f.InodeAttrs.Init(ctx, creds, devMajor, devMinor, ino, linux.ModeRegular|perm) 58 f.data = data 59 } 60 61 // Open implements Inode.Open. 62 func (f *DynamicBytesFile) Open(ctx context.Context, rp *vfs.ResolvingPath, d *Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) { 63 fd := &DynamicBytesFD{} 64 if err := fd.Init(rp.Mount(), d, f.data, &f.locks, opts.Flags); err != nil { 65 return nil, err 66 } 67 return &fd.vfsfd, nil 68 } 69 70 // SetStat implements Inode.SetStat. By default DynamicBytesFile doesn't allow 71 // inode attributes to be changed. Override SetStat() making it call 72 // f.InodeAttrs to allow it. 73 func (*DynamicBytesFile) SetStat(context.Context, *vfs.Filesystem, *auth.Credentials, vfs.SetStatOptions) error { 74 return linuxerr.EPERM 75 } 76 77 // DynamicBytesFD implements vfs.FileDescriptionImpl for an FD backed by a 78 // DynamicBytesFile. 79 // 80 // Must be initialized with Init before first use. 81 // 82 // +stateify savable 83 type DynamicBytesFD struct { 84 vfs.FileDescriptionDefaultImpl 85 vfs.DynamicBytesFileDescriptionImpl 86 vfs.LockFD 87 88 vfsfd vfs.FileDescription 89 inode Inode 90 } 91 92 // Init initializes a DynamicBytesFD. 93 func (fd *DynamicBytesFD) Init(m *vfs.Mount, d *Dentry, data vfs.DynamicBytesSource, locks *vfs.FileLocks, flags uint32) error { 94 fd.LockFD.Init(locks) 95 if err := fd.vfsfd.Init(fd, flags, m, d.VFSDentry(), &vfs.FileDescriptionOptions{}); err != nil { 96 return err 97 } 98 fd.inode = d.inode 99 fd.SetDataSource(data) 100 return nil 101 } 102 103 // Seek implements vfs.FileDescriptionImpl.Seek. 104 func (fd *DynamicBytesFD) Seek(ctx context.Context, offset int64, whence int32) (int64, error) { 105 return fd.DynamicBytesFileDescriptionImpl.Seek(ctx, offset, whence) 106 } 107 108 // Read implements vfs.FileDescriptionImpl.Read. 109 func (fd *DynamicBytesFD) Read(ctx context.Context, dst usermem.IOSequence, opts vfs.ReadOptions) (int64, error) { 110 return fd.DynamicBytesFileDescriptionImpl.Read(ctx, dst, opts) 111 } 112 113 // PRead implements vfs.FileDescriptionImpl.PRead. 114 func (fd *DynamicBytesFD) PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts vfs.ReadOptions) (int64, error) { 115 return fd.DynamicBytesFileDescriptionImpl.PRead(ctx, dst, offset, opts) 116 } 117 118 // Write implements vfs.FileDescriptionImpl.Write. 119 func (fd *DynamicBytesFD) Write(ctx context.Context, src usermem.IOSequence, opts vfs.WriteOptions) (int64, error) { 120 return fd.DynamicBytesFileDescriptionImpl.Write(ctx, src, opts) 121 } 122 123 // PWrite implements vfs.FileDescriptionImpl.PWrite. 124 func (fd *DynamicBytesFD) PWrite(ctx context.Context, src usermem.IOSequence, offset int64, opts vfs.WriteOptions) (int64, error) { 125 return fd.DynamicBytesFileDescriptionImpl.PWrite(ctx, src, offset, opts) 126 } 127 128 // Release implements vfs.FileDescriptionImpl.Release. 129 func (fd *DynamicBytesFD) Release(context.Context) {} 130 131 // Stat implements vfs.FileDescriptionImpl.Stat. 132 func (fd *DynamicBytesFD) Stat(ctx context.Context, opts vfs.StatOptions) (linux.Statx, error) { 133 fs := fd.vfsfd.VirtualDentry().Mount().Filesystem() 134 return fd.inode.Stat(ctx, fs, opts) 135 } 136 137 // SetStat implements vfs.FileDescriptionImpl.SetStat. 138 func (fd *DynamicBytesFD) SetStat(context.Context, vfs.SetStatOptions) error { 139 // DynamicBytesFiles are immutable. 140 return linuxerr.EPERM 141 }