aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/process_keys.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-04-29 04:01:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-29 11:06:17 -0400
commit69664cf16af4f31cd54d77948a4baf9c7e0ca7b9 (patch)
tree3ff4ecae21c140a2beed25cfa9e55b788f9814ac /security/keys/process_keys.c
parent6b79ccb5144f9ffb4d4596c23e7570238dd12abc (diff)
keys: don't generate user and user session keyrings unless they're accessed
Don't generate the per-UID user and user session keyrings unless they're explicitly accessed. This solves a problem during a login process whereby set*uid() is called before the SELinux PAM module, resulting in the per-UID keyrings having the wrong security labels. This also cures the problem of multiple per-UID keyrings sometimes appearing due to PAM modules (including pam_keyinit) setuiding and causing user_structs to come into and go out of existence whilst the session keyring pins the user keyring. This is achieved by first searching for extant per-UID keyrings before inventing new ones. The serial bound argument is also dropped from find_keyring_by_name() as it's not currently made use of (setting it to 0 disables the feature). Signed-off-by: David Howells <dhowells@redhat.com> Cc: <kwc@citi.umich.edu> Cc: <arunsr@cse.iitk.ac.in> Cc: <dwalsh@redhat.com> Cc: Stephen Smalley <sds@tycho.nsa.gov> Cc: James Morris <jmorris@namei.org> Cc: Chris Wright <chrisw@sous-sol.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'security/keys/process_keys.c')
-rw-r--r--security/keys/process_keys.c142
1 files changed, 83 insertions, 59 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index c886a2bb792a..5be6d018759a 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -1,6 +1,6 @@
1/* process_keys.c: management of a process's keyrings 1/* Management of a process's keyrings
2 * 2 *
3 * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -23,6 +23,9 @@
23/* session keyring create vs join semaphore */ 23/* session keyring create vs join semaphore */
24static DEFINE_MUTEX(key_session_mutex); 24static DEFINE_MUTEX(key_session_mutex);
25 25
26/* user keyring creation semaphore */
27static DEFINE_MUTEX(key_user_keyring_mutex);
28
26/* the root user's tracking struct */ 29/* the root user's tracking struct */
27struct key_user root_key_user = { 30struct key_user root_key_user = {
28 .usage = ATOMIC_INIT(3), 31 .usage = ATOMIC_INIT(3),
@@ -33,78 +36,84 @@ struct key_user root_key_user = {
33 .uid = 0, 36 .uid = 0,
34}; 37};
35 38
36/* the root user's UID keyring */
37struct key root_user_keyring = {
38 .usage = ATOMIC_INIT(1),
39 .serial = 2,
40 .type = &key_type_keyring,
41 .user = &root_key_user,
42 .sem = __RWSEM_INITIALIZER(root_user_keyring.sem),
43 .perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
44 .flags = 1 << KEY_FLAG_INSTANTIATED,
45 .description = "_uid.0",
46#ifdef KEY_DEBUGGING
47 .magic = KEY_DEBUG_MAGIC,
48#endif
49};
50
51/* the root user's default session keyring */
52struct key root_session_keyring = {
53 .usage = ATOMIC_INIT(1),
54 .serial = 1,
55 .type = &key_type_keyring,
56 .user = &root_key_user,
57 .sem = __RWSEM_INITIALIZER(root_session_keyring.sem),
58 .perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
59 .flags = 1 << KEY_FLAG_INSTANTIATED,
60 .description = "_uid_ses.0",
61#ifdef KEY_DEBUGGING
62 .magic = KEY_DEBUG_MAGIC,
63#endif
64};
65
66/*****************************************************************************/ 39/*****************************************************************************/
67/* 40/*
68 * allocate the keyrings to be associated with a UID 41 * install user and user session keyrings for a particular UID
69 */ 42 */
70int alloc_uid_keyring(struct user_struct *user, 43static int install_user_keyrings(struct task_struct *tsk)
71 struct task_struct *ctx)
72{ 44{
45 struct user_struct *user = tsk->user;
73 struct key *uid_keyring, *session_keyring; 46 struct key *uid_keyring, *session_keyring;
74 char buf[20]; 47 char buf[20];
75 int ret; 48 int ret;
76 49
77 /* concoct a default session keyring */ 50 kenter("%p{%u}", user, user->uid);
78 sprintf(buf, "_uid_ses.%u", user->uid);
79 51
80 session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 52 if (user->uid_keyring) {
81 KEY_ALLOC_IN_QUOTA, NULL); 53 kleave(" = 0 [exist]");
82 if (IS_ERR(session_keyring)) { 54 return 0;
83 ret = PTR_ERR(session_keyring);
84 goto error;
85 } 55 }
86 56
87 /* and a UID specific keyring, pointed to by the default session 57 mutex_lock(&key_user_keyring_mutex);
88 * keyring */ 58 ret = 0;
89 sprintf(buf, "_uid.%u", user->uid);
90 59
91 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 60 if (!user->uid_keyring) {
92 KEY_ALLOC_IN_QUOTA, session_keyring); 61 /* get the UID-specific keyring
93 if (IS_ERR(uid_keyring)) { 62 * - there may be one in existence already as it may have been
94 key_put(session_keyring); 63 * pinned by a session, but the user_struct pointing to it
95 ret = PTR_ERR(uid_keyring); 64 * may have been destroyed by setuid */
96 goto error; 65 sprintf(buf, "_uid.%u", user->uid);
66
67 uid_keyring = find_keyring_by_name(buf, true);
68 if (IS_ERR(uid_keyring)) {
69 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
70 tsk, KEY_ALLOC_IN_QUOTA,
71 NULL);
72 if (IS_ERR(uid_keyring)) {
73 ret = PTR_ERR(uid_keyring);
74 goto error;
75 }
76 }
77
78 /* get a default session keyring (which might also exist
79 * already) */
80 sprintf(buf, "_uid_ses.%u", user->uid);
81
82 session_keyring = find_keyring_by_name(buf, true);
83 if (IS_ERR(session_keyring)) {
84 session_keyring =
85 keyring_alloc(buf, user->uid, (gid_t) -1,
86 tsk, KEY_ALLOC_IN_QUOTA, NULL);
87 if (IS_ERR(session_keyring)) {
88 ret = PTR_ERR(session_keyring);
89 goto error_release;
90 }
91
92 /* we install a link from the user session keyring to
93 * the user keyring */
94 ret = key_link(session_keyring, uid_keyring);
95 if (ret < 0)
96 goto error_release_both;
97 }
98
99 /* install the keyrings */
100 user->uid_keyring = uid_keyring;
101 user->session_keyring = session_keyring;
97 } 102 }
98 103
99 /* install the keyrings */ 104 mutex_unlock(&key_user_keyring_mutex);
100 user->uid_keyring = uid_keyring; 105 kleave(" = 0");
101 user->session_keyring = session_keyring; 106 return 0;
102 ret = 0;
103 107
108error_release_both:
109 key_put(session_keyring);
110error_release:
111 key_put(uid_keyring);
104error: 112error:
113 mutex_unlock(&key_user_keyring_mutex);
114 kleave(" = %d", ret);
105 return ret; 115 return ret;
106 116}
107} /* end alloc_uid_keyring() */
108 117
109/*****************************************************************************/ 118/*****************************************************************************/
110/* 119/*
@@ -481,7 +490,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
481 } 490 }
482 } 491 }
483 /* or search the user-session keyring */ 492 /* or search the user-session keyring */
484 else { 493 else if (context->user->session_keyring) {
485 key_ref = keyring_search_aux( 494 key_ref = keyring_search_aux(
486 make_key_ref(context->user->session_keyring, 1), 495 make_key_ref(context->user->session_keyring, 1),
487 context, type, description, match); 496 context, type, description, match);
@@ -614,6 +623,9 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
614 if (!context->signal->session_keyring) { 623 if (!context->signal->session_keyring) {
615 /* always install a session keyring upon access if one 624 /* always install a session keyring upon access if one
616 * doesn't exist yet */ 625 * doesn't exist yet */
626 ret = install_user_keyrings(context);
627 if (ret < 0)
628 goto error;
617 ret = install_session_keyring( 629 ret = install_session_keyring(
618 context, context->user->session_keyring); 630 context, context->user->session_keyring);
619 if (ret < 0) 631 if (ret < 0)
@@ -628,12 +640,24 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
628 break; 640 break;
629 641
630 case KEY_SPEC_USER_KEYRING: 642 case KEY_SPEC_USER_KEYRING:
643 if (!context->user->uid_keyring) {
644 ret = install_user_keyrings(context);
645 if (ret < 0)
646 goto error;
647 }
648
631 key = context->user->uid_keyring; 649 key = context->user->uid_keyring;
632 atomic_inc(&key->usage); 650 atomic_inc(&key->usage);
633 key_ref = make_key_ref(key, 1); 651 key_ref = make_key_ref(key, 1);
634 break; 652 break;
635 653
636 case KEY_SPEC_USER_SESSION_KEYRING: 654 case KEY_SPEC_USER_SESSION_KEYRING:
655 if (!context->user->session_keyring) {
656 ret = install_user_keyrings(context);
657 if (ret < 0)
658 goto error;
659 }
660
637 key = context->user->session_keyring; 661 key = context->user->session_keyring;
638 atomic_inc(&key->usage); 662 atomic_inc(&key->usage);
639 key_ref = make_key_ref(key, 1); 663 key_ref = make_key_ref(key, 1);
@@ -744,7 +768,7 @@ long join_session_keyring(const char *name)
744 mutex_lock(&key_session_mutex); 768 mutex_lock(&key_session_mutex);
745 769
746 /* look for an existing keyring of this name */ 770 /* look for an existing keyring of this name */
747 keyring = find_keyring_by_name(name, 0); 771 keyring = find_keyring_by_name(name, false);
748 if (PTR_ERR(keyring) == -ENOKEY) { 772 if (PTR_ERR(keyring) == -ENOKEY) {
749 /* not found - try and create a new one */ 773 /* not found - try and create a new one */
750 keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 774 keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk,