aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/process_keys.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/process_keys.c')
-rw-r--r--security/keys/process_keys.c94
1 files changed, 39 insertions, 55 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 54339cfd6734..b58d93892740 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -46,9 +46,11 @@ int install_user_keyrings(void)
46 struct user_struct *user; 46 struct user_struct *user;
47 const struct cred *cred; 47 const struct cred *cred;
48 struct key *uid_keyring, *session_keyring; 48 struct key *uid_keyring, *session_keyring;
49 key_perm_t user_keyring_perm;
49 char buf[20]; 50 char buf[20];
50 int ret; 51 int ret;
51 52
53 user_keyring_perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL;
52 cred = current_cred(); 54 cred = current_cred();
53 user = cred->user; 55 user = cred->user;
54 56
@@ -72,8 +74,8 @@ int install_user_keyrings(void)
72 uid_keyring = find_keyring_by_name(buf, true); 74 uid_keyring = find_keyring_by_name(buf, true);
73 if (IS_ERR(uid_keyring)) { 75 if (IS_ERR(uid_keyring)) {
74 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 76 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
75 cred, KEY_ALLOC_IN_QUOTA, 77 cred, user_keyring_perm,
76 NULL); 78 KEY_ALLOC_IN_QUOTA, NULL);
77 if (IS_ERR(uid_keyring)) { 79 if (IS_ERR(uid_keyring)) {
78 ret = PTR_ERR(uid_keyring); 80 ret = PTR_ERR(uid_keyring);
79 goto error; 81 goto error;
@@ -88,7 +90,8 @@ int install_user_keyrings(void)
88 if (IS_ERR(session_keyring)) { 90 if (IS_ERR(session_keyring)) {
89 session_keyring = 91 session_keyring =
90 keyring_alloc(buf, user->uid, (gid_t) -1, 92 keyring_alloc(buf, user->uid, (gid_t) -1,
91 cred, KEY_ALLOC_IN_QUOTA, NULL); 93 cred, user_keyring_perm,
94 KEY_ALLOC_IN_QUOTA, NULL);
92 if (IS_ERR(session_keyring)) { 95 if (IS_ERR(session_keyring)) {
93 ret = PTR_ERR(session_keyring); 96 ret = PTR_ERR(session_keyring);
94 goto error_release; 97 goto error_release;
@@ -129,6 +132,7 @@ int install_thread_keyring_to_cred(struct cred *new)
129 struct key *keyring; 132 struct key *keyring;
130 133
131 keyring = keyring_alloc("_tid", new->uid, new->gid, new, 134 keyring = keyring_alloc("_tid", new->uid, new->gid, new,
135 KEY_POS_ALL | KEY_USR_VIEW,
132 KEY_ALLOC_QUOTA_OVERRUN, NULL); 136 KEY_ALLOC_QUOTA_OVERRUN, NULL);
133 if (IS_ERR(keyring)) 137 if (IS_ERR(keyring))
134 return PTR_ERR(keyring); 138 return PTR_ERR(keyring);
@@ -169,27 +173,18 @@ static int install_thread_keyring(void)
169int install_process_keyring_to_cred(struct cred *new) 173int install_process_keyring_to_cred(struct cred *new)
170{ 174{
171 struct key *keyring; 175 struct key *keyring;
172 int ret;
173 176
174 if (new->tgcred->process_keyring) 177 if (new->process_keyring)
175 return -EEXIST; 178 return -EEXIST;
176 179
177 keyring = keyring_alloc("_pid", new->uid, new->gid, 180 keyring = keyring_alloc("_pid", new->uid, new->gid, new,
178 new, KEY_ALLOC_QUOTA_OVERRUN, NULL); 181 KEY_POS_ALL | KEY_USR_VIEW,
182 KEY_ALLOC_QUOTA_OVERRUN, NULL);
179 if (IS_ERR(keyring)) 183 if (IS_ERR(keyring))
180 return PTR_ERR(keyring); 184 return PTR_ERR(keyring);
181 185
182 spin_lock_irq(&new->tgcred->lock); 186 new->process_keyring = keyring;
183 if (!new->tgcred->process_keyring) { 187 return 0;
184 new->tgcred->process_keyring = keyring;
185 keyring = NULL;
186 ret = 0;
187 } else {
188 ret = -EEXIST;
189 }
190 spin_unlock_irq(&new->tgcred->lock);
191 key_put(keyring);
192 return ret;
193} 188}
194 189
195/* 190/*
@@ -230,11 +225,12 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
230 /* create an empty session keyring */ 225 /* create an empty session keyring */
231 if (!keyring) { 226 if (!keyring) {
232 flags = KEY_ALLOC_QUOTA_OVERRUN; 227 flags = KEY_ALLOC_QUOTA_OVERRUN;
233 if (cred->tgcred->session_keyring) 228 if (cred->session_keyring)
234 flags = KEY_ALLOC_IN_QUOTA; 229 flags = KEY_ALLOC_IN_QUOTA;
235 230
236 keyring = keyring_alloc("_ses", cred->uid, cred->gid, 231 keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred,
237 cred, flags, NULL); 232 KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
233 flags, NULL);
238 if (IS_ERR(keyring)) 234 if (IS_ERR(keyring))
239 return PTR_ERR(keyring); 235 return PTR_ERR(keyring);
240 } else { 236 } else {
@@ -242,17 +238,11 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
242 } 238 }
243 239
244 /* install the keyring */ 240 /* install the keyring */
245 spin_lock_irq(&cred->tgcred->lock); 241 old = cred->session_keyring;
246 old = cred->tgcred->session_keyring; 242 rcu_assign_pointer(cred->session_keyring, keyring);
247 rcu_assign_pointer(cred->tgcred->session_keyring, keyring); 243
248 spin_unlock_irq(&cred->tgcred->lock); 244 if (old)
249
250 /* we're using RCU on the pointer, but there's no point synchronising
251 * on it if it didn't previously point to anything */
252 if (old) {
253 synchronize_rcu();
254 key_put(old); 245 key_put(old);
255 }
256 246
257 return 0; 247 return 0;
258} 248}
@@ -357,8 +347,6 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
357 347
358 switch (PTR_ERR(key_ref)) { 348 switch (PTR_ERR(key_ref)) {
359 case -EAGAIN: /* no key */ 349 case -EAGAIN: /* no key */
360 if (ret)
361 break;
362 case -ENOKEY: /* negative key */ 350 case -ENOKEY: /* negative key */
363 ret = key_ref; 351 ret = key_ref;
364 break; 352 break;
@@ -369,9 +357,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
369 } 357 }
370 358
371 /* search the process keyring second */ 359 /* search the process keyring second */
372 if (cred->tgcred->process_keyring) { 360 if (cred->process_keyring) {
373 key_ref = keyring_search_aux( 361 key_ref = keyring_search_aux(
374 make_key_ref(cred->tgcred->process_keyring, 1), 362 make_key_ref(cred->process_keyring, 1),
375 cred, type, description, match, no_state_check); 363 cred, type, description, match, no_state_check);
376 if (!IS_ERR(key_ref)) 364 if (!IS_ERR(key_ref))
377 goto found; 365 goto found;
@@ -390,12 +378,10 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
390 } 378 }
391 379
392 /* search the session keyring */ 380 /* search the session keyring */
393 if (cred->tgcred->session_keyring) { 381 if (cred->session_keyring) {
394 rcu_read_lock(); 382 rcu_read_lock();
395 key_ref = keyring_search_aux( 383 key_ref = keyring_search_aux(
396 make_key_ref(rcu_dereference( 384 make_key_ref(rcu_dereference(cred->session_keyring), 1),
397 cred->tgcred->session_keyring),
398 1),
399 cred, type, description, match, no_state_check); 385 cred, type, description, match, no_state_check);
400 rcu_read_unlock(); 386 rcu_read_unlock();
401 387
@@ -565,7 +551,7 @@ try_again:
565 break; 551 break;
566 552
567 case KEY_SPEC_PROCESS_KEYRING: 553 case KEY_SPEC_PROCESS_KEYRING:
568 if (!cred->tgcred->process_keyring) { 554 if (!cred->process_keyring) {
569 if (!(lflags & KEY_LOOKUP_CREATE)) 555 if (!(lflags & KEY_LOOKUP_CREATE))
570 goto error; 556 goto error;
571 557
@@ -577,13 +563,13 @@ try_again:
577 goto reget_creds; 563 goto reget_creds;
578 } 564 }
579 565
580 key = cred->tgcred->process_keyring; 566 key = cred->process_keyring;
581 atomic_inc(&key->usage); 567 atomic_inc(&key->usage);
582 key_ref = make_key_ref(key, 1); 568 key_ref = make_key_ref(key, 1);
583 break; 569 break;
584 570
585 case KEY_SPEC_SESSION_KEYRING: 571 case KEY_SPEC_SESSION_KEYRING:
586 if (!cred->tgcred->session_keyring) { 572 if (!cred->session_keyring) {
587 /* always install a session keyring upon access if one 573 /* always install a session keyring upon access if one
588 * doesn't exist yet */ 574 * doesn't exist yet */
589 ret = install_user_keyrings(); 575 ret = install_user_keyrings();
@@ -598,7 +584,7 @@ try_again:
598 if (ret < 0) 584 if (ret < 0)
599 goto error; 585 goto error;
600 goto reget_creds; 586 goto reget_creds;
601 } else if (cred->tgcred->session_keyring == 587 } else if (cred->session_keyring ==
602 cred->user->session_keyring && 588 cred->user->session_keyring &&
603 lflags & KEY_LOOKUP_CREATE) { 589 lflags & KEY_LOOKUP_CREATE) {
604 ret = join_session_keyring(NULL); 590 ret = join_session_keyring(NULL);
@@ -608,7 +594,7 @@ try_again:
608 } 594 }
609 595
610 rcu_read_lock(); 596 rcu_read_lock();
611 key = rcu_dereference(cred->tgcred->session_keyring); 597 key = rcu_dereference(cred->session_keyring);
612 atomic_inc(&key->usage); 598 atomic_inc(&key->usage);
613 rcu_read_unlock(); 599 rcu_read_unlock();
614 key_ref = make_key_ref(key, 1); 600 key_ref = make_key_ref(key, 1);
@@ -768,12 +754,6 @@ long join_session_keyring(const char *name)
768 struct key *keyring; 754 struct key *keyring;
769 long ret, serial; 755 long ret, serial;
770 756
771 /* only permit this if there's a single thread in the thread group -
772 * this avoids us having to adjust the creds on all threads and risking
773 * ENOMEM */
774 if (!current_is_single_threaded())
775 return -EMLINK;
776
777 new = prepare_creds(); 757 new = prepare_creds();
778 if (!new) 758 if (!new)
779 return -ENOMEM; 759 return -ENOMEM;
@@ -785,7 +765,7 @@ long join_session_keyring(const char *name)
785 if (ret < 0) 765 if (ret < 0)
786 goto error; 766 goto error;
787 767
788 serial = new->tgcred->session_keyring->serial; 768 serial = new->session_keyring->serial;
789 ret = commit_creds(new); 769 ret = commit_creds(new);
790 if (ret == 0) 770 if (ret == 0)
791 ret = serial; 771 ret = serial;
@@ -799,8 +779,10 @@ 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, old->uid, old->gid, old, 782 keyring = keyring_alloc(
803 KEY_ALLOC_IN_QUOTA, NULL); 783 name, old->uid, old->gid, old,
784 KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK,
785 KEY_ALLOC_IN_QUOTA, NULL);
804 if (IS_ERR(keyring)) { 786 if (IS_ERR(keyring)) {
805 ret = PTR_ERR(keyring); 787 ret = PTR_ERR(keyring);
806 goto error2; 788 goto error2;
@@ -808,6 +790,9 @@ long join_session_keyring(const char *name)
808 } else if (IS_ERR(keyring)) { 790 } else if (IS_ERR(keyring)) {
809 ret = PTR_ERR(keyring); 791 ret = PTR_ERR(keyring);
810 goto error2; 792 goto error2;
793 } else if (keyring == new->session_keyring) {
794 ret = 0;
795 goto error2;
811 } 796 }
812 797
813 /* we've got a keyring - now to install it */ 798 /* we've got a keyring - now to install it */
@@ -864,8 +849,7 @@ void key_change_session_keyring(struct callback_head *twork)
864 849
865 new->jit_keyring = old->jit_keyring; 850 new->jit_keyring = old->jit_keyring;
866 new->thread_keyring = key_get(old->thread_keyring); 851 new->thread_keyring = key_get(old->thread_keyring);
867 new->tgcred->tgid = old->tgcred->tgid; 852 new->process_keyring = key_get(old->process_keyring);
868 new->tgcred->process_keyring = key_get(old->tgcred->process_keyring);
869 853
870 security_transfer_creds(new, old); 854 security_transfer_creds(new, old);
871 855