aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2007-10-17 02:29:46 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:42:57 -0400
commit76181c134f87479fa13bf2548ddf2999055d34d4 (patch)
tree34694341c190e7ecdd3111ee48e4b98602ff012f /security/keys
parent398c95bdf2c24d7866692a40ba04425aef238cdd (diff)
KEYS: Make request_key() and co fundamentally asynchronous
Make request_key() and co fundamentally asynchronous to make it easier for NFS to make use of them. There are now accessor functions that do asynchronous constructions, a wait function to wait for construction to complete, and a completion function for the key type to indicate completion of construction. Note that the construction queue is now gone. Instead, keys under construction are linked in to the appropriate keyring in advance, and that anyone encountering one must wait for it to be complete before they can use it. This is done automatically for userspace. The following auxiliary changes are also made: (1) Key type implementation stuff is split from linux/key.h into linux/key-type.h. (2) AF_RXRPC provides a way to allocate null rxrpc-type keys so that AFS does not need to call key_instantiate_and_link() directly. (3) Adjust the debugging macros so that they're -Wformat checked even if they are disabled, and make it so they can be enabled simply by defining __KDEBUG to be consistent with other code of mine. (3) Documentation. [alan@lxorguk.ukuu.org.uk: keys: missing word in documentation] Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'security/keys')
-rw-r--r--security/keys/internal.h35
-rw-r--r--security/keys/key.c34
-rw-r--r--security/keys/process_keys.c16
-rw-r--r--security/keys/request_key.c556
-rw-r--r--security/keys/request_key_auth.c11
5 files changed, 335 insertions, 317 deletions
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 1bb416f4bbce..d36d69393356 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -1,6 +1,6 @@
1/* internal.h: authentication token and access key management internal defs 1/* internal.h: authentication token and access key management internal defs
2 * 2 *
3 * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2003-5, 2007 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
@@ -12,17 +12,28 @@
12#ifndef _INTERNAL_H 12#ifndef _INTERNAL_H
13#define _INTERNAL_H 13#define _INTERNAL_H
14 14
15#include <linux/key.h> 15#include <linux/key-type.h>
16#include <linux/key-ui.h> 16#include <linux/key-ui.h>
17 17
18#if 0 18static inline __attribute__((format(printf, 1, 2)))
19#define kenter(FMT, a...) printk("==> %s("FMT")\n",__FUNCTION__ , ## a) 19void no_printk(const char *fmt, ...)
20#define kleave(FMT, a...) printk("<== %s()"FMT"\n",__FUNCTION__ , ## a) 20{
21#define kdebug(FMT, a...) printk(FMT"\n" , ## a) 21}
22
23#ifdef __KDEBUG
24#define kenter(FMT, ...) \
25 printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
26#define kleave(FMT, ...) \
27 printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
28#define kdebug(FMT, ...) \
29 printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__)
22#else 30#else
23#define kenter(FMT, a...) do {} while(0) 31#define kenter(FMT, ...) \
24#define kleave(FMT, a...) do {} while(0) 32 no_printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
25#define kdebug(FMT, a...) do {} while(0) 33#define kleave(FMT, ...) \
34 no_printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
35#define kdebug(FMT, ...) \
36 no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__)
26#endif 37#endif
27 38
28extern struct key_type key_type_user; 39extern struct key_type key_type_user;
@@ -36,7 +47,7 @@ extern struct key_type key_type_user;
36 */ 47 */
37struct key_user { 48struct key_user {
38 struct rb_node node; 49 struct rb_node node;
39 struct list_head consq; /* construction queue */ 50 struct mutex cons_lock; /* construction initiation lock */
40 spinlock_t lock; 51 spinlock_t lock;
41 atomic_t usage; /* for accessing qnkeys & qnbytes */ 52 atomic_t usage; /* for accessing qnkeys & qnbytes */
42 atomic_t nkeys; /* number of keys */ 53 atomic_t nkeys; /* number of keys */
@@ -62,7 +73,7 @@ extern void key_user_put(struct key_user *user);
62extern struct rb_root key_serial_tree; 73extern struct rb_root key_serial_tree;
63extern spinlock_t key_serial_lock; 74extern spinlock_t key_serial_lock;
64extern struct semaphore key_alloc_sem; 75extern struct semaphore key_alloc_sem;
65extern struct rw_semaphore key_construction_sem; 76extern struct mutex key_construction_mutex;
66extern wait_queue_head_t request_key_conswq; 77extern wait_queue_head_t request_key_conswq;
67 78
68 79
@@ -109,7 +120,7 @@ extern struct key *request_key_and_link(struct key_type *type,
109struct request_key_auth { 120struct request_key_auth {
110 struct key *target_key; 121 struct key *target_key;
111 struct task_struct *context; 122 struct task_struct *context;
112 const char *callout_info; 123 char *callout_info;
113 pid_t pid; 124 pid_t pid;
114}; 125};
115 126
diff --git a/security/keys/key.c b/security/keys/key.c
index 01bbc6d9d19b..fdd5ca6d89fc 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1,6 +1,6 @@
1/* key.c: basic authentication token and access key management 1/* Basic authentication token and access key management
2 * 2 *
3 * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004-2007 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
@@ -34,7 +34,7 @@ static void key_cleanup(struct work_struct *work);
34static DECLARE_WORK(key_cleanup_task, key_cleanup); 34static DECLARE_WORK(key_cleanup_task, key_cleanup);
35 35
36/* we serialise key instantiation and link */ 36/* we serialise key instantiation and link */
37DECLARE_RWSEM(key_construction_sem); 37DEFINE_MUTEX(key_construction_mutex);
38 38
39/* any key who's type gets unegistered will be re-typed to this */ 39/* any key who's type gets unegistered will be re-typed to this */
40static struct key_type key_type_dead = { 40static struct key_type key_type_dead = {
@@ -104,7 +104,7 @@ struct key_user *key_user_lookup(uid_t uid)
104 candidate->qnkeys = 0; 104 candidate->qnkeys = 0;
105 candidate->qnbytes = 0; 105 candidate->qnbytes = 0;
106 spin_lock_init(&candidate->lock); 106 spin_lock_init(&candidate->lock);
107 INIT_LIST_HEAD(&candidate->consq); 107 mutex_init(&candidate->cons_lock);
108 108
109 rb_link_node(&candidate->node, parent, p); 109 rb_link_node(&candidate->node, parent, p);
110 rb_insert_color(&candidate->node, &key_user_tree); 110 rb_insert_color(&candidate->node, &key_user_tree);
@@ -418,7 +418,7 @@ static int __key_instantiate_and_link(struct key *key,
418 awaken = 0; 418 awaken = 0;
419 ret = -EBUSY; 419 ret = -EBUSY;
420 420
421 down_write(&key_construction_sem); 421 mutex_lock(&key_construction_mutex);
422 422
423 /* can't instantiate twice */ 423 /* can't instantiate twice */
424 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { 424 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
@@ -443,11 +443,11 @@ static int __key_instantiate_and_link(struct key *key,
443 } 443 }
444 } 444 }
445 445
446 up_write(&key_construction_sem); 446 mutex_unlock(&key_construction_mutex);
447 447
448 /* wake up anyone waiting for a key to be constructed */ 448 /* wake up anyone waiting for a key to be constructed */
449 if (awaken) 449 if (awaken)
450 wake_up_all(&request_key_conswq); 450 wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT);
451 451
452 return ret; 452 return ret;
453 453
@@ -500,7 +500,7 @@ int key_negate_and_link(struct key *key,
500 if (keyring) 500 if (keyring)
501 down_write(&keyring->sem); 501 down_write(&keyring->sem);
502 502
503 down_write(&key_construction_sem); 503 mutex_lock(&key_construction_mutex);
504 504
505 /* can't instantiate twice */ 505 /* can't instantiate twice */
506 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { 506 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
@@ -525,14 +525,14 @@ int key_negate_and_link(struct key *key,
525 key_revoke(instkey); 525 key_revoke(instkey);
526 } 526 }
527 527
528 up_write(&key_construction_sem); 528 mutex_unlock(&key_construction_mutex);
529 529
530 if (keyring) 530 if (keyring)
531 up_write(&keyring->sem); 531 up_write(&keyring->sem);
532 532
533 /* wake up anyone waiting for a key to be constructed */ 533 /* wake up anyone waiting for a key to be constructed */
534 if (awaken) 534 if (awaken)
535 wake_up_all(&request_key_conswq); 535 wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT);
536 536
537 return ret; 537 return ret;
538 538
@@ -899,12 +899,14 @@ void key_revoke(struct key *key)
899{ 899{
900 key_check(key); 900 key_check(key);
901 901
902 /* make sure no one's trying to change or use the key when we mark 902 /* make sure no one's trying to change or use the key when we mark it
903 * it */ 903 * - we tell lockdep that we might nest because we might be revoking an
904 down_write(&key->sem); 904 * authorisation key whilst holding the sem on a key we've just
905 set_bit(KEY_FLAG_REVOKED, &key->flags); 905 * instantiated
906 906 */
907 if (key->type->revoke) 907 down_write_nested(&key->sem, 1);
908 if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags) &&
909 key->type->revoke)
908 key->type->revoke(key); 910 key->type->revoke(key);
909 911
910 up_write(&key->sem); 912 up_write(&key->sem);
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index b6f86808475a..2a0eb946fc7e 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -26,7 +26,7 @@ static DEFINE_MUTEX(key_session_mutex);
26/* the root user's tracking struct */ 26/* the root user's tracking struct */
27struct key_user root_key_user = { 27struct key_user root_key_user = {
28 .usage = ATOMIC_INIT(3), 28 .usage = ATOMIC_INIT(3),
29 .consq = LIST_HEAD_INIT(root_key_user.consq), 29 .cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock),
30 .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), 30 .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock),
31 .nkeys = ATOMIC_INIT(2), 31 .nkeys = ATOMIC_INIT(2),
32 .nikeys = ATOMIC_INIT(2), 32 .nikeys = ATOMIC_INIT(2),
@@ -679,8 +679,18 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
679 break; 679 break;
680 } 680 }
681 681
682 /* check the status */ 682 if (!partial) {
683 if (perm) { 683 ret = wait_for_key_construction(key, true);
684 switch (ret) {
685 case -ERESTARTSYS:
686 goto invalid_key;
687 default:
688 if (perm)
689 goto invalid_key;
690 case 0:
691 break;
692 }
693 } else if (perm) {
684 ret = key_validate(key); 694 ret = key_validate(key);
685 if (ret < 0) 695 if (ret < 0)
686 goto invalid_key; 696 goto invalid_key;
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 557500110a13..6381e616c477 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -1,6 +1,6 @@
1/* request_key.c: request a key from userspace 1/* Request a key from userspace
2 * 2 *
3 * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004-2007 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
@@ -18,27 +18,54 @@
18#include <linux/keyctl.h> 18#include <linux/keyctl.h>
19#include "internal.h" 19#include "internal.h"
20 20
21struct key_construction { 21/*
22 struct list_head link; /* link in construction queue */ 22 * wait_on_bit() sleep function for uninterruptible waiting
23 struct key *key; /* key being constructed */ 23 */
24}; 24static int key_wait_bit(void *flags)
25{
26 schedule();
27 return 0;
28}
29
30/*
31 * wait_on_bit() sleep function for interruptible waiting
32 */
33static int key_wait_bit_intr(void *flags)
34{
35 schedule();
36 return signal_pending(current) ? -ERESTARTSYS : 0;
37}
38
39/*
40 * call to complete the construction of a key
41 */
42void complete_request_key(struct key_construction *cons, int error)
43{
44 kenter("{%d,%d},%d", cons->key->serial, cons->authkey->serial, error);
25 45
26/* when waiting for someone else's keys, you get added to this */ 46 if (error < 0)
27DECLARE_WAIT_QUEUE_HEAD(request_key_conswq); 47 key_negate_and_link(cons->key, key_negative_timeout, NULL,
48 cons->authkey);
49 else
50 key_revoke(cons->authkey);
51
52 key_put(cons->key);
53 key_put(cons->authkey);
54 kfree(cons);
55}
56EXPORT_SYMBOL(complete_request_key);
28 57
29/*****************************************************************************/
30/* 58/*
31 * request userspace finish the construction of a key 59 * request userspace finish the construction of a key
32 * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>" 60 * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>"
33 */ 61 */
34static int call_sbin_request_key(struct key *key, 62static int call_sbin_request_key(struct key_construction *cons,
35 struct key *authkey,
36 const char *op, 63 const char *op,
37 void *aux) 64 void *aux)
38{ 65{
39 struct task_struct *tsk = current; 66 struct task_struct *tsk = current;
40 key_serial_t prkey, sskey; 67 key_serial_t prkey, sskey;
41 struct key *keyring; 68 struct key *key = cons->key, *authkey = cons->authkey, *keyring;
42 char *argv[9], *envp[3], uid_str[12], gid_str[12]; 69 char *argv[9], *envp[3], uid_str[12], gid_str[12];
43 char key_str[12], keyring_str[3][12]; 70 char key_str[12], keyring_str[3][12];
44 char desc[20]; 71 char desc[20];
@@ -82,8 +109,7 @@ static int call_sbin_request_key(struct key *key,
82 rcu_read_lock(); 109 rcu_read_lock();
83 sskey = rcu_dereference(tsk->signal->session_keyring)->serial; 110 sskey = rcu_dereference(tsk->signal->session_keyring)->serial;
84 rcu_read_unlock(); 111 rcu_read_unlock();
85 } 112 } else {
86 else {
87 sskey = tsk->user->session_keyring->serial; 113 sskey = tsk->user->session_keyring->serial;
88 } 114 }
89 115
@@ -110,228 +136,77 @@ static int call_sbin_request_key(struct key *key,
110 /* do it */ 136 /* do it */
111 ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, 137 ret = call_usermodehelper_keys(argv[0], argv, envp, keyring,
112 UMH_WAIT_PROC); 138 UMH_WAIT_PROC);
139 kdebug("usermode -> 0x%x", ret);
140 if (ret >= 0) {
141 /* ret is the exit/wait code */
142 if (test_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags) ||
143 key_validate(key) < 0)
144 ret = -ENOKEY;
145 else
146 /* ignore any errors from userspace if the key was
147 * instantiated */
148 ret = 0;
149 }
113 150
114error_link: 151error_link:
115 key_put(keyring); 152 key_put(keyring);
116 153
117error_alloc: 154error_alloc:
118 kleave(" = %d", ret); 155 kleave(" = %d", ret);
156 complete_request_key(cons, ret);
119 return ret; 157 return ret;
158}
120 159
121} /* end call_sbin_request_key() */
122
123/*****************************************************************************/
124/* 160/*
125 * call out to userspace for the key 161 * call out to userspace for key construction
126 * - called with the construction sem held, but the sem is dropped here
127 * - we ignore program failure and go on key status instead 162 * - we ignore program failure and go on key status instead
128 */ 163 */
129static struct key *__request_key_construction(struct key_type *type, 164static int construct_key(struct key *key, const char *callout_info, void *aux)
130 const char *description,
131 const char *callout_info,
132 void *aux,
133 unsigned long flags)
134{ 165{
166 struct key_construction *cons;
135 request_key_actor_t actor; 167 request_key_actor_t actor;
136 struct key_construction cons; 168 struct key *authkey;
137 struct timespec now; 169 int ret;
138 struct key *key, *authkey;
139 int ret, negated;
140 170
141 kenter("%s,%s,%s,%lx", type->name, description, callout_info, flags); 171 kenter("%d,%s,%p", key->serial, callout_info, aux);
142 172
143 /* create a key and add it to the queue */ 173 cons = kmalloc(sizeof(*cons), GFP_KERNEL);
144 key = key_alloc(type, description, 174 if (!cons)
145 current->fsuid, current->fsgid, current, KEY_POS_ALL, 175 return -ENOMEM;
146 flags);
147 if (IS_ERR(key))
148 goto alloc_failed;
149
150 set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
151
152 cons.key = key;
153 list_add_tail(&cons.link, &key->user->consq);
154
155 /* we drop the construction sem here on behalf of the caller */
156 up_write(&key_construction_sem);
157 176
158 /* allocate an authorisation key */ 177 /* allocate an authorisation key */
159 authkey = request_key_auth_new(key, callout_info); 178 authkey = request_key_auth_new(key, callout_info);
160 if (IS_ERR(authkey)) { 179 if (IS_ERR(authkey)) {
180 kfree(cons);
161 ret = PTR_ERR(authkey); 181 ret = PTR_ERR(authkey);
162 authkey = NULL; 182 authkey = NULL;
163 goto alloc_authkey_failed; 183 } else {
164 } 184 cons->authkey = key_get(authkey);
165 185 cons->key = key_get(key);
166 /* make the call */ 186
167 actor = call_sbin_request_key; 187 /* make the call */
168 if (type->request_key) 188 actor = call_sbin_request_key;
169 actor = type->request_key; 189 if (key->type->request_key)
170 ret = actor(key, authkey, "create", aux); 190 actor = key->type->request_key;
171 if (ret < 0) 191
172 goto request_failed; 192 ret = actor(cons, "create", aux);
173 193
174 /* if the key wasn't instantiated, then we want to give an error */ 194 /* check that the actor called complete_request_key() prior to
175 ret = -ENOKEY; 195 * returning an error */
176 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) 196 WARN_ON(ret < 0 &&
177 goto request_failed; 197 !test_bit(KEY_FLAG_REVOKED, &authkey->flags));
178 198 key_put(authkey);
179 key_revoke(authkey);
180 key_put(authkey);
181
182 down_write(&key_construction_sem);
183 list_del(&cons.link);
184 up_write(&key_construction_sem);
185
186 /* also give an error if the key was negatively instantiated */
187check_not_negative:
188 if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
189 key_put(key);
190 key = ERR_PTR(-ENOKEY);
191 }
192
193out:
194 kleave(" = %p", key);
195 return key;
196
197request_failed:
198 key_revoke(authkey);
199 key_put(authkey);
200
201alloc_authkey_failed:
202 /* it wasn't instantiated
203 * - remove from construction queue
204 * - mark the key as dead
205 */
206 negated = 0;
207 down_write(&key_construction_sem);
208
209 list_del(&cons.link);
210
211 /* check it didn't get instantiated between the check and the down */
212 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
213 set_bit(KEY_FLAG_NEGATIVE, &key->flags);
214 set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
215 negated = 1;
216 }
217
218 clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
219
220 up_write(&key_construction_sem);
221
222 if (!negated)
223 goto check_not_negative; /* surprisingly, the key got
224 * instantiated */
225
226 /* set the timeout and store in the session keyring if we can */
227 now = current_kernel_time();
228 key->expiry = now.tv_sec + key_negative_timeout;
229
230 if (current->signal->session_keyring) {
231 struct key *keyring;
232
233 rcu_read_lock();
234 keyring = rcu_dereference(current->signal->session_keyring);
235 atomic_inc(&keyring->usage);
236 rcu_read_unlock();
237
238 key_link(keyring, key);
239 key_put(keyring);
240 }
241
242 key_put(key);
243
244 /* notify anyone who was waiting */
245 wake_up_all(&request_key_conswq);
246
247 key = ERR_PTR(ret);
248 goto out;
249
250alloc_failed:
251 up_write(&key_construction_sem);
252 goto out;
253
254} /* end __request_key_construction() */
255
256/*****************************************************************************/
257/*
258 * call out to userspace to request the key
259 * - we check the construction queue first to see if an appropriate key is
260 * already being constructed by userspace
261 */
262static struct key *request_key_construction(struct key_type *type,
263 const char *description,
264 const char *callout_info,
265 void *aux,
266 struct key_user *user,
267 unsigned long flags)
268{
269 struct key_construction *pcons;
270 struct key *key, *ckey;
271
272 DECLARE_WAITQUEUE(myself, current);
273
274 kenter("%s,%s,{%d},%s,%lx",
275 type->name, description, user->uid, callout_info, flags);
276
277 /* see if there's such a key under construction already */
278 down_write(&key_construction_sem);
279
280 list_for_each_entry(pcons, &user->consq, link) {
281 ckey = pcons->key;
282
283 if (ckey->type != type)
284 continue;
285
286 if (type->match(ckey, description))
287 goto found_key_under_construction;
288 } 199 }
289 200
290 /* see about getting userspace to construct the key */ 201 kleave(" = %d", ret);
291 key = __request_key_construction(type, description, callout_info, aux, 202 return ret;
292 flags); 203}
293 error:
294 kleave(" = %p", key);
295 return key;
296
297 /* someone else has the same key under construction
298 * - we want to keep an eye on their key
299 */
300 found_key_under_construction:
301 atomic_inc(&ckey->usage);
302 up_write(&key_construction_sem);
303
304 /* wait for the key to be completed one way or another */
305 add_wait_queue(&request_key_conswq, &myself);
306
307 for (;;) {
308 set_current_state(TASK_INTERRUPTIBLE);
309 if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags))
310 break;
311 if (signal_pending(current))
312 break;
313 schedule();
314 }
315
316 set_current_state(TASK_RUNNING);
317 remove_wait_queue(&request_key_conswq, &myself);
318
319 /* we'll need to search this process's keyrings to see if the key is
320 * now there since we can't automatically assume it's also available
321 * there */
322 key_put(ckey);
323 ckey = NULL;
324
325 key = NULL; /* request a retry */
326 goto error;
327
328} /* end request_key_construction() */
329 204
330/*****************************************************************************/
331/* 205/*
332 * link a freshly minted key to an appropriate destination keyring 206 * link a key to the appropriate destination keyring
207 * - the caller must hold a write lock on the destination keyring
333 */ 208 */
334static void request_key_link(struct key *key, struct key *dest_keyring) 209static void construct_key_make_link(struct key *key, struct key *dest_keyring)
335{ 210{
336 struct task_struct *tsk = current; 211 struct task_struct *tsk = current;
337 struct key *drop = NULL; 212 struct key *drop = NULL;
@@ -363,11 +238,11 @@ static void request_key_link(struct key *key, struct key *dest_keyring)
363 break; 238 break;
364 239
365 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: 240 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
366 dest_keyring = current->user->session_keyring; 241 dest_keyring = tsk->user->session_keyring;
367 break; 242 break;
368 243
369 case KEY_REQKEY_DEFL_USER_KEYRING: 244 case KEY_REQKEY_DEFL_USER_KEYRING:
370 dest_keyring = current->user->uid_keyring; 245 dest_keyring = tsk->user->uid_keyring;
371 break; 246 break;
372 247
373 case KEY_REQKEY_DEFL_GROUP_KEYRING: 248 case KEY_REQKEY_DEFL_GROUP_KEYRING:
@@ -377,15 +252,115 @@ static void request_key_link(struct key *key, struct key *dest_keyring)
377 } 252 }
378 253
379 /* and attach the key to it */ 254 /* and attach the key to it */
380 key_link(dest_keyring, key); 255 __key_link(dest_keyring, key);
381
382 key_put(drop); 256 key_put(drop);
383
384 kleave(""); 257 kleave("");
258}
385 259
386} /* end request_key_link() */ 260/*
261 * allocate a new key in under-construction state and attempt to link it in to
262 * the requested place
263 * - may return a key that's already under construction instead
264 */
265static int construct_alloc_key(struct key_type *type,
266 const char *description,
267 struct key *dest_keyring,
268 unsigned long flags,
269 struct key_user *user,
270 struct key **_key)
271{
272 struct key *key;
273 key_ref_t key_ref;
274
275 kenter("%s,%s,,,", type->name, description);
276
277 mutex_lock(&user->cons_lock);
278
279 key = key_alloc(type, description,
280 current->fsuid, current->fsgid, current, KEY_POS_ALL,
281 flags);
282 if (IS_ERR(key))
283 goto alloc_failed;
284
285 set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
286
287 if (dest_keyring)
288 down_write(&dest_keyring->sem);
289
290 /* attach the key to the destination keyring under lock, but we do need
291 * to do another check just in case someone beat us to it whilst we
292 * waited for locks */
293 mutex_lock(&key_construction_mutex);
294
295 key_ref = search_process_keyrings(type, description, type->match,
296 current);
297 if (!IS_ERR(key_ref))
298 goto key_already_present;
299
300 if (dest_keyring)
301 construct_key_make_link(key, dest_keyring);
302
303 mutex_unlock(&key_construction_mutex);
304 if (dest_keyring)
305 up_write(&dest_keyring->sem);
306 mutex_unlock(&user->cons_lock);
307 *_key = key;
308 kleave(" = 0 [%d]", key_serial(key));
309 return 0;
310
311key_already_present:
312 mutex_unlock(&key_construction_mutex);
313 if (dest_keyring)
314 up_write(&dest_keyring->sem);
315 mutex_unlock(&user->cons_lock);
316 key_put(key);
317 *_key = key = key_ref_to_ptr(key_ref);
318 kleave(" = -EINPROGRESS [%d]", key_serial(key));
319 return -EINPROGRESS;
320
321alloc_failed:
322 mutex_unlock(&user->cons_lock);
323 *_key = NULL;
324 kleave(" = %ld", PTR_ERR(key));
325 return PTR_ERR(key);
326}
327
328/*
329 * commence key construction
330 */
331static struct key *construct_key_and_link(struct key_type *type,
332 const char *description,
333 const char *callout_info,
334 void *aux,
335 struct key *dest_keyring,
336 unsigned long flags)
337{
338 struct key_user *user;
339 struct key *key;
340 int ret;
341
342 user = key_user_lookup(current->fsuid);
343 if (!user)
344 return ERR_PTR(-ENOMEM);
345
346 ret = construct_alloc_key(type, description, dest_keyring, flags, user,
347 &key);
348 key_user_put(user);
349
350 if (ret == 0) {
351 ret = construct_key(key, callout_info, aux);
352 if (ret < 0)
353 goto construction_failed;
354 }
355
356 return key;
357
358construction_failed:
359 key_negate_and_link(key, key_negative_timeout, NULL, NULL);
360 key_put(key);
361 return ERR_PTR(ret);
362}
387 363
388/*****************************************************************************/
389/* 364/*
390 * request a key 365 * request a key
391 * - search the process's keyrings 366 * - search the process's keyrings
@@ -400,7 +375,6 @@ struct key *request_key_and_link(struct key_type *type,
400 struct key *dest_keyring, 375 struct key *dest_keyring,
401 unsigned long flags) 376 unsigned long flags)
402{ 377{
403 struct key_user *user;
404 struct key *key; 378 struct key *key;
405 key_ref_t key_ref; 379 key_ref_t key_ref;
406 380
@@ -412,112 +386,124 @@ struct key *request_key_and_link(struct key_type *type,
412 key_ref = search_process_keyrings(type, description, type->match, 386 key_ref = search_process_keyrings(type, description, type->match,
413 current); 387 current);
414 388
415 kdebug("search 1: %p", key_ref);
416
417 if (!IS_ERR(key_ref)) { 389 if (!IS_ERR(key_ref)) {
418 key = key_ref_to_ptr(key_ref); 390 key = key_ref_to_ptr(key_ref);
419 } 391 } else if (PTR_ERR(key_ref) != -EAGAIN) {
420 else if (PTR_ERR(key_ref) != -EAGAIN) {
421 key = ERR_PTR(PTR_ERR(key_ref)); 392 key = ERR_PTR(PTR_ERR(key_ref));
422 } 393 } else {
423 else {
424 /* the search failed, but the keyrings were searchable, so we 394 /* the search failed, but the keyrings were searchable, so we
425 * should consult userspace if we can */ 395 * should consult userspace if we can */
426 key = ERR_PTR(-ENOKEY); 396 key = ERR_PTR(-ENOKEY);
427 if (!callout_info) 397 if (!callout_info)
428 goto error; 398 goto error;
429 399
430 /* - get hold of the user's construction queue */ 400 key = construct_key_and_link(type, description, callout_info,
431 user = key_user_lookup(current->fsuid); 401 aux, dest_keyring, flags);
432 if (!user)
433 goto nomem;
434
435 for (;;) {
436 if (signal_pending(current))
437 goto interrupted;
438
439 /* ask userspace (returns NULL if it waited on a key
440 * being constructed) */
441 key = request_key_construction(type, description,
442 callout_info, aux,
443 user, flags);
444 if (key)
445 break;
446
447 /* someone else made the key we want, so we need to
448 * search again as it might now be available to us */
449 key_ref = search_process_keyrings(type, description,
450 type->match,
451 current);
452
453 kdebug("search 2: %p", key_ref);
454
455 if (!IS_ERR(key_ref)) {
456 key = key_ref_to_ptr(key_ref);
457 break;
458 }
459
460 if (PTR_ERR(key_ref) != -EAGAIN) {
461 key = ERR_PTR(PTR_ERR(key_ref));
462 break;
463 }
464 }
465
466 key_user_put(user);
467
468 /* link the new key into the appropriate keyring */
469 if (!IS_ERR(key))
470 request_key_link(key, dest_keyring);
471 } 402 }
472 403
473error: 404error:
474 kleave(" = %p", key); 405 kleave(" = %p", key);
475 return key; 406 return key;
407}
476 408
477nomem: 409/*
478 key = ERR_PTR(-ENOMEM); 410 * wait for construction of a key to complete
479 goto error; 411 */
480 412int wait_for_key_construction(struct key *key, bool intr)
481interrupted: 413{
482 key_user_put(user); 414 int ret;
483 key = ERR_PTR(-EINTR);
484 goto error;
485 415
486} /* end request_key_and_link() */ 416 ret = wait_on_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT,
417 intr ? key_wait_bit_intr : key_wait_bit,
418 intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
419 if (ret < 0)
420 return ret;
421 return key_validate(key);
422}
423EXPORT_SYMBOL(wait_for_key_construction);
487 424
488/*****************************************************************************/
489/* 425/*
490 * request a key 426 * request a key
491 * - search the process's keyrings 427 * - search the process's keyrings
492 * - check the list of keys being created or updated 428 * - check the list of keys being created or updated
493 * - call out to userspace for a key if supplementary info was provided 429 * - call out to userspace for a key if supplementary info was provided
430 * - waits uninterruptible for creation to complete
494 */ 431 */
495struct key *request_key(struct key_type *type, 432struct key *request_key(struct key_type *type,
496 const char *description, 433 const char *description,
497 const char *callout_info) 434 const char *callout_info)
498{ 435{
499 return request_key_and_link(type, description, callout_info, NULL, 436 struct key *key;
500 NULL, KEY_ALLOC_IN_QUOTA); 437 int ret;
501 438
502} /* end request_key() */ 439 key = request_key_and_link(type, description, callout_info, NULL,
503 440 NULL, KEY_ALLOC_IN_QUOTA);
441 if (!IS_ERR(key)) {
442 ret = wait_for_key_construction(key, false);
443 if (ret < 0) {
444 key_put(key);
445 return ERR_PTR(ret);
446 }
447 }
448 return key;
449}
504EXPORT_SYMBOL(request_key); 450EXPORT_SYMBOL(request_key);
505 451
506/*****************************************************************************/
507/* 452/*
508 * request a key with auxiliary data for the upcaller 453 * request a key with auxiliary data for the upcaller
509 * - search the process's keyrings 454 * - search the process's keyrings
510 * - check the list of keys being created or updated 455 * - check the list of keys being created or updated
511 * - call out to userspace for a key if supplementary info was provided 456 * - call out to userspace for a key if supplementary info was provided
457 * - waits uninterruptible for creation to complete
512 */ 458 */
513struct key *request_key_with_auxdata(struct key_type *type, 459struct key *request_key_with_auxdata(struct key_type *type,
514 const char *description, 460 const char *description,
515 const char *callout_info, 461 const char *callout_info,
516 void *aux) 462 void *aux)
517{ 463{
518 return request_key_and_link(type, description, callout_info, aux, 464 struct key *key;
519 NULL, KEY_ALLOC_IN_QUOTA); 465 int ret;
466
467 key = request_key_and_link(type, description, callout_info, aux,
468 NULL, KEY_ALLOC_IN_QUOTA);
469 if (!IS_ERR(key)) {
470 ret = wait_for_key_construction(key, false);
471 if (ret < 0) {
472 key_put(key);
473 return ERR_PTR(ret);
474 }
475 }
476 return key;
477}
478EXPORT_SYMBOL(request_key_with_auxdata);
520 479
521} /* end request_key_with_auxdata() */ 480/*
481 * request a key (allow async construction)
482 * - search the process's keyrings
483 * - check the list of keys being created or updated
484 * - call out to userspace for a key if supplementary info was provided
485 */
486struct key *request_key_async(struct key_type *type,
487 const char *description,
488 const char *callout_info)
489{
490 return request_key_and_link(type, description, callout_info, NULL,
491 NULL, KEY_ALLOC_IN_QUOTA);
492}
493EXPORT_SYMBOL(request_key_async);
522 494
523EXPORT_SYMBOL(request_key_with_auxdata); 495/*
496 * request a key with auxiliary data for the upcaller (allow async construction)
497 * - search the process's keyrings
498 * - check the list of keys being created or updated
499 * - call out to userspace for a key if supplementary info was provided
500 */
501struct key *request_key_async_with_auxdata(struct key_type *type,
502 const char *description,
503 const char *callout_info,
504 void *aux)
505{
506 return request_key_and_link(type, description, callout_info, aux,
507 NULL, KEY_ALLOC_IN_QUOTA);
508}
509EXPORT_SYMBOL(request_key_async_with_auxdata);
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index cbf58a91b00a..510f7be73a2d 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -127,6 +127,7 @@ static void request_key_auth_destroy(struct key *key)
127 } 127 }
128 128
129 key_put(rka->target_key); 129 key_put(rka->target_key);
130 kfree(rka->callout_info);
130 kfree(rka); 131 kfree(rka);
131 132
132} /* end request_key_auth_destroy() */ 133} /* end request_key_auth_destroy() */
@@ -151,6 +152,12 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
151 kleave(" = -ENOMEM"); 152 kleave(" = -ENOMEM");
152 return ERR_PTR(-ENOMEM); 153 return ERR_PTR(-ENOMEM);
153 } 154 }
155 rka->callout_info = kmalloc(strlen(callout_info) + 1, GFP_KERNEL);
156 if (!rka->callout_info) {
157 kleave(" = -ENOMEM");
158 kfree(rka);
159 return ERR_PTR(-ENOMEM);
160 }
154 161
155 /* see if the calling process is already servicing the key request of 162 /* see if the calling process is already servicing the key request of
156 * another process */ 163 * another process */
@@ -179,7 +186,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
179 } 186 }
180 187
181 rka->target_key = key_get(target); 188 rka->target_key = key_get(target);
182 rka->callout_info = callout_info; 189 strcpy(rka->callout_info, callout_info);
183 190
184 /* allocate the auth key */ 191 /* allocate the auth key */
185 sprintf(desc, "%x", target->serial); 192 sprintf(desc, "%x", target->serial);
@@ -203,6 +210,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
203 210
204auth_key_revoked: 211auth_key_revoked:
205 up_read(&current->request_key_auth->sem); 212 up_read(&current->request_key_auth->sem);
213 kfree(rka->callout_info);
206 kfree(rka); 214 kfree(rka);
207 kleave("= -EKEYREVOKED"); 215 kleave("= -EKEYREVOKED");
208 return ERR_PTR(-EKEYREVOKED); 216 return ERR_PTR(-EKEYREVOKED);
@@ -212,6 +220,7 @@ error_inst:
212 key_put(authkey); 220 key_put(authkey);
213error_alloc: 221error_alloc:
214 key_put(rka->target_key); 222 key_put(rka->target_key);
223 kfree(rka->callout_info);
215 kfree(rka); 224 kfree(rka);
216 kleave("= %d", ret); 225 kleave("= %d", ret);
217 return ERR_PTR(ret); 226 return ERR_PTR(ret);