diff options
author | Zyad A. Ali <zyad.ali.me@gmail.com> | 2021-08-03 07:48:24 +0200 |
---|---|---|
committer | Zyad A. Ali <zyad.ali.me@gmail.com> | 2021-09-28 20:43:52 +0200 |
commit | f03dc73f0f46d0ff1ae209fefc98ee3d7fc725d2 (patch) | |
tree | ee84a03ddfd6c96c8be7d2a4050caf2875127fb9 /pkg/sentry/syscalls/linux/vfs2/mq.go | |
parent | 9bde727f4f2e5b7cf52211a3a4fe71c7a0e4f1ea (diff) |
Implement stubs for mq_open(2) and mq_unlink(2).
Support mq_open and mq_unlink, and enable syscall tests.
Updates #136
Diffstat (limited to 'pkg/sentry/syscalls/linux/vfs2/mq.go')
-rw-r--r-- | pkg/sentry/syscalls/linux/vfs2/mq.go | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/pkg/sentry/syscalls/linux/vfs2/mq.go b/pkg/sentry/syscalls/linux/vfs2/mq.go new file mode 100644 index 000000000..d5d81c6e2 --- /dev/null +++ b/pkg/sentry/syscalls/linux/vfs2/mq.go @@ -0,0 +1,98 @@ +// Copyright 2021 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vfs2 + +import ( + "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/sentry/arch" + "gvisor.dev/gvisor/pkg/sentry/kernel" + "gvisor.dev/gvisor/pkg/sentry/kernel/mq" +) + +// MqOpen implements mq_open(2). +func MqOpen(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { + nameAddr := args[0].Pointer() + flag := args[1].Int() + mode := args[2].ModeT() + attrAddr := args[3].Pointer() + + name, err := t.CopyInString(nameAddr, mq.MaxName) + if err != nil { + return 0, nil, err + } + + rOnly := flag&linux.O_RDONLY == linux.O_RDONLY + wOnly := flag&linux.O_WRONLY == linux.O_WRONLY + readWrite := flag&linux.O_RDWR == linux.O_RDWR + + create := flag&linux.O_CREAT == linux.O_CREAT + exclusive := flag&linux.O_EXCL == linux.O_EXCL + block := flag&linux.O_NONBLOCK != linux.O_NONBLOCK + + var attr linux.MqAttr + var attrPtr *linux.MqAttr + if attrAddr != 0 { + if _, err := attr.CopyIn(t, attrAddr); err != nil { + return 0, nil, err + } + attrPtr = &attr + } + + opts := openOpts(name, rOnly, wOnly, readWrite, create, exclusive, block) + + r := t.IPCNamespace().PosixQueues() + queue, err := r.FindOrCreate(t, opts, linux.FileMode(mode), attrPtr) + if err != nil { + return 0, nil, err + } + + fd, err := t.NewFDFromVFS2(0, queue, kernel.FDFlags{ + CloseOnExec: flag&linux.O_CLOEXEC != 0, + }) + if err != nil { + return 0, nil, err + } + return uintptr(fd), nil, nil +} + +// MqUnlink implements mq_unlink(2). +func MqUnlink(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { + nameAddr := args[0].Pointer() + name, err := t.CopyInString(nameAddr, mq.MaxName) + if err != nil { + return 0, nil, err + } + return 0, nil, t.IPCNamespace().PosixQueues().Remove(t, name) +} + +func openOpts(name string, rOnly, wOnly, readWrite, create, exclusive, block bool) mq.OpenOpts { + var access mq.AccessType + switch { + case readWrite: + access = mq.ReadWrite + case wOnly: + access = mq.WriteOnly + case rOnly: + access = mq.ReadOnly + } + + return mq.OpenOpts{ + Name: name, + Access: access, + Create: create, + Exclusive: exclusive, + Block: block, + } +} |