gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/fsimpl/mqfs/mqfs.go (about) 1 // Copyright 2021 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 mqfs provides a filesystem implementation to back POSIX message 16 // queues. 17 package mqfs 18 19 import ( 20 "fmt" 21 22 "gvisor.dev/gvisor/pkg/context" 23 "gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs" 24 "gvisor.dev/gvisor/pkg/sentry/kernel/auth" 25 "gvisor.dev/gvisor/pkg/sentry/kernel/ipc" 26 "gvisor.dev/gvisor/pkg/sentry/kernel/mq" 27 "gvisor.dev/gvisor/pkg/sentry/vfs" 28 ) 29 30 const ( 31 // Name is the user-visible filesystem name. 32 Name = "mqueue" 33 ) 34 35 // FilesystemType implements vfs.FilesystemType. 36 // 37 // +stateify savable 38 type FilesystemType struct{} 39 40 // Name implements vfs.FilesystemType.Name. 41 func (FilesystemType) Name() string { 42 return Name 43 } 44 45 // Release implements vfs.FilesystemType.Release. 46 func (FilesystemType) Release(ctx context.Context) {} 47 48 // GetFilesystem implements vfs.FilesystemType.GetFilesystem. 49 func (ft FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials, source string, opts vfs.GetFilesystemOptions) (*vfs.Filesystem, *vfs.Dentry, error) { 50 // mqfs is initialized only once per ipc namespace. Each ipc namespace has 51 // a POSIX message registry with a root dentry, filesystem, and a 52 // disconnected mount. We want the fs to be consistent for all processes in 53 // the same ipc namespace, so instead of creating a new fs and root dentry, 54 // we retrieve them using IPCNamespace.PosixQueues and use them. 55 56 i := ipcNamespaceFromContext(ctx) 57 if i == nil { 58 return nil, nil, fmt.Errorf("mqfs.FilesystemType.GetFilesystem: ipc namespace doesn't exist") 59 } 60 defer i.DecRef(ctx) 61 62 registry := i.PosixQueues() 63 if registry == nil { 64 return nil, nil, fmt.Errorf("mqfs.FilesystemType.GetFilesystem: ipc namespace doesn't have a POSIX registry") 65 } 66 impl := registry.Impl().(*RegistryImpl) 67 impl.fs.VFSFilesystem().IncRef() 68 impl.root.IncRef() 69 return impl.fs.VFSFilesystem(), impl.root.VFSDentry(), nil 70 } 71 72 // filesystem implements kernfs.Filesystem. 73 // 74 // +stateify savable 75 type filesystem struct { 76 kernfs.Filesystem 77 devMinor uint32 78 } 79 80 // Release implements vfs.FilesystemImpl.Release. 81 func (fs *filesystem) Release(ctx context.Context) { 82 fs.Filesystem.VFSFilesystem().VirtualFilesystem().PutAnonBlockDevMinor(fs.devMinor) 83 fs.Filesystem.Release(ctx) 84 } 85 86 // MountOptions implements vfs.FilesystemImpl.MountOptions. 87 func (fs *filesystem) MountOptions() string { 88 return "" 89 } 90 91 // ipcNamespace defines functions we need from kernel.IPCNamespace. We redefine 92 // ipcNamespace along with ipcNamespaceFromContext to avoid circular dependency 93 // with package sentry/kernel. 94 type ipcNamespace interface { 95 // PosixQueues returns a POSIX message queue registry. 96 PosixQueues() *mq.Registry 97 98 // DecRef decrements ipcNamespace's number of references. 99 DecRef(ctx context.Context) 100 } 101 102 // ipcNamespaceFromContext returns the IPC namespace in which ctx is executing. 103 // Copied from package sentry/kernel. 104 func ipcNamespaceFromContext(ctx context.Context) ipcNamespace { 105 if v := ctx.Value(ipc.CtxIPCNamespace); v != nil { 106 return v.(ipcNamespace) 107 } 108 return nil 109 }