1/* request_key.c: request a key from userspace 2 * 3 * Copyright (C) 2004-6 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 21struct key_construction { 22 struct list_head link; /* link in construction queue */ 23 struct key *key; /* key being constructed */ 24}; 25 26/* when waiting for someone else's keys, you get added to this */ 27DECLARE_WAIT_QUEUE_HEAD(request_key_conswq); 28 29/*****************************************************************************/ 30/* 31 * request userspace finish the construction of a key 32 * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>" 33 */ 34static int call_sbin_request_key(struct key *key, 35 struct key *authkey, 36 const char *op, 37 void *aux) 38{ 39 struct task_struct *tsk = current; 40 key_serial_t prkey, sskey; 41 struct key *keyring; 42 char *argv[9], *envp[3], uid_str[12], gid_str[12]; 43 char key_str[12], keyring_str[3][12]; 44 char desc[20]; 45 int ret, i; 46 47 kenter("{%d},{%d},%s", key->serial, authkey->serial, op); 48 49 /* allocate a new session keyring */ 50 sprintf(desc, "_req.%u", key->serial); 51 52 keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current, 53 KEY_ALLOC_QUOTA_OVERRUN, NULL); 54 if (IS_ERR(keyring)) { 55 ret = PTR_ERR(keyring); 56 goto error_alloc; 57 } 58 59 /* attach the auth key to the session keyring */ 60 ret = __key_link(keyring, authkey); 61 if (ret < 0) 62 goto error_link; 63 64 /* record the UID and GID */ 65 sprintf(uid_str, "%d", current->fsuid); 66 sprintf(gid_str, "%d", current->fsgid); 67 68 /* we say which key is under construction */ 69 sprintf(key_str, "%d", key->serial); 70 71 /* we specify the process's default keyrings */ 72 sprintf(keyring_str[0], "%d", 73 tsk->thread_keyring ? tsk->thread_keyring->serial : 0); 74 75 prkey = 0; 76 if (tsk->signal->process_keyring) 77 prkey = tsk->signal->process_keyring->serial; 78 79 sprintf(keyring_str[1], "%d", prkey); 80 81 if (tsk->signal->session_keyring) { 82 rcu_read_lock(); 83 sskey = rcu_dereference(tsk->signal->session_keyring)->serial; 84 rcu_read_unlock(); 85 } 86 else { 87 sskey = tsk->user->session_keyring->serial; 88 } 89 90 sprintf(keyring_str[2], "%d", sskey); 91 92 /* set up a minimal environment */ 93 i = 0; 94 envp[i++] = "HOME=/"; 95 envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; 96 envp[i] = NULL; 97 98 /* set up the argument list */ 99 i = 0; 100 argv[i++] = "/sbin/request-key"; 101 argv[i++] = (char *) op; 102 argv[i++] = key_str; 103 argv[i++] = uid_str; 104 argv[i++] = gid_str; 105 argv[i++] = keyring_str[0]; 106 argv[i++] = keyring_str[1]; 107 argv[i++] = keyring_str[2]; 108 argv[i] = NULL; 109 110 /* do it */ 111 ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, 1); 112 113error_link: 114 key_put(keyring); 115 116error_alloc: 117 kleave(" = %d", ret); 118 return ret; 119 120} /* end call_sbin_request_key() */ 121 122/*****************************************************************************/ 123/* 124 * call out to userspace for the key 125 * - called with the construction sem held, but the sem is dropped here 126 * - we ignore program failure and go on key status instead 127 */ 128static struct key *__request_key_construction(struct key_type *type, 129 const char *description, 130 const char *callout_info, 131 void *aux, 132 unsigned long flags) 133{ 134 request_key_actor_t actor; 135 struct key_construction cons; 136 struct timespec now; 137 struct key *key, *authkey; 138 int ret, negated; 139 140 kenter("%s,%s,%s,%lx", type->name, description, callout_info, flags); 141 142 /* create a key and add it to the queue */ 143 key = key_alloc(type, description, 144 current->fsuid, current->fsgid, current, KEY_POS_ALL, 145 flags); 146 if (IS_ERR(key)) 147 goto alloc_failed; 148 149 set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); 150 151 cons.key = key; 152 list_add_tail(&cons.link, &key->user->consq); 153 154 /* we drop the construction sem here on behalf of the caller */ 155 up_write(&key_construction_sem); 156 157 /* allocate an authorisation key */ 158 authkey = request_key_auth_new(key, callout_info); 159 if (IS_ERR(authkey)) { 160 ret = PTR_ERR(authkey); 161 authkey = NULL; 162 goto alloc_authkey_failed; 163 } 164 165 /* make the call */ 166 actor = call_sbin_request_key; 167 if (type->request_key) 168 actor = type->request_key; 169 ret = actor(key, authkey, "create", aux); 170 if (ret < 0) 171 goto request_failed; 172 173 /* if the key wasn't instantiated, then we want to give an error */ 174 ret = -ENOKEY; 175 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) 176 goto request_failed; 177 178 key_revoke(authkey); 179 key_put(authkey); 180 181 down_write(&key_construction_sem); 182 list_del(&cons.link); 183 up_write(&key_construction_sem); 184 185 /* also give an error if the key was negatively instantiated */ 186check_not_negative: 187 if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { 188 key_put(key); 189 key = ERR_PTR(-ENOKEY); 190 } 191 192out: 193 kleave(" = %p", key); 194 return key; 195 196request_failed: 197 key_revoke(authkey); 198 key_put(authkey); 199 200alloc_authkey_failed: 201 /* it wasn't instantiated 202 * - remove from construction queue 203 * - mark the key as dead 204 */ 205 negated = 0; 206 down_write(&key_construction_sem); 207 208 list_del(&cons.link); 209 210 /* check it didn't get instantiated between the check and the down */ 211 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { 212 set_bit(KEY_FLAG_NEGATIVE, &key->flags); 213 set_bit(KEY_FLAG_INSTANTIATED, &key->flags); 214 negated = 1; 215 } 216 217 clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); 218 219 up_write(&key_construction_sem); 220 221 if (!negated) 222 goto check_not_negative; /* surprisingly, the key got 223 * instantiated */ 224 225 /* set the timeout and store in the session keyring if we can */ 226 now = current_kernel_time(); 227 key->expiry = now.tv_sec + key_negative_timeout; 228 229 if (current->signal->session_keyring) { 230 struct key *keyring; 231 232 rcu_read_lock(); 233 keyring = rcu_dereference(current->signal->session_keyring); 234 atomic_inc(&keyring->usage); 235 rcu_read_unlock(); 236 237 key_link(keyring, key); 238 key_put(keyring); 239 } 240 241 key_put(key); 242 243 /* notify anyone who was waiting */ 244 wake_up_all(&request_key_conswq); 245 246 key = ERR_PTR(ret); 247 goto out; 248 249alloc_failed: 250 up_write(&key_construction_sem); 251 goto out; 252 253} /* end __request_key_construction() */ 254 255/*****************************************************************************/ 256/* 257 * call out to userspace to request the key 258 * - we check the construction queue first to see if an appropriate key is 259 * already being constructed by userspace 260 */ 261static struct key *request_key_construction(struct key_type *type, 262 const char *description, 263 const char *callout_info, 264 void *aux, 265 struct key_user *user, 266 unsigned long flags) 267{ 268 struct key_construction *pcons; 269 struct key *key, *ckey; 270 271 DECLARE_WAITQUEUE(myself, current); 272 273 kenter("%s,%s,{%d},%s,%lx", 274 type->name, description, user->uid, callout_info, flags); 275 276 /* see if there's such a key under construction already */ 277 down_write(&key_construction_sem); 278 279 list_for_each_entry(pcons, &user->consq, link) { 280 ckey = pcons->key; 281 282 if (ckey->type != type) 283 continue; 284 285 if (type->match(ckey, description)) 286 goto found_key_under_construction; 287 } 288 289 /* see about getting userspace to construct the key */ 290 key = __request_key_construction(type, description, callout_info, aux, 291 flags); 292 error: 293 kleave(" = %p", key); 294 return key; 295 296 /* someone else has the same key under construction 297 * - we want to keep an eye on their key 298 */ 299 found_key_under_construction: 300 atomic_inc(&ckey->usage); 301 up_write(&key_construction_sem); 302 303 /* wait for the key to be completed one way or another */ 304 add_wait_queue(&request_key_conswq, &myself); 305 306 for (;;) { 307 set_current_state(TASK_INTERRUPTIBLE); 308 if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags)) 309 break; 310 if (signal_pending(current)) 311 break; 312 schedule(); 313 } 314 315 set_current_state(TASK_RUNNING); 316 remove_wait_queue(&request_key_conswq, &myself); 317 318 /* we'll need to search this process's keyrings to see if the key is 319 * now there since we can't automatically assume it's also available 320 * there */ 321 key_put(ckey); 322 ckey = NULL; 323 324 key = NULL; /* request a retry */ 325 goto error; 326 327} /* end request_key_construction() */ 328 329/*****************************************************************************/ 330/* 331 * link a freshly minted key to an appropriate destination keyring 332 */ 333static void request_key_link(struct key *key, struct key *dest_keyring) 334{ 335 struct task_struct *tsk = current; 336 struct key *drop = NULL; 337 338 kenter("{%d},%p", key->serial, dest_keyring); 339 340 /* find the appropriate keyring */ 341 if (!dest_keyring) { 342 switch (tsk->jit_keyring) { 343 case KEY_REQKEY_DEFL_DEFAULT: 344 case KEY_REQKEY_DEFL_THREAD_KEYRING: 345 dest_keyring = tsk->thread_keyring; 346 if (dest_keyring) 347 break; 348 349 case KEY_REQKEY_DEFL_PROCESS_KEYRING: 350 dest_keyring = tsk->signal->process_keyring; 351 if (dest_keyring) 352 break; 353 354 case KEY_REQKEY_DEFL_SESSION_KEYRING: 355 rcu_read_lock(); 356 dest_keyring = key_get( 357 rcu_dereference(tsk->signal->session_keyring)); 358 rcu_read_unlock(); 359 drop = dest_keyring; 360 361 if (dest_keyring) 362 break; 363 364 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: 365 dest_keyring = current->user->session_keyring; 366 break; 367 368 case KEY_REQKEY_DEFL_USER_KEYRING: 369 dest_keyring = current->user->uid_keyring; 370 break; 371 372 case KEY_REQKEY_DEFL_GROUP_KEYRING: 373 default: 374 BUG(); 375 } 376 } 377 378 /* and attach the key to it */ 379 key_link(dest_keyring, key); 380 381 key_put(drop); 382 383 kleave(""); 384 385} /* end request_key_link() */ 386 387/*****************************************************************************/ 388/* 389 * request a key 390 * - search the process's keyrings 391 * - check the list of keys being created or updated 392 * - call out to userspace for a key if supplementary info was provided 393 * - cache the key in an appropriate keyring 394 */ 395struct key *request_key_and_link(struct key_type *type, 396 const char *description, 397 const char *callout_info, 398 void *aux, 399 struct key *dest_keyring, 400 unsigned long flags) 401{ 402 struct key_user *user; 403 struct key *key; 404 key_ref_t key_ref; 405 406 kenter("%s,%s,%s,%p,%p,%lx", 407 type->name, description, callout_info, aux, 408 dest_keyring, flags); 409 410 /* search all the process keyrings for a key */ 411 key_ref = search_process_keyrings(type, description, type->match, 412 current); 413 414 kdebug("search 1: %p", key_ref); 415 416 if (!IS_ERR(key_ref)) { 417 key = key_ref_to_ptr(key_ref); 418 } 419 else if (PTR_ERR(key_ref) != -EAGAIN) { 420 key = ERR_PTR(PTR_ERR(key_ref)); 421 } 422 else { 423 /* the search failed, but the keyrings were searchable, so we 424 * should consult userspace if we can */ 425 key = ERR_PTR(-ENOKEY); 426 if (!callout_info) 427 goto error; 428 429 /* - get hold of the user's construction queue */ 430 user = key_user_lookup(current->fsuid); 431 if (!user) 432 goto nomem; 433 434 for (;;) { 435 if (signal_pending(current)) 436 goto interrupted; 437 438 /* ask userspace (returns NULL if it waited on a key 439 * being constructed) */ 440 key = request_key_construction(type, description, 441 callout_info, aux, 442 user, flags); 443 if (key) 444 break; 445 446 /* someone else made the key we want, so we need to 447 * search again as it might now be available to us */ 448 key_ref = search_process_keyrings(type, description, 449 type->match, 450 current); 451 452 kdebug("search 2: %p", key_ref); 453 454 if (!IS_ERR(key_ref)) { 455 key = key_ref_to_ptr(key_ref); 456 break; 457 } 458 459 if (PTR_ERR(key_ref) != -EAGAIN) { 460 key = ERR_PTR(PTR_ERR(key_ref)); 461 break; 462 } 463 } 464 465 key_user_put(user); 466 467 /* link the new key into the appropriate keyring */ 468 if (!IS_ERR(key)) 469 request_key_link(key, dest_keyring); 470 } 471 472error: 473 kleave(" = %p", key); 474 return key; 475 476nomem: 477 key = ERR_PTR(-ENOMEM); 478 goto error; 479 480interrupted: 481 key_user_put(user); 482 key = ERR_PTR(-EINTR); 483 goto error; 484 485} /* end request_key_and_link() */ 486 487/*****************************************************************************/ 488/* 489 * request a key 490 * - search the process's keyrings 491 * - check the list of keys being created or updated 492 * - call out to userspace for a key if supplementary info was provided 493 */ 494struct key *request_key(struct key_type *type, 495 const char *description, 496 const char *callout_info) 497{ 498 return request_key_and_link(type, description, callout_info, NULL, 499 NULL, KEY_ALLOC_IN_QUOTA); 500 501} /* end request_key() */ 502 503EXPORT_SYMBOL(request_key); 504 505/*****************************************************************************/ 506/* 507 * request a key with auxiliary data for the upcaller 508 * - search the process's keyrings 509 * - check the list of keys being created or updated 510 * - call out to userspace for a key if supplementary info was provided 511 */ 512struct key *request_key_with_auxdata(struct key_type *type, 513 const char *description, 514 const char *callout_info, 515 void *aux) 516{ 517 return request_key_and_link(type, description, callout_info, aux, 518 NULL, KEY_ALLOC_IN_QUOTA); 519 520} /* end request_key_with_auxdata() */ 521 522EXPORT_SYMBOL(request_key_with_auxdata); 523