gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/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 "gvisor.dev/gvisor/pkg/abi/linux" 21 "gvisor.dev/gvisor/pkg/context" 22 "gvisor.dev/gvisor/pkg/errors/linuxerr" 23 "gvisor.dev/gvisor/pkg/sentry/kernel/auth" 24 "gvisor.dev/gvisor/pkg/sentry/vfs" 25 "gvisor.dev/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 InodeNotAnonymous 42 InodeNotDirectory 43 InodeNotSymlink 44 InodeWatches 45 46 locks vfs.FileLocks 47 // data can additionally implement vfs.WritableDynamicBytesSource to support 48 // writes. This field cannot be changed to a different bytes source after 49 // Init. 50 data vfs.DynamicBytesSource 51 } 52 53 var _ Inode = (*DynamicBytesFile)(nil) 54 55 // Init initializes a dynamic bytes file. 56 func (f *DynamicBytesFile) Init(ctx context.Context, creds *auth.Credentials, devMajor, devMinor uint32, ino uint64, data vfs.DynamicBytesSource, perm linux.FileMode) { 57 if perm&^linux.PermissionsMask != 0 { 58 panic(fmt.Sprintf("Only permission mask must be set: %x", perm&linux.PermissionsMask)) 59 } 60 f.InodeAttrs.Init(ctx, creds, devMajor, devMinor, ino, linux.ModeRegular|perm) 61 f.data = data 62 } 63 64 // Open implements Inode.Open. 65 func (f *DynamicBytesFile) Open(ctx context.Context, rp *vfs.ResolvingPath, d *Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) { 66 fd := &DynamicBytesFD{} 67 if err := fd.Init(rp.Mount(), d, f.data, &f.locks, opts.Flags); err != nil { 68 return nil, err 69 } 70 return &fd.vfsfd, nil 71 } 72 73 // SetStat implements Inode.SetStat. By default DynamicBytesFile doesn't allow 74 // inode attributes to be changed. Override SetStat() making it call 75 // f.InodeAttrs to allow it. 76 func (*DynamicBytesFile) SetStat(context.Context, *vfs.Filesystem, *auth.Credentials, vfs.SetStatOptions) error { 77 return linuxerr.EPERM 78 } 79 80 // Locks returns the file locks for this file. 81 func (f *DynamicBytesFile) Locks() *vfs.FileLocks { 82 return &f.locks 83 } 84 85 // Data returns the underlying data source. 86 func (f *DynamicBytesFile) Data() vfs.DynamicBytesSource { 87 return f.data 88 } 89 90 // DynamicBytesFD implements vfs.FileDescriptionImpl for an FD backed by a 91 // DynamicBytesFile. 92 // 93 // Must be initialized with Init before first use. 94 // 95 // +stateify savable 96 type DynamicBytesFD struct { 97 vfs.FileDescriptionDefaultImpl 98 vfs.DynamicBytesFileDescriptionImpl 99 vfs.LockFD 100 101 vfsfd vfs.FileDescription 102 inode Inode 103 } 104 105 // Init initializes a DynamicBytesFD. 106 func (fd *DynamicBytesFD) Init(m *vfs.Mount, d *Dentry, data vfs.DynamicBytesSource, locks *vfs.FileLocks, flags uint32) error { 107 fd.LockFD.Init(locks) 108 if err := fd.vfsfd.Init(fd, flags, m, d.VFSDentry(), 109 &vfs.FileDescriptionOptions{ 110 DenySpliceIn: true, 111 }, 112 ); err != nil { 113 return err 114 } 115 fd.inode = d.inode 116 fd.DynamicBytesFileDescriptionImpl.Init(&fd.vfsfd, data) 117 return nil 118 } 119 120 // Seek implements vfs.FileDescriptionImpl.Seek. 121 func (fd *DynamicBytesFD) Seek(ctx context.Context, offset int64, whence int32) (int64, error) { 122 return fd.DynamicBytesFileDescriptionImpl.Seek(ctx, offset, whence) 123 } 124 125 // Read implements vfs.FileDescriptionImpl.Read. 126 func (fd *DynamicBytesFD) Read(ctx context.Context, dst usermem.IOSequence, opts vfs.ReadOptions) (int64, error) { 127 return fd.DynamicBytesFileDescriptionImpl.Read(ctx, dst, opts) 128 } 129 130 // PRead implements vfs.FileDescriptionImpl.PRead. 131 func (fd *DynamicBytesFD) PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts vfs.ReadOptions) (int64, error) { 132 return fd.DynamicBytesFileDescriptionImpl.PRead(ctx, dst, offset, opts) 133 } 134 135 // Write implements vfs.FileDescriptionImpl.Write. 136 func (fd *DynamicBytesFD) Write(ctx context.Context, src usermem.IOSequence, opts vfs.WriteOptions) (int64, error) { 137 return fd.DynamicBytesFileDescriptionImpl.Write(ctx, src, opts) 138 } 139 140 // PWrite implements vfs.FileDescriptionImpl.PWrite. 141 func (fd *DynamicBytesFD) PWrite(ctx context.Context, src usermem.IOSequence, offset int64, opts vfs.WriteOptions) (int64, error) { 142 return fd.DynamicBytesFileDescriptionImpl.PWrite(ctx, src, offset, opts) 143 } 144 145 // Release implements vfs.FileDescriptionImpl.Release. 146 func (fd *DynamicBytesFD) Release(context.Context) {} 147 148 // Stat implements vfs.FileDescriptionImpl.Stat. 149 func (fd *DynamicBytesFD) Stat(ctx context.Context, opts vfs.StatOptions) (linux.Statx, error) { 150 fs := fd.vfsfd.VirtualDentry().Mount().Filesystem() 151 return fd.inode.Stat(ctx, fs, opts) 152 } 153 154 // SetStat implements vfs.FileDescriptionImpl.SetStat. 155 func (fd *DynamicBytesFD) SetStat(context.Context, vfs.SetStatOptions) error { 156 // DynamicBytesFiles are immutable. 157 return linuxerr.EPERM 158 }