KEYS: Do some style cleanup in the key management code.
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / security / keys / process_keys.c
CommitLineData
69664cf1 1/* Management of a process's keyrings
1da177e4 2 *
69664cf1 3 * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved.
1da177e4
LT
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/sched.h>
1da177e4
LT
15#include <linux/keyctl.h>
16#include <linux/fs.h>
17#include <linux/err.h>
bb003079 18#include <linux/mutex.h>
ee18d64c 19#include <linux/security.h>
1d1e9756 20#include <linux/user_namespace.h>
1da177e4
LT
21#include <asm/uaccess.h>
22#include "internal.h"
23
24/* session keyring create vs join semaphore */
bb003079 25static DEFINE_MUTEX(key_session_mutex);
1da177e4 26
69664cf1
DH
27/* user keyring creation semaphore */
28static DEFINE_MUTEX(key_user_keyring_mutex);
29
1da177e4
LT
30/* the root user's tracking struct */
31struct key_user root_key_user = {
32 .usage = ATOMIC_INIT(3),
76181c13 33 .cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock),
6cfd76a2 34 .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock),
1da177e4
LT
35 .nkeys = ATOMIC_INIT(2),
36 .nikeys = ATOMIC_INIT(2),
37 .uid = 0,
1d1e9756 38 .user_ns = &init_user_ns,
1da177e4
LT
39};
40
1da177e4 41/*
69664cf1 42 * install user and user session keyrings for a particular UID
1da177e4 43 */
8bbf4976 44int install_user_keyrings(void)
1da177e4 45{
d84f4f99
DH
46 struct user_struct *user;
47 const struct cred *cred;
1da177e4
LT
48 struct key *uid_keyring, *session_keyring;
49 char buf[20];
50 int ret;
51
d84f4f99
DH
52 cred = current_cred();
53 user = cred->user;
54
69664cf1 55 kenter("%p{%u}", user, user->uid);
1da177e4 56
69664cf1
DH
57 if (user->uid_keyring) {
58 kleave(" = 0 [exist]");
59 return 0;
1da177e4
LT
60 }
61
69664cf1
DH
62 mutex_lock(&key_user_keyring_mutex);
63 ret = 0;
1da177e4 64
69664cf1
DH
65 if (!user->uid_keyring) {
66 /* get the UID-specific keyring
67 * - there may be one in existence already as it may have been
68 * pinned by a session, but the user_struct pointing to it
69 * may have been destroyed by setuid */
70 sprintf(buf, "_uid.%u", user->uid);
71
72 uid_keyring = find_keyring_by_name(buf, true);
73 if (IS_ERR(uid_keyring)) {
74 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
d84f4f99 75 cred, KEY_ALLOC_IN_QUOTA,
69664cf1
DH
76 NULL);
77 if (IS_ERR(uid_keyring)) {
78 ret = PTR_ERR(uid_keyring);
79 goto error;
80 }
81 }
82
83 /* get a default session keyring (which might also exist
84 * already) */
85 sprintf(buf, "_uid_ses.%u", user->uid);
86
87 session_keyring = find_keyring_by_name(buf, true);
88 if (IS_ERR(session_keyring)) {
89 session_keyring =
90 keyring_alloc(buf, user->uid, (gid_t) -1,
d84f4f99 91 cred, KEY_ALLOC_IN_QUOTA, NULL);
69664cf1
DH
92 if (IS_ERR(session_keyring)) {
93 ret = PTR_ERR(session_keyring);
94 goto error_release;
95 }
96
97 /* we install a link from the user session keyring to
98 * the user keyring */
99 ret = key_link(session_keyring, uid_keyring);
100 if (ret < 0)
101 goto error_release_both;
102 }
103
104 /* install the keyrings */
105 user->uid_keyring = uid_keyring;
106 user->session_keyring = session_keyring;
1da177e4
LT
107 }
108
69664cf1
DH
109 mutex_unlock(&key_user_keyring_mutex);
110 kleave(" = 0");
111 return 0;
1da177e4 112
69664cf1
DH
113error_release_both:
114 key_put(session_keyring);
115error_release:
116 key_put(uid_keyring);
664cceb0 117error:
69664cf1
DH
118 mutex_unlock(&key_user_keyring_mutex);
119 kleave(" = %d", ret);
1da177e4 120 return ret;
69664cf1 121}
1da177e4 122
1da177e4 123/*
d84f4f99 124 * install a fresh thread keyring directly to new credentials
1da177e4 125 */
d84f4f99 126int install_thread_keyring_to_cred(struct cred *new)
1da177e4 127{
d84f4f99 128 struct key *keyring;
1da177e4 129
d84f4f99
DH
130 keyring = keyring_alloc("_tid", new->uid, new->gid, new,
131 KEY_ALLOC_QUOTA_OVERRUN, NULL);
132 if (IS_ERR(keyring))
133 return PTR_ERR(keyring);
1da177e4 134
d84f4f99
DH
135 new->thread_keyring = keyring;
136 return 0;
137}
1da177e4 138
1da177e4
LT
139/*
140 * install a fresh thread keyring, discarding the old one
141 */
d84f4f99 142static int install_thread_keyring(void)
1da177e4 143{
d84f4f99 144 struct cred *new;
1da177e4
LT
145 int ret;
146
d84f4f99
DH
147 new = prepare_creds();
148 if (!new)
149 return -ENOMEM;
1da177e4 150
d84f4f99
DH
151 BUG_ON(new->thread_keyring);
152
153 ret = install_thread_keyring_to_cred(new);
154 if (ret < 0) {
155 abort_creds(new);
156 return ret;
1da177e4
LT
157 }
158
d84f4f99
DH
159 return commit_creds(new);
160}
1da177e4 161
d84f4f99
DH
162/*
163 * install a process keyring directly to a credentials struct
164 * - returns -EEXIST if there was already a process keyring, 0 if one installed,
165 * and other -ve on any other error
166 */
167int install_process_keyring_to_cred(struct cred *new)
168{
169 struct key *keyring;
170 int ret;
1da177e4 171
d84f4f99
DH
172 if (new->tgcred->process_keyring)
173 return -EEXIST;
174
175 keyring = keyring_alloc("_pid", new->uid, new->gid,
176 new, KEY_ALLOC_QUOTA_OVERRUN, NULL);
177 if (IS_ERR(keyring))
178 return PTR_ERR(keyring);
179
180 spin_lock_irq(&new->tgcred->lock);
181 if (!new->tgcred->process_keyring) {
182 new->tgcred->process_keyring = keyring;
183 keyring = NULL;
184 ret = 0;
185 } else {
186 ret = -EEXIST;
187 }
188 spin_unlock_irq(&new->tgcred->lock);
189 key_put(keyring);
1da177e4 190 return ret;
d84f4f99 191}
1da177e4 192
1da177e4
LT
193/*
194 * make sure a process keyring is installed
d84f4f99 195 * - we
1da177e4 196 */
d84f4f99 197static int install_process_keyring(void)
1da177e4 198{
d84f4f99 199 struct cred *new;
1da177e4
LT
200 int ret;
201
d84f4f99
DH
202 new = prepare_creds();
203 if (!new)
204 return -ENOMEM;
1da177e4 205
d84f4f99
DH
206 ret = install_process_keyring_to_cred(new);
207 if (ret < 0) {
208 abort_creds(new);
27d63798 209 return ret != -EEXIST ? ret : 0;
1da177e4
LT
210 }
211
d84f4f99
DH
212 return commit_creds(new);
213}
1da177e4 214
1da177e4 215/*
d84f4f99 216 * install a session keyring directly to a credentials struct
1da177e4 217 */
685bfd2c 218int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
1da177e4 219{
7e047ef5 220 unsigned long flags;
1da177e4 221 struct key *old;
1a26feb9
DH
222
223 might_sleep();
1da177e4
LT
224
225 /* create an empty session keyring */
226 if (!keyring) {
7e047ef5 227 flags = KEY_ALLOC_QUOTA_OVERRUN;
d84f4f99 228 if (cred->tgcred->session_keyring)
7e047ef5
DH
229 flags = KEY_ALLOC_IN_QUOTA;
230
d84f4f99
DH
231 keyring = keyring_alloc("_ses", cred->uid, cred->gid,
232 cred, flags, NULL);
1a26feb9
DH
233 if (IS_ERR(keyring))
234 return PTR_ERR(keyring);
d84f4f99 235 } else {
1da177e4
LT
236 atomic_inc(&keyring->usage);
237 }
238
239 /* install the keyring */
d84f4f99
DH
240 spin_lock_irq(&cred->tgcred->lock);
241 old = cred->tgcred->session_keyring;
242 rcu_assign_pointer(cred->tgcred->session_keyring, keyring);
243 spin_unlock_irq(&cred->tgcred->lock);
1da177e4 244
1a26feb9
DH
245 /* we're using RCU on the pointer, but there's no point synchronising
246 * on it if it didn't previously point to anything */
247 if (old) {
248 synchronize_rcu();
249 key_put(old);
250 }
1da177e4 251
1a26feb9 252 return 0;
d84f4f99 253}
1da177e4 254
1da177e4 255/*
d84f4f99
DH
256 * install a session keyring, discarding the old one
257 * - if a keyring is not supplied, an empty one is invented
1da177e4 258 */
d84f4f99 259static int install_session_keyring(struct key *keyring)
1da177e4 260{
d84f4f99
DH
261 struct cred *new;
262 int ret;
1da177e4 263
d84f4f99
DH
264 new = prepare_creds();
265 if (!new)
266 return -ENOMEM;
1da177e4 267
d84f4f99
DH
268 ret = install_session_keyring_to_cred(new, NULL);
269 if (ret < 0) {
270 abort_creds(new);
271 return ret;
272 }
1da177e4 273
d84f4f99
DH
274 return commit_creds(new);
275}
1da177e4 276
1da177e4
LT
277/*
278 * the filesystem user ID changed
279 */
280void key_fsuid_changed(struct task_struct *tsk)
281{
282 /* update the ownership of the thread keyring */
b6dff3ec
DH
283 BUG_ON(!tsk->cred);
284 if (tsk->cred->thread_keyring) {
285 down_write(&tsk->cred->thread_keyring->sem);
286 tsk->cred->thread_keyring->uid = tsk->cred->fsuid;
287 up_write(&tsk->cred->thread_keyring->sem);
1da177e4 288 }
a8b17ed0 289}
1da177e4 290
1da177e4
LT
291/*
292 * the filesystem group ID changed
293 */
294void key_fsgid_changed(struct task_struct *tsk)
295{
296 /* update the ownership of the thread keyring */
b6dff3ec
DH
297 BUG_ON(!tsk->cred);
298 if (tsk->cred->thread_keyring) {
299 down_write(&tsk->cred->thread_keyring->sem);
300 tsk->cred->thread_keyring->gid = tsk->cred->fsgid;
301 up_write(&tsk->cred->thread_keyring->sem);
1da177e4 302 }
a8b17ed0 303}
1da177e4 304
1da177e4 305/*
927942aa 306 * search only my process keyrings for the first matching key
1da177e4
LT
307 * - we use the supplied match function to see if the description (or other
308 * feature of interest) matches
309 * - we return -EAGAIN if we didn't find any matching key
310 * - we return -ENOKEY if we found only negative matching keys
311 */
927942aa
DH
312key_ref_t search_my_process_keyrings(struct key_type *type,
313 const void *description,
314 key_match_func_t match,
315 const struct cred *cred)
1da177e4 316{
b5f545c8 317 key_ref_t key_ref, ret, err;
1da177e4
LT
318
319 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
320 * searchable, but we failed to find a key or we found a negative key;
321 * otherwise we want to return a sample error (probably -EACCES) if
322 * none of the keyrings were searchable
323 *
324 * in terms of priority: success > -ENOKEY > -EAGAIN > other error
325 */
664cceb0 326 key_ref = NULL;
1da177e4
LT
327 ret = NULL;
328 err = ERR_PTR(-EAGAIN);
329
330 /* search the thread keyring first */
c69e8d9c 331 if (cred->thread_keyring) {
664cceb0 332 key_ref = keyring_search_aux(
c69e8d9c 333 make_key_ref(cred->thread_keyring, 1),
d84f4f99 334 cred, type, description, match);
664cceb0 335 if (!IS_ERR(key_ref))
1da177e4
LT
336 goto found;
337
664cceb0 338 switch (PTR_ERR(key_ref)) {
1da177e4
LT
339 case -EAGAIN: /* no key */
340 if (ret)
341 break;
342 case -ENOKEY: /* negative key */
664cceb0 343 ret = key_ref;
1da177e4
LT
344 break;
345 default:
664cceb0 346 err = key_ref;
1da177e4
LT
347 break;
348 }
349 }
350
351 /* search the process keyring second */
bb952bb9 352 if (cred->tgcred->process_keyring) {
664cceb0 353 key_ref = keyring_search_aux(
bb952bb9 354 make_key_ref(cred->tgcred->process_keyring, 1),
d84f4f99 355 cred, type, description, match);
664cceb0 356 if (!IS_ERR(key_ref))
1da177e4
LT
357 goto found;
358
664cceb0 359 switch (PTR_ERR(key_ref)) {
1da177e4
LT
360 case -EAGAIN: /* no key */
361 if (ret)
362 break;
363 case -ENOKEY: /* negative key */
664cceb0 364 ret = key_ref;
1da177e4
LT
365 break;
366 default:
664cceb0 367 err = key_ref;
1da177e4
LT
368 break;
369 }
370 }
371
3e30148c 372 /* search the session keyring */
bb952bb9 373 if (cred->tgcred->session_keyring) {
8589b4e0 374 rcu_read_lock();
664cceb0
DH
375 key_ref = keyring_search_aux(
376 make_key_ref(rcu_dereference(
bb952bb9 377 cred->tgcred->session_keyring),
664cceb0 378 1),
d84f4f99 379 cred, type, description, match);
8589b4e0 380 rcu_read_unlock();
3e30148c 381
664cceb0 382 if (!IS_ERR(key_ref))
3e30148c
DH
383 goto found;
384
664cceb0 385 switch (PTR_ERR(key_ref)) {
3e30148c
DH
386 case -EAGAIN: /* no key */
387 if (ret)
388 break;
389 case -ENOKEY: /* negative key */
664cceb0 390 ret = key_ref;
3e30148c
DH
391 break;
392 default:
664cceb0 393 err = key_ref;
3e30148c
DH
394 break;
395 }
b5f545c8
DH
396 }
397 /* or search the user-session keyring */
c69e8d9c 398 else if (cred->user->session_keyring) {
b5f545c8 399 key_ref = keyring_search_aux(
c69e8d9c 400 make_key_ref(cred->user->session_keyring, 1),
d84f4f99 401 cred, type, description, match);
664cceb0 402 if (!IS_ERR(key_ref))
3e30148c
DH
403 goto found;
404
664cceb0 405 switch (PTR_ERR(key_ref)) {
3e30148c
DH
406 case -EAGAIN: /* no key */
407 if (ret)
408 break;
409 case -ENOKEY: /* negative key */
664cceb0 410 ret = key_ref;
3e30148c
DH
411 break;
412 default:
664cceb0 413 err = key_ref;
3e30148c
DH
414 break;
415 }
8589b4e0 416 }
b5f545c8 417
927942aa
DH
418 /* no key - decide on the error we're going to go for */
419 key_ref = ret ? ret : err;
420
421found:
422 return key_ref;
423}
424
927942aa
DH
425/*
426 * search the process keyrings for the first matching key
427 * - we use the supplied match function to see if the description (or other
428 * feature of interest) matches
429 * - we return -EAGAIN if we didn't find any matching key
430 * - we return -ENOKEY if we found only negative matching keys
431 */
432key_ref_t search_process_keyrings(struct key_type *type,
433 const void *description,
434 key_match_func_t match,
435 const struct cred *cred)
436{
437 struct request_key_auth *rka;
438 key_ref_t key_ref, ret = ERR_PTR(-EACCES), err;
439
440 might_sleep();
441
442 key_ref = search_my_process_keyrings(type, description, match, cred);
443 if (!IS_ERR(key_ref))
444 goto found;
445 err = key_ref;
446
b5f545c8
DH
447 /* if this process has an instantiation authorisation key, then we also
448 * search the keyrings of the process mentioned there
449 * - we don't permit access to request_key auth keys via this method
450 */
c69e8d9c 451 if (cred->request_key_auth &&
d84f4f99 452 cred == current_cred() &&
04c567d9 453 type != &key_type_request_key_auth
b5f545c8 454 ) {
04c567d9 455 /* defend against the auth key being revoked */
c69e8d9c 456 down_read(&cred->request_key_auth->sem);
b5f545c8 457
c69e8d9c
DH
458 if (key_validate(cred->request_key_auth) == 0) {
459 rka = cred->request_key_auth->payload.data;
b5f545c8 460
04c567d9 461 key_ref = search_process_keyrings(type, description,
d84f4f99 462 match, rka->cred);
1da177e4 463
c69e8d9c 464 up_read(&cred->request_key_auth->sem);
04c567d9
DH
465
466 if (!IS_ERR(key_ref))
467 goto found;
468
927942aa 469 ret = key_ref;
04c567d9 470 } else {
c69e8d9c 471 up_read(&cred->request_key_auth->sem);
3e30148c 472 }
1da177e4
LT
473 }
474
475 /* no key - decide on the error we're going to go for */
927942aa
DH
476 if (err == ERR_PTR(-ENOKEY) || ret == ERR_PTR(-ENOKEY))
477 key_ref = ERR_PTR(-ENOKEY);
478 else if (err == ERR_PTR(-EACCES))
479 key_ref = ret;
480 else
481 key_ref = err;
1da177e4 482
3e30148c 483found:
664cceb0 484 return key_ref;
a8b17ed0 485}
1da177e4 486
664cceb0
DH
487/*
488 * see if the key we're looking at is the target key
489 */
927942aa 490int lookup_user_key_possessed(const struct key *key, const void *target)
664cceb0
DH
491{
492 return key == target;
a8b17ed0 493}
664cceb0 494
1da177e4
LT
495/*
496 * lookup a key given a key ID from userspace with a given permissions mask
497 * - don't create special keyrings unless so requested
498 * - partially constructed keys aren't found unless requested
499 */
5593122e 500key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
8bbf4976 501 key_perm_t perm)
1da177e4 502{
8bbf4976 503 struct request_key_auth *rka;
d84f4f99 504 const struct cred *cred;
1da177e4 505 struct key *key;
b6dff3ec 506 key_ref_t key_ref, skey_ref;
1da177e4
LT
507 int ret;
508
bb952bb9
DH
509try_again:
510 cred = get_current_cred();
664cceb0 511 key_ref = ERR_PTR(-ENOKEY);
1da177e4
LT
512
513 switch (id) {
514 case KEY_SPEC_THREAD_KEYRING:
b6dff3ec 515 if (!cred->thread_keyring) {
5593122e 516 if (!(lflags & KEY_LOOKUP_CREATE))
1da177e4
LT
517 goto error;
518
8bbf4976 519 ret = install_thread_keyring();
1da177e4 520 if (ret < 0) {
4d09ec0f 521 key_ref = ERR_PTR(ret);
1da177e4
LT
522 goto error;
523 }
bb952bb9 524 goto reget_creds;
1da177e4
LT
525 }
526
b6dff3ec 527 key = cred->thread_keyring;
1da177e4 528 atomic_inc(&key->usage);
664cceb0 529 key_ref = make_key_ref(key, 1);
1da177e4
LT
530 break;
531
532 case KEY_SPEC_PROCESS_KEYRING:
bb952bb9 533 if (!cred->tgcred->process_keyring) {
5593122e 534 if (!(lflags & KEY_LOOKUP_CREATE))
1da177e4
LT
535 goto error;
536
8bbf4976 537 ret = install_process_keyring();
1da177e4 538 if (ret < 0) {
4d09ec0f 539 key_ref = ERR_PTR(ret);
1da177e4
LT
540 goto error;
541 }
bb952bb9 542 goto reget_creds;
1da177e4
LT
543 }
544
bb952bb9 545 key = cred->tgcred->process_keyring;
1da177e4 546 atomic_inc(&key->usage);
664cceb0 547 key_ref = make_key_ref(key, 1);
1da177e4
LT
548 break;
549
550 case KEY_SPEC_SESSION_KEYRING:
bb952bb9 551 if (!cred->tgcred->session_keyring) {
1da177e4
LT
552 /* always install a session keyring upon access if one
553 * doesn't exist yet */
8bbf4976 554 ret = install_user_keyrings();
69664cf1
DH
555 if (ret < 0)
556 goto error;
b6dff3ec
DH
557 ret = install_session_keyring(
558 cred->user->session_keyring);
d84f4f99 559
1da177e4
LT
560 if (ret < 0)
561 goto error;
bb952bb9 562 goto reget_creds;
1da177e4
LT
563 }
564
3e30148c 565 rcu_read_lock();
bb952bb9 566 key = rcu_dereference(cred->tgcred->session_keyring);
1da177e4 567 atomic_inc(&key->usage);
3e30148c 568 rcu_read_unlock();
664cceb0 569 key_ref = make_key_ref(key, 1);
1da177e4
LT
570 break;
571
572 case KEY_SPEC_USER_KEYRING:
b6dff3ec 573 if (!cred->user->uid_keyring) {
8bbf4976 574 ret = install_user_keyrings();
69664cf1
DH
575 if (ret < 0)
576 goto error;
577 }
578
b6dff3ec 579 key = cred->user->uid_keyring;
1da177e4 580 atomic_inc(&key->usage);
664cceb0 581 key_ref = make_key_ref(key, 1);
1da177e4
LT
582 break;
583
584 case KEY_SPEC_USER_SESSION_KEYRING:
b6dff3ec 585 if (!cred->user->session_keyring) {
8bbf4976 586 ret = install_user_keyrings();
69664cf1
DH
587 if (ret < 0)
588 goto error;
589 }
590
b6dff3ec 591 key = cred->user->session_keyring;
1da177e4 592 atomic_inc(&key->usage);
664cceb0 593 key_ref = make_key_ref(key, 1);
1da177e4
LT
594 break;
595
596 case KEY_SPEC_GROUP_KEYRING:
597 /* group keyrings are not yet supported */
4d09ec0f 598 key_ref = ERR_PTR(-EINVAL);
1da177e4
LT
599 goto error;
600
b5f545c8 601 case KEY_SPEC_REQKEY_AUTH_KEY:
b6dff3ec 602 key = cred->request_key_auth;
b5f545c8
DH
603 if (!key)
604 goto error;
605
606 atomic_inc(&key->usage);
607 key_ref = make_key_ref(key, 1);
608 break;
609
8bbf4976 610 case KEY_SPEC_REQUESTOR_KEYRING:
b6dff3ec 611 if (!cred->request_key_auth)
8bbf4976
DH
612 goto error;
613
b6dff3ec
DH
614 down_read(&cred->request_key_auth->sem);
615 if (cred->request_key_auth->flags & KEY_FLAG_REVOKED) {
8bbf4976
DH
616 key_ref = ERR_PTR(-EKEYREVOKED);
617 key = NULL;
618 } else {
b6dff3ec 619 rka = cred->request_key_auth->payload.data;
8bbf4976
DH
620 key = rka->dest_keyring;
621 atomic_inc(&key->usage);
622 }
b6dff3ec 623 up_read(&cred->request_key_auth->sem);
8bbf4976
DH
624 if (!key)
625 goto error;
626 key_ref = make_key_ref(key, 1);
627 break;
628
1da177e4 629 default:
664cceb0 630 key_ref = ERR_PTR(-EINVAL);
1da177e4
LT
631 if (id < 1)
632 goto error;
633
634 key = key_lookup(id);
664cceb0 635 if (IS_ERR(key)) {
e231c2ee 636 key_ref = ERR_CAST(key);
1da177e4 637 goto error;
664cceb0
DH
638 }
639
640 key_ref = make_key_ref(key, 0);
641
642 /* check to see if we possess the key */
643 skey_ref = search_process_keyrings(key->type, key,
644 lookup_user_key_possessed,
d84f4f99 645 cred);
664cceb0
DH
646
647 if (!IS_ERR(skey_ref)) {
648 key_put(key);
649 key_ref = skey_ref;
650 }
651
1da177e4
LT
652 break;
653 }
654
5593122e
DH
655 /* unlink does not use the nominated key in any way, so can skip all
656 * the permission checks as it is only concerned with the keyring */
657 if (lflags & KEY_LOOKUP_FOR_UNLINK) {
658 ret = 0;
659 goto error;
660 }
661
662 if (!(lflags & KEY_LOOKUP_PARTIAL)) {
76181c13
DH
663 ret = wait_for_key_construction(key, true);
664 switch (ret) {
665 case -ERESTARTSYS:
666 goto invalid_key;
667 default:
668 if (perm)
669 goto invalid_key;
670 case 0:
671 break;
672 }
673 } else if (perm) {
1da177e4
LT
674 ret = key_validate(key);
675 if (ret < 0)
676 goto invalid_key;
677 }
678
679 ret = -EIO;
5593122e
DH
680 if (!(lflags & KEY_LOOKUP_PARTIAL) &&
681 !test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
1da177e4
LT
682 goto invalid_key;
683
3e30148c 684 /* check the permissions */
d84f4f99 685 ret = key_task_permission(key_ref, cred, perm);
29db9190 686 if (ret < 0)
1da177e4
LT
687 goto invalid_key;
688
664cceb0 689error:
bb952bb9 690 put_cred(cred);
664cceb0 691 return key_ref;
1da177e4 692
664cceb0
DH
693invalid_key:
694 key_ref_put(key_ref);
695 key_ref = ERR_PTR(ret);
1da177e4
LT
696 goto error;
697
bb952bb9
DH
698 /* if we attempted to install a keyring, then it may have caused new
699 * creds to be installed */
700reget_creds:
701 put_cred(cred);
702 goto try_again;
a8b17ed0 703}
bb952bb9 704
1da177e4
LT
705/*
706 * join the named keyring as the session keyring if possible, or attempt to
707 * create a new one of that name if not
708 * - if the name is NULL, an empty anonymous keyring is installed instead
709 * - named session keyring joining is done with a semaphore held
710 */
711long join_session_keyring(const char *name)
712{
d84f4f99
DH
713 const struct cred *old;
714 struct cred *new;
1da177e4 715 struct key *keyring;
d84f4f99
DH
716 long ret, serial;
717
718 /* only permit this if there's a single thread in the thread group -
719 * this avoids us having to adjust the creds on all threads and risking
720 * ENOMEM */
5bb459bb 721 if (!current_is_single_threaded())
d84f4f99
DH
722 return -EMLINK;
723
724 new = prepare_creds();
725 if (!new)
726 return -ENOMEM;
727 old = current_cred();
1da177e4
LT
728
729 /* if no name is provided, install an anonymous keyring */
730 if (!name) {
d84f4f99 731 ret = install_session_keyring_to_cred(new, NULL);
1da177e4
LT
732 if (ret < 0)
733 goto error;
734
d84f4f99
DH
735 serial = new->tgcred->session_keyring->serial;
736 ret = commit_creds(new);
737 if (ret == 0)
738 ret = serial;
739 goto okay;
1da177e4
LT
740 }
741
742 /* allow the user to join or create a named keyring */
bb003079 743 mutex_lock(&key_session_mutex);
1da177e4
LT
744
745 /* look for an existing keyring of this name */
69664cf1 746 keyring = find_keyring_by_name(name, false);
1da177e4
LT
747 if (PTR_ERR(keyring) == -ENOKEY) {
748 /* not found - try and create a new one */
d84f4f99 749 keyring = keyring_alloc(name, old->uid, old->gid, old,
7e047ef5 750 KEY_ALLOC_IN_QUOTA, NULL);
1da177e4
LT
751 if (IS_ERR(keyring)) {
752 ret = PTR_ERR(keyring);
bcf945d3 753 goto error2;
1da177e4 754 }
d84f4f99 755 } else if (IS_ERR(keyring)) {
1da177e4
LT
756 ret = PTR_ERR(keyring);
757 goto error2;
758 }
759
760 /* we've got a keyring - now to install it */
d84f4f99 761 ret = install_session_keyring_to_cred(new, keyring);
1da177e4
LT
762 if (ret < 0)
763 goto error2;
764
d84f4f99
DH
765 commit_creds(new);
766 mutex_unlock(&key_session_mutex);
767
1da177e4
LT
768 ret = keyring->serial;
769 key_put(keyring);
d84f4f99
DH
770okay:
771 return ret;
1da177e4 772
664cceb0 773error2:
bb003079 774 mutex_unlock(&key_session_mutex);
664cceb0 775error:
d84f4f99 776 abort_creds(new);
1da177e4 777 return ret;
d84f4f99 778}
ee18d64c
DH
779
780/*
781 * Replace a process's session keyring when that process resumes userspace on
782 * behalf of one of its children
783 */
784void key_replace_session_keyring(void)
785{
786 const struct cred *old;
787 struct cred *new;
788
789 if (!current->replacement_session_keyring)
790 return;
791
792 write_lock_irq(&tasklist_lock);
793 new = current->replacement_session_keyring;
794 current->replacement_session_keyring = NULL;
795 write_unlock_irq(&tasklist_lock);
796
797 if (!new)
798 return;
799
800 old = current_cred();
801 new-> uid = old-> uid;
802 new-> euid = old-> euid;
803 new-> suid = old-> suid;
804 new->fsuid = old->fsuid;
805 new-> gid = old-> gid;
806 new-> egid = old-> egid;
807 new-> sgid = old-> sgid;
808 new->fsgid = old->fsgid;
809 new->user = get_uid(old->user);
810 new->group_info = get_group_info(old->group_info);
811
812 new->securebits = old->securebits;
813 new->cap_inheritable = old->cap_inheritable;
814 new->cap_permitted = old->cap_permitted;
815 new->cap_effective = old->cap_effective;
816 new->cap_bset = old->cap_bset;
817
818 new->jit_keyring = old->jit_keyring;
819 new->thread_keyring = key_get(old->thread_keyring);
820 new->tgcred->tgid = old->tgcred->tgid;
821 new->tgcred->process_keyring = key_get(old->tgcred->process_keyring);
822
823 security_transfer_creds(new, old);
824
825 commit_creds(new);
826}