mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
1fa3c06f1e
- Delete pkg/sentry/fs/*. - Move pkg/sentry/fs/fsutil out of VFS1 directory and remove VFS1 components. - Remove remaining unused references to VFS1 from remaining codebase. - Rename/refactor code to avoid even referencing VFS2, unless necessary. - Rewrite VFS1-only tests to VFS2. Updates #1624 PiperOrigin-RevId: 490064269
159 lines
5.1 KiB
Go
159 lines
5.1 KiB
Go
// 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 ipc defines functionality and utilities common to sysvipc mechanisms.
|
|
//
|
|
// Lock ordering: [shm/semaphore/msgqueue].Registry.mu -> Mechanism
|
|
package ipc
|
|
|
|
import (
|
|
"gvisor.dev/gvisor/pkg/abi/linux"
|
|
"gvisor.dev/gvisor/pkg/context"
|
|
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
|
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
|
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
|
)
|
|
|
|
// Key is a user-provided identifier for IPC objects.
|
|
type Key int32
|
|
|
|
// ID is a kernel identifier for IPC objects.
|
|
type ID int32
|
|
|
|
// Object represents an abstract IPC object with fields common to all IPC
|
|
// mechanisms.
|
|
//
|
|
// +stateify savable
|
|
type Object struct {
|
|
// User namespace which owns the IPC namespace which owns the IPC object.
|
|
// Immutable.
|
|
UserNS *auth.UserNamespace
|
|
|
|
// ID is a kernel identifier for the IPC object. Immutable.
|
|
ID ID
|
|
|
|
// Key is a user-provided identifier for the IPC object. Immutable.
|
|
Key Key
|
|
|
|
// CreatorUID is the UID of user who created the IPC object. Immutable.
|
|
CreatorUID auth.KUID
|
|
|
|
// CreatorGID is the GID of user who created the IPC object. Immutable.
|
|
CreatorGID auth.KGID
|
|
|
|
// OwnerUID is the UID of the current owner of the IPC object. Immutable.
|
|
OwnerUID auth.KUID
|
|
|
|
// OwnerGID is the GID of the current owner of the IPC object. Immutable.
|
|
OwnerGID auth.KGID
|
|
|
|
// Mode is the access permissions the IPC object.
|
|
Mode linux.FileMode
|
|
}
|
|
|
|
// Mechanism represents a SysV mechanism that holds an IPC object. It can also
|
|
// be looked at as a container for an ipc.Object, which is by definition a fully
|
|
// functional SysV object.
|
|
type Mechanism interface {
|
|
// Lock behaves the same as Mutex.Lock on the mechanism.
|
|
Lock()
|
|
|
|
// Unlock behaves the same as Mutex.Unlock on the mechanism.
|
|
Unlock()
|
|
|
|
// Object returns a pointer to the mechanism's ipc.Object. Mechanism.Lock,
|
|
// and Mechanism.Unlock should be used when the object is used.
|
|
Object() *Object
|
|
|
|
// Destroy destroys the mechanism.
|
|
Destroy()
|
|
}
|
|
|
|
// NewObject returns a new, initialized ipc.Object. The newly returned object
|
|
// doesn't have a valid ID. When the object is registered, the registry assigns
|
|
// it a new unique ID.
|
|
func NewObject(un *auth.UserNamespace, key Key, creator, owner *auth.Credentials, mode linux.FileMode) *Object {
|
|
return &Object{
|
|
UserNS: un,
|
|
Key: key,
|
|
CreatorUID: creator.EffectiveKUID,
|
|
CreatorGID: creator.EffectiveKGID,
|
|
OwnerUID: owner.EffectiveKUID,
|
|
OwnerGID: owner.EffectiveKGID,
|
|
Mode: mode,
|
|
}
|
|
}
|
|
|
|
// CheckOwnership verifies whether an IPC object may be accessed using creds as
|
|
// an owner. See ipc/util.c:ipcctl_obtain_check() in Linux.
|
|
func (o *Object) CheckOwnership(creds *auth.Credentials) bool {
|
|
if o.OwnerUID == creds.EffectiveKUID || o.CreatorUID == creds.EffectiveKUID {
|
|
return true
|
|
}
|
|
|
|
// Tasks with CAP_SYS_ADMIN may bypass ownership checks. Strangely, Linux
|
|
// doesn't use CAP_IPC_OWNER for this despite CAP_IPC_OWNER being documented
|
|
// for use to "override IPC ownership checks".
|
|
return creds.HasCapabilityIn(linux.CAP_SYS_ADMIN, o.UserNS)
|
|
}
|
|
|
|
// CheckPermissions verifies whether an IPC object is accessible using creds for
|
|
// access described by req. See ipc/util.c:ipcperms() in Linux.
|
|
func (o *Object) CheckPermissions(creds *auth.Credentials, req vfs.AccessTypes) bool {
|
|
perms := uint16(o.Mode.Permissions())
|
|
if o.OwnerUID == creds.EffectiveKUID {
|
|
perms >>= 6
|
|
} else if creds.InGroup(o.OwnerGID) {
|
|
perms >>= 3
|
|
}
|
|
|
|
if uint16(req)&perms == uint16(req) {
|
|
return true
|
|
}
|
|
return creds.HasCapabilityIn(linux.CAP_IPC_OWNER, o.UserNS)
|
|
}
|
|
|
|
// Set modifies attributes for an IPC object. See *ctl(IPC_SET).
|
|
//
|
|
// Precondition: Mechanism.mu must be held.
|
|
func (o *Object) Set(ctx context.Context, perm *linux.IPCPerm) error {
|
|
creds := auth.CredentialsFromContext(ctx)
|
|
uid := creds.UserNamespace.MapToKUID(auth.UID(perm.UID))
|
|
gid := creds.UserNamespace.MapToKGID(auth.GID(perm.GID))
|
|
if !uid.Ok() || !gid.Ok() {
|
|
// The man pages don't specify an errno for invalid uid/gid, but EINVAL
|
|
// is generally used for invalid arguments.
|
|
return linuxerr.EINVAL
|
|
}
|
|
|
|
if !o.CheckOwnership(creds) {
|
|
// "The argument cmd has the value IPC_SET or IPC_RMID, but the
|
|
// effective user ID of the calling process is not the creator (as
|
|
// found in msg_perm.cuid) or the owner (as found in msg_perm.uid)
|
|
// of the message queue, and the caller is not privileged (Linux:
|
|
// does not have the CAP_SYS_ADMIN capability)."
|
|
return linuxerr.EPERM
|
|
}
|
|
|
|
// User may only modify the lower 9 bits of the mode. All the other bits are
|
|
// always 0 for the underlying inode.
|
|
mode := linux.FileMode(perm.Mode & 0x1ff)
|
|
|
|
o.Mode = mode
|
|
o.OwnerUID = uid
|
|
o.OwnerGID = gid
|
|
|
|
return nil
|
|
}
|