github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/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  	"github.com/MerlinKodo/gvisor/pkg/errors/linuxerr"
    19  	"github.com/MerlinKodo/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  }