github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/sentry/kernel/auth/key.go (about)

     1  // Copyright 2020 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package auth
    16  
    17  import (
    18  	"encoding/binary"
    19  	"fmt"
    20  	"strings"
    21  
    22  	"github.com/MerlinKodo/gvisor/pkg/errors/linuxerr"
    23  	"github.com/MerlinKodo/gvisor/pkg/rand"
    24  )
    25  
    26  // KeySerial is a key ID type.
    27  // Only strictly positive IDs are valid key IDs.
    28  // The zero ID is meaningless but is specified when creating new keyrings.
    29  // Strictly negative IDs are used for special key IDs which are internally
    30  // translated to real key IDs (e.g. KEY_SPEC_SESSION_KEYRING is translated
    31  // to the caller process's session keyring).
    32  type KeySerial int32
    33  
    34  // KeyType is the type of a key.
    35  // This is an enum, but is also exposed to userspace in KEYCTL_DESCRIBE.
    36  // For this reason, it must match Linux.
    37  type KeyType string
    38  
    39  // List of known key types.
    40  const (
    41  	KeyTypeKeyring KeyType = "keyring"
    42  	// Other types are not yet supported.
    43  )
    44  
    45  // KeyPermission represents a permission on a key.
    46  type KeyPermission int
    47  
    48  // List of known key permissions.
    49  const (
    50  	KeyView KeyPermission = iota
    51  	KeyRead
    52  	KeyWrite
    53  	KeySearch
    54  	KeyLink
    55  	KeySetAttr
    56  )
    57  
    58  // KeyPermissions is the full set of permissions on a single Key.
    59  type KeyPermissions uint64
    60  
    61  const (
    62  	// MaxKeyDescSize is the maximum size of the "Description" field of keys.
    63  	// Corresponds to `KEY_MAX_DESC_SIZE` in Linux.
    64  	MaxKeyDescSize = 4096
    65  
    66  	// maxSetSize is the maximum number of a keys in a `Set`.
    67  	// By default, Linux limits this number to 200 per non-root user.
    68  	// Here, we limit it to 200 per Set, which is stricter.
    69  	maxSetSize = 200
    70  )
    71  
    72  // Key represents a key in the keyrings subsystem.
    73  //
    74  // +stateify savable
    75  type Key struct {
    76  	// ID is the ID of the key, also often referred to as "serial number".
    77  	// Note that key IDs passed in syscalls may be negative when they refer to
    78  	// "special keys", sometimes also referred to as "shortcut IDs".
    79  	// Key IDs of real instantiated keys are always > 0.
    80  	// The key ID never changes and is unique within a KeySet (i.e. a user
    81  	// namespace).
    82  	// It must be chosen with cryptographic randomness to make enumeration
    83  	// attacks harder.
    84  	ID KeySerial
    85  
    86  	// Description is a description of the key. It is also often referred to the
    87  	// "name" of the key. Keys are canonically identified by their ID, but the
    88  	// syscall ABI also allows look up keys by their description.
    89  	// It may not be larger than `KeyMaxDescSize`.
    90  	// Confusingly, the information returned by the KEYCTL_DESCRIBE operation,
    91  	// which you'd think means "get the key description", actually returns a
    92  	// superset of this `Description`.
    93  	Description string
    94  
    95  	// kuid is the owner of the key in the root namespace.
    96  	// kuid is only mutable in KeySet transactions.
    97  	kuid KUID
    98  
    99  	// kgid is the group of the key in the root namespace.
   100  	// kgid is only mutable in KeySet transactions.
   101  	kgid KGID
   102  
   103  	// perms is a bitfield of key permissions.
   104  	// perms is only mutable in KeySet transactions.
   105  	perms KeyPermissions
   106  }
   107  
   108  // Type returns the type of this key.
   109  func (*Key) Type() KeyType {
   110  	return KeyTypeKeyring
   111  }
   112  
   113  // KUID returns the KUID (owner ID) of the key.
   114  func (k *Key) KUID() KUID { return k.kuid }
   115  
   116  // KGID returns the KGID (group ID) of the key.
   117  func (k *Key) KGID() KGID { return k.kgid }
   118  
   119  // Permissions returns the permission bits of the key.
   120  func (k *Key) Permissions() KeyPermissions { return k.perms }
   121  
   122  // String is a human-friendly representation of the key.
   123  // Notably, this is *not* the string returned to userspace when requested
   124  // using `KEYCTL_DESCRIBE`.
   125  func (k *Key) String() string {
   126  	return fmt.Sprintf("id=%d,perms=0x%x,desc=%q", k.ID, k.perms, k.Description)
   127  }
   128  
   129  // Bitmasks for permission checks.
   130  const (
   131  	keyPossessorPermissionsMask  = 0x3f000000
   132  	keyPossessorPermissionsShift = 24
   133  	keyOwnerPermissionsMask      = 0x003f0000
   134  	keyOwnerPermissionsShift     = 16
   135  	keyGroupPermissionsMask      = 0x00003f00
   136  	keyGroupPermissionsShift     = 8
   137  	keyOtherPermissionsMask      = 0x0000003f
   138  	keyOtherPermissionsShift     = 0
   139  
   140  	keyPermissionView    = 0x00000001
   141  	keyPermissionRead    = 0x00000002
   142  	keyPermissionWrite   = 0x00000004
   143  	keyPermissionSearch  = 0x00000008
   144  	keyPermissionLink    = 0x00000010
   145  	keyPermissionSetAttr = 0x00000020
   146  	keyPermissionAll     = (keyPermissionView |
   147  		keyPermissionRead |
   148  		keyPermissionWrite |
   149  		keyPermissionSearch |
   150  		keyPermissionLink |
   151  		keyPermissionSetAttr)
   152  )
   153  
   154  // String returns a human-readable version of the permission bits.
   155  func (p KeyPermissions) String() string {
   156  	var perms strings.Builder
   157  	for i, s := range [4]struct {
   158  		kind  string
   159  		shift int
   160  	}{
   161  		{kind: "possessor", shift: keyPossessorPermissionsShift},
   162  		{kind: "owner", shift: keyOwnerPermissionsShift},
   163  		{kind: "group", shift: keyGroupPermissionsShift},
   164  		{kind: "other", shift: keyOtherPermissionsShift},
   165  	} {
   166  		if i != 0 {
   167  			perms.WriteRune(',')
   168  		}
   169  		perms.WriteString(s.kind)
   170  		perms.WriteRune('=')
   171  		kindPerms := p >> s.shift
   172  		for _, b := range [6]struct {
   173  			mask int
   174  			r    rune
   175  		}{
   176  			{mask: keyPermissionView, r: 'v'},
   177  			{mask: keyPermissionRead, r: 'r'},
   178  			{mask: keyPermissionWrite, r: 'w'},
   179  			{mask: keyPermissionSearch, r: 's'},
   180  			{mask: keyPermissionLink, r: 'l'},
   181  			{mask: keyPermissionSetAttr, r: 'a'},
   182  		} {
   183  			if uint64(kindPerms)&uint64(b.mask) != 0 {
   184  				perms.WriteRune(b.r)
   185  			} else {
   186  				perms.WriteRune('-')
   187  			}
   188  		}
   189  	}
   190  	return fmt.Sprintf("%08x[%s]", uint64(p), perms.String())
   191  }
   192  
   193  // Default key settings.
   194  const (
   195  	// Default session keyring name.
   196  	DefaultSessionKeyringName = "_ses"
   197  
   198  	// Default permissions for unnamed session keyrings:
   199  	// Possessors have full permissions.
   200  	// Owners have view and read permissions.
   201  	DefaultUnnamedSessionKeyringPermissions KeyPermissions = ((keyPermissionAll << keyPossessorPermissionsShift) |
   202  		((keyPermissionView | keyPermissionRead) << keyOwnerPermissionsShift))
   203  
   204  	// Default permissions for named session keyrings:
   205  	// Possessors have full permissions.
   206  	// Owners have view, read, and link permissions.
   207  	DefaultNamedSessionKeyringPermissions KeyPermissions = ((keyPermissionAll << keyPossessorPermissionsShift) |
   208  		((keyPermissionView | keyPermissionRead | keyPermissionLink) << keyOwnerPermissionsShift))
   209  )
   210  
   211  // PossessedKeys is an opaque type used during key permission check.
   212  // When iterating over all keys, the possessed set of keys should only be
   213  // built once. Since key possession is a recursive property, it can be
   214  // expensive to determine. PossessedKeys holds all possessed keys at
   215  // the time it is computed.
   216  // PossessedKeys is short-lived; it should only live for so long as there
   217  // are no changes to the KeySet or to any key permissions.
   218  type PossessedKeys struct {
   219  	// possessed is a list of possessed key IDs.
   220  	possessed map[KeySerial]struct{}
   221  }
   222  
   223  // PossessedKeys returns a new fully-expanded set of PossessedKeys.
   224  // The keys passed in are the set of keys that a task directly possesses:
   225  // session keyring, process keyring, thread keyring. Each key may be nil.
   226  // PossessedKeys is short-lived; it should only live for so long as there
   227  // are no changes to the KeySet or to any key permissions.
   228  func (c *Credentials) PossessedKeys(sessionKeyring, processKeyring, threadKeyring *Key) *PossessedKeys {
   229  	possessed := &PossessedKeys{possessed: make(map[KeySerial]struct{})}
   230  	for _, k := range [3]*Key{sessionKeyring, processKeyring, threadKeyring} {
   231  		if k == nil {
   232  			continue
   233  		}
   234  		// The possessor still needs "search" permission in order to actually possess anything.
   235  		if ((k.perms&keyPossessorPermissionsMask)>>keyPossessorPermissionsShift)&keyPermissionSearch != 0 {
   236  			possessed.possessed[k.ID] = struct{}{}
   237  		}
   238  	}
   239  
   240  	// If we implement keyrings that contain other keys, this is where the
   241  	// recursion would happen.
   242  
   243  	return possessed
   244  }
   245  
   246  // HasKeyPermission returns whether the credentials grant `permission` on `k`.
   247  //
   248  //go:nosplit
   249  func (c *Credentials) HasKeyPermission(k *Key, possessed *PossessedKeys, permission KeyPermission) bool {
   250  	perms := k.perms & keyOtherPermissionsMask
   251  	if _, ok := possessed.possessed[k.ID]; ok {
   252  		perms |= (k.perms & keyPossessorPermissionsMask) >> keyPossessorPermissionsShift
   253  	}
   254  	if c.EffectiveKUID == k.kuid {
   255  		perms |= (k.perms & keyOwnerPermissionsMask) >> keyOwnerPermissionsShift
   256  	}
   257  	if c.EffectiveKGID == k.kgid {
   258  		perms |= (k.perms & keyGroupPermissionsMask) >> keyGroupPermissionsShift
   259  	}
   260  	switch permission {
   261  	case KeyView:
   262  		return perms&keyPermissionView != 0
   263  	case KeyRead:
   264  		return perms&keyPermissionRead != 0
   265  	case KeyWrite:
   266  		return perms&keyPermissionWrite != 0
   267  	case KeySearch:
   268  		return perms&keyPermissionSearch != 0
   269  	case KeyLink:
   270  		return perms&keyPermissionLink != 0
   271  	case KeySetAttr:
   272  		return perms&keyPermissionSetAttr != 0
   273  	default:
   274  		panic("unknown key permission")
   275  	}
   276  }
   277  
   278  // KeySet is a set of keys.
   279  //
   280  // +stateify savable
   281  type KeySet struct {
   282  	// txnMu is used for transactionality of key changes.
   283  	// This blocks multiple tasks for concurrently changing the keyset or the
   284  	// permissions of any keys.
   285  	txnMu keysetTransactionMutex `state:"nosave"`
   286  
   287  	// mu protects the fields below.
   288  	// Within functions on `KeySet`, `mu` may only be locked for reading.
   289  	// Locking `mu` for writing may only be done in `LockedKeySet` functions.
   290  	mu keysetRWMutex `state:"nosave"`
   291  
   292  	// keys maps key IDs to the underlying Key struct.
   293  	// It is initially nil to save on heap space.
   294  	// It is only initialized when doing mutable transactions on it using `Do`.
   295  	keys map[KeySerial]*Key
   296  }
   297  
   298  // LockedKeySet is a KeySet in a transaction.
   299  // It exposes functions that can mutate the KeySet or its keys.
   300  type LockedKeySet struct {
   301  	*KeySet
   302  }
   303  
   304  // Do executes the given function as a transaction on the KeySet.
   305  // It returns the error that `fn` returns.
   306  // This is the only function where functions that lock the KeySet.mu for
   307  // writing may be called.
   308  func (s *KeySet) Do(fn func(*LockedKeySet) error) error {
   309  	s.txnMu.Lock()
   310  	defer s.txnMu.Unlock()
   311  	ls := &LockedKeySet{s}
   312  	ls.mu.Lock()
   313  	if s.keys == nil {
   314  		// Initialize the map from its zero value, if it hasn't been done yet.
   315  		s.keys = make(map[KeySerial]*Key)
   316  	}
   317  	ls.mu.Unlock()
   318  	return fn(ls)
   319  }
   320  
   321  // Lookup looks up a key by ID.
   322  // Callers must exercise care to verify that the key can be accessed with
   323  // proper credentials.
   324  func (s *KeySet) Lookup(keyID KeySerial) (*Key, error) {
   325  	s.mu.RLock()
   326  	defer s.mu.RUnlock()
   327  	key, found := s.keys[keyID]
   328  	if !found {
   329  		return nil, linuxerr.ENOKEY
   330  	}
   331  	return key, nil
   332  }
   333  
   334  // ForEach iterates over all keys.
   335  // If `fn` returns true, iteration stops immediately.
   336  // Callers must exercise care to only process keys to which they have access.
   337  func (s *KeySet) ForEach(fn func(*Key) bool) {
   338  	s.mu.RLock()
   339  	defer s.mu.RUnlock()
   340  	for _, key := range s.keys {
   341  		if fn(key) {
   342  			return
   343  		}
   344  	}
   345  }
   346  
   347  // getNewID returns a new random key ID strictly larger than zero.
   348  // It uses cryptographic randomness in order to make enumeration attacks
   349  // harder.
   350  func getNewID() (KeySerial, error) {
   351  	var newID int32
   352  	for newID == 0 {
   353  		if err := binary.Read(rand.Reader, binary.LittleEndian, &newID); err != nil {
   354  			return 0, err
   355  		}
   356  	}
   357  	if newID < 0 {
   358  		newID = -newID
   359  	}
   360  	return KeySerial(newID), nil
   361  }
   362  
   363  // Add adds a new Key to the KeySet.
   364  func (s *LockedKeySet) Add(description string, creds *Credentials, perms KeyPermissions) (*Key, error) {
   365  	if len(description) >= MaxKeyDescSize {
   366  		return nil, linuxerr.EINVAL
   367  	}
   368  	s.mu.Lock()
   369  	defer s.mu.Unlock()
   370  	if len(s.keys) >= maxSetSize {
   371  		return nil, linuxerr.EDQUOT
   372  	}
   373  	newID, err := getNewID()
   374  	if err != nil {
   375  		return nil, err
   376  	}
   377  	for s.keys[newID] != nil {
   378  		newID, err = getNewID()
   379  		if err != nil {
   380  			return nil, err
   381  		}
   382  	}
   383  	k := &Key{
   384  		ID:          newID,
   385  		Description: description,
   386  		kuid:        creds.EffectiveKUID,
   387  		kgid:        creds.EffectiveKGID,
   388  		perms:       perms,
   389  	}
   390  	s.keys[newID] = k
   391  	return k, nil
   392  }
   393  
   394  // SetPerms sets the permissions on a given key.
   395  // The caller must have SetAttr permission on the key.
   396  func (s *LockedKeySet) SetPerms(key *Key, newPerms KeyPermissions) {
   397  	key.perms = newPerms
   398  }