gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/kernel/ipc_namespace.go (about)

     1  // Copyright 2018 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 kernel
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"gvisor.dev/gvisor/pkg/context"
    21  	"gvisor.dev/gvisor/pkg/sentry/fsimpl/mqfs"
    22  	"gvisor.dev/gvisor/pkg/sentry/fsimpl/nsfs"
    23  	"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
    24  	"gvisor.dev/gvisor/pkg/sentry/kernel/mq"
    25  	"gvisor.dev/gvisor/pkg/sentry/kernel/msgqueue"
    26  	"gvisor.dev/gvisor/pkg/sentry/kernel/semaphore"
    27  	"gvisor.dev/gvisor/pkg/sentry/kernel/shm"
    28  	"gvisor.dev/gvisor/pkg/sentry/vfs"
    29  )
    30  
    31  // IPCNamespace represents an IPC namespace.
    32  //
    33  // +stateify savable
    34  type IPCNamespace struct {
    35  	inode *nsfs.Inode
    36  
    37  	// User namespace which owns this IPC namespace. Immutable.
    38  	userNS *auth.UserNamespace
    39  
    40  	// System V utilities.
    41  	queues     *msgqueue.Registry
    42  	semaphores *semaphore.Registry
    43  	shms       *shm.Registry
    44  
    45  	// posixQueues is a POSIX message queue registry.
    46  	//
    47  	// posixQueues is somewhat equivalent to Linux's ipc_namespace.mq_mnt.
    48  	// Unlike SysV utilities, mq.Registry is not map-based, but is backed by
    49  	// a virtual filesystem.
    50  	posixQueues *mq.Registry
    51  }
    52  
    53  // NewIPCNamespace creates a new IPC namespace.
    54  func NewIPCNamespace(userNS *auth.UserNamespace) *IPCNamespace {
    55  	ns := &IPCNamespace{
    56  		userNS:     userNS,
    57  		queues:     msgqueue.NewRegistry(userNS),
    58  		semaphores: semaphore.NewRegistry(userNS),
    59  		shms:       shm.NewRegistry(userNS),
    60  	}
    61  	return ns
    62  }
    63  
    64  // Type implements nsfs.Namespace.Type.
    65  func (i *IPCNamespace) Type() string {
    66  	return "ipc"
    67  }
    68  
    69  // Destroy implements nsfs.Namespace.Destroy.
    70  func (i *IPCNamespace) Destroy(ctx context.Context) {
    71  	i.shms.Release(ctx)
    72  	if i.posixQueues != nil {
    73  		i.posixQueues.Destroy(ctx)
    74  	}
    75  }
    76  
    77  // SetInode sets the nsfs `inode` to the IPC namespace.
    78  func (i *IPCNamespace) SetInode(inode *nsfs.Inode) {
    79  	i.inode = inode
    80  }
    81  
    82  // GetInode returns the nsfs inode associated with the IPC namespace.
    83  func (i *IPCNamespace) GetInode() *nsfs.Inode {
    84  	return i.inode
    85  }
    86  
    87  // UserNamespace returns the user namespace associated with the namespace.
    88  func (i *IPCNamespace) UserNamespace() *auth.UserNamespace {
    89  	return i.userNS
    90  }
    91  
    92  // MsgqueueRegistry returns the message queue registry for this namespace.
    93  func (i *IPCNamespace) MsgqueueRegistry() *msgqueue.Registry {
    94  	return i.queues
    95  }
    96  
    97  // SemaphoreRegistry returns the semaphore set registry for this namespace.
    98  func (i *IPCNamespace) SemaphoreRegistry() *semaphore.Registry {
    99  	return i.semaphores
   100  }
   101  
   102  // ShmRegistry returns the shm segment registry for this namespace.
   103  func (i *IPCNamespace) ShmRegistry() *shm.Registry {
   104  	return i.shms
   105  }
   106  
   107  // InitPosixQueues creates a new POSIX queue registry, and returns an error if
   108  // the registry was previously initialized.
   109  func (i *IPCNamespace) InitPosixQueues(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials) error {
   110  	if i.posixQueues != nil {
   111  		return fmt.Errorf("IPCNamespace.InitPosixQueues: already initialized")
   112  	}
   113  
   114  	impl, err := mqfs.NewRegistryImpl(ctx, vfsObj, creds)
   115  	if err != nil {
   116  		return err
   117  	}
   118  	i.posixQueues = mq.NewRegistry(i.userNS, impl)
   119  	return nil
   120  }
   121  
   122  // PosixQueues returns the posix message queue registry for this namespace.
   123  //
   124  // Precondition: i.InitPosixQueues must have been called.
   125  func (i *IPCNamespace) PosixQueues() *mq.Registry {
   126  	return i.posixQueues
   127  }
   128  
   129  // IncRef increments the Namespace's refcount.
   130  func (i *IPCNamespace) IncRef() {
   131  	i.inode.IncRef()
   132  }
   133  
   134  // DecRef decrements the namespace's refcount.
   135  func (i *IPCNamespace) DecRef(ctx context.Context) {
   136  	i.inode.DecRef(ctx)
   137  }
   138  
   139  // IPCNamespace returns the task's IPC namespace.
   140  func (t *Task) IPCNamespace() *IPCNamespace {
   141  	t.mu.Lock()
   142  	defer t.mu.Unlock()
   143  	return t.ipcns
   144  }
   145  
   146  // GetIPCNamespace takes a reference on the task IPC namespace and
   147  // returns it. It will return nil if the task isn't alive.
   148  func (t *Task) GetIPCNamespace() *IPCNamespace {
   149  	t.mu.Lock()
   150  	defer t.mu.Unlock()
   151  	if t.ipcns != nil {
   152  		t.ipcns.IncRef()
   153  	}
   154  	return t.ipcns
   155  }