mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Implement stub for msgctl(2).
Add support for msgctl and enable tests. Fixes #135
This commit is contained in:
@@ -124,7 +124,7 @@ var AMD64 = &kernel.SyscallTable{
|
||||
68: syscalls.Supported("msgget", Msgget),
|
||||
69: syscalls.Supported("msgsnd", Msgsnd),
|
||||
70: syscalls.Supported("msgrcv", Msgrcv),
|
||||
71: syscalls.PartiallySupported("msgctl", Msgctl, "Only supports IPC_RMID option.", []string{"gvisor.dev/issue/135"}),
|
||||
71: syscalls.Supported("msgctl", Msgctl),
|
||||
72: syscalls.PartiallySupported("fcntl", Fcntl, "Not all options are supported.", nil),
|
||||
73: syscalls.PartiallySupported("flock", Flock, "Locks are held within the sandbox only.", nil),
|
||||
74: syscalls.PartiallySupported("fsync", Fsync, "Full data flush is not guaranteed at this time.", nil),
|
||||
@@ -617,7 +617,7 @@ var ARM64 = &kernel.SyscallTable{
|
||||
184: syscalls.ErrorWithEvent("mq_notify", syserror.ENOSYS, "", []string{"gvisor.dev/issue/136"}), // TODO(b/29354921)
|
||||
185: syscalls.ErrorWithEvent("mq_getsetattr", syserror.ENOSYS, "", []string{"gvisor.dev/issue/136"}), // TODO(b/29354921)
|
||||
186: syscalls.Supported("msgget", Msgget),
|
||||
187: syscalls.PartiallySupported("msgctl", Msgctl, "Only supports IPC_RMID option.", []string{"gvisor.dev/issue/135"}),
|
||||
187: syscalls.Supported("msgctl", Msgctl),
|
||||
188: syscalls.Supported("msgrcv", Msgrcv),
|
||||
189: syscalls.Supported("msgsnd", Msgsnd),
|
||||
190: syscalls.Supported("semget", Semget),
|
||||
|
||||
@@ -130,12 +130,63 @@ func receive(t *kernel.Task, id ipc.ID, mType int64, maxSize int64, msgCopy, wai
|
||||
func Msgctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
|
||||
id := ipc.ID(args[0].Int())
|
||||
cmd := args[1].Int()
|
||||
buf := args[2].Pointer()
|
||||
|
||||
creds := auth.CredentialsFromContext(t)
|
||||
|
||||
r := t.IPCNamespace().MsgqueueRegistry()
|
||||
|
||||
switch cmd {
|
||||
case linux.IPC_INFO:
|
||||
info := r.IPCInfo(t)
|
||||
_, err := info.CopyOut(t, buf)
|
||||
return 0, nil, err
|
||||
case linux.MSG_INFO:
|
||||
msgInfo := r.MsgInfo(t)
|
||||
_, err := msgInfo.CopyOut(t, buf)
|
||||
return 0, nil, err
|
||||
case linux.IPC_RMID:
|
||||
return 0, nil, t.IPCNamespace().MsgqueueRegistry().Remove(id, creds)
|
||||
return 0, nil, r.Remove(id, creds)
|
||||
}
|
||||
|
||||
// Remaining commands use a queue.
|
||||
queue, err := r.FindByID(id)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
switch cmd {
|
||||
case linux.MSG_STAT:
|
||||
// Technically, we should be treating id as "an index into the kernel's
|
||||
// internal array that maintains information about all shared memory
|
||||
// segments on the system". Since we don't track segments in an array,
|
||||
// we'll just pretend the msqid is the index and do the same thing as
|
||||
// IPC_STAT. Linux also uses the index as the msqid.
|
||||
fallthrough
|
||||
case linux.IPC_STAT:
|
||||
stat, err := queue.Stat(t)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
_, err = stat.CopyOut(t, buf)
|
||||
return 0, nil, err
|
||||
|
||||
case linux.MSG_STAT_ANY:
|
||||
stat, err := queue.StatAny(t)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
_, err = stat.CopyOut(t, buf)
|
||||
return 0, nil, err
|
||||
|
||||
case linux.IPC_SET:
|
||||
var ds linux.MsqidDS
|
||||
if _, err := ds.CopyIn(t, buf); err != nil {
|
||||
return 0, nil, linuxerr.EINVAL
|
||||
}
|
||||
err := queue.Set(t, &ds)
|
||||
return 0, nil, err
|
||||
|
||||
default:
|
||||
return 0, nil, linuxerr.EINVAL
|
||||
}
|
||||
|
||||
@@ -662,8 +662,6 @@ TEST(MsgqueueTest, MsgOpGeneral) {
|
||||
|
||||
// Test msgctl with IPC_STAT option.
|
||||
TEST(MsgqueueTest, MsgCtlIpcStat) {
|
||||
GTEST_SKIP();
|
||||
|
||||
auto start = absl::Now();
|
||||
|
||||
Queue queue(msgget(IPC_PRIVATE, 0600));
|
||||
@@ -734,8 +732,6 @@ TEST(MsgqueueTest, MsgCtlIpcStat) {
|
||||
|
||||
// Test msgctl with IPC_STAT option on a write-only queue.
|
||||
TEST(MsgqueueTest, MsgCtlIpcStatWriteOnly) {
|
||||
GTEST_SKIP();
|
||||
|
||||
// Drop CAP_IPC_OWNER which allows us to bypass permissions.
|
||||
AutoCapability cap(CAP_IPC_OWNER, false);
|
||||
|
||||
@@ -749,8 +745,6 @@ TEST(MsgqueueTest, MsgCtlIpcStatWriteOnly) {
|
||||
|
||||
// Test msgctl with IPC_SET option.
|
||||
TEST(MsgqueueTest, MsgCtlIpcSet) {
|
||||
GTEST_SKIP();
|
||||
|
||||
Queue queue(msgget(IPC_PRIVATE, 0600));
|
||||
ASSERT_THAT(queue.get(), SyscallSucceeds());
|
||||
|
||||
@@ -767,8 +761,6 @@ TEST(MsgqueueTest, MsgCtlIpcSet) {
|
||||
|
||||
// Test increasing msg_qbytes beyond limit with IPC_SET.
|
||||
TEST(MsgqueueTest, MsgCtlIpcSetMaxBytes) {
|
||||
GTEST_SKIP();
|
||||
|
||||
// Drop CAP_SYS_RESOURCE which allows us to increase msg_qbytes beyond the
|
||||
// system parameter MSGMNB.
|
||||
AutoCapability cap(CAP_SYS_RESOURCE, false);
|
||||
@@ -792,8 +784,6 @@ TEST(MsgqueueTest, MsgCtlIpcSetMaxBytes) {
|
||||
|
||||
// Test msgctl with IPC_INFO option.
|
||||
TEST(MsgqueueTest, MsgCtlIpcInfo) {
|
||||
GTEST_SKIP();
|
||||
|
||||
struct msginfo info;
|
||||
ASSERT_THAT(msgctl(0, IPC_INFO, reinterpret_cast<struct msqid_ds*>(&info)),
|
||||
SyscallSucceeds());
|
||||
@@ -809,8 +799,6 @@ TEST(MsgqueueTest, MsgCtlIpcInfo) {
|
||||
|
||||
// Test msgctl with MSG_INFO option.
|
||||
TEST(MsgqueueTest, MsgCtlMsgInfo) {
|
||||
GTEST_SKIP();
|
||||
|
||||
struct msginfo info;
|
||||
ASSERT_THAT(msgctl(0, MSG_INFO, reinterpret_cast<struct msqid_ds*>(&info)),
|
||||
SyscallSucceeds());
|
||||
|
||||
Reference in New Issue
Block a user