From a78cef0ed7ce15583424f5873f0aa6fdad1d5c2f Mon Sep 17 00:00:00 2001 From: Jing Chen Date: Thu, 3 Dec 2020 19:55:20 -0800 Subject: Implement command IPC_INFO for semctl. PiperOrigin-RevId: 345589628 --- pkg/abi/linux/sem.go | 24 ++++++++++++++++++++++++ pkg/sentry/kernel/semaphore/semaphore.go | 16 ++++++++++++++++ pkg/sentry/syscalls/linux/linux64.go | 4 ++-- pkg/sentry/syscalls/linux/sys_sem.go | 11 +++++++++-- test/syscalls/linux/semaphore.cc | 15 +++++++++++++++ 5 files changed, 66 insertions(+), 4 deletions(-) diff --git a/pkg/abi/linux/sem.go b/pkg/abi/linux/sem.go index 167d2ff74..0adff8dff 100644 --- a/pkg/abi/linux/sem.go +++ b/pkg/abi/linux/sem.go @@ -41,6 +41,12 @@ const ( SEMMNS = SEMMNI * SEMMSL SEMOPM = 500 SEMVMX = 32767 + SEMAEM = SEMVMX + + // followings are unused in kernel + SEMUME = SEMOPM + SEMMNU = SEMMNS + SEMMAP = SEMMNS ) const SEM_UNDO = 0x1000 @@ -53,3 +59,21 @@ type Sembuf struct { SemOp int16 SemFlg int16 } + +// SemInfo is equivalent to struct seminfo. +// +// Source: include/uapi/linux/sem.h +// +// +marshal +type SemInfo struct { + SemMap uint32 + SemMni uint32 + SemMns uint32 + SemMnu uint32 + SemMsl uint32 + SemOpm uint32 + SemUme uint32 + SemUsz uint32 + SemVmx uint32 + SemAem uint32 +} diff --git a/pkg/sentry/kernel/semaphore/semaphore.go b/pkg/sentry/kernel/semaphore/semaphore.go index 335be8edd..31198d772 100644 --- a/pkg/sentry/kernel/semaphore/semaphore.go +++ b/pkg/sentry/kernel/semaphore/semaphore.go @@ -176,6 +176,22 @@ func (r *Registry) FindOrCreate(ctx context.Context, key, nsems int32, mode linu return r.newSet(ctx, key, owner, owner, perms, nsems) } +// IPCInfo returns information about system-wide semaphore limits and parameters. +func (r *Registry) IPCInfo() *linux.SemInfo { + return &linux.SemInfo{ + SemMap: linux.SEMMAP, + SemMni: linux.SEMMNI, + SemMns: linux.SEMMNS, + SemMnu: linux.SEMMNU, + SemMsl: linux.SEMMSL, + SemOpm: linux.SEMOPM, + SemUme: linux.SEMUME, + SemUsz: 0, // SemUsz not supported. + SemVmx: linux.SEMVMX, + SemAem: linux.SEMAEM, + } +} + // RemoveID removes set with give 'id' from the registry and marks the set as // dead. All waiters will be awakened and fail. func (r *Registry) RemoveID(id int32, creds *auth.Credentials) error { diff --git a/pkg/sentry/syscalls/linux/linux64.go b/pkg/sentry/syscalls/linux/linux64.go index bb1f715e2..cff442846 100644 --- a/pkg/sentry/syscalls/linux/linux64.go +++ b/pkg/sentry/syscalls/linux/linux64.go @@ -118,7 +118,7 @@ var AMD64 = &kernel.SyscallTable{ 63: syscalls.Supported("uname", Uname), 64: syscalls.Supported("semget", Semget), 65: syscalls.PartiallySupported("semop", Semop, "Option SEM_UNDO not supported.", nil), - 66: syscalls.PartiallySupported("semctl", Semctl, "Options IPC_INFO, SEM_INFO, SEM_STAT, SEM_STAT_ANY not supported.", nil), + 66: syscalls.PartiallySupported("semctl", Semctl, "Options SEM_INFO, SEM_STAT, SEM_STAT_ANY not supported.", nil), 67: syscalls.Supported("shmdt", Shmdt), 68: syscalls.ErrorWithEvent("msgget", syserror.ENOSYS, "", []string{"gvisor.dev/issue/135"}), // TODO(b/29354921) 69: syscalls.ErrorWithEvent("msgsnd", syserror.ENOSYS, "", []string{"gvisor.dev/issue/135"}), // TODO(b/29354921) @@ -619,7 +619,7 @@ var ARM64 = &kernel.SyscallTable{ 188: syscalls.ErrorWithEvent("msgrcv", syserror.ENOSYS, "", []string{"gvisor.dev/issue/135"}), // TODO(b/29354921) 189: syscalls.ErrorWithEvent("msgsnd", syserror.ENOSYS, "", []string{"gvisor.dev/issue/135"}), // TODO(b/29354921) 190: syscalls.Supported("semget", Semget), - 191: syscalls.PartiallySupported("semctl", Semctl, "Options IPC_INFO, SEM_INFO, SEM_STAT, SEM_STAT_ANY not supported.", nil), + 191: syscalls.PartiallySupported("semctl", Semctl, "Options SEM_INFO, SEM_STAT, SEM_STAT_ANY not supported.", nil), 192: syscalls.ErrorWithEvent("semtimedop", syserror.ENOSYS, "", []string{"gvisor.dev/issue/137"}), 193: syscalls.PartiallySupported("semop", Semop, "Option SEM_UNDO not supported.", nil), 194: syscalls.PartiallySupported("shmget", Shmget, "Option SHM_HUGETLB is not supported.", nil), diff --git a/pkg/sentry/syscalls/linux/sys_sem.go b/pkg/sentry/syscalls/linux/sys_sem.go index e383a0a87..a1601676f 100644 --- a/pkg/sentry/syscalls/linux/sys_sem.go +++ b/pkg/sentry/syscalls/linux/sys_sem.go @@ -146,8 +146,15 @@ func Semctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal v, err := getNCnt(t, id, num) return uintptr(v), nil, err - case linux.IPC_INFO, - linux.SEM_INFO, + case linux.IPC_INFO: + buf := args[3].Pointer() + r := t.IPCNamespace().SemaphoreRegistry() + info := r.IPCInfo() + _, err := info.CopyOut(t, buf) + // TODO(gvisor.dev/issue/137): Return the index of the highest used entry. + return 0, nil, err + + case linux.SEM_INFO, linux.SEM_STAT, linux.SEM_STAT_ANY: diff --git a/test/syscalls/linux/semaphore.cc b/test/syscalls/linux/semaphore.cc index 890f4a246..1c1bf6a57 100644 --- a/test/syscalls/linux/semaphore.cc +++ b/test/syscalls/linux/semaphore.cc @@ -773,6 +773,21 @@ TEST(SemaphoreTest, SemopGetncntOnSignal_NoRandomSave) { EXPECT_EQ(semctl(sem.get(), 0, GETNCNT), 0); } +TEST(SemaphoreTest, IpcInfo) { + struct seminfo info; + ASSERT_THAT(semctl(0, 0, IPC_INFO, &info), SyscallSucceeds()); + + EXPECT_EQ(info.semmap, 1024000000); + EXPECT_EQ(info.semmni, 32000); + EXPECT_EQ(info.semmns, 1024000000); + EXPECT_EQ(info.semmnu, 1024000000); + EXPECT_EQ(info.semmsl, 32000); + EXPECT_EQ(info.semopm, 500); + EXPECT_EQ(info.semume, 500); + EXPECT_EQ(info.semvmx, 32767); + EXPECT_EQ(info.semaem, 32767); +} + } // namespace } // namespace testing } // namespace gvisor -- cgit v1.2.3