github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/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  	"github.com/nicocha30/gvisor-ligolo/pkg/context"
    23  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/fsimpl/kernfs"
    24  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel/auth"
    25  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel/ipc"
    26  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel/mq"
    27  	"github.com/nicocha30/gvisor-ligolo/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 retreive 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  }