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