[IA64] Minimize per_cpu reservations.
[linux-2.6] / security / keys / request_key.c
1 /* Request a key from userspace
2  *
3  * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved.
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  * See Documentation/keys-request-key.txt
12  */
13
14 #include <linux/module.h>
15 #include <linux/sched.h>
16 #include <linux/kmod.h>
17 #include <linux/err.h>
18 #include <linux/keyctl.h>
19 #include "internal.h"
20
21 /*
22  * wait_on_bit() sleep function for uninterruptible waiting
23  */
24 static 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  */
33 static 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  */
42 void complete_request_key(struct key_construction *cons, int error)
43 {
44         kenter("{%d,%d},%d", cons->key->serial, cons->authkey->serial, error);
45
46         if (error < 0)
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 }
56 EXPORT_SYMBOL(complete_request_key);
57
58 /*
59  * request userspace finish the construction of a key
60  * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>"
61  */
62 static int call_sbin_request_key(struct key_construction *cons,
63                                  const char *op,
64                                  void *aux)
65 {
66         struct task_struct *tsk = current;
67         key_serial_t prkey, sskey;
68         struct key *key = cons->key, *authkey = cons->authkey, *keyring;
69         char *argv[9], *envp[3], uid_str[12], gid_str[12];
70         char key_str[12], keyring_str[3][12];
71         char desc[20];
72         int ret, i;
73
74         kenter("{%d},{%d},%s", key->serial, authkey->serial, op);
75
76         /* allocate a new session keyring */
77         sprintf(desc, "_req.%u", key->serial);
78
79         keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current,
80                                 KEY_ALLOC_QUOTA_OVERRUN, NULL);
81         if (IS_ERR(keyring)) {
82                 ret = PTR_ERR(keyring);
83                 goto error_alloc;
84         }
85
86         /* attach the auth key to the session keyring */
87         ret = __key_link(keyring, authkey);
88         if (ret < 0)
89                 goto error_link;
90
91         /* record the UID and GID */
92         sprintf(uid_str, "%d", current->fsuid);
93         sprintf(gid_str, "%d", current->fsgid);
94
95         /* we say which key is under construction */
96         sprintf(key_str, "%d", key->serial);
97
98         /* we specify the process's default keyrings */
99         sprintf(keyring_str[0], "%d",
100                 tsk->thread_keyring ? tsk->thread_keyring->serial : 0);
101
102         prkey = 0;
103         if (tsk->signal->process_keyring)
104                 prkey = tsk->signal->process_keyring->serial;
105
106         sprintf(keyring_str[1], "%d", prkey);
107
108         if (tsk->signal->session_keyring) {
109                 rcu_read_lock();
110                 sskey = rcu_dereference(tsk->signal->session_keyring)->serial;
111                 rcu_read_unlock();
112         } else {
113                 sskey = tsk->user->session_keyring->serial;
114         }
115
116         sprintf(keyring_str[2], "%d", sskey);
117
118         /* set up a minimal environment */
119         i = 0;
120         envp[i++] = "HOME=/";
121         envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
122         envp[i] = NULL;
123
124         /* set up the argument list */
125         i = 0;
126         argv[i++] = "/sbin/request-key";
127         argv[i++] = (char *) op;
128         argv[i++] = key_str;
129         argv[i++] = uid_str;
130         argv[i++] = gid_str;
131         argv[i++] = keyring_str[0];
132         argv[i++] = keyring_str[1];
133         argv[i++] = keyring_str[2];
134         argv[i] = NULL;
135
136         /* do it */
137         ret = call_usermodehelper_keys(argv[0], argv, envp, keyring,
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         }
150
151 error_link:
152         key_put(keyring);
153
154 error_alloc:
155         kleave(" = %d", ret);
156         complete_request_key(cons, ret);
157         return ret;
158 }
159
160 /*
161  * call out to userspace for key construction
162  * - we ignore program failure and go on key status instead
163  */
164 static int construct_key(struct key *key, const char *callout_info, void *aux)
165 {
166         struct key_construction *cons;
167         request_key_actor_t actor;
168         struct key *authkey;
169         int ret;
170
171         kenter("%d,%s,%p", key->serial, callout_info, aux);
172
173         cons = kmalloc(sizeof(*cons), GFP_KERNEL);
174         if (!cons)
175                 return -ENOMEM;
176
177         /* allocate an authorisation key */
178         authkey = request_key_auth_new(key, callout_info);
179         if (IS_ERR(authkey)) {
180                 kfree(cons);
181                 ret = PTR_ERR(authkey);
182                 authkey = NULL;
183         } else {
184                 cons->authkey = key_get(authkey);
185                 cons->key = key_get(key);
186
187                 /* make the call */
188                 actor = call_sbin_request_key;
189                 if (key->type->request_key)
190                         actor = key->type->request_key;
191
192                 ret = actor(cons, "create", aux);
193
194                 /* check that the actor called complete_request_key() prior to
195                  * returning an error */
196                 WARN_ON(ret < 0 &&
197                         !test_bit(KEY_FLAG_REVOKED, &authkey->flags));
198                 key_put(authkey);
199         }
200
201         kleave(" = %d", ret);
202         return ret;
203 }
204
205 /*
206  * link a key to the appropriate destination keyring
207  * - the caller must hold a write lock on the destination keyring
208  */
209 static void construct_key_make_link(struct key *key, struct key *dest_keyring)
210 {
211         struct task_struct *tsk = current;
212         struct key *drop = NULL;
213
214         kenter("{%d},%p", key->serial, dest_keyring);
215
216         /* find the appropriate keyring */
217         if (!dest_keyring) {
218                 switch (tsk->jit_keyring) {
219                 case KEY_REQKEY_DEFL_DEFAULT:
220                 case KEY_REQKEY_DEFL_THREAD_KEYRING:
221                         dest_keyring = tsk->thread_keyring;
222                         if (dest_keyring)
223                                 break;
224
225                 case KEY_REQKEY_DEFL_PROCESS_KEYRING:
226                         dest_keyring = tsk->signal->process_keyring;
227                         if (dest_keyring)
228                                 break;
229
230                 case KEY_REQKEY_DEFL_SESSION_KEYRING:
231                         rcu_read_lock();
232                         dest_keyring = key_get(
233                                 rcu_dereference(tsk->signal->session_keyring));
234                         rcu_read_unlock();
235                         drop = dest_keyring;
236
237                         if (dest_keyring)
238                                 break;
239
240                 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
241                         dest_keyring = tsk->user->session_keyring;
242                         break;
243
244                 case KEY_REQKEY_DEFL_USER_KEYRING:
245                         dest_keyring = tsk->user->uid_keyring;
246                         break;
247
248                 case KEY_REQKEY_DEFL_GROUP_KEYRING:
249                 default:
250                         BUG();
251                 }
252         }
253
254         /* and attach the key to it */
255         __key_link(dest_keyring, key);
256         key_put(drop);
257         kleave("");
258 }
259
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  */
265 static 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
311 key_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
321 alloc_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  */
331 static 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
358 construction_failed:
359         key_negate_and_link(key, key_negative_timeout, NULL, NULL);
360         key_put(key);
361         return ERR_PTR(ret);
362 }
363
364 /*
365  * request a key
366  * - search the process's keyrings
367  * - check the list of keys being created or updated
368  * - call out to userspace for a key if supplementary info was provided
369  * - cache the key in an appropriate keyring
370  */
371 struct key *request_key_and_link(struct key_type *type,
372                                  const char *description,
373                                  const char *callout_info,
374                                  void *aux,
375                                  struct key *dest_keyring,
376                                  unsigned long flags)
377 {
378         struct key *key;
379         key_ref_t key_ref;
380
381         kenter("%s,%s,%s,%p,%p,%lx",
382                type->name, description, callout_info, aux,
383                dest_keyring, flags);
384
385         /* search all the process keyrings for a key */
386         key_ref = search_process_keyrings(type, description, type->match,
387                                           current);
388
389         if (!IS_ERR(key_ref)) {
390                 key = key_ref_to_ptr(key_ref);
391         } else if (PTR_ERR(key_ref) != -EAGAIN) {
392                 key = ERR_CAST(key_ref);
393         } else  {
394                 /* the search failed, but the keyrings were searchable, so we
395                  * should consult userspace if we can */
396                 key = ERR_PTR(-ENOKEY);
397                 if (!callout_info)
398                         goto error;
399
400                 key = construct_key_and_link(type, description, callout_info,
401                                              aux, dest_keyring, flags);
402         }
403
404 error:
405         kleave(" = %p", key);
406         return key;
407 }
408
409 /*
410  * wait for construction of a key to complete
411  */
412 int wait_for_key_construction(struct key *key, bool intr)
413 {
414         int ret;
415
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 }
423 EXPORT_SYMBOL(wait_for_key_construction);
424
425 /*
426  * request a key
427  * - search the process's keyrings
428  * - check the list of keys being created or updated
429  * - call out to userspace for a key if supplementary info was provided
430  * - waits uninterruptible for creation to complete
431  */
432 struct key *request_key(struct key_type *type,
433                         const char *description,
434                         const char *callout_info)
435 {
436         struct key *key;
437         int ret;
438
439         key = request_key_and_link(type, description, callout_info, NULL,
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 }
450 EXPORT_SYMBOL(request_key);
451
452 /*
453  * request a key with auxiliary data for the upcaller
454  * - search the process's keyrings
455  * - check the list of keys being created or updated
456  * - call out to userspace for a key if supplementary info was provided
457  * - waits uninterruptible for creation to complete
458  */
459 struct key *request_key_with_auxdata(struct key_type *type,
460                                      const char *description,
461                                      const char *callout_info,
462                                      void *aux)
463 {
464         struct key *key;
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 }
478 EXPORT_SYMBOL(request_key_with_auxdata);
479
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  */
486 struct 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 }
493 EXPORT_SYMBOL(request_key_async);
494
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  */
501 struct 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 }
509 EXPORT_SYMBOL(request_key_async_with_auxdata);