aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-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);