gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/kernel/task_key.go (about) 1 // Copyright 2023 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 kernel 16 17 import ( 18 "gvisor.dev/gvisor/pkg/errors/linuxerr" 19 "gvisor.dev/gvisor/pkg/sentry/kernel/auth" 20 ) 21 22 // SessionKeyring returns this Task's session keyring. 23 // Session keyrings are inherited from the parent when a task is started. 24 // If the session keyring is unset, it is implicitly initialized. 25 // As such, this function should never return ENOKEY. 26 func (t *Task) SessionKeyring() (*auth.Key, error) { 27 t.mu.Lock() 28 defer t.mu.Unlock() 29 if t.sessionKeyring != nil { 30 // Verify that we still have access to this keyring. 31 creds := t.Credentials() 32 if !creds.HasKeyPermission(t.sessionKeyring, creds.PossessedKeys(t.sessionKeyring, nil, nil), auth.KeySearch) { 33 return nil, linuxerr.EACCES 34 } 35 return t.sessionKeyring, nil 36 } 37 // If we don't have a session keyring, implicitly create one. 38 return t.joinNewSessionKeyringLocked(auth.DefaultSessionKeyringName, auth.DefaultUnnamedSessionKeyringPermissions) 39 } 40 41 // joinNewSessionKeyringLocked creates a new session keyring with the given 42 // description, and joins it immediately. 43 // Preconditions: t.mu is held. 44 // 45 // +checklocks:t.mu 46 func (t *Task) joinNewSessionKeyringLocked(newKeyDesc string, newKeyPerms auth.KeyPermissions) (*auth.Key, error) { 47 var sessionKeyring *auth.Key 48 err := t.UserNamespace().Keys.Do(func(keySet *auth.LockedKeySet) error { 49 creds := t.Credentials() 50 var err error 51 sessionKeyring, err = keySet.Add(newKeyDesc, creds, newKeyPerms) 52 return err 53 }) 54 if err != nil { 55 return nil, err 56 } 57 t.Debugf("Joining newly-created session keyring with ID %d, permissions %v", sessionKeyring.ID, newKeyPerms) 58 t.sessionKeyring = sessionKeyring 59 return sessionKeyring, nil 60 } 61 62 // JoinSessionKeyring causes the task to join a keyring with the given 63 // key description (not ID). 64 // If `keyDesc` is nil, then the task joins a newly-instantiated session 65 // keyring instead. 66 func (t *Task) JoinSessionKeyring(keyDesc *string) (*auth.Key, error) { 67 t.mu.Lock() 68 defer t.mu.Unlock() 69 creds := t.Credentials() 70 possessed := creds.PossessedKeys(t.sessionKeyring, nil, nil) 71 var sessionKeyring *auth.Key 72 newKeyPerms := auth.DefaultUnnamedSessionKeyringPermissions 73 newKeyDesc := auth.DefaultSessionKeyringName 74 if keyDesc != nil { 75 creds.UserNamespace.Keys.ForEach(func(k *auth.Key) bool { 76 if k.Description == *keyDesc && creds.HasKeyPermission(k, possessed, auth.KeySearch) { 77 sessionKeyring = k 78 return true 79 } 80 return false 81 }) 82 if sessionKeyring != nil { 83 t.Debugf("Joining existing session keyring with ID %d", sessionKeyring.ID) 84 t.sessionKeyring = sessionKeyring 85 return sessionKeyring, nil 86 } 87 newKeyDesc = *keyDesc 88 newKeyPerms = auth.DefaultNamedSessionKeyringPermissions 89 } 90 return t.joinNewSessionKeyringLocked(newKeyDesc, newKeyPerms) 91 } 92 93 // LookupKey looks up a key by ID using this task's credentials. 94 func (t *Task) LookupKey(keyID auth.KeySerial) (*auth.Key, error) { 95 t.mu.Lock() 96 defer t.mu.Unlock() 97 creds := t.Credentials() 98 key, err := creds.UserNamespace.Keys.Lookup(keyID) 99 if err != nil { 100 return nil, err 101 } 102 if !creds.HasKeyPermission(key, creds.PossessedKeys(t.sessionKeyring, nil, nil), auth.KeySearch) { 103 return nil, linuxerr.EACCES 104 } 105 return key, nil 106 } 107 108 // SetPermsOnKey sets the permission bits on the given key using the task's 109 // credentials. 110 func (t *Task) SetPermsOnKey(key *auth.Key, perms auth.KeyPermissions) error { 111 t.mu.Lock() 112 defer t.mu.Unlock() 113 creds := t.Credentials() 114 possessed := creds.PossessedKeys(t.sessionKeyring, nil, nil) 115 return creds.UserNamespace.Keys.Do(func(keySet *auth.LockedKeySet) error { 116 if !creds.HasKeyPermission(key, possessed, auth.KeySetAttr) { 117 return linuxerr.EACCES 118 } 119 keySet.SetPerms(key, perms) 120 return nil 121 }) 122 }