aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:20 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:20 -0500
commitbb952bb98a7e479262c7eb25d5592545a3af147d (patch)
tree9a2158c07a22a5fbddcec412944d2e7534eecc8f /security/keys
parent275bb41e9d058fbb327e7642f077e1beaeac162e (diff)
CRED: Separate per-task-group keyrings from signal_struct
Separate per-task-group keyrings from signal_struct and dangle their anchor from the cred struct rather than the signal_struct. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: James Morris <jmorris@namei.org> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/keys')
-rw-r--r--security/keys/process_keys.c100
-rw-r--r--security/keys/request_key.c34
2 files changed, 54 insertions, 80 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 212601ebaa46..70ee93406f30 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -189,7 +189,7 @@ int install_process_keyring(void)
189 189
190 might_sleep(); 190 might_sleep();
191 191
192 if (!tsk->signal->process_keyring) { 192 if (!tsk->cred->tgcred->process_keyring) {
193 sprintf(buf, "_pid.%u", tsk->tgid); 193 sprintf(buf, "_pid.%u", tsk->tgid);
194 194
195 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, tsk, 195 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, tsk,
@@ -200,12 +200,12 @@ int install_process_keyring(void)
200 } 200 }
201 201
202 /* attach keyring */ 202 /* attach keyring */
203 spin_lock_irq(&tsk->sighand->siglock); 203 spin_lock_irq(&tsk->cred->tgcred->lock);
204 if (!tsk->signal->process_keyring) { 204 if (!tsk->cred->tgcred->process_keyring) {
205 tsk->signal->process_keyring = keyring; 205 tsk->cred->tgcred->process_keyring = keyring;
206 keyring = NULL; 206 keyring = NULL;
207 } 207 }
208 spin_unlock_irq(&tsk->sighand->siglock); 208 spin_unlock_irq(&tsk->cred->tgcred->lock);
209 209
210 key_put(keyring); 210 key_put(keyring);
211 } 211 }
@@ -235,11 +235,11 @@ static int install_session_keyring(struct key *keyring)
235 sprintf(buf, "_ses.%u", tsk->tgid); 235 sprintf(buf, "_ses.%u", tsk->tgid);
236 236
237 flags = KEY_ALLOC_QUOTA_OVERRUN; 237 flags = KEY_ALLOC_QUOTA_OVERRUN;
238 if (tsk->signal->session_keyring) 238 if (tsk->cred->tgcred->session_keyring)
239 flags = KEY_ALLOC_IN_QUOTA; 239 flags = KEY_ALLOC_IN_QUOTA;
240 240
241 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, tsk, 241 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid,
242 flags, NULL); 242 tsk, flags, NULL);
243 if (IS_ERR(keyring)) 243 if (IS_ERR(keyring))
244 return PTR_ERR(keyring); 244 return PTR_ERR(keyring);
245 } 245 }
@@ -248,10 +248,10 @@ static int install_session_keyring(struct key *keyring)
248 } 248 }
249 249
250 /* install the keyring */ 250 /* install the keyring */
251 spin_lock_irq(&tsk->sighand->siglock); 251 spin_lock_irq(&tsk->cred->tgcred->lock);
252 old = tsk->signal->session_keyring; 252 old = tsk->cred->tgcred->session_keyring;
253 rcu_assign_pointer(tsk->signal->session_keyring, keyring); 253 rcu_assign_pointer(tsk->cred->tgcred->session_keyring, keyring);
254 spin_unlock_irq(&tsk->sighand->siglock); 254 spin_unlock_irq(&tsk->cred->tgcred->lock);
255 255
256 /* we're using RCU on the pointer, but there's no point synchronising 256 /* we're using RCU on the pointer, but there's no point synchronising
257 * on it if it didn't previously point to anything */ 257 * on it if it didn't previously point to anything */
@@ -266,28 +266,6 @@ static int install_session_keyring(struct key *keyring)
266 266
267/*****************************************************************************/ 267/*****************************************************************************/
268/* 268/*
269 * copy the keys in a thread group for fork without CLONE_THREAD
270 */
271int copy_thread_group_keys(struct task_struct *tsk)
272{
273 key_check(current->thread_group->session_keyring);
274 key_check(current->thread_group->process_keyring);
275
276 /* no process keyring yet */
277 tsk->signal->process_keyring = NULL;
278
279 /* same session keyring */
280 rcu_read_lock();
281 tsk->signal->session_keyring =
282 key_get(rcu_dereference(current->signal->session_keyring));
283 rcu_read_unlock();
284
285 return 0;
286
287} /* end copy_thread_group_keys() */
288
289/*****************************************************************************/
290/*
291 * copy the keys for fork 269 * copy the keys for fork
292 */ 270 */
293int copy_keys(unsigned long clone_flags, struct task_struct *tsk) 271int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
@@ -307,17 +285,6 @@ int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
307 285
308/*****************************************************************************/ 286/*****************************************************************************/
309/* 287/*
310 * dispose of thread group keys upon thread group destruction
311 */
312void exit_thread_group_keys(struct signal_struct *tg)
313{
314 key_put(tg->session_keyring);
315 key_put(tg->process_keyring);
316
317} /* end exit_thread_group_keys() */
318
319/*****************************************************************************/
320/*
321 * dispose of per-thread keys upon thread exit 288 * dispose of per-thread keys upon thread exit
322 */ 289 */
323void exit_keys(struct task_struct *tsk) 290void exit_keys(struct task_struct *tsk)
@@ -344,10 +311,10 @@ int exec_keys(struct task_struct *tsk)
344 key_put(old); 311 key_put(old);
345 312
346 /* discard the process keyring from a newly exec'd task */ 313 /* discard the process keyring from a newly exec'd task */
347 spin_lock_irq(&tsk->sighand->siglock); 314 spin_lock_irq(&tsk->cred->tgcred->lock);
348 old = tsk->signal->process_keyring; 315 old = tsk->cred->tgcred->process_keyring;
349 tsk->signal->process_keyring = NULL; 316 tsk->cred->tgcred->process_keyring = NULL;
350 spin_unlock_irq(&tsk->sighand->siglock); 317 spin_unlock_irq(&tsk->cred->tgcred->lock);
351 318
352 key_put(old); 319 key_put(old);
353 320
@@ -452,9 +419,9 @@ key_ref_t search_process_keyrings(struct key_type *type,
452 } 419 }
453 420
454 /* search the process keyring second */ 421 /* search the process keyring second */
455 if (context->signal->process_keyring) { 422 if (cred->tgcred->process_keyring) {
456 key_ref = keyring_search_aux( 423 key_ref = keyring_search_aux(
457 make_key_ref(context->signal->process_keyring, 1), 424 make_key_ref(cred->tgcred->process_keyring, 1),
458 context, type, description, match); 425 context, type, description, match);
459 if (!IS_ERR(key_ref)) 426 if (!IS_ERR(key_ref))
460 goto found; 427 goto found;
@@ -473,11 +440,11 @@ key_ref_t search_process_keyrings(struct key_type *type,
473 } 440 }
474 441
475 /* search the session keyring */ 442 /* search the session keyring */
476 if (context->signal->session_keyring) { 443 if (cred->tgcred->session_keyring) {
477 rcu_read_lock(); 444 rcu_read_lock();
478 key_ref = keyring_search_aux( 445 key_ref = keyring_search_aux(
479 make_key_ref(rcu_dereference( 446 make_key_ref(rcu_dereference(
480 context->signal->session_keyring), 447 cred->tgcred->session_keyring),
481 1), 448 1),
482 context, type, description, match); 449 context, type, description, match);
483 rcu_read_unlock(); 450 rcu_read_unlock();
@@ -586,11 +553,13 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
586{ 553{
587 struct request_key_auth *rka; 554 struct request_key_auth *rka;
588 struct task_struct *t = current; 555 struct task_struct *t = current;
589 struct cred *cred = current_cred(); 556 struct cred *cred;
590 struct key *key; 557 struct key *key;
591 key_ref_t key_ref, skey_ref; 558 key_ref_t key_ref, skey_ref;
592 int ret; 559 int ret;
593 560
561try_again:
562 cred = get_current_cred();
594 key_ref = ERR_PTR(-ENOKEY); 563 key_ref = ERR_PTR(-ENOKEY);
595 564
596 switch (id) { 565 switch (id) {
@@ -604,6 +573,7 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
604 key = ERR_PTR(ret); 573 key = ERR_PTR(ret);
605 goto error; 574 goto error;
606 } 575 }
576 goto reget_creds;
607 } 577 }
608 578
609 key = cred->thread_keyring; 579 key = cred->thread_keyring;
@@ -612,7 +582,7 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
612 break; 582 break;
613 583
614 case KEY_SPEC_PROCESS_KEYRING: 584 case KEY_SPEC_PROCESS_KEYRING:
615 if (!t->signal->process_keyring) { 585 if (!cred->tgcred->process_keyring) {
616 if (!create) 586 if (!create)
617 goto error; 587 goto error;
618 588
@@ -621,15 +591,16 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
621 key = ERR_PTR(ret); 591 key = ERR_PTR(ret);
622 goto error; 592 goto error;
623 } 593 }
594 goto reget_creds;
624 } 595 }
625 596
626 key = t->signal->process_keyring; 597 key = cred->tgcred->process_keyring;
627 atomic_inc(&key->usage); 598 atomic_inc(&key->usage);
628 key_ref = make_key_ref(key, 1); 599 key_ref = make_key_ref(key, 1);
629 break; 600 break;
630 601
631 case KEY_SPEC_SESSION_KEYRING: 602 case KEY_SPEC_SESSION_KEYRING:
632 if (!t->signal->session_keyring) { 603 if (!cred->tgcred->session_keyring) {
633 /* always install a session keyring upon access if one 604 /* always install a session keyring upon access if one
634 * doesn't exist yet */ 605 * doesn't exist yet */
635 ret = install_user_keyrings(); 606 ret = install_user_keyrings();
@@ -639,10 +610,11 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
639 cred->user->session_keyring); 610 cred->user->session_keyring);
640 if (ret < 0) 611 if (ret < 0)
641 goto error; 612 goto error;
613 goto reget_creds;
642 } 614 }
643 615
644 rcu_read_lock(); 616 rcu_read_lock();
645 key = rcu_dereference(t->signal->session_keyring); 617 key = rcu_dereference(cred->tgcred->session_keyring);
646 atomic_inc(&key->usage); 618 atomic_inc(&key->usage);
647 rcu_read_unlock(); 619 rcu_read_unlock();
648 key_ref = make_key_ref(key, 1); 620 key_ref = make_key_ref(key, 1);
@@ -758,6 +730,7 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
758 goto invalid_key; 730 goto invalid_key;
759 731
760error: 732error:
733 put_cred(cred);
761 return key_ref; 734 return key_ref;
762 735
763invalid_key: 736invalid_key:
@@ -765,6 +738,12 @@ invalid_key:
765 key_ref = ERR_PTR(ret); 738 key_ref = ERR_PTR(ret);
766 goto error; 739 goto error;
767 740
741 /* if we attempted to install a keyring, then it may have caused new
742 * creds to be installed */
743reget_creds:
744 put_cred(cred);
745 goto try_again;
746
768} /* end lookup_user_key() */ 747} /* end lookup_user_key() */
769 748
770/*****************************************************************************/ 749/*****************************************************************************/
@@ -777,6 +756,7 @@ invalid_key:
777long join_session_keyring(const char *name) 756long join_session_keyring(const char *name)
778{ 757{
779 struct task_struct *tsk = current; 758 struct task_struct *tsk = current;
759 struct cred *cred = current->cred;
780 struct key *keyring; 760 struct key *keyring;
781 long ret; 761 long ret;
782 762
@@ -787,7 +767,7 @@ long join_session_keyring(const char *name)
787 goto error; 767 goto error;
788 768
789 rcu_read_lock(); 769 rcu_read_lock();
790 ret = rcu_dereference(tsk->signal->session_keyring)->serial; 770 ret = rcu_dereference(cred->tgcred->session_keyring)->serial;
791 rcu_read_unlock(); 771 rcu_read_unlock();
792 goto error; 772 goto error;
793 } 773 }
@@ -799,7 +779,7 @@ long join_session_keyring(const char *name)
799 keyring = find_keyring_by_name(name, false); 779 keyring = find_keyring_by_name(name, false);
800 if (PTR_ERR(keyring) == -ENOKEY) { 780 if (PTR_ERR(keyring) == -ENOKEY) {
801 /* not found - try and create a new one */ 781 /* not found - try and create a new one */
802 keyring = keyring_alloc(name, tsk->cred->uid, tsk->cred->gid, tsk, 782 keyring = keyring_alloc(name, cred->uid, cred->gid, tsk,
803 KEY_ALLOC_IN_QUOTA, NULL); 783 KEY_ALLOC_IN_QUOTA, NULL);
804 if (IS_ERR(keyring)) { 784 if (IS_ERR(keyring)) {
805 ret = PTR_ERR(keyring); 785 ret = PTR_ERR(keyring);
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 0488b0af5bd6..3d12558362df 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -66,7 +66,6 @@ static int call_sbin_request_key(struct key_construction *cons,
66 const char *op, 66 const char *op,
67 void *aux) 67 void *aux)
68{ 68{
69 struct task_struct *tsk = current;
70 const struct cred *cred = current_cred(); 69 const struct cred *cred = current_cred();
71 key_serial_t prkey, sskey; 70 key_serial_t prkey, sskey;
72 struct key *key = cons->key, *authkey = cons->authkey, *keyring; 71 struct key *key = cons->key, *authkey = cons->authkey, *keyring;
@@ -109,18 +108,13 @@ static int call_sbin_request_key(struct key_construction *cons,
109 cred->thread_keyring->serial : 0); 108 cred->thread_keyring->serial : 0);
110 109
111 prkey = 0; 110 prkey = 0;
112 if (tsk->signal->process_keyring) 111 if (cred->tgcred->process_keyring)
113 prkey = tsk->signal->process_keyring->serial; 112 prkey = cred->tgcred->process_keyring->serial;
114 113
115 sprintf(keyring_str[1], "%d", prkey); 114 if (cred->tgcred->session_keyring)
116 115 sskey = rcu_dereference(cred->tgcred->session_keyring)->serial;
117 if (tsk->signal->session_keyring) { 116 else
118 rcu_read_lock();
119 sskey = rcu_dereference(tsk->signal->session_keyring)->serial;
120 rcu_read_unlock();
121 } else {
122 sskey = cred->user->session_keyring->serial; 117 sskey = cred->user->session_keyring->serial;
123 }
124 118
125 sprintf(keyring_str[2], "%d", sskey); 119 sprintf(keyring_str[2], "%d", sskey);
126 120
@@ -222,7 +216,7 @@ static int construct_key(struct key *key, const void *callout_info,
222static void construct_get_dest_keyring(struct key **_dest_keyring) 216static void construct_get_dest_keyring(struct key **_dest_keyring)
223{ 217{
224 struct request_key_auth *rka; 218 struct request_key_auth *rka;
225 struct task_struct *tsk = current; 219 const struct cred *cred = current_cred();
226 struct key *dest_keyring = *_dest_keyring, *authkey; 220 struct key *dest_keyring = *_dest_keyring, *authkey;
227 221
228 kenter("%p", dest_keyring); 222 kenter("%p", dest_keyring);
@@ -234,11 +228,11 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
234 } else { 228 } else {
235 /* use a default keyring; falling through the cases until we 229 /* use a default keyring; falling through the cases until we
236 * find one that we actually have */ 230 * find one that we actually have */
237 switch (tsk->cred->jit_keyring) { 231 switch (cred->jit_keyring) {
238 case KEY_REQKEY_DEFL_DEFAULT: 232 case KEY_REQKEY_DEFL_DEFAULT:
239 case KEY_REQKEY_DEFL_REQUESTOR_KEYRING: 233 case KEY_REQKEY_DEFL_REQUESTOR_KEYRING:
240 if (tsk->cred->request_key_auth) { 234 if (cred->request_key_auth) {
241 authkey = tsk->cred->request_key_auth; 235 authkey = cred->request_key_auth;
242 down_read(&authkey->sem); 236 down_read(&authkey->sem);
243 rka = authkey->payload.data; 237 rka = authkey->payload.data;
244 if (!test_bit(KEY_FLAG_REVOKED, 238 if (!test_bit(KEY_FLAG_REVOKED,
@@ -251,19 +245,19 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
251 } 245 }
252 246
253 case KEY_REQKEY_DEFL_THREAD_KEYRING: 247 case KEY_REQKEY_DEFL_THREAD_KEYRING:
254 dest_keyring = key_get(tsk->cred->thread_keyring); 248 dest_keyring = key_get(cred->thread_keyring);
255 if (dest_keyring) 249 if (dest_keyring)
256 break; 250 break;
257 251
258 case KEY_REQKEY_DEFL_PROCESS_KEYRING: 252 case KEY_REQKEY_DEFL_PROCESS_KEYRING:
259 dest_keyring = key_get(tsk->signal->process_keyring); 253 dest_keyring = key_get(cred->tgcred->process_keyring);
260 if (dest_keyring) 254 if (dest_keyring)
261 break; 255 break;
262 256
263 case KEY_REQKEY_DEFL_SESSION_KEYRING: 257 case KEY_REQKEY_DEFL_SESSION_KEYRING:
264 rcu_read_lock(); 258 rcu_read_lock();
265 dest_keyring = key_get( 259 dest_keyring = key_get(
266 rcu_dereference(tsk->signal->session_keyring)); 260 rcu_dereference(cred->tgcred->session_keyring));
267 rcu_read_unlock(); 261 rcu_read_unlock();
268 262
269 if (dest_keyring) 263 if (dest_keyring)
@@ -271,11 +265,11 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
271 265
272 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: 266 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
273 dest_keyring = 267 dest_keyring =
274 key_get(tsk->cred->user->session_keyring); 268 key_get(cred->user->session_keyring);
275 break; 269 break;
276 270
277 case KEY_REQKEY_DEFL_USER_KEYRING: 271 case KEY_REQKEY_DEFL_USER_KEYRING:
278 dest_keyring = key_get(tsk->cred->user->uid_keyring); 272 dest_keyring = key_get(cred->user->uid_keyring);
279 break; 273 break;
280 274
281 case KEY_REQKEY_DEFL_GROUP_KEYRING: 275 case KEY_REQKEY_DEFL_GROUP_KEYRING: