process_keys.c revision 69664cf16af4f31cd54d77948a4baf9c7e0ca7b9
169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells/* Management of 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/slab.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/keyctl.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/err.h> 19bb0030797f55c9996ea1cebd16b65750ceb7e4fdIngo Molnar#include <linux/mutex.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "internal.h" 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* session keyring create vs join semaphore */ 24bb0030797f55c9996ea1cebd16b65750ceb7e4fdIngo Molnarstatic DEFINE_MUTEX(key_session_mutex); 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells/* user keyring creation semaphore */ 2769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howellsstatic DEFINE_MUTEX(key_user_keyring_mutex); 2869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* the root user's tracking struct */ 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct key_user root_key_user = { 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .usage = ATOMIC_INIT(3), 3276181c134f87479fa13bf2548ddf2999055d34d4David Howells .cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock), 336cfd76a26d9fe2ba54b9d496a48c1d9285e5c5edPeter Zijlstra .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .nkeys = ATOMIC_INIT(2), 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .nikeys = ATOMIC_INIT(2), 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .uid = 0, 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells * install user and user session keyrings for a particular UID 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howellsstatic int install_user_keyrings(struct task_struct *tsk) 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells struct user_struct *user = tsk->user; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *uid_keyring, *session_keyring; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buf[20]; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells kenter("%p{%u}", user, user->uid); 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5269664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (user->uid_keyring) { 5369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells kleave(" = 0 [exist]"); 5469664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells return 0; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells mutex_lock(&key_user_keyring_mutex); 5869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells ret = 0; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (!user->uid_keyring) { 6169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells /* get the UID-specific keyring 6269664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells * - there may be one in existence already as it may have been 6369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells * pinned by a session, but the user_struct pointing to it 6469664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells * may have been destroyed by setuid */ 6569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells sprintf(buf, "_uid.%u", user->uid); 6669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 6769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells uid_keyring = find_keyring_by_name(buf, true); 6869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (IS_ERR(uid_keyring)) { 6969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 7069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells tsk, KEY_ALLOC_IN_QUOTA, 7169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells NULL); 7269664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (IS_ERR(uid_keyring)) { 7369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells ret = PTR_ERR(uid_keyring); 7469664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells goto error; 7569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells } 7669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells } 7769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 7869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells /* get a default session keyring (which might also exist 7969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells * already) */ 8069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells sprintf(buf, "_uid_ses.%u", user->uid); 8169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 8269664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells session_keyring = find_keyring_by_name(buf, true); 8369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (IS_ERR(session_keyring)) { 8469664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells session_keyring = 8569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells keyring_alloc(buf, user->uid, (gid_t) -1, 8669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells tsk, KEY_ALLOC_IN_QUOTA, NULL); 8769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (IS_ERR(session_keyring)) { 8869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells ret = PTR_ERR(session_keyring); 8969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells goto error_release; 9069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells } 9169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 9269664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells /* we install a link from the user session keyring to 9369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells * the user keyring */ 9469664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells ret = key_link(session_keyring, uid_keyring); 9569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (ret < 0) 9669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells goto error_release_both; 9769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells } 9869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 9969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells /* install the keyrings */ 10069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells user->uid_keyring = uid_keyring; 10169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells user->session_keyring = session_keyring; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10469664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells mutex_unlock(&key_user_keyring_mutex); 10569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells kleave(" = 0"); 10669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells return 0; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howellserror_release_both: 10969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells key_put(session_keyring); 11069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howellserror_release: 11169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells key_put(uid_keyring); 112664cceb0093b755739e56572b836a99104ee8a75David Howellserror: 11369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells mutex_unlock(&key_user_keyring_mutex); 11469664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells kleave(" = %d", ret); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 11669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells} 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * deal with the UID changing 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid switch_uid_keyring(struct user_struct *new_user) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 /* do nothing for now */ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *old; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* switch to the new user's session keyring if we were running under 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * root's default session keyring */ 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_user->uid != 0 && 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current->session_keyring == &root_session_keyring 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ) { 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&new_user->session_keyring->usage); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds task_lock(current); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old = current->session_keyring; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current->session_keyring = new_user->session_keyring; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds task_unlock(current); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_put(old); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end switch_uid_keyring() */ 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * install a fresh thread keyring, discarding the old one 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint install_thread_keyring(struct task_struct *tsk) 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *keyring, *old; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buf[20]; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "_tid.%u", tsk->pid); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1577e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1587e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells KEY_ALLOC_QUOTA_OVERRUN, NULL); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(keyring)) { 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = PTR_ERR(keyring); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds task_lock(tsk); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old = tsk->thread_keyring; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tsk->thread_keyring = keyring; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds task_unlock(tsk); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_put(old); 172664cceb0093b755739e56572b836a99104ee8a75David Howellserror: 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end install_thread_keyring() */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * make sure a process keyring is installed 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1813e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howellsint install_process_keyring(struct task_struct *tsk) 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *keyring; 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buf[20]; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells might_sleep(); 1881a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!tsk->signal->process_keyring) { 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "_pid.%u", tsk->tgid); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1927e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1937e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells KEY_ALLOC_QUOTA_OVERRUN, NULL); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(keyring)) { 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = PTR_ERR(keyring); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1998589b4e00e352f983259140f25a262d973be6bc5David Howells /* attach keyring */ 2001a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells spin_lock_irq(&tsk->sighand->siglock); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!tsk->signal->process_keyring) { 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tsk->signal->process_keyring = keyring; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds keyring = NULL; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2051a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells spin_unlock_irq(&tsk->sighand->siglock); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_put(keyring); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 211664cceb0093b755739e56572b836a99104ee8a75David Howellserror: 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end install_process_keyring() */ 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * install a session keyring, discarding the old one 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - if a keyring is not supplied, an empty one is invented 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int install_session_keyring(struct task_struct *tsk, 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *keyring) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2247e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells unsigned long flags; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *old; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buf[20]; 2271a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells 2281a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells might_sleep(); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* create an empty session keyring */ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!keyring) { 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "_ses.%u", tsk->tgid); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2347e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells flags = KEY_ALLOC_QUOTA_OVERRUN; 2357e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells if (tsk->signal->session_keyring) 2367e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells flags = KEY_ALLOC_IN_QUOTA; 2377e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells 2387e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 2397e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells flags, NULL); 2401a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells if (IS_ERR(keyring)) 2411a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells return PTR_ERR(keyring); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&keyring->usage); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* install the keyring */ 2481a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells spin_lock_irq(&tsk->sighand->siglock); 2491a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells old = tsk->signal->session_keyring; 2508589b4e00e352f983259140f25a262d973be6bc5David Howells rcu_assign_pointer(tsk->signal->session_keyring, keyring); 2511a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells spin_unlock_irq(&tsk->sighand->siglock); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells /* we're using RCU on the pointer, but there's no point synchronising 2541a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells * on it if it didn't previously point to anything */ 2551a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells if (old) { 2561a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells synchronize_rcu(); 2571a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells key_put(old); 2581a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells } 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2601a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells return 0; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end install_session_keyring() */ 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copy the keys in a thread group for fork without CLONE_THREAD 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint copy_thread_group_keys(struct task_struct *tsk) 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_check(current->thread_group->session_keyring); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_check(current->thread_group->process_keyring); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* no process keyring yet */ 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tsk->signal->process_keyring = NULL; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* same session keyring */ 2778589b4e00e352f983259140f25a262d973be6bc5David Howells rcu_read_lock(); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tsk->signal->session_keyring = 2798589b4e00e352f983259140f25a262d973be6bc5David Howells key_get(rcu_dereference(current->signal->session_keyring)); 2808589b4e00e352f983259140f25a262d973be6bc5David Howells rcu_read_unlock(); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end copy_thread_group_keys() */ 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copy the keys for fork 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint copy_keys(unsigned long clone_flags, struct task_struct *tsk) 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_check(tsk->thread_keyring); 293b5f545c880a2a47947ba2118b2509644ab7a2969David Howells key_check(tsk->request_key_auth); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* no thread keyring yet */ 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tsk->thread_keyring = NULL; 297b5f545c880a2a47947ba2118b2509644ab7a2969David Howells 298b5f545c880a2a47947ba2118b2509644ab7a2969David Howells /* copy the request_key() authorisation for this thread */ 299b5f545c880a2a47947ba2118b2509644ab7a2969David Howells key_get(tsk->request_key_auth); 300b5f545c880a2a47947ba2118b2509644ab7a2969David Howells 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end copy_keys() */ 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dispose of thread group keys upon thread group destruction 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid exit_thread_group_keys(struct signal_struct *tg) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_put(tg->session_keyring); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_put(tg->process_keyring); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end exit_thread_group_keys() */ 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 318b5f545c880a2a47947ba2118b2509644ab7a2969David Howells * dispose of per-thread keys upon thread exit 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid exit_keys(struct task_struct *tsk) 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_put(tsk->thread_keyring); 323b5f545c880a2a47947ba2118b2509644ab7a2969David Howells key_put(tsk->request_key_auth); 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end exit_keys() */ 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * deal with execve() 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint exec_keys(struct task_struct *tsk) 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *old; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* newly exec'd tasks don't get a thread keyring */ 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds task_lock(tsk); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old = tsk->thread_keyring; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tsk->thread_keyring = NULL; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds task_unlock(tsk); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_put(old); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* discard the process keyring from a newly exec'd task */ 3441a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells spin_lock_irq(&tsk->sighand->siglock); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old = tsk->signal->process_keyring; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tsk->signal->process_keyring = NULL; 3471a26feb9622f1b1bc5e4f5f60f65557b73c38cbfDavid Howells spin_unlock_irq(&tsk->sighand->siglock); 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_put(old); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end exec_keys() */ 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * deal with SUID programs 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - we might want to make this invent a new session keyring 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint suid_keys(struct task_struct *tsk) 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end suid_keys() */ 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the filesystem user ID changed 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid key_fsuid_changed(struct task_struct *tsk) 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* update the ownership of the thread keyring */ 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tsk->thread_keyring) { 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down_write(&tsk->thread_keyring->sem); 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tsk->thread_keyring->uid = tsk->fsuid; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up_write(&tsk->thread_keyring->sem); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end key_fsuid_changed() */ 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the filesystem group ID changed 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid key_fsgid_changed(struct task_struct *tsk) 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* update the ownership of the thread keyring */ 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tsk->thread_keyring) { 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down_write(&tsk->thread_keyring->sem); 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tsk->thread_keyring->gid = tsk->fsgid; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up_write(&tsk->thread_keyring->sem); 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end key_fsgid_changed() */ 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * search the process keyrings for the first matching key 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - we use the supplied match function to see if the description (or other 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * feature of interest) matches 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - we return -EAGAIN if we didn't find any matching key 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - we return -ENOKEY if we found only negative matching keys 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 404664cceb0093b755739e56572b836a99104ee8a75David Howellskey_ref_t search_process_keyrings(struct key_type *type, 405664cceb0093b755739e56572b836a99104ee8a75David Howells const void *description, 406664cceb0093b755739e56572b836a99104ee8a75David Howells key_match_func_t match, 407664cceb0093b755739e56572b836a99104ee8a75David Howells struct task_struct *context) 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4093e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells struct request_key_auth *rka; 410b5f545c880a2a47947ba2118b2509644ab7a2969David Howells key_ref_t key_ref, ret, err; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41204c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells might_sleep(); 41304c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * searchable, but we failed to find a key or we found a negative key; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * otherwise we want to return a sample error (probably -EACCES) if 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * none of the keyrings were searchable 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in terms of priority: success > -ENOKEY > -EAGAIN > other error 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 421664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = NULL; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = NULL; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = ERR_PTR(-EAGAIN); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* search the thread keyring first */ 4263e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells if (context->thread_keyring) { 427664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = keyring_search_aux( 428664cceb0093b755739e56572b836a99104ee8a75David Howells make_key_ref(context->thread_keyring, 1), 429664cceb0093b755739e56572b836a99104ee8a75David Howells context, type, description, match); 430664cceb0093b755739e56572b836a99104ee8a75David Howells if (!IS_ERR(key_ref)) 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto found; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 433664cceb0093b755739e56572b836a99104ee8a75David Howells switch (PTR_ERR(key_ref)) { 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -EAGAIN: /* no key */ 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOKEY: /* negative key */ 438664cceb0093b755739e56572b836a99104ee8a75David Howells ret = key_ref; 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 441664cceb0093b755739e56572b836a99104ee8a75David Howells err = key_ref; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* search the process keyring second */ 4473e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells if (context->signal->process_keyring) { 448664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = keyring_search_aux( 449664cceb0093b755739e56572b836a99104ee8a75David Howells make_key_ref(context->signal->process_keyring, 1), 450664cceb0093b755739e56572b836a99104ee8a75David Howells context, type, description, match); 451664cceb0093b755739e56572b836a99104ee8a75David Howells if (!IS_ERR(key_ref)) 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto found; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 454664cceb0093b755739e56572b836a99104ee8a75David Howells switch (PTR_ERR(key_ref)) { 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -EAGAIN: /* no key */ 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOKEY: /* negative key */ 459664cceb0093b755739e56572b836a99104ee8a75David Howells ret = key_ref; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 462664cceb0093b755739e56572b836a99104ee8a75David Howells err = key_ref; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4673e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells /* search the session keyring */ 4683e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells if (context->signal->session_keyring) { 4698589b4e00e352f983259140f25a262d973be6bc5David Howells rcu_read_lock(); 470664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = keyring_search_aux( 471664cceb0093b755739e56572b836a99104ee8a75David Howells make_key_ref(rcu_dereference( 472664cceb0093b755739e56572b836a99104ee8a75David Howells context->signal->session_keyring), 473664cceb0093b755739e56572b836a99104ee8a75David Howells 1), 4743e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells context, type, description, match); 4758589b4e00e352f983259140f25a262d973be6bc5David Howells rcu_read_unlock(); 4763e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells 477664cceb0093b755739e56572b836a99104ee8a75David Howells if (!IS_ERR(key_ref)) 4783e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells goto found; 4793e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells 480664cceb0093b755739e56572b836a99104ee8a75David Howells switch (PTR_ERR(key_ref)) { 4813e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells case -EAGAIN: /* no key */ 4823e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells if (ret) 4833e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 4843e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells case -ENOKEY: /* negative key */ 485664cceb0093b755739e56572b836a99104ee8a75David Howells ret = key_ref; 4863e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 4873e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells default: 488664cceb0093b755739e56572b836a99104ee8a75David Howells err = key_ref; 4893e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 4903e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells } 491b5f545c880a2a47947ba2118b2509644ab7a2969David Howells } 492b5f545c880a2a47947ba2118b2509644ab7a2969David Howells /* or search the user-session keyring */ 49369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells else if (context->user->session_keyring) { 494b5f545c880a2a47947ba2118b2509644ab7a2969David Howells key_ref = keyring_search_aux( 495b5f545c880a2a47947ba2118b2509644ab7a2969David Howells make_key_ref(context->user->session_keyring, 1), 496b5f545c880a2a47947ba2118b2509644ab7a2969David Howells context, type, description, match); 497664cceb0093b755739e56572b836a99104ee8a75David Howells if (!IS_ERR(key_ref)) 4983e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells goto found; 4993e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells 500664cceb0093b755739e56572b836a99104ee8a75David Howells switch (PTR_ERR(key_ref)) { 5013e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells case -EAGAIN: /* no key */ 5023e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells if (ret) 5033e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 5043e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells case -ENOKEY: /* negative key */ 505664cceb0093b755739e56572b836a99104ee8a75David Howells ret = key_ref; 5063e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 5073e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells default: 508664cceb0093b755739e56572b836a99104ee8a75David Howells err = key_ref; 5093e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 5103e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells } 5118589b4e00e352f983259140f25a262d973be6bc5David Howells } 512b5f545c880a2a47947ba2118b2509644ab7a2969David Howells 513b5f545c880a2a47947ba2118b2509644ab7a2969David Howells /* if this process has an instantiation authorisation key, then we also 514b5f545c880a2a47947ba2118b2509644ab7a2969David Howells * search the keyrings of the process mentioned there 515b5f545c880a2a47947ba2118b2509644ab7a2969David Howells * - we don't permit access to request_key auth keys via this method 516b5f545c880a2a47947ba2118b2509644ab7a2969David Howells */ 517b5f545c880a2a47947ba2118b2509644ab7a2969David Howells if (context->request_key_auth && 518b5f545c880a2a47947ba2118b2509644ab7a2969David Howells context == current && 51904c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells type != &key_type_request_key_auth 520b5f545c880a2a47947ba2118b2509644ab7a2969David Howells ) { 52104c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells /* defend against the auth key being revoked */ 52204c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells down_read(&context->request_key_auth->sem); 523b5f545c880a2a47947ba2118b2509644ab7a2969David Howells 52404c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells if (key_validate(context->request_key_auth) == 0) { 52504c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells rka = context->request_key_auth->payload.data; 526b5f545c880a2a47947ba2118b2509644ab7a2969David Howells 52704c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells key_ref = search_process_keyrings(type, description, 52804c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells match, rka->context); 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 53004c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells up_read(&context->request_key_auth->sem); 53104c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells 53204c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells if (!IS_ERR(key_ref)) 53304c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells goto found; 53404c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells 53504c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells switch (PTR_ERR(key_ref)) { 53604c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells case -EAGAIN: /* no key */ 53704c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells if (ret) 53804c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells break; 53904c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells case -ENOKEY: /* negative key */ 54004c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells ret = key_ref; 5413e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells break; 54204c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells default: 54304c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells err = key_ref; 54404c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells break; 54504c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells } 54604c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells } else { 54704c567d9313e4927b9835361d8ac0318ce65af6bDavid Howells up_read(&context->request_key_auth->sem); 5483e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells } 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* no key - decide on the error we're going to go for */ 552664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = ret ? ret : err; 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5543e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howellsfound: 555664cceb0093b755739e56572b836a99104ee8a75David Howells return key_ref; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end search_process_keyrings() */ 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 561664cceb0093b755739e56572b836a99104ee8a75David Howells * see if the key we're looking at is the target key 562664cceb0093b755739e56572b836a99104ee8a75David Howells */ 563664cceb0093b755739e56572b836a99104ee8a75David Howellsstatic int lookup_user_key_possessed(const struct key *key, const void *target) 564664cceb0093b755739e56572b836a99104ee8a75David Howells{ 565664cceb0093b755739e56572b836a99104ee8a75David Howells return key == target; 566664cceb0093b755739e56572b836a99104ee8a75David Howells 567664cceb0093b755739e56572b836a99104ee8a75David Howells} /* end lookup_user_key_possessed() */ 568664cceb0093b755739e56572b836a99104ee8a75David Howells 569664cceb0093b755739e56572b836a99104ee8a75David Howells/*****************************************************************************/ 570664cceb0093b755739e56572b836a99104ee8a75David Howells/* 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * lookup a key given a key ID from userspace with a given permissions mask 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - don't create special keyrings unless so requested 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - partially constructed keys aren't found unless requested 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 575664cceb0093b755739e56572b836a99104ee8a75David Howellskey_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, 576664cceb0093b755739e56572b836a99104ee8a75David Howells int create, int partial, key_perm_t perm) 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 578664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref_t key_ref, skey_ref; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *key; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5823e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells if (!context) 5833e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells context = current; 5843e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells 585664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = ERR_PTR(-ENOKEY); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (id) { 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KEY_SPEC_THREAD_KEYRING: 5893e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells if (!context->thread_keyring) { 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!create) 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5933e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells ret = install_thread_keyring(context); 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) { 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key = ERR_PTR(ret); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6003e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells key = context->thread_keyring; 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&key->usage); 602664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = make_key_ref(key, 1); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KEY_SPEC_PROCESS_KEYRING: 6063e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells if (!context->signal->process_keyring) { 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!create) 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6103e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells ret = install_process_keyring(context); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) { 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key = ERR_PTR(ret); 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6173e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells key = context->signal->process_keyring; 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&key->usage); 619664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = make_key_ref(key, 1); 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KEY_SPEC_SESSION_KEYRING: 6233e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells if (!context->signal->session_keyring) { 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* always install a session keyring upon access if one 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doesn't exist yet */ 62669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells ret = install_user_keyrings(context); 62769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (ret < 0) 62869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells goto error; 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = install_session_keyring( 630664cceb0093b755739e56572b836a99104ee8a75David Howells context, context->user->session_keyring); 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6353e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells rcu_read_lock(); 6363e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells key = rcu_dereference(context->signal->session_keyring); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&key->usage); 6383e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells rcu_read_unlock(); 639664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = make_key_ref(key, 1); 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KEY_SPEC_USER_KEYRING: 64369664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (!context->user->uid_keyring) { 64469664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells ret = install_user_keyrings(context); 64569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (ret < 0) 64669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells goto error; 64769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells } 64869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 6493e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells key = context->user->uid_keyring; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&key->usage); 651664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = make_key_ref(key, 1); 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KEY_SPEC_USER_SESSION_KEYRING: 65569664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (!context->user->session_keyring) { 65669664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells ret = install_user_keyrings(context); 65769664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells if (ret < 0) 65869664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells goto error; 65969664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells } 66069664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells 6613e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells key = context->user->session_keyring; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&key->usage); 663664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = make_key_ref(key, 1); 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KEY_SPEC_GROUP_KEYRING: 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* group keyrings are not yet supported */ 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key = ERR_PTR(-EINVAL); 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671b5f545c880a2a47947ba2118b2509644ab7a2969David Howells case KEY_SPEC_REQKEY_AUTH_KEY: 672b5f545c880a2a47947ba2118b2509644ab7a2969David Howells key = context->request_key_auth; 673b5f545c880a2a47947ba2118b2509644ab7a2969David Howells if (!key) 674b5f545c880a2a47947ba2118b2509644ab7a2969David Howells goto error; 675b5f545c880a2a47947ba2118b2509644ab7a2969David Howells 676b5f545c880a2a47947ba2118b2509644ab7a2969David Howells atomic_inc(&key->usage); 677b5f545c880a2a47947ba2118b2509644ab7a2969David Howells key_ref = make_key_ref(key, 1); 678b5f545c880a2a47947ba2118b2509644ab7a2969David Howells break; 679b5f545c880a2a47947ba2118b2509644ab7a2969David Howells 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 681664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = ERR_PTR(-EINVAL); 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (id < 1) 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key = key_lookup(id); 686664cceb0093b755739e56572b836a99104ee8a75David Howells if (IS_ERR(key)) { 687e231c2ee64eb1c5cd3c63c31da9dac7d888dcf7fDavid Howells key_ref = ERR_CAST(key); 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 689664cceb0093b755739e56572b836a99104ee8a75David Howells } 690664cceb0093b755739e56572b836a99104ee8a75David Howells 691664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = make_key_ref(key, 0); 692664cceb0093b755739e56572b836a99104ee8a75David Howells 693664cceb0093b755739e56572b836a99104ee8a75David Howells /* check to see if we possess the key */ 694664cceb0093b755739e56572b836a99104ee8a75David Howells skey_ref = search_process_keyrings(key->type, key, 695664cceb0093b755739e56572b836a99104ee8a75David Howells lookup_user_key_possessed, 696664cceb0093b755739e56572b836a99104ee8a75David Howells current); 697664cceb0093b755739e56572b836a99104ee8a75David Howells 698664cceb0093b755739e56572b836a99104ee8a75David Howells if (!IS_ERR(skey_ref)) { 699664cceb0093b755739e56572b836a99104ee8a75David Howells key_put(key); 700664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = skey_ref; 701664cceb0093b755739e56572b836a99104ee8a75David Howells } 702664cceb0093b755739e56572b836a99104ee8a75David Howells 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 70676181c134f87479fa13bf2548ddf2999055d34d4David Howells if (!partial) { 70776181c134f87479fa13bf2548ddf2999055d34d4David Howells ret = wait_for_key_construction(key, true); 70876181c134f87479fa13bf2548ddf2999055d34d4David Howells switch (ret) { 70976181c134f87479fa13bf2548ddf2999055d34d4David Howells case -ERESTARTSYS: 71076181c134f87479fa13bf2548ddf2999055d34d4David Howells goto invalid_key; 71176181c134f87479fa13bf2548ddf2999055d34d4David Howells default: 71276181c134f87479fa13bf2548ddf2999055d34d4David Howells if (perm) 71376181c134f87479fa13bf2548ddf2999055d34d4David Howells goto invalid_key; 71476181c134f87479fa13bf2548ddf2999055d34d4David Howells case 0: 71576181c134f87479fa13bf2548ddf2999055d34d4David Howells break; 71676181c134f87479fa13bf2548ddf2999055d34d4David Howells } 71776181c134f87479fa13bf2548ddf2999055d34d4David Howells } else if (perm) { 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = key_validate(key); 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto invalid_key; 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EIO; 72476d8aeabfeb1c42641a81c44280177b9a08670d8David Howells if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto invalid_key; 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7273e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells /* check the permissions */ 72829db9190634067c5a328ee5fcc2890251b836b4bDavid Howells ret = key_task_permission(key_ref, context, perm); 72929db9190634067c5a328ee5fcc2890251b836b4bDavid Howells if (ret < 0) 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto invalid_key; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 732664cceb0093b755739e56572b836a99104ee8a75David Howellserror: 733664cceb0093b755739e56572b836a99104ee8a75David Howells return key_ref; 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 735664cceb0093b755739e56572b836a99104ee8a75David Howellsinvalid_key: 736664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref_put(key_ref); 737664cceb0093b755739e56572b836a99104ee8a75David Howells key_ref = ERR_PTR(ret); 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end lookup_user_key() */ 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * join the named keyring as the session keyring if possible, or attempt to 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * create a new one of that name if not 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - if the name is NULL, an empty anonymous keyring is installed instead 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - named session keyring joining is done with a semaphore held 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslong join_session_keyring(const char *name) 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct task_struct *tsk = current; 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct key *keyring; 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long ret; 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if no name is provided, install an anonymous keyring */ 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!name) { 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = install_session_keyring(tsk, NULL); 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7613e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells rcu_read_lock(); 7623e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells ret = rcu_dereference(tsk->signal->session_keyring)->serial; 7633e30148c3d524a9c1c63ca28261bc24c457eb07aDavid Howells rcu_read_unlock(); 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allow the user to join or create a named keyring */ 768bb0030797f55c9996ea1cebd16b65750ceb7e4fdIngo Molnar mutex_lock(&key_session_mutex); 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* look for an existing keyring of this name */ 77169664cf16af4f31cd54d77948a4baf9c7e0ca7b9David Howells keyring = find_keyring_by_name(name, false); 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (PTR_ERR(keyring) == -ENOKEY) { 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* not found - try and create a new one */ 7747e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 7757e047ef5fe2d52e83020e856b1bf2556a6a2ce98David Howells KEY_ALLOC_IN_QUOTA, NULL); 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(keyring)) { 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = PTR_ERR(keyring); 778bcf945d36fa0598f41ac4ad46a9dc43135460263David Howells goto error2; 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (IS_ERR(keyring)) { 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = PTR_ERR(keyring); 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error2; 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we've got a keyring - now to install it */ 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = install_session_keyring(tsk, keyring); 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error2; 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = keyring->serial; 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_put(keyring); 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 794664cceb0093b755739e56572b836a99104ee8a75David Howellserror2: 795bb0030797f55c9996ea1cebd16b65750ceb7e4fdIngo Molnar mutex_unlock(&key_session_mutex); 796664cceb0093b755739e56572b836a99104ee8a75David Howellserror: 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end join_session_keyring() */ 800