github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/sentry/syscalls/linux/sys_mq.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 linux
    16  
    17  import (
    18  	"github.com/metacubex/gvisor/pkg/abi/linux"
    19  	"github.com/metacubex/gvisor/pkg/sentry/arch"
    20  	"github.com/metacubex/gvisor/pkg/sentry/kernel"
    21  	"github.com/metacubex/gvisor/pkg/sentry/kernel/mq"
    22  )
    23  
    24  // MqOpen implements mq_open(2).
    25  func MqOpen(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
    26  	nameAddr := args[0].Pointer()
    27  	flag := args[1].Int()
    28  	mode := args[2].ModeT()
    29  	attrAddr := args[3].Pointer()
    30  
    31  	name, err := t.CopyInString(nameAddr, mq.MaxName)
    32  	if err != nil {
    33  		return 0, nil, err
    34  	}
    35  
    36  	rOnly := flag&linux.O_RDONLY == linux.O_RDONLY
    37  	wOnly := flag&linux.O_WRONLY == linux.O_WRONLY
    38  	readWrite := flag&linux.O_RDWR == linux.O_RDWR
    39  
    40  	create := flag&linux.O_CREAT == linux.O_CREAT
    41  	exclusive := flag&linux.O_EXCL == linux.O_EXCL
    42  	block := flag&linux.O_NONBLOCK != linux.O_NONBLOCK
    43  
    44  	var attr linux.MqAttr
    45  	var attrPtr *linux.MqAttr
    46  	if attrAddr != 0 {
    47  		if _, err := attr.CopyIn(t, attrAddr); err != nil {
    48  			return 0, nil, err
    49  		}
    50  		attrPtr = &attr
    51  	}
    52  
    53  	opts := openOpts(name, rOnly, wOnly, readWrite, create, exclusive, block)
    54  
    55  	r := t.IPCNamespace().PosixQueues()
    56  	queue, err := r.FindOrCreate(t, opts, linux.FileMode(mode), attrPtr)
    57  	if err != nil {
    58  		return 0, nil, err
    59  	}
    60  	defer queue.DecRef(t)
    61  
    62  	fd, err := t.NewFDFrom(0, queue, kernel.FDFlags{
    63  		CloseOnExec: flag&linux.O_CLOEXEC != 0,
    64  	})
    65  	if err != nil {
    66  		return 0, nil, err
    67  	}
    68  	return uintptr(fd), nil, nil
    69  }
    70  
    71  // MqUnlink implements mq_unlink(2).
    72  func MqUnlink(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
    73  	nameAddr := args[0].Pointer()
    74  	name, err := t.CopyInString(nameAddr, mq.MaxName)
    75  	if err != nil {
    76  		return 0, nil, err
    77  	}
    78  	return 0, nil, t.IPCNamespace().PosixQueues().Remove(t, name)
    79  }
    80  
    81  func openOpts(name string, rOnly, wOnly, readWrite, create, exclusive, block bool) mq.OpenOpts {
    82  	var access mq.AccessType
    83  	switch {
    84  	case readWrite:
    85  		access = mq.ReadWrite
    86  	case wOnly:
    87  		access = mq.WriteOnly
    88  	case rOnly:
    89  		access = mq.ReadOnly
    90  	}
    91  
    92  	return mq.OpenOpts{
    93  		Name:      name,
    94  		Access:    access,
    95  		Create:    create,
    96  		Exclusive: exclusive,
    97  		Block:     block,
    98  	}
    99  }