github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/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/metacubex/gvisor/pkg/errors/linuxerr" 23 "github.com/metacubex/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 }