diff options
Diffstat (limited to 'security/keys/process_keys.c')
-rw-r--r-- | security/keys/process_keys.c | 57 |
1 files changed, 34 insertions, 23 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 217a0bef3c82..4d9825f9962c 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -67,7 +67,8 @@ struct key root_session_keyring = { | |||
67 | /* | 67 | /* |
68 | * allocate the keyrings to be associated with a UID | 68 | * allocate the keyrings to be associated with a UID |
69 | */ | 69 | */ |
70 | int alloc_uid_keyring(struct user_struct *user) | 70 | int alloc_uid_keyring(struct user_struct *user, |
71 | struct task_struct *ctx) | ||
71 | { | 72 | { |
72 | struct key *uid_keyring, *session_keyring; | 73 | struct key *uid_keyring, *session_keyring; |
73 | char buf[20]; | 74 | char buf[20]; |
@@ -76,7 +77,7 @@ int alloc_uid_keyring(struct user_struct *user) | |||
76 | /* concoct a default session keyring */ | 77 | /* concoct a default session keyring */ |
77 | sprintf(buf, "_uid_ses.%u", user->uid); | 78 | sprintf(buf, "_uid_ses.%u", user->uid); |
78 | 79 | ||
79 | session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0, NULL); | 80 | session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, NULL); |
80 | if (IS_ERR(session_keyring)) { | 81 | if (IS_ERR(session_keyring)) { |
81 | ret = PTR_ERR(session_keyring); | 82 | ret = PTR_ERR(session_keyring); |
82 | goto error; | 83 | goto error; |
@@ -86,7 +87,7 @@ int alloc_uid_keyring(struct user_struct *user) | |||
86 | * keyring */ | 87 | * keyring */ |
87 | sprintf(buf, "_uid.%u", user->uid); | 88 | sprintf(buf, "_uid.%u", user->uid); |
88 | 89 | ||
89 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0, | 90 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, |
90 | session_keyring); | 91 | session_keyring); |
91 | if (IS_ERR(uid_keyring)) { | 92 | if (IS_ERR(uid_keyring)) { |
92 | key_put(session_keyring); | 93 | key_put(session_keyring); |
@@ -143,7 +144,7 @@ int install_thread_keyring(struct task_struct *tsk) | |||
143 | 144 | ||
144 | sprintf(buf, "_tid.%u", tsk->pid); | 145 | sprintf(buf, "_tid.%u", tsk->pid); |
145 | 146 | ||
146 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); | 147 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); |
147 | if (IS_ERR(keyring)) { | 148 | if (IS_ERR(keyring)) { |
148 | ret = PTR_ERR(keyring); | 149 | ret = PTR_ERR(keyring); |
149 | goto error; | 150 | goto error; |
@@ -177,7 +178,7 @@ int install_process_keyring(struct task_struct *tsk) | |||
177 | if (!tsk->signal->process_keyring) { | 178 | if (!tsk->signal->process_keyring) { |
178 | sprintf(buf, "_pid.%u", tsk->tgid); | 179 | sprintf(buf, "_pid.%u", tsk->tgid); |
179 | 180 | ||
180 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); | 181 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); |
181 | if (IS_ERR(keyring)) { | 182 | if (IS_ERR(keyring)) { |
182 | ret = PTR_ERR(keyring); | 183 | ret = PTR_ERR(keyring); |
183 | goto error; | 184 | goto error; |
@@ -217,7 +218,7 @@ static int install_session_keyring(struct task_struct *tsk, | |||
217 | if (!keyring) { | 218 | if (!keyring) { |
218 | sprintf(buf, "_ses.%u", tsk->tgid); | 219 | sprintf(buf, "_ses.%u", tsk->tgid); |
219 | 220 | ||
220 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); | 221 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); |
221 | if (IS_ERR(keyring)) | 222 | if (IS_ERR(keyring)) |
222 | return PTR_ERR(keyring); | 223 | return PTR_ERR(keyring); |
223 | } | 224 | } |
@@ -390,6 +391,8 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
390 | struct request_key_auth *rka; | 391 | struct request_key_auth *rka; |
391 | key_ref_t key_ref, ret, err; | 392 | key_ref_t key_ref, ret, err; |
392 | 393 | ||
394 | might_sleep(); | ||
395 | |||
393 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were | 396 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were |
394 | * searchable, but we failed to find a key or we found a negative key; | 397 | * searchable, but we failed to find a key or we found a negative key; |
395 | * otherwise we want to return a sample error (probably -EACCES) if | 398 | * otherwise we want to return a sample error (probably -EACCES) if |
@@ -495,27 +498,35 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
495 | */ | 498 | */ |
496 | if (context->request_key_auth && | 499 | if (context->request_key_auth && |
497 | context == current && | 500 | context == current && |
498 | type != &key_type_request_key_auth && | 501 | type != &key_type_request_key_auth |
499 | key_validate(context->request_key_auth) == 0 | ||
500 | ) { | 502 | ) { |
501 | rka = context->request_key_auth->payload.data; | 503 | /* defend against the auth key being revoked */ |
504 | down_read(&context->request_key_auth->sem); | ||
502 | 505 | ||
503 | key_ref = search_process_keyrings(type, description, match, | 506 | if (key_validate(context->request_key_auth) == 0) { |
504 | rka->context); | 507 | rka = context->request_key_auth->payload.data; |
505 | 508 | ||
506 | if (!IS_ERR(key_ref)) | 509 | key_ref = search_process_keyrings(type, description, |
507 | goto found; | 510 | match, rka->context); |
508 | 511 | ||
509 | switch (PTR_ERR(key_ref)) { | 512 | up_read(&context->request_key_auth->sem); |
510 | case -EAGAIN: /* no key */ | 513 | |
511 | if (ret) | 514 | if (!IS_ERR(key_ref)) |
515 | goto found; | ||
516 | |||
517 | switch (PTR_ERR(key_ref)) { | ||
518 | case -EAGAIN: /* no key */ | ||
519 | if (ret) | ||
520 | break; | ||
521 | case -ENOKEY: /* negative key */ | ||
522 | ret = key_ref; | ||
512 | break; | 523 | break; |
513 | case -ENOKEY: /* negative key */ | 524 | default: |
514 | ret = key_ref; | 525 | err = key_ref; |
515 | break; | 526 | break; |
516 | default: | 527 | } |
517 | err = key_ref; | 528 | } else { |
518 | break; | 529 | up_read(&context->request_key_auth->sem); |
519 | } | 530 | } |
520 | } | 531 | } |
521 | 532 | ||
@@ -717,7 +728,7 @@ long join_session_keyring(const char *name) | |||
717 | keyring = find_keyring_by_name(name, 0); | 728 | keyring = find_keyring_by_name(name, 0); |
718 | if (PTR_ERR(keyring) == -ENOKEY) { | 729 | if (PTR_ERR(keyring) == -ENOKEY) { |
719 | /* not found - try and create a new one */ | 730 | /* not found - try and create a new one */ |
720 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL); | 731 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 0, NULL); |
721 | if (IS_ERR(keyring)) { | 732 | if (IS_ERR(keyring)) { |
722 | ret = PTR_ERR(keyring); | 733 | ret = PTR_ERR(keyring); |
723 | goto error2; | 734 | goto error2; |