From b904250b862c5c14da84e08b6a5400c7bf2458b0 Mon Sep 17 00:00:00 2001 From: Rahat Mahmood Date: Thu, 17 May 2018 15:37:19 -0700 Subject: Fix capability check for sysv semaphores. Capabilities for sysv sem operations were being checked against the current task's user namespace. They should be checked against the user namespace owning the ipc namespace for the sems instead, per ipc/util.c:ipcperms(). PiperOrigin-RevId: 197063111 Change-Id: Iba29486b316f2e01ee331dda4e48a6ab7960d589 --- pkg/sentry/kernel/semaphore/semaphore.go | 15 ++++++++++++--- pkg/sentry/kernel/semaphore/semaphore_test.go | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'pkg/sentry/kernel/semaphore') diff --git a/pkg/sentry/kernel/semaphore/semaphore.go b/pkg/sentry/kernel/semaphore/semaphore.go index fb8c2f98c..e9027dc14 100644 --- a/pkg/sentry/kernel/semaphore/semaphore.go +++ b/pkg/sentry/kernel/semaphore/semaphore.go @@ -43,6 +43,8 @@ const ( // Registry maintains a set of semaphores that can be found by key or ID. type Registry struct { + // userNS owning the ipc name this registry belongs to. Immutable. + userNS *auth.UserNamespace // mu protects all fields below. mu sync.Mutex `state:"nosave"` semaphores map[int32]*Set @@ -51,6 +53,9 @@ type Registry struct { // Set represents a set of semaphores that can be operated atomically. type Set struct { + // registry owning this sem set. Immutable. + registry *Registry + // Id is a handle that identifies the set. ID int32 @@ -90,8 +95,11 @@ type waiter struct { } // NewRegistry creates a new semaphore set registry. -func NewRegistry() *Registry { - return &Registry{semaphores: make(map[int32]*Set)} +func NewRegistry(userNS *auth.UserNamespace) *Registry { + return &Registry{ + userNS: userNS, + semaphores: make(map[int32]*Set), + } } // FindOrCreate searches for a semaphore set that matches 'key'. If not found, @@ -175,6 +183,7 @@ func (r *Registry) RemoveID(id int32, creds *auth.Credentials) error { func (r *Registry) newSet(ctx context.Context, key int32, owner, creator fs.FileOwner, perms fs.FilePermissions, nsems int32) (*Set, error) { set := &Set{ + registry: r, key: key, owner: owner, creator: owner, @@ -415,7 +424,7 @@ func (s *Set) checkCredentials(creds *auth.Credentials) bool { } func (s *Set) checkCapability(creds *auth.Credentials) bool { - return creds.HasCapability(linux.CAP_IPC_OWNER) && creds.UserNamespace.MapFromKUID(s.owner.UID).Ok() + return creds.HasCapabilityIn(linux.CAP_IPC_OWNER, s.registry.userNS) && creds.UserNamespace.MapFromKUID(s.owner.UID).Ok() } func (s *Set) checkPerms(creds *auth.Credentials, reqPerms fs.PermMask) bool { diff --git a/pkg/sentry/kernel/semaphore/semaphore_test.go b/pkg/sentry/kernel/semaphore/semaphore_test.go index 1c6a2e1e9..f9eb382e9 100644 --- a/pkg/sentry/kernel/semaphore/semaphore_test.go +++ b/pkg/sentry/kernel/semaphore/semaphore_test.go @@ -136,7 +136,7 @@ func TestNoWait(t *testing.T) { func TestUnregister(t *testing.T) { ctx := contexttest.Context(t) - r := NewRegistry() + r := NewRegistry(auth.NewRootUserNamespace()) set, err := r.FindOrCreate(ctx, 123, 2, linux.FileMode(0x600), true, true, true) if err != nil { t.Fatalf("FindOrCreate() failed, err: %v", err) -- cgit v1.2.3