1973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells/* Manage a process's keyrings 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Written by David Howells (dhowells@redhat.com) 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as published by the Free Software Foundation; either version 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 of the License, or (at your option) any later version. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/keyctl.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/err.h> 18bb0030797f55c9996ea1cebd16b65750ceb7e4fdIngo Molnar#include <linux/mutex.h> 19ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells#include <linux/security.h> 201d1e97562e5e2ac60fb7b25437ba619f95f67fabSerge E. Hallyn#include <linux/user_namespace.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "internal.h" 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells/* Session keyring create vs join semaphore */ 25bb0030797f55c9996ea1cebd16b65750ceb7e4fdIngo Molnarstatic DEFINE_MUTEX(key_session_mutex); 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells/* User keyring creation semaphore */ 2869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howellsstatic DEFINE_MUTEX(key_user_keyring_mutex); 2969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 30973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells/* The root user's tracking struct */ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct key_user root_key_user = { 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .usage = ATOMIC_INIT(3), 3376181c134f87479fa13bf2548ddf2999055d34d4David Howells .cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock), 346cfd76a26d9fe2ba54b9d496a48c1d9285e5c5edPeter Zijlstra .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .nkeys = ATOMIC_INIT(2), 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .nikeys = ATOMIC_INIT(2), 379a56c2db49e7349c7963f0ce66c1ef578d44ebd3Eric W. Biederman .uid = GLOBAL_ROOT_UID, 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 41973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Install the user and user session keyrings for the current process's UID. 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 438bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howellsint install_user_keyrings(void) 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 45d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells struct user_struct *user; 46d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells const struct cred *cred; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *uid_keyring, *session_keyring; 4896b5c8fea6c0861621051290d705ec2e971963f1David Howells key_perm_t user_keyring_perm; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buf[20]; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 519a56c2db49e7349c7963f0ce66c1ef578d44ebd3Eric W. Biederman uid_t uid; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5396b5c8fea6c0861621051290d705ec2e971963f1David Howells user_keyring_perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL; 54d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells cred = current_cred(); 55d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells user = cred->user; 569a56c2db49e7349c7963f0ce66c1ef578d44ebd3Eric W. Biederman uid = from_kuid(cred->user_ns, user->uid); 57d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells 589a56c2db49e7349c7963f0ce66c1ef578d44ebd3Eric W. Biederman kenter("%p{%u}", user, uid); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 600da9dfdd2cd9889201bc6f6f43580c99165cd087David Howells if (user->uid_keyring && user->session_keyring) { 6169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells kleave(" = 0 [exist]"); 6269664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells return 0; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells mutex_lock(&key_user_keyring_mutex); 6669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells ret = 0; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (!user->uid_keyring) { 6969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells /* get the UID-specific keyring 7069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells * - there may be one in existence already as it may have been 7169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells * pinned by a session, but the user_struct pointing to it 7269664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells * may have been destroyed by setuid */ 739a56c2db49e7349c7963f0ce66c1ef578d44ebd3Eric W. Biederman sprintf(buf, "_uid.%u", uid); 7469664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 7569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells uid_keyring = find_keyring_by_name(buf, true); 7669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (IS_ERR(uid_keyring)) { 779a56c2db49e7349c7963f0ce66c1ef578d44ebd3Eric W. Biederman uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID, 7896b5c8fea6c0861621051290d705ec2e971963f1David Howells cred, user_keyring_perm, 7996b5c8fea6c0861621051290d705ec2e971963f1David Howells KEY_ALLOC_IN_QUOTA, NULL); 8069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (IS_ERR(uid_keyring)) { 8169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells ret = PTR_ERR(uid_keyring); 8269664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells goto error; 8369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells } 8469664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells } 8569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 8669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells /* get a default session keyring (which might also exist 8769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells * already) */ 889a56c2db49e7349c7963f0ce66c1ef578d44ebd3Eric W. Biederman sprintf(buf, "_uid_ses.%u", uid); 8969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 9069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells session_keyring = find_keyring_by_name(buf, true); 9169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (IS_ERR(session_keyring)) { 9269664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells session_keyring = 939a56c2db49e7349c7963f0ce66c1ef578d44ebd3Eric W. Biederman keyring_alloc(buf, user->uid, INVALID_GID, 9496b5c8fea6c0861621051290d705ec2e971963f1David Howells cred, user_keyring_perm, 9596b5c8fea6c0861621051290d705ec2e971963f1David Howells KEY_ALLOC_IN_QUOTA, NULL); 9669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (IS_ERR(session_keyring)) { 9769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells ret = PTR_ERR(session_keyring); 9869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells goto error_release; 9969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells } 10069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 10169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells /* we install a link from the user session keyring to 10269664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells * the user keyring */ 10369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells ret = key_link(session_keyring, uid_keyring); 10469664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (ret < 0) 10569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells goto error_release_both; 10669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells } 10769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 10869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells /* install the keyrings */ 10969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells user->uid_keyring = uid_keyring; 11069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells user->session_keyring = session_keyring; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells mutex_unlock(&key_user_keyring_mutex); 11469664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells kleave(" = 0"); 11569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells return 0; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howellserror_release_both: 11869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells key_put(session_keyring); 11969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howellserror_release: 12069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells key_put(uid_keyring); 121664cceb0093b755739e56572b836a99104ee8a75David Howellserror: 12269664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells mutex_unlock(&key_user_keyring_mutex); 12369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells kleave(" = %d", ret); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 12569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells} 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 128973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Install a fresh thread keyring directly to new credentials. This keyring is 129973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * allowed to overrun the quota. 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 131d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howellsint install_thread_keyring_to_cred(struct cred *new) 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 133d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells struct key *keyring; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 135d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells keyring = keyring_alloc("_tid", new->uid, new->gid, new, 13696b5c8fea6c0861621051290d705ec2e971963f1David Howells KEY_POS_ALL | KEY_USR_VIEW, 137d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells KEY_ALLOC_QUOTA_OVERRUN, NULL); 138d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells if (IS_ERR(keyring)) 139d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return PTR_ERR(keyring); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 141d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells new->thread_keyring = keyring; 142d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return 0; 143d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells} 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 146973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Install a fresh thread keyring, discarding the old one. 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 148d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howellsstatic int install_thread_keyring(void) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 150d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells struct cred *new; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 153d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells new = prepare_creds(); 154d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells if (!new) 155d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return -ENOMEM; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 157d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells BUG_ON(new->thread_keyring); 158d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells 159d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells ret = install_thread_keyring_to_cred(new); 160d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells if (ret < 0) { 161d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells abort_creds(new); 162d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return ret; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 165d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return commit_creds(new); 166d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells} 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 168d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells/* 169973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Install a process keyring directly to a credentials struct. 170973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * 171973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Returns -EEXIST if there was already a process keyring, 0 if one installed, 172973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * and other value on any other error 173d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells */ 174d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howellsint install_process_keyring_to_cred(struct cred *new) 175d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells{ 176d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells struct key *keyring; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1783a50597de8635cd05133bd12c95681c82fe7b878David Howells if (new->process_keyring) 179d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return -EEXIST; 180d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells 18196b5c8fea6c0861621051290d705ec2e971963f1David Howells keyring = keyring_alloc("_pid", new->uid, new->gid, new, 18296b5c8fea6c0861621051290d705ec2e971963f1David Howells KEY_POS_ALL | KEY_USR_VIEW, 18396b5c8fea6c0861621051290d705ec2e971963f1David Howells KEY_ALLOC_QUOTA_OVERRUN, NULL); 184d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells if (IS_ERR(keyring)) 185d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return PTR_ERR(keyring); 186d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells 1873a50597de8635cd05133bd12c95681c82fe7b878David Howells new->process_keyring = keyring; 1883a50597de8635cd05133bd12c95681c82fe7b878David Howells return 0; 189d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells} 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 192973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Make sure a process keyring is installed for the current process. The 193973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * existing process keyring is not replaced. 194973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * 195973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Returns 0 if there is a process keyring by the end of this function, some 196973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * error otherwise. 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 198d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howellsstatic int install_process_keyring(void) 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 200d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells struct cred *new; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 203d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells new = prepare_creds(); 204d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells if (!new) 205d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return -ENOMEM; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 207d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells ret = install_process_keyring_to_cred(new); 208d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells if (ret < 0) { 209d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells abort_creds(new); 21027d6379894be4a81984da4d48002196a83939ca9Andi Kleen return ret != -EEXIST ? ret : 0; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 213d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return commit_creds(new); 214d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells} 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 217973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Install a session keyring directly to a credentials struct. 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 219685bfd2c48bb3284d31e73ff3151c957d76deda9Oleg Nesterovint install_session_keyring_to_cred(struct cred *cred, struct key *keyring) 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2217e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells unsigned long flags; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *old; 2231a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells 2241a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells might_sleep(); 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* create an empty session keyring */ 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!keyring) { 2287e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells flags = KEY_ALLOC_QUOTA_OVERRUN; 2293a50597de8635cd05133bd12c95681c82fe7b878David Howells if (cred->session_keyring) 2307e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells flags = KEY_ALLOC_IN_QUOTA; 2317e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells 23296b5c8fea6c0861621051290d705ec2e971963f1David Howells keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred, 23396b5c8fea6c0861621051290d705ec2e971963f1David Howells KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, 23496b5c8fea6c0861621051290d705ec2e971963f1David Howells flags, NULL); 2351a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells if (IS_ERR(keyring)) 2361a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells return PTR_ERR(keyring); 237d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells } else { 238ccc3e6d9c9aea07a0b60b2b0bfc5b05a704b66d5David Howells __key_get(keyring); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* install the keyring */ 2423a50597de8635cd05133bd12c95681c82fe7b878David Howells old = cred->session_keyring; 2433a50597de8635cd05133bd12c95681c82fe7b878David Howells rcu_assign_pointer(cred->session_keyring, keyring); 2443a50597de8635cd05133bd12c95681c82fe7b878David Howells 2453a50597de8635cd05133bd12c95681c82fe7b878David Howells if (old) 2461a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells key_put(old); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells return 0; 249d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells} 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 252973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Install a session keyring, discarding the old one. If a keyring is not 253973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * supplied, an empty one is invented. 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 255d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howellsstatic int install_session_keyring(struct key *keyring) 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 257d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells struct cred *new; 258d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells int ret; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 260d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells new = prepare_creds(); 261d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells if (!new) 262d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return -ENOMEM; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 264995995378f996a8aa1cf4e4ddc0f79fbfd45496fDavid Howells ret = install_session_keyring_to_cred(new, keyring); 265d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells if (ret < 0) { 266d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells abort_creds(new); 267d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return ret; 268d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells } 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 270d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return commit_creds(new); 271d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells} 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 274973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Handle the fsuid changing. 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid key_fsuid_changed(struct task_struct *tsk) 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* update the ownership of the thread keyring */ 279b6dff3ec5e116e3af6f537d4caedcad6b9e5082aDavid Howells BUG_ON(!tsk->cred); 280b6dff3ec5e116e3af6f537d4caedcad6b9e5082aDavid Howells if (tsk->cred->thread_keyring) { 281b6dff3ec5e116e3af6f537d4caedcad6b9e5082aDavid Howells down_write(&tsk->cred->thread_keyring->sem); 282b6dff3ec5e116e3af6f537d4caedcad6b9e5082aDavid Howells tsk->cred->thread_keyring->uid = tsk->cred->fsuid; 283b6dff3ec5e116e3af6f537d4caedcad6b9e5082aDavid Howells up_write(&tsk->cred->thread_keyring->sem); 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 285a8b17ed019bd40d3bfa20439d9c36a99f9be9180David Howells} 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 288973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Handle the fsgid changing. 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid key_fsgid_changed(struct task_struct *tsk) 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* update the ownership of the thread keyring */ 293b6dff3ec5e116e3af6f537d4caedcad6b9e5082aDavid Howells BUG_ON(!tsk->cred); 294b6dff3ec5e116e3af6f537d4caedcad6b9e5082aDavid Howells if (tsk->cred->thread_keyring) { 295b6dff3ec5e116e3af6f537d4caedcad6b9e5082aDavid Howells down_write(&tsk->cred->thread_keyring->sem); 296b6dff3ec5e116e3af6f537d4caedcad6b9e5082aDavid Howells tsk->cred->thread_keyring->gid = tsk->cred->fsgid; 297b6dff3ec5e116e3af6f537d4caedcad6b9e5082aDavid Howells up_write(&tsk->cred->thread_keyring->sem); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 299a8b17ed019bd40d3bfa20439d9c36a99f9be9180David Howells} 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 302973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Search the process keyrings attached to the supplied cred for the first 303973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * matching key. 304973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * 305973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * The search criteria are the type and the match function. The description is 306973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * given to the match function as a parameter, but doesn't otherwise influence 307973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * the search. Typically the match function will compare the description 308973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * parameter to the key's description. 309973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * 310973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * This can only search keyrings that grant Search permission to the supplied 311973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * credentials. Keyrings linked to searched keyrings will also be searched if 312973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * they grant Search permission too. Keys can only be found if they grant 313973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Search permission to the credentials. 314973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * 315973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Returns a pointer to the key with the key usage count incremented if 316973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * successful, -EAGAIN if we didn't find any matching key or -ENOKEY if we only 317973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * matched negative keys. 318973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * 319973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * In the case of a successful return, the possession attribute is set on the 320973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * returned key reference. 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3224bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howellskey_ref_t search_my_process_keyrings(struct keyring_search_context *ctx) 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 324b5f545c880a2a47947ba2118b2509644ab7a2969David Howells key_ref_t key_ref, ret, err; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * searchable, but we failed to find a key or we found a negative key; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * otherwise we want to return a sample error (probably -EACCES) if 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * none of the keyrings were searchable 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in terms of priority: success > -ENOKEY > -EAGAIN > other error 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 333664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = NULL; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = NULL; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = ERR_PTR(-EAGAIN); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* search the thread keyring first */ 3384bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells if (ctx->cred->thread_keyring) { 339664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = keyring_search_aux( 3404bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells make_key_ref(ctx->cred->thread_keyring, 1), ctx); 341664cceb0093b755739e56572b836a99104ee8a75David Howells if (!IS_ERR(key_ref)) 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto found; 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 344664cceb0093b755739e56572b836a99104ee8a75David Howells switch (PTR_ERR(key_ref)) { 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -EAGAIN: /* no key */ 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOKEY: /* negative key */ 347664cceb0093b755739e56572b836a99104ee8a75David Howells ret = key_ref; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 350664cceb0093b755739e56572b836a99104ee8a75David Howells err = key_ref; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* search the process keyring second */ 3564bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells if (ctx->cred->process_keyring) { 357664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = keyring_search_aux( 3584bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells make_key_ref(ctx->cred->process_keyring, 1), ctx); 359664cceb0093b755739e56572b836a99104ee8a75David Howells if (!IS_ERR(key_ref)) 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto found; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 362664cceb0093b755739e56572b836a99104ee8a75David Howells switch (PTR_ERR(key_ref)) { 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -EAGAIN: /* no key */ 364fe9453a1dcb5fb146f9653267e78f4a558066f6fDavid Howells if (ret) 365fe9453a1dcb5fb146f9653267e78f4a558066f6fDavid Howells break; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOKEY: /* negative key */ 367664cceb0093b755739e56572b836a99104ee8a75David Howells ret = key_ref; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 370664cceb0093b755739e56572b836a99104ee8a75David Howells err = key_ref; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3753e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells /* search the session keyring */ 3764bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells if (ctx->cred->session_keyring) { 3778589b4e00e352f983259140f25a262d973be6bc5David Howells rcu_read_lock(); 378664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = keyring_search_aux( 3794bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells make_key_ref(rcu_dereference(ctx->cred->session_keyring), 1), 3804bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ctx); 3818589b4e00e352f983259140f25a262d973be6bc5David Howells rcu_read_unlock(); 3823e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells 383664cceb0093b755739e56572b836a99104ee8a75David Howells if (!IS_ERR(key_ref)) 3843e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells goto found; 3853e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells 386664cceb0093b755739e56572b836a99104ee8a75David Howells switch (PTR_ERR(key_ref)) { 3873e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells case -EAGAIN: /* no key */ 3883e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells if (ret) 3893e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 3903e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells case -ENOKEY: /* negative key */ 391664cceb0093b755739e56572b836a99104ee8a75David Howells ret = key_ref; 3923e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 3933e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells default: 394664cceb0093b755739e56572b836a99104ee8a75David Howells err = key_ref; 3953e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 3963e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells } 397b5f545c880a2a47947ba2118b2509644ab7a2969David Howells } 398b5f545c880a2a47947ba2118b2509644ab7a2969David Howells /* or search the user-session keyring */ 3994bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells else if (ctx->cred->user->session_keyring) { 400b5f545c880a2a47947ba2118b2509644ab7a2969David Howells key_ref = keyring_search_aux( 4014bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells make_key_ref(ctx->cred->user->session_keyring, 1), 4024bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ctx); 403664cceb0093b755739e56572b836a99104ee8a75David Howells if (!IS_ERR(key_ref)) 4043e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells goto found; 4053e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells 406664cceb0093b755739e56572b836a99104ee8a75David Howells switch (PTR_ERR(key_ref)) { 4073e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells case -EAGAIN: /* no key */ 4083e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells if (ret) 4093e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 4103e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells case -ENOKEY: /* negative key */ 411664cceb0093b755739e56572b836a99104ee8a75David Howells ret = key_ref; 4123e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 4133e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells default: 414664cceb0093b755739e56572b836a99104ee8a75David Howells err = key_ref; 4153e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 4163e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells } 4178589b4e00e352f983259140f25a262d973be6bc5David Howells } 418b5f545c880a2a47947ba2118b2509644ab7a2969David Howells 419927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells /* no key - decide on the error we're going to go for */ 420927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells key_ref = ret ? ret : err; 421927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells 422927942aabbbe506bf9bc70a16dc5460ecc64c148David Howellsfound: 423927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells return key_ref; 424927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells} 425927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells 426927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells/* 427973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Search the process keyrings attached to the supplied cred for the first 428973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * matching key in the manner of search_my_process_keyrings(), but also search 429973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * the keys attached to the assumed authorisation key using its credentials if 430973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * one is available. 431973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * 432973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Return same as search_my_process_keyrings(). 433927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells */ 4344bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howellskey_ref_t search_process_keyrings(struct keyring_search_context *ctx) 435927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells{ 436927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells struct request_key_auth *rka; 437927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells key_ref_t key_ref, ret = ERR_PTR(-EACCES), err; 438927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells 439927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells might_sleep(); 440927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells 4414bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells key_ref = search_my_process_keyrings(ctx); 442927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells if (!IS_ERR(key_ref)) 443927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells goto found; 444927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells err = key_ref; 445927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells 446b5f545c880a2a47947ba2118b2509644ab7a2969David Howells /* if this process has an instantiation authorisation key, then we also 447b5f545c880a2a47947ba2118b2509644ab7a2969David Howells * search the keyrings of the process mentioned there 448b5f545c880a2a47947ba2118b2509644ab7a2969David Howells * - we don't permit access to request_key auth keys via this method 449b5f545c880a2a47947ba2118b2509644ab7a2969David Howells */ 4504bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells if (ctx->cred->request_key_auth && 4514bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ctx->cred == current_cred() && 4524bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ctx->index_key.type != &key_type_request_key_auth 453b5f545c880a2a47947ba2118b2509644ab7a2969David Howells ) { 4544bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells const struct cred *cred = ctx->cred; 4554bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells 45604c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells /* defend against the auth key being revoked */ 457c69e8d9c01db2adc503464993c358901c9af9de4David Howells down_read(&cred->request_key_auth->sem); 458b5f545c880a2a47947ba2118b2509644ab7a2969David Howells 4594bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells if (key_validate(ctx->cred->request_key_auth) == 0) { 4604bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells rka = ctx->cred->request_key_auth->payload.data; 461b5f545c880a2a47947ba2118b2509644ab7a2969David Howells 4624bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ctx->cred = rka->cred; 4634bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells key_ref = search_process_keyrings(ctx); 4644bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ctx->cred = cred; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 466c69e8d9c01db2adc503464993c358901c9af9de4David Howells up_read(&cred->request_key_auth->sem); 46704c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells 46804c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells if (!IS_ERR(key_ref)) 46904c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells goto found; 47004c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells 471927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells ret = key_ref; 47204c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells } else { 473c69e8d9c01db2adc503464993c358901c9af9de4David Howells up_read(&cred->request_key_auth->sem); 4743e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells } 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* no key - decide on the error we're going to go for */ 478927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells if (err == ERR_PTR(-ENOKEY) || ret == ERR_PTR(-ENOKEY)) 479927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells key_ref = ERR_PTR(-ENOKEY); 480927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells else if (err == ERR_PTR(-EACCES)) 481927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells key_ref = ret; 482927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells else 483927942aabbbe506bf9bc70a16dc5460ecc64c148David Howells key_ref = err; 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4853e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howellsfound: 486664cceb0093b755739e56572b836a99104ee8a75David Howells return key_ref; 487a8b17ed019bd40d3bfa20439d9c36a99f9be9180David Howells} 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 490973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * See if the key we're looking at is the target key. 491664cceb0093b755739e56572b836a99104ee8a75David Howells */ 4920c903ab64feb0fe83eac9f67a06e2f5b9508de16David Howellsbool lookup_user_key_possessed(const struct key *key, 4930c903ab64feb0fe83eac9f67a06e2f5b9508de16David Howells const struct key_match_data *match_data) 494664cceb0093b755739e56572b836a99104ee8a75David Howells{ 495462919591a1791e76042dc5c1e0148715df59bebDavid Howells return key == match_data->raw_data; 496a8b17ed019bd40d3bfa20439d9c36a99f9be9180David Howells} 497664cceb0093b755739e56572b836a99104ee8a75David Howells 498664cceb0093b755739e56572b836a99104ee8a75David Howells/* 499973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Look up a key ID given us by userspace with a given permissions mask to get 500973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * the key it refers to. 501973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * 502973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Flags can be passed to request that special keyrings be created if referred 503973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * to directly, to permit partially constructed keys to be found and to skip 504973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * validity and permission checks on the found key. 505973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * 506973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Returns a pointer to the key with an incremented usage count if successful; 507973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * -EINVAL if the key ID is invalid; -ENOKEY if the key ID does not correspond 508973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * to a key or the best found key was a negative key; -EKEYREVOKED or 509973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * -EKEYEXPIRED if the best found key was revoked or expired; -EACCES if the 510973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * found key doesn't grant the requested permit or the LSM denied access to it; 511973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * or -ENOMEM if a special keyring couldn't be created. 512973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * 513973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * In the case of a successful return, the possession attribute is set on the 514973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * returned key reference. 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5165593122eec26b061cc0b6fbff32118f1aadf4a27David Howellskey_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, 5178bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells key_perm_t perm) 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5194bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells struct keyring_search_context ctx = { 520462919591a1791e76042dc5c1e0148715df59bebDavid Howells .match_data.cmp = lookup_user_key_possessed, 521462919591a1791e76042dc5c1e0148715df59bebDavid Howells .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, 522462919591a1791e76042dc5c1e0148715df59bebDavid Howells .flags = KEYRING_SEARCH_NO_STATE_CHECK, 5234bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells }; 5248bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells struct request_key_auth *rka; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *key; 526b6dff3ec5e116e3af6f537d4caedcad6b9e5082aDavid Howells key_ref_t key_ref, skey_ref; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 529bb952bb98a7e479262c7eb25d5592545a3af147dDavid Howellstry_again: 5304bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ctx.cred = get_current_cred(); 531664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = ERR_PTR(-ENOKEY); 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (id) { 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KEY_SPEC_THREAD_KEYRING: 5354bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells if (!ctx.cred->thread_keyring) { 5365593122eec26b061cc0b6fbff32118f1aadf4a27David Howells if (!(lflags & KEY_LOOKUP_CREATE)) 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5398bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells ret = install_thread_keyring(); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) { 5414d09ec0f705cf88a12add029c058b53f288cfaa2Dan Carpenter key_ref = ERR_PTR(ret); 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 544bb952bb98a7e479262c7eb25d5592545a3af147dDavid Howells goto reget_creds; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5474bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells key = ctx.cred->thread_keyring; 548ccc3e6d9c9aea07a0b60b2b0bfc5b05a704b66d5David Howells __key_get(key); 549664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = make_key_ref(key, 1); 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KEY_SPEC_PROCESS_KEYRING: 5534bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells if (!ctx.cred->process_keyring) { 5545593122eec26b061cc0b6fbff32118f1aadf4a27David Howells if (!(lflags & KEY_LOOKUP_CREATE)) 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5578bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells ret = install_process_keyring(); 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) { 5594d09ec0f705cf88a12add029c058b53f288cfaa2Dan Carpenter key_ref = ERR_PTR(ret); 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 562bb952bb98a7e479262c7eb25d5592545a3af147dDavid Howells goto reget_creds; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5654bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells key = ctx.cred->process_keyring; 566ccc3e6d9c9aea07a0b60b2b0bfc5b05a704b66d5David Howells __key_get(key); 567664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = make_key_ref(key, 1); 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KEY_SPEC_SESSION_KEYRING: 5714bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells if (!ctx.cred->session_keyring) { 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* always install a session keyring upon access if one 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doesn't exist yet */ 5748bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells ret = install_user_keyrings(); 57569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (ret < 0) 57669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells goto error; 5773ecf1b4f347210e39b156177e5b8a26ff8d00279David Howells if (lflags & KEY_LOOKUP_CREATE) 5783ecf1b4f347210e39b156177e5b8a26ff8d00279David Howells ret = join_session_keyring(NULL); 5793ecf1b4f347210e39b156177e5b8a26ff8d00279David Howells else 5803ecf1b4f347210e39b156177e5b8a26ff8d00279David Howells ret = install_session_keyring( 5814bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ctx.cred->user->session_keyring); 582d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 585bb952bb98a7e479262c7eb25d5592545a3af147dDavid Howells goto reget_creds; 5864bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells } else if (ctx.cred->session_keyring == 5874bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ctx.cred->user->session_keyring && 5883ecf1b4f347210e39b156177e5b8a26ff8d00279David Howells lflags & KEY_LOOKUP_CREATE) { 5893ecf1b4f347210e39b156177e5b8a26ff8d00279David Howells ret = join_session_keyring(NULL); 5903ecf1b4f347210e39b156177e5b8a26ff8d00279David Howells if (ret < 0) 5913ecf1b4f347210e39b156177e5b8a26ff8d00279David Howells goto error; 5923ecf1b4f347210e39b156177e5b8a26ff8d00279David Howells goto reget_creds; 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5953e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells rcu_read_lock(); 5964bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells key = rcu_dereference(ctx.cred->session_keyring); 597ccc3e6d9c9aea07a0b60b2b0bfc5b05a704b66d5David Howells __key_get(key); 5983e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells rcu_read_unlock(); 599664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = make_key_ref(key, 1); 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KEY_SPEC_USER_KEYRING: 6034bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells if (!ctx.cred->user->uid_keyring) { 6048bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells ret = install_user_keyrings(); 60569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (ret < 0) 60669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells goto error; 60769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells } 60869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 6094bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells key = ctx.cred->user->uid_keyring; 610ccc3e6d9c9aea07a0b60b2b0bfc5b05a704b66d5David Howells __key_get(key); 611664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = make_key_ref(key, 1); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KEY_SPEC_USER_SESSION_KEYRING: 6154bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells if (!ctx.cred->user->session_keyring) { 6168bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells ret = install_user_keyrings(); 61769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (ret < 0) 61869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells goto error; 61969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells } 62069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 6214bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells key = ctx.cred->user->session_keyring; 622ccc3e6d9c9aea07a0b60b2b0bfc5b05a704b66d5David Howells __key_get(key); 623664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = make_key_ref(key, 1); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KEY_SPEC_GROUP_KEYRING: 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* group keyrings are not yet supported */ 6284d09ec0f705cf88a12add029c058b53f288cfaa2Dan Carpenter key_ref = ERR_PTR(-EINVAL); 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631b5f545c880a2a47947ba2118b2509644ab7a2969David Howells case KEY_SPEC_REQKEY_AUTH_KEY: 6324bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells key = ctx.cred->request_key_auth; 633b5f545c880a2a47947ba2118b2509644ab7a2969David Howells if (!key) 634b5f545c880a2a47947ba2118b2509644ab7a2969David Howells goto error; 635b5f545c880a2a47947ba2118b2509644ab7a2969David Howells 636ccc3e6d9c9aea07a0b60b2b0bfc5b05a704b66d5David Howells __key_get(key); 637b5f545c880a2a47947ba2118b2509644ab7a2969David Howells key_ref = make_key_ref(key, 1); 638b5f545c880a2a47947ba2118b2509644ab7a2969David Howells break; 639b5f545c880a2a47947ba2118b2509644ab7a2969David Howells 6408bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells case KEY_SPEC_REQUESTOR_KEYRING: 6414bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells if (!ctx.cred->request_key_auth) 6428bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells goto error; 6438bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells 6444bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells down_read(&ctx.cred->request_key_auth->sem); 645f67dabbdde1fe112dfff05d02890f1e0d54117a8Dan Carpenter if (test_bit(KEY_FLAG_REVOKED, 6464bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells &ctx.cred->request_key_auth->flags)) { 6478bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells key_ref = ERR_PTR(-EKEYREVOKED); 6488bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells key = NULL; 6498bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells } else { 6504bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells rka = ctx.cred->request_key_auth->payload.data; 6518bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells key = rka->dest_keyring; 652ccc3e6d9c9aea07a0b60b2b0bfc5b05a704b66d5David Howells __key_get(key); 6538bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells } 6544bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells up_read(&ctx.cred->request_key_auth->sem); 6558bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells if (!key) 6568bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells goto error; 6578bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells key_ref = make_key_ref(key, 1); 6588bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells break; 6598bbf4976b59fc9fc2861e79cab7beb3f6d647640David Howells 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 661664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = ERR_PTR(-EINVAL); 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (id < 1) 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key = key_lookup(id); 666664cceb0093b755739e56572b836a99104ee8a75David Howells if (IS_ERR(key)) { 667e231c2ee64eb1c5cd3c63c31da9dac7d888dcf7fDavid Howells key_ref = ERR_CAST(key); 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 669664cceb0093b755739e56572b836a99104ee8a75David Howells } 670664cceb0093b755739e56572b836a99104ee8a75David Howells 671664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = make_key_ref(key, 0); 672664cceb0093b755739e56572b836a99104ee8a75David Howells 673664cceb0093b755739e56572b836a99104ee8a75David Howells /* check to see if we possess the key */ 6744bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ctx.index_key.type = key->type; 6754bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ctx.index_key.description = key->description; 6764bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ctx.index_key.desc_len = strlen(key->description); 677462919591a1791e76042dc5c1e0148715df59bebDavid Howells ctx.match_data.raw_data = key; 6784bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells kdebug("check possessed"); 6794bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells skey_ref = search_process_keyrings(&ctx); 6804bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells kdebug("possessed=%p", skey_ref); 681664cceb0093b755739e56572b836a99104ee8a75David Howells 682664cceb0093b755739e56572b836a99104ee8a75David Howells if (!IS_ERR(skey_ref)) { 683664cceb0093b755739e56572b836a99104ee8a75David Howells key_put(key); 684664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = skey_ref; 685664cceb0093b755739e56572b836a99104ee8a75David Howells } 686664cceb0093b755739e56572b836a99104ee8a75David Howells 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6905593122eec26b061cc0b6fbff32118f1aadf4a27David Howells /* unlink does not use the nominated key in any way, so can skip all 6915593122eec26b061cc0b6fbff32118f1aadf4a27David Howells * the permission checks as it is only concerned with the keyring */ 6925593122eec26b061cc0b6fbff32118f1aadf4a27David Howells if (lflags & KEY_LOOKUP_FOR_UNLINK) { 6935593122eec26b061cc0b6fbff32118f1aadf4a27David Howells ret = 0; 6945593122eec26b061cc0b6fbff32118f1aadf4a27David Howells goto error; 6955593122eec26b061cc0b6fbff32118f1aadf4a27David Howells } 6965593122eec26b061cc0b6fbff32118f1aadf4a27David Howells 6975593122eec26b061cc0b6fbff32118f1aadf4a27David Howells if (!(lflags & KEY_LOOKUP_PARTIAL)) { 69876181c134f87479fa13bf2548ddf2999055d34d4David Howells ret = wait_for_key_construction(key, true); 69976181c134f87479fa13bf2548ddf2999055d34d4David Howells switch (ret) { 70076181c134f87479fa13bf2548ddf2999055d34d4David Howells case -ERESTARTSYS: 70176181c134f87479fa13bf2548ddf2999055d34d4David Howells goto invalid_key; 70276181c134f87479fa13bf2548ddf2999055d34d4David Howells default: 70376181c134f87479fa13bf2548ddf2999055d34d4David Howells if (perm) 70476181c134f87479fa13bf2548ddf2999055d34d4David Howells goto invalid_key; 70576181c134f87479fa13bf2548ddf2999055d34d4David Howells case 0: 70676181c134f87479fa13bf2548ddf2999055d34d4David Howells break; 70776181c134f87479fa13bf2548ddf2999055d34d4David Howells } 70876181c134f87479fa13bf2548ddf2999055d34d4David Howells } else if (perm) { 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = key_validate(key); 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto invalid_key; 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EIO; 7155593122eec26b061cc0b6fbff32118f1aadf4a27David Howells if (!(lflags & KEY_LOOKUP_PARTIAL) && 7165593122eec26b061cc0b6fbff32118f1aadf4a27David Howells !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto invalid_key; 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7193e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells /* check the permissions */ 7204bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells ret = key_task_permission(key_ref, ctx.cred, perm); 72129db9190634067c5a328ee5fcc2890251b836b4bDavid Howells if (ret < 0) 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto invalid_key; 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 72431d5a79d7f3d436da176a78ebc12d53c06da402eDavid Howells key->last_used_at = current_kernel_time().tv_sec; 72531d5a79d7f3d436da176a78ebc12d53c06da402eDavid Howells 726664cceb0093b755739e56572b836a99104ee8a75David Howellserror: 7274bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells put_cred(ctx.cred); 728664cceb0093b755739e56572b836a99104ee8a75David Howells return key_ref; 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 730664cceb0093b755739e56572b836a99104ee8a75David Howellsinvalid_key: 731664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref_put(key_ref); 732664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = ERR_PTR(ret); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 735bb952bb98a7e479262c7eb25d5592545a3af147dDavid Howells /* if we attempted to install a keyring, then it may have caused new 736bb952bb98a7e479262c7eb25d5592545a3af147dDavid Howells * creds to be installed */ 737bb952bb98a7e479262c7eb25d5592545a3af147dDavid Howellsreget_creds: 7384bdf0bc300314141e5475e145acb8b5ad846f00dDavid Howells put_cred(ctx.cred); 739bb952bb98a7e479262c7eb25d5592545a3af147dDavid Howells goto try_again; 740a8b17ed019bd40d3bfa20439d9c36a99f9be9180David Howells} 741bb952bb98a7e479262c7eb25d5592545a3af147dDavid Howells 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 743973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Join the named keyring as the session keyring if possible else attempt to 744973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * create a new one of that name and join that. 745973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * 746973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * If the name is NULL, an empty anonymous keyring will be installed as the 747973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * session keyring. 748973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * 749973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Named session keyrings are joined with a semaphore held to prevent the 750973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * keyrings from going away whilst the attempt is made to going them and also 751973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * to prevent a race in creating compatible session keyrings. 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslong join_session_keyring(const char *name) 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 755d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells const struct cred *old; 756d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells struct cred *new; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *keyring; 758d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells long ret, serial; 759d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells 760d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells new = prepare_creds(); 761d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells if (!new) 762d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return -ENOMEM; 763d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells old = current_cred(); 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if no name is provided, install an anonymous keyring */ 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!name) { 767d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells ret = install_session_keyring_to_cred(new, NULL); 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7713a50597de8635cd05133bd12c95681c82fe7b878David Howells serial = new->session_keyring->serial; 772d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells ret = commit_creds(new); 773d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells if (ret == 0) 774d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells ret = serial; 775d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells goto okay; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allow the user to join or create a named keyring */ 779bb0030797f55c9996ea1cebd16b65750ceb7e4fdIngo Molnar mutex_lock(&key_session_mutex); 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* look for an existing keyring of this name */ 78269664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells keyring = find_keyring_by_name(name, false); 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (PTR_ERR(keyring) == -ENOKEY) { 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* not found - try and create a new one */ 78596b5c8fea6c0861621051290d705ec2e971963f1David Howells keyring = keyring_alloc( 78696b5c8fea6c0861621051290d705ec2e971963f1David Howells name, old->uid, old->gid, old, 78796b5c8fea6c0861621051290d705ec2e971963f1David Howells KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK, 78896b5c8fea6c0861621051290d705ec2e971963f1David Howells KEY_ALLOC_IN_QUOTA, NULL); 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(keyring)) { 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = PTR_ERR(keyring); 791bcf945d36fa0598f41ac4ad46a9dc43135460263David Howells goto error2; 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 793d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells } else if (IS_ERR(keyring)) { 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = PTR_ERR(keyring); 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error2; 7963a50597de8635cd05133bd12c95681c82fe7b878David Howells } else if (keyring == new->session_keyring) { 7973a50597de8635cd05133bd12c95681c82fe7b878David Howells ret = 0; 7983a50597de8635cd05133bd12c95681c82fe7b878David Howells goto error2; 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we've got a keyring - now to install it */ 802d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells ret = install_session_keyring_to_cred(new, keyring); 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error2; 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 806d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells commit_creds(new); 807d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells mutex_unlock(&key_session_mutex); 808d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = keyring->serial; 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_put(keyring); 811d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howellsokay: 812d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells return ret; 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 814664cceb0093b755739e56572b836a99104ee8a75David Howellserror2: 815bb0030797f55c9996ea1cebd16b65750ceb7e4fdIngo Molnar mutex_unlock(&key_session_mutex); 816664cceb0093b755739e56572b836a99104ee8a75David Howellserror: 817d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells abort_creds(new); 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 819d84f4f992cbd76e8f39c488cf0c5d123843923b1David Howells} 820ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells 821ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells/* 822973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * Replace a process's session keyring on behalf of one of its children when 823973c9f4f49ca96a53bcf6384c4c59ccd26c33906David Howells * the target process is about to resume userspace execution. 824ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells */ 82567d1214551e800f9fe7dc7c47a346d2df0fafed5Al Virovoid key_change_session_keyring(struct callback_head *twork) 826ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells{ 827413cd3d9abeaef590e5ce00564f7a443165db238Oleg Nesterov const struct cred *old = current_cred(); 82867d1214551e800f9fe7dc7c47a346d2df0fafed5Al Viro struct cred *new = container_of(twork, struct cred, rcu); 829ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells 830413cd3d9abeaef590e5ce00564f7a443165db238Oleg Nesterov if (unlikely(current->flags & PF_EXITING)) { 831413cd3d9abeaef590e5ce00564f7a443165db238Oleg Nesterov put_cred(new); 832ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells return; 833413cd3d9abeaef590e5ce00564f7a443165db238Oleg Nesterov } 834ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells 835ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new-> uid = old-> uid; 836ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new-> euid = old-> euid; 837ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new-> suid = old-> suid; 838ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new->fsuid = old->fsuid; 839ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new-> gid = old-> gid; 840ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new-> egid = old-> egid; 841ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new-> sgid = old-> sgid; 842ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new->fsgid = old->fsgid; 843ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new->user = get_uid(old->user); 844ba0e3427b03c3d1550239779eca5c1c5a53a2152Eric W. Biederman new->user_ns = get_user_ns(old->user_ns); 845ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new->group_info = get_group_info(old->group_info); 846ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells 847ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new->securebits = old->securebits; 848ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new->cap_inheritable = old->cap_inheritable; 849ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new->cap_permitted = old->cap_permitted; 850ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new->cap_effective = old->cap_effective; 851ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new->cap_bset = old->cap_bset; 852ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells 853ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new->jit_keyring = old->jit_keyring; 854ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells new->thread_keyring = key_get(old->thread_keyring); 8553a50597de8635cd05133bd12c95681c82fe7b878David Howells new->process_keyring = key_get(old->process_keyring); 856ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells 857ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells security_transfer_creds(new, old); 858ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells 859ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells commit_creds(new); 860ee18d64c1f632043a02e6f5ba5e045bb26a5465fDavid Howells} 861c124bde28bce41f9e46e32d03d134a81e116d38cMimi Zohar 862c124bde28bce41f9e46e32d03d134a81e116d38cMimi Zohar/* 863c124bde28bce41f9e46e32d03d134a81e116d38cMimi Zohar * Make sure that root's user and user-session keyrings exist. 864c124bde28bce41f9e46e32d03d134a81e116d38cMimi Zohar */ 865c124bde28bce41f9e46e32d03d134a81e116d38cMimi Zoharstatic int __init init_root_keyring(void) 866c124bde28bce41f9e46e32d03d134a81e116d38cMimi Zohar{ 867c124bde28bce41f9e46e32d03d134a81e116d38cMimi Zohar return install_user_keyrings(); 868c124bde28bce41f9e46e32d03d134a81e116d38cMimi Zohar} 869c124bde28bce41f9e46e32d03d134a81e116d38cMimi Zohar 870c124bde28bce41f9e46e32d03d134a81e116d38cMimi Zoharlate_initcall(init_root_keyring); 871