github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/fsimpl/sockfs/sockfs.go (about) 1 // Copyright 2020 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 sockfs provides a filesystem implementation for anonymous sockets. 16 package sockfs 17 18 import ( 19 "fmt" 20 21 "github.com/nicocha30/gvisor-ligolo/pkg/abi/linux" 22 "github.com/nicocha30/gvisor-ligolo/pkg/context" 23 "github.com/nicocha30/gvisor-ligolo/pkg/errors/linuxerr" 24 "github.com/nicocha30/gvisor-ligolo/pkg/fspath" 25 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/fsimpl/kernfs" 26 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel/auth" 27 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/vfs" 28 ) 29 30 // filesystemType implements vfs.FilesystemType. 31 // 32 // +stateify savable 33 type filesystemType struct{} 34 35 // GetFilesystem implements vfs.FilesystemType.GetFilesystem. 36 func (fsType filesystemType) GetFilesystem(_ context.Context, vfsObj *vfs.VirtualFilesystem, _ *auth.Credentials, _ string, _ vfs.GetFilesystemOptions) (*vfs.Filesystem, *vfs.Dentry, error) { 37 panic("sockfs.filesystemType.GetFilesystem should never be called") 38 } 39 40 // Name implements vfs.FilesystemType.Name. 41 // 42 // Note that registering sockfs is unnecessary, except for the fact that it 43 // will not show up under /proc/filesystems as a result. This is a very minor 44 // discrepancy from Linux. 45 func (filesystemType) Name() string { 46 return "sockfs" 47 } 48 49 // Release implements vfs.FilesystemType.Release. 50 func (filesystemType) Release(ctx context.Context) {} 51 52 // +stateify savable 53 type filesystem struct { 54 kernfs.Filesystem 55 56 devMinor uint32 57 } 58 59 // NewFilesystem sets up and returns a new sockfs filesystem. 60 // 61 // Note that there should only ever be one instance of sockfs.Filesystem, 62 // backing a global socket mount. 63 func NewFilesystem(vfsObj *vfs.VirtualFilesystem) (*vfs.Filesystem, error) { 64 devMinor, err := vfsObj.GetAnonBlockDevMinor() 65 if err != nil { 66 return nil, err 67 } 68 fs := &filesystem{ 69 devMinor: devMinor, 70 } 71 fs.Filesystem.VFSFilesystem().Init(vfsObj, filesystemType{}, fs) 72 return fs.Filesystem.VFSFilesystem(), nil 73 } 74 75 // Release implements vfs.FilesystemImpl.Release. 76 func (fs *filesystem) Release(ctx context.Context) { 77 fs.Filesystem.VFSFilesystem().VirtualFilesystem().PutAnonBlockDevMinor(fs.devMinor) 78 fs.Filesystem.Release(ctx) 79 } 80 81 // PrependPath implements vfs.FilesystemImpl.PrependPath. 82 func (fs *filesystem) PrependPath(ctx context.Context, vfsroot, vd vfs.VirtualDentry, b *fspath.Builder) error { 83 inode := vd.Dentry().Impl().(*kernfs.Dentry).Inode().(*inode) 84 b.PrependComponent(fmt.Sprintf("socket:[%d]", inode.InodeAttrs.Ino())) 85 return vfs.PrependPathSyntheticError{} 86 } 87 88 // MountOptions implements vfs.FilesystemImpl.MountOptions. 89 func (fs *filesystem) MountOptions() string { 90 return "" 91 } 92 93 // inode implements kernfs.Inode. 94 // 95 // +stateify savable 96 type inode struct { 97 kernfs.InodeAnonymous 98 kernfs.InodeAttrs 99 kernfs.InodeNoopRefCount 100 kernfs.InodeNotDirectory 101 kernfs.InodeNotSymlink 102 kernfs.InodeWatches 103 } 104 105 // Open implements kernfs.Inode.Open. 106 func (i *inode) Open(ctx context.Context, rp *vfs.ResolvingPath, d *kernfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) { 107 return nil, linuxerr.ENXIO 108 } 109 110 // StatFS implements kernfs.Inode.StatFS. 111 func (i *inode) StatFS(ctx context.Context, fs *vfs.Filesystem) (linux.Statfs, error) { 112 return vfs.GenericStatFS(linux.SOCKFS_MAGIC), nil 113 } 114 115 // NewDentry constructs and returns a sockfs dentry. 116 // 117 // Preconditions: mnt.Filesystem() must have been returned by NewFilesystem(). 118 func NewDentry(ctx context.Context, mnt *vfs.Mount) *vfs.Dentry { 119 fs := mnt.Filesystem().Impl().(*filesystem) 120 121 // File mode matches net/socket.c:sock_alloc. 122 filemode := linux.FileMode(linux.S_IFSOCK | 0777) 123 i := &inode{} 124 i.InodeAttrs.Init(ctx, auth.CredentialsFromContext(ctx), linux.UNNAMED_MAJOR, fs.devMinor, fs.Filesystem.NextIno(), filemode) 125 126 d := &kernfs.Dentry{} 127 d.Init(&fs.Filesystem, i) 128 return d.VFSDentry() 129 }