diff options
Diffstat (limited to 'security/keys/request_key.c')
| -rw-r--r-- | security/keys/request_key.c | 135 |
1 files changed, 82 insertions, 53 deletions
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index abea08f87fe2..0e04f72ef2d4 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | #include "internal.h" | 20 | #include "internal.h" |
| 21 | 21 | ||
| 22 | #define key_negative_timeout 60 /* default timeout on a negative key's existence */ | ||
| 23 | |||
| 22 | /* | 24 | /* |
| 23 | * wait_on_bit() sleep function for uninterruptible waiting | 25 | * wait_on_bit() sleep function for uninterruptible waiting |
| 24 | */ | 26 | */ |
| @@ -64,7 +66,7 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
| 64 | const char *op, | 66 | const char *op, |
| 65 | void *aux) | 67 | void *aux) |
| 66 | { | 68 | { |
| 67 | struct task_struct *tsk = current; | 69 | const struct cred *cred = current_cred(); |
| 68 | key_serial_t prkey, sskey; | 70 | key_serial_t prkey, sskey; |
| 69 | struct key *key = cons->key, *authkey = cons->authkey, *keyring; | 71 | struct key *key = cons->key, *authkey = cons->authkey, *keyring; |
| 70 | char *argv[9], *envp[3], uid_str[12], gid_str[12]; | 72 | char *argv[9], *envp[3], uid_str[12], gid_str[12]; |
| @@ -74,15 +76,17 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
| 74 | 76 | ||
| 75 | kenter("{%d},{%d},%s", key->serial, authkey->serial, op); | 77 | kenter("{%d},{%d},%s", key->serial, authkey->serial, op); |
| 76 | 78 | ||
| 77 | ret = install_user_keyrings(tsk); | 79 | ret = install_user_keyrings(); |
| 78 | if (ret < 0) | 80 | if (ret < 0) |
| 79 | goto error_alloc; | 81 | goto error_alloc; |
| 80 | 82 | ||
| 81 | /* allocate a new session keyring */ | 83 | /* allocate a new session keyring */ |
| 82 | sprintf(desc, "_req.%u", key->serial); | 84 | sprintf(desc, "_req.%u", key->serial); |
| 83 | 85 | ||
| 84 | keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current, | 86 | cred = get_current_cred(); |
| 87 | keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, | ||
| 85 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 88 | KEY_ALLOC_QUOTA_OVERRUN, NULL); |
| 89 | put_cred(cred); | ||
| 86 | if (IS_ERR(keyring)) { | 90 | if (IS_ERR(keyring)) { |
| 87 | ret = PTR_ERR(keyring); | 91 | ret = PTR_ERR(keyring); |
| 88 | goto error_alloc; | 92 | goto error_alloc; |
| @@ -94,29 +98,24 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
| 94 | goto error_link; | 98 | goto error_link; |
| 95 | 99 | ||
| 96 | /* record the UID and GID */ | 100 | /* record the UID and GID */ |
| 97 | sprintf(uid_str, "%d", current->fsuid); | 101 | sprintf(uid_str, "%d", cred->fsuid); |
| 98 | sprintf(gid_str, "%d", current->fsgid); | 102 | sprintf(gid_str, "%d", cred->fsgid); |
| 99 | 103 | ||
| 100 | /* we say which key is under construction */ | 104 | /* we say which key is under construction */ |
| 101 | sprintf(key_str, "%d", key->serial); | 105 | sprintf(key_str, "%d", key->serial); |
| 102 | 106 | ||
| 103 | /* we specify the process's default keyrings */ | 107 | /* we specify the process's default keyrings */ |
| 104 | sprintf(keyring_str[0], "%d", | 108 | sprintf(keyring_str[0], "%d", |
| 105 | tsk->thread_keyring ? tsk->thread_keyring->serial : 0); | 109 | cred->thread_keyring ? cred->thread_keyring->serial : 0); |
| 106 | 110 | ||
| 107 | prkey = 0; | 111 | prkey = 0; |
| 108 | if (tsk->signal->process_keyring) | 112 | if (cred->tgcred->process_keyring) |
| 109 | prkey = tsk->signal->process_keyring->serial; | 113 | prkey = cred->tgcred->process_keyring->serial; |
| 110 | |||
| 111 | sprintf(keyring_str[1], "%d", prkey); | ||
| 112 | 114 | ||
| 113 | if (tsk->signal->session_keyring) { | 115 | if (cred->tgcred->session_keyring) |
| 114 | rcu_read_lock(); | 116 | sskey = rcu_dereference(cred->tgcred->session_keyring)->serial; |
| 115 | sskey = rcu_dereference(tsk->signal->session_keyring)->serial; | 117 | else |
| 116 | rcu_read_unlock(); | 118 | sskey = cred->user->session_keyring->serial; |
| 117 | } else { | ||
| 118 | sskey = tsk->user->session_keyring->serial; | ||
| 119 | } | ||
| 120 | 119 | ||
| 121 | sprintf(keyring_str[2], "%d", sskey); | 120 | sprintf(keyring_str[2], "%d", sskey); |
| 122 | 121 | ||
| @@ -157,8 +156,8 @@ error_link: | |||
| 157 | key_put(keyring); | 156 | key_put(keyring); |
| 158 | 157 | ||
| 159 | error_alloc: | 158 | error_alloc: |
| 160 | kleave(" = %d", ret); | ||
| 161 | complete_request_key(cons, ret); | 159 | complete_request_key(cons, ret); |
| 160 | kleave(" = %d", ret); | ||
| 162 | return ret; | 161 | return ret; |
| 163 | } | 162 | } |
| 164 | 163 | ||
| @@ -167,7 +166,8 @@ error_alloc: | |||
| 167 | * - we ignore program failure and go on key status instead | 166 | * - we ignore program failure and go on key status instead |
| 168 | */ | 167 | */ |
| 169 | static int construct_key(struct key *key, const void *callout_info, | 168 | static int construct_key(struct key *key, const void *callout_info, |
| 170 | size_t callout_len, void *aux) | 169 | size_t callout_len, void *aux, |
| 170 | struct key *dest_keyring) | ||
| 171 | { | 171 | { |
| 172 | struct key_construction *cons; | 172 | struct key_construction *cons; |
| 173 | request_key_actor_t actor; | 173 | request_key_actor_t actor; |
| @@ -181,7 +181,8 @@ static int construct_key(struct key *key, const void *callout_info, | |||
| 181 | return -ENOMEM; | 181 | return -ENOMEM; |
| 182 | 182 | ||
| 183 | /* allocate an authorisation key */ | 183 | /* allocate an authorisation key */ |
| 184 | authkey = request_key_auth_new(key, callout_info, callout_len); | 184 | authkey = request_key_auth_new(key, callout_info, callout_len, |
| 185 | dest_keyring); | ||
| 185 | if (IS_ERR(authkey)) { | 186 | if (IS_ERR(authkey)) { |
| 186 | kfree(cons); | 187 | kfree(cons); |
| 187 | ret = PTR_ERR(authkey); | 188 | ret = PTR_ERR(authkey); |
| @@ -209,46 +210,67 @@ static int construct_key(struct key *key, const void *callout_info, | |||
| 209 | } | 210 | } |
| 210 | 211 | ||
| 211 | /* | 212 | /* |
| 212 | * link a key to the appropriate destination keyring | 213 | * get the appropriate destination keyring for the request |
| 213 | * - the caller must hold a write lock on the destination keyring | 214 | * - we return whatever keyring we select with an extra reference upon it which |
| 215 | * the caller must release | ||
| 214 | */ | 216 | */ |
| 215 | static void construct_key_make_link(struct key *key, struct key *dest_keyring) | 217 | static void construct_get_dest_keyring(struct key **_dest_keyring) |
| 216 | { | 218 | { |
| 217 | struct task_struct *tsk = current; | 219 | struct request_key_auth *rka; |
| 218 | struct key *drop = NULL; | 220 | const struct cred *cred = current_cred(); |
| 221 | struct key *dest_keyring = *_dest_keyring, *authkey; | ||
| 219 | 222 | ||
| 220 | kenter("{%d},%p", key->serial, dest_keyring); | 223 | kenter("%p", dest_keyring); |
| 221 | 224 | ||
| 222 | /* find the appropriate keyring */ | 225 | /* find the appropriate keyring */ |
| 223 | if (!dest_keyring) { | 226 | if (dest_keyring) { |
| 224 | switch (tsk->jit_keyring) { | 227 | /* the caller supplied one */ |
| 228 | key_get(dest_keyring); | ||
| 229 | } else { | ||
| 230 | /* use a default keyring; falling through the cases until we | ||
| 231 | * find one that we actually have */ | ||
| 232 | switch (cred->jit_keyring) { | ||
| 225 | case KEY_REQKEY_DEFL_DEFAULT: | 233 | case KEY_REQKEY_DEFL_DEFAULT: |
| 234 | case KEY_REQKEY_DEFL_REQUESTOR_KEYRING: | ||
| 235 | if (cred->request_key_auth) { | ||
| 236 | authkey = cred->request_key_auth; | ||
| 237 | down_read(&authkey->sem); | ||
| 238 | rka = authkey->payload.data; | ||
| 239 | if (!test_bit(KEY_FLAG_REVOKED, | ||
| 240 | &authkey->flags)) | ||
| 241 | dest_keyring = | ||
| 242 | key_get(rka->dest_keyring); | ||
| 243 | up_read(&authkey->sem); | ||
| 244 | if (dest_keyring) | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | |||
| 226 | case KEY_REQKEY_DEFL_THREAD_KEYRING: | 248 | case KEY_REQKEY_DEFL_THREAD_KEYRING: |
| 227 | dest_keyring = tsk->thread_keyring; | 249 | dest_keyring = key_get(cred->thread_keyring); |
| 228 | if (dest_keyring) | 250 | if (dest_keyring) |
| 229 | break; | 251 | break; |
| 230 | 252 | ||
| 231 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | 253 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: |
| 232 | dest_keyring = tsk->signal->process_keyring; | 254 | dest_keyring = key_get(cred->tgcred->process_keyring); |
| 233 | if (dest_keyring) | 255 | if (dest_keyring) |
| 234 | break; | 256 | break; |
| 235 | 257 | ||
| 236 | case KEY_REQKEY_DEFL_SESSION_KEYRING: | 258 | case KEY_REQKEY_DEFL_SESSION_KEYRING: |
| 237 | rcu_read_lock(); | 259 | rcu_read_lock(); |
| 238 | dest_keyring = key_get( | 260 | dest_keyring = key_get( |
| 239 | rcu_dereference(tsk->signal->session_keyring)); | 261 | rcu_dereference(cred->tgcred->session_keyring)); |
| 240 | rcu_read_unlock(); | 262 | rcu_read_unlock(); |
| 241 | drop = dest_keyring; | ||
| 242 | 263 | ||
| 243 | if (dest_keyring) | 264 | if (dest_keyring) |
| 244 | break; | 265 | break; |
| 245 | 266 | ||
| 246 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: | 267 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: |
| 247 | dest_keyring = tsk->user->session_keyring; | 268 | dest_keyring = |
| 269 | key_get(cred->user->session_keyring); | ||
| 248 | break; | 270 | break; |
| 249 | 271 | ||
| 250 | case KEY_REQKEY_DEFL_USER_KEYRING: | 272 | case KEY_REQKEY_DEFL_USER_KEYRING: |
| 251 | dest_keyring = tsk->user->uid_keyring; | 273 | dest_keyring = key_get(cred->user->uid_keyring); |
| 252 | break; | 274 | break; |
| 253 | 275 | ||
| 254 | case KEY_REQKEY_DEFL_GROUP_KEYRING: | 276 | case KEY_REQKEY_DEFL_GROUP_KEYRING: |
| @@ -257,10 +279,9 @@ static void construct_key_make_link(struct key *key, struct key *dest_keyring) | |||
| 257 | } | 279 | } |
| 258 | } | 280 | } |
| 259 | 281 | ||
| 260 | /* and attach the key to it */ | 282 | *_dest_keyring = dest_keyring; |
| 261 | __key_link(dest_keyring, key); | 283 | kleave(" [dk %d]", key_serial(dest_keyring)); |
| 262 | key_put(drop); | 284 | return; |
| 263 | kleave(""); | ||
| 264 | } | 285 | } |
| 265 | 286 | ||
| 266 | /* | 287 | /* |
| @@ -275,6 +296,7 @@ static int construct_alloc_key(struct key_type *type, | |||
| 275 | struct key_user *user, | 296 | struct key_user *user, |
| 276 | struct key **_key) | 297 | struct key **_key) |
| 277 | { | 298 | { |
| 299 | const struct cred *cred = current_cred(); | ||
| 278 | struct key *key; | 300 | struct key *key; |
| 279 | key_ref_t key_ref; | 301 | key_ref_t key_ref; |
| 280 | 302 | ||
| @@ -282,33 +304,28 @@ static int construct_alloc_key(struct key_type *type, | |||
| 282 | 304 | ||
| 283 | mutex_lock(&user->cons_lock); | 305 | mutex_lock(&user->cons_lock); |
| 284 | 306 | ||
| 285 | key = key_alloc(type, description, | 307 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, |
| 286 | current->fsuid, current->fsgid, current, KEY_POS_ALL, | 308 | KEY_POS_ALL, flags); |
| 287 | flags); | ||
| 288 | if (IS_ERR(key)) | 309 | if (IS_ERR(key)) |
| 289 | goto alloc_failed; | 310 | goto alloc_failed; |
| 290 | 311 | ||
| 291 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); | 312 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); |
| 292 | 313 | ||
| 293 | if (dest_keyring) | 314 | down_write(&dest_keyring->sem); |
| 294 | down_write(&dest_keyring->sem); | ||
| 295 | 315 | ||
| 296 | /* attach the key to the destination keyring under lock, but we do need | 316 | /* attach the key to the destination keyring under lock, but we do need |
| 297 | * to do another check just in case someone beat us to it whilst we | 317 | * to do another check just in case someone beat us to it whilst we |
| 298 | * waited for locks */ | 318 | * waited for locks */ |
| 299 | mutex_lock(&key_construction_mutex); | 319 | mutex_lock(&key_construction_mutex); |
| 300 | 320 | ||
| 301 | key_ref = search_process_keyrings(type, description, type->match, | 321 | key_ref = search_process_keyrings(type, description, type->match, cred); |
| 302 | current); | ||
| 303 | if (!IS_ERR(key_ref)) | 322 | if (!IS_ERR(key_ref)) |
| 304 | goto key_already_present; | 323 | goto key_already_present; |
| 305 | 324 | ||
| 306 | if (dest_keyring) | 325 | __key_link(dest_keyring, key); |
| 307 | construct_key_make_link(key, dest_keyring); | ||
| 308 | 326 | ||
| 309 | mutex_unlock(&key_construction_mutex); | 327 | mutex_unlock(&key_construction_mutex); |
| 310 | if (dest_keyring) | 328 | up_write(&dest_keyring->sem); |
| 311 | up_write(&dest_keyring->sem); | ||
| 312 | mutex_unlock(&user->cons_lock); | 329 | mutex_unlock(&user->cons_lock); |
| 313 | *_key = key; | 330 | *_key = key; |
| 314 | kleave(" = 0 [%d]", key_serial(key)); | 331 | kleave(" = 0 [%d]", key_serial(key)); |
| @@ -346,25 +363,36 @@ static struct key *construct_key_and_link(struct key_type *type, | |||
| 346 | struct key *key; | 363 | struct key *key; |
| 347 | int ret; | 364 | int ret; |
| 348 | 365 | ||
| 349 | user = key_user_lookup(current->fsuid); | 366 | kenter(""); |
| 367 | |||
| 368 | user = key_user_lookup(current_fsuid()); | ||
| 350 | if (!user) | 369 | if (!user) |
| 351 | return ERR_PTR(-ENOMEM); | 370 | return ERR_PTR(-ENOMEM); |
| 352 | 371 | ||
| 372 | construct_get_dest_keyring(&dest_keyring); | ||
| 373 | |||
| 353 | ret = construct_alloc_key(type, description, dest_keyring, flags, user, | 374 | ret = construct_alloc_key(type, description, dest_keyring, flags, user, |
| 354 | &key); | 375 | &key); |
| 355 | key_user_put(user); | 376 | key_user_put(user); |
| 356 | 377 | ||
| 357 | if (ret == 0) { | 378 | if (ret == 0) { |
| 358 | ret = construct_key(key, callout_info, callout_len, aux); | 379 | ret = construct_key(key, callout_info, callout_len, aux, |
| 359 | if (ret < 0) | 380 | dest_keyring); |
| 381 | if (ret < 0) { | ||
| 382 | kdebug("cons failed"); | ||
| 360 | goto construction_failed; | 383 | goto construction_failed; |
| 384 | } | ||
| 361 | } | 385 | } |
| 362 | 386 | ||
| 387 | key_put(dest_keyring); | ||
| 388 | kleave(" = key %d", key_serial(key)); | ||
| 363 | return key; | 389 | return key; |
| 364 | 390 | ||
| 365 | construction_failed: | 391 | construction_failed: |
| 366 | key_negate_and_link(key, key_negative_timeout, NULL, NULL); | 392 | key_negate_and_link(key, key_negative_timeout, NULL, NULL); |
| 367 | key_put(key); | 393 | key_put(key); |
| 394 | key_put(dest_keyring); | ||
| 395 | kleave(" = %d", ret); | ||
| 368 | return ERR_PTR(ret); | 396 | return ERR_PTR(ret); |
| 369 | } | 397 | } |
| 370 | 398 | ||
| @@ -383,6 +411,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
| 383 | struct key *dest_keyring, | 411 | struct key *dest_keyring, |
| 384 | unsigned long flags) | 412 | unsigned long flags) |
| 385 | { | 413 | { |
| 414 | const struct cred *cred = current_cred(); | ||
| 386 | struct key *key; | 415 | struct key *key; |
| 387 | key_ref_t key_ref; | 416 | key_ref_t key_ref; |
| 388 | 417 | ||
| @@ -392,7 +421,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
| 392 | 421 | ||
| 393 | /* search all the process keyrings for a key */ | 422 | /* search all the process keyrings for a key */ |
| 394 | key_ref = search_process_keyrings(type, description, type->match, | 423 | key_ref = search_process_keyrings(type, description, type->match, |
| 395 | current); | 424 | cred); |
| 396 | 425 | ||
| 397 | if (!IS_ERR(key_ref)) { | 426 | if (!IS_ERR(key_ref)) { |
| 398 | key = key_ref_to_ptr(key_ref); | 427 | key = key_ref_to_ptr(key_ref); |
