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.c333
1 files changed, 164 insertions, 169 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 70ee93406f30..df329f684a65 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -42,11 +42,15 @@ struct key_user root_key_user = {
42 */ 42 */
43int install_user_keyrings(void) 43int install_user_keyrings(void)
44{ 44{
45 struct user_struct *user = current->cred->user; 45 struct user_struct *user;
46 const struct cred *cred;
46 struct key *uid_keyring, *session_keyring; 47 struct key *uid_keyring, *session_keyring;
47 char buf[20]; 48 char buf[20];
48 int ret; 49 int ret;
49 50
51 cred = current_cred();
52 user = cred->user;
53
50 kenter("%p{%u}", user, user->uid); 54 kenter("%p{%u}", user, user->uid);
51 55
52 if (user->uid_keyring) { 56 if (user->uid_keyring) {
@@ -67,7 +71,7 @@ int install_user_keyrings(void)
67 uid_keyring = find_keyring_by_name(buf, true); 71 uid_keyring = find_keyring_by_name(buf, true);
68 if (IS_ERR(uid_keyring)) { 72 if (IS_ERR(uid_keyring)) {
69 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 73 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
70 current, KEY_ALLOC_IN_QUOTA, 74 cred, KEY_ALLOC_IN_QUOTA,
71 NULL); 75 NULL);
72 if (IS_ERR(uid_keyring)) { 76 if (IS_ERR(uid_keyring)) {
73 ret = PTR_ERR(uid_keyring); 77 ret = PTR_ERR(uid_keyring);
@@ -83,8 +87,7 @@ int install_user_keyrings(void)
83 if (IS_ERR(session_keyring)) { 87 if (IS_ERR(session_keyring)) {
84 session_keyring = 88 session_keyring =
85 keyring_alloc(buf, user->uid, (gid_t) -1, 89 keyring_alloc(buf, user->uid, (gid_t) -1,
86 current, KEY_ALLOC_IN_QUOTA, 90 cred, KEY_ALLOC_IN_QUOTA, NULL);
87 NULL);
88 if (IS_ERR(session_keyring)) { 91 if (IS_ERR(session_keyring)) {
89 ret = PTR_ERR(session_keyring); 92 ret = PTR_ERR(session_keyring);
90 goto error_release; 93 goto error_release;
@@ -116,142 +119,128 @@ error:
116 return ret; 119 return ret;
117} 120}
118 121
119/*****************************************************************************/
120/* 122/*
121 * deal with the UID changing 123 * install a fresh thread keyring directly to new credentials
122 */ 124 */
123void switch_uid_keyring(struct user_struct *new_user) 125int install_thread_keyring_to_cred(struct cred *new)
124{ 126{
125#if 0 /* do nothing for now */ 127 struct key *keyring;
126 struct key *old;
127
128 /* switch to the new user's session keyring if we were running under
129 * root's default session keyring */
130 if (new_user->uid != 0 &&
131 current->session_keyring == &root_session_keyring
132 ) {
133 atomic_inc(&new_user->session_keyring->usage);
134
135 task_lock(current);
136 old = current->session_keyring;
137 current->session_keyring = new_user->session_keyring;
138 task_unlock(current);
139 128
140 key_put(old); 129 keyring = keyring_alloc("_tid", new->uid, new->gid, new,
141 } 130 KEY_ALLOC_QUOTA_OVERRUN, NULL);
142#endif 131 if (IS_ERR(keyring))
132 return PTR_ERR(keyring);
143 133
144} /* end switch_uid_keyring() */ 134 new->thread_keyring = keyring;
135 return 0;
136}
145 137
146/*****************************************************************************/
147/* 138/*
148 * install a fresh thread keyring, discarding the old one 139 * install a fresh thread keyring, discarding the old one
149 */ 140 */
150int install_thread_keyring(void) 141static int install_thread_keyring(void)
151{ 142{
152 struct task_struct *tsk = current; 143 struct cred *new;
153 struct key *keyring, *old;
154 char buf[20];
155 int ret; 144 int ret;
156 145
157 sprintf(buf, "_tid.%u", tsk->pid); 146 new = prepare_creds();
147 if (!new)
148 return -ENOMEM;
158 149
159 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, tsk, 150 BUG_ON(new->thread_keyring);
160 KEY_ALLOC_QUOTA_OVERRUN, NULL); 151
161 if (IS_ERR(keyring)) { 152 ret = install_thread_keyring_to_cred(new);
162 ret = PTR_ERR(keyring); 153 if (ret < 0) {
163 goto error; 154 abort_creds(new);
155 return ret;
164 } 156 }
165 157
166 task_lock(tsk); 158 return commit_creds(new);
167 old = tsk->cred->thread_keyring; 159}
168 tsk->cred->thread_keyring = keyring;
169 task_unlock(tsk);
170 160
171 ret = 0; 161/*
162 * install a process keyring directly to a credentials struct
163 * - returns -EEXIST if there was already a process keyring, 0 if one installed,
164 * and other -ve on any other error
165 */
166int install_process_keyring_to_cred(struct cred *new)
167{
168 struct key *keyring;
169 int ret;
172 170
173 key_put(old); 171 if (new->tgcred->process_keyring)
174error: 172 return -EEXIST;
173
174 keyring = keyring_alloc("_pid", new->uid, new->gid,
175 new, KEY_ALLOC_QUOTA_OVERRUN, NULL);
176 if (IS_ERR(keyring))
177 return PTR_ERR(keyring);
178
179 spin_lock_irq(&new->tgcred->lock);
180 if (!new->tgcred->process_keyring) {
181 new->tgcred->process_keyring = keyring;
182 keyring = NULL;
183 ret = 0;
184 } else {
185 ret = -EEXIST;
186 }
187 spin_unlock_irq(&new->tgcred->lock);
188 key_put(keyring);
175 return ret; 189 return ret;
190}
176 191
177} /* end install_thread_keyring() */
178
179/*****************************************************************************/
180/* 192/*
181 * make sure a process keyring is installed 193 * make sure a process keyring is installed
194 * - we
182 */ 195 */
183int install_process_keyring(void) 196static int install_process_keyring(void)
184{ 197{
185 struct task_struct *tsk = current; 198 struct cred *new;
186 struct key *keyring;
187 char buf[20];
188 int ret; 199 int ret;
189 200
190 might_sleep(); 201 new = prepare_creds();
191 202 if (!new)
192 if (!tsk->cred->tgcred->process_keyring) { 203 return -ENOMEM;
193 sprintf(buf, "_pid.%u", tsk->tgid);
194
195 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, tsk,
196 KEY_ALLOC_QUOTA_OVERRUN, NULL);
197 if (IS_ERR(keyring)) {
198 ret = PTR_ERR(keyring);
199 goto error;
200 }
201
202 /* attach keyring */
203 spin_lock_irq(&tsk->cred->tgcred->lock);
204 if (!tsk->cred->tgcred->process_keyring) {
205 tsk->cred->tgcred->process_keyring = keyring;
206 keyring = NULL;
207 }
208 spin_unlock_irq(&tsk->cred->tgcred->lock);
209 204
210 key_put(keyring); 205 ret = install_process_keyring_to_cred(new);
206 if (ret < 0) {
207 abort_creds(new);
208 return ret != -EEXIST ?: 0;
211 } 209 }
212 210
213 ret = 0; 211 return commit_creds(new);
214error: 212}
215 return ret;
216
217} /* end install_process_keyring() */
218 213
219/*****************************************************************************/
220/* 214/*
221 * install a session keyring, discarding the old one 215 * install a session keyring directly to a credentials struct
222 * - if a keyring is not supplied, an empty one is invented
223 */ 216 */
224static int install_session_keyring(struct key *keyring) 217static int install_session_keyring_to_cred(struct cred *cred,
218 struct key *keyring)
225{ 219{
226 struct task_struct *tsk = current;
227 unsigned long flags; 220 unsigned long flags;
228 struct key *old; 221 struct key *old;
229 char buf[20];
230 222
231 might_sleep(); 223 might_sleep();
232 224
233 /* create an empty session keyring */ 225 /* create an empty session keyring */
234 if (!keyring) { 226 if (!keyring) {
235 sprintf(buf, "_ses.%u", tsk->tgid);
236
237 flags = KEY_ALLOC_QUOTA_OVERRUN; 227 flags = KEY_ALLOC_QUOTA_OVERRUN;
238 if (tsk->cred->tgcred->session_keyring) 228 if (cred->tgcred->session_keyring)
239 flags = KEY_ALLOC_IN_QUOTA; 229 flags = KEY_ALLOC_IN_QUOTA;
240 230
241 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, 231 keyring = keyring_alloc("_ses", cred->uid, cred->gid,
242 tsk, flags, NULL); 232 cred, flags, NULL);
243 if (IS_ERR(keyring)) 233 if (IS_ERR(keyring))
244 return PTR_ERR(keyring); 234 return PTR_ERR(keyring);
245 } 235 } else {
246 else {
247 atomic_inc(&keyring->usage); 236 atomic_inc(&keyring->usage);
248 } 237 }
249 238
250 /* install the keyring */ 239 /* install the keyring */
251 spin_lock_irq(&tsk->cred->tgcred->lock); 240 spin_lock_irq(&cred->tgcred->lock);
252 old = tsk->cred->tgcred->session_keyring; 241 old = cred->tgcred->session_keyring;
253 rcu_assign_pointer(tsk->cred->tgcred->session_keyring, keyring); 242 rcu_assign_pointer(cred->tgcred->session_keyring, keyring);
254 spin_unlock_irq(&tsk->cred->tgcred->lock); 243 spin_unlock_irq(&cred->tgcred->lock);
255 244
256 /* we're using RCU on the pointer, but there's no point synchronising 245 /* we're using RCU on the pointer, but there's no point synchronising
257 * on it if it didn't previously point to anything */ 246 * on it if it didn't previously point to anything */
@@ -261,38 +250,29 @@ static int install_session_keyring(struct key *keyring)
261 } 250 }
262 251
263 return 0; 252 return 0;
253}
264 254
265} /* end install_session_keyring() */
266
267/*****************************************************************************/
268/* 255/*
269 * copy the keys for fork 256 * install a session keyring, discarding the old one
257 * - if a keyring is not supplied, an empty one is invented
270 */ 258 */
271int copy_keys(unsigned long clone_flags, struct task_struct *tsk) 259static int install_session_keyring(struct key *keyring)
272{ 260{
273 key_check(tsk->cred->thread_keyring); 261 struct cred *new;
274 key_check(tsk->cred->request_key_auth); 262 int ret;
275
276 /* no thread keyring yet */
277 tsk->cred->thread_keyring = NULL;
278
279 /* copy the request_key() authorisation for this thread */
280 key_get(tsk->cred->request_key_auth);
281
282 return 0;
283 263
284} /* end copy_keys() */ 264 new = prepare_creds();
265 if (!new)
266 return -ENOMEM;
285 267
286/*****************************************************************************/ 268 ret = install_session_keyring_to_cred(new, NULL);
287/* 269 if (ret < 0) {
288 * dispose of per-thread keys upon thread exit 270 abort_creds(new);
289 */ 271 return ret;
290void exit_keys(struct task_struct *tsk) 272 }
291{
292 key_put(tsk->cred->thread_keyring);
293 key_put(tsk->cred->request_key_auth);
294 273
295} /* end exit_keys() */ 274 return commit_creds(new);
275}
296 276
297/*****************************************************************************/ 277/*****************************************************************************/
298/* 278/*
@@ -300,38 +280,41 @@ void exit_keys(struct task_struct *tsk)
300 */ 280 */
301int exec_keys(struct task_struct *tsk) 281int exec_keys(struct task_struct *tsk)
302{ 282{
303 struct key *old; 283 struct thread_group_cred *tgcred = NULL;
284 struct cred *new;
304 285
305 /* newly exec'd tasks don't get a thread keyring */ 286#ifdef CONFIG_KEYS
306 task_lock(tsk); 287 tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
307 old = tsk->cred->thread_keyring; 288 if (!tgcred)
308 tsk->cred->thread_keyring = NULL; 289 return -ENOMEM;
309 task_unlock(tsk); 290#endif
310 291
311 key_put(old); 292 new = prepare_creds();
293 if (new < 0)
294 return -ENOMEM;
312 295
313 /* discard the process keyring from a newly exec'd task */ 296 /* newly exec'd tasks don't get a thread keyring */
314 spin_lock_irq(&tsk->cred->tgcred->lock); 297 key_put(new->thread_keyring);
315 old = tsk->cred->tgcred->process_keyring; 298 new->thread_keyring = NULL;
316 tsk->cred->tgcred->process_keyring = NULL;
317 spin_unlock_irq(&tsk->cred->tgcred->lock);
318 299
319 key_put(old); 300 /* create a new per-thread-group creds for all this set of threads to
301 * share */
302 memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred));
320 303
321 return 0; 304 atomic_set(&tgcred->usage, 1);
305 spin_lock_init(&tgcred->lock);
322 306
323} /* end exec_keys() */ 307 /* inherit the session keyring; new process keyring */
308 key_get(tgcred->session_keyring);
309 tgcred->process_keyring = NULL;
324 310
325/*****************************************************************************/ 311 release_tgcred(new);
326/* 312 new->tgcred = tgcred;
327 * deal with SUID programs 313
328 * - we might want to make this invent a new session keyring 314 commit_creds(new);
329 */
330int suid_keys(struct task_struct *tsk)
331{
332 return 0; 315 return 0;
333 316
334} /* end suid_keys() */ 317} /* end exec_keys() */
335 318
336/*****************************************************************************/ 319/*****************************************************************************/
337/* 320/*
@@ -376,16 +359,13 @@ void key_fsgid_changed(struct task_struct *tsk)
376key_ref_t search_process_keyrings(struct key_type *type, 359key_ref_t search_process_keyrings(struct key_type *type,
377 const void *description, 360 const void *description,
378 key_match_func_t match, 361 key_match_func_t match,
379 struct task_struct *context) 362 const struct cred *cred)
380{ 363{
381 struct request_key_auth *rka; 364 struct request_key_auth *rka;
382 struct cred *cred;
383 key_ref_t key_ref, ret, err; 365 key_ref_t key_ref, ret, err;
384 366
385 might_sleep(); 367 might_sleep();
386 368
387 cred = get_task_cred(context);
388
389 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 369 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
390 * searchable, but we failed to find a key or we found a negative key; 370 * searchable, but we failed to find a key or we found a negative key;
391 * otherwise we want to return a sample error (probably -EACCES) if 371 * otherwise we want to return a sample error (probably -EACCES) if
@@ -401,7 +381,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
401 if (cred->thread_keyring) { 381 if (cred->thread_keyring) {
402 key_ref = keyring_search_aux( 382 key_ref = keyring_search_aux(
403 make_key_ref(cred->thread_keyring, 1), 383 make_key_ref(cred->thread_keyring, 1),
404 context, type, description, match); 384 cred, type, description, match);
405 if (!IS_ERR(key_ref)) 385 if (!IS_ERR(key_ref))
406 goto found; 386 goto found;
407 387
@@ -422,7 +402,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
422 if (cred->tgcred->process_keyring) { 402 if (cred->tgcred->process_keyring) {
423 key_ref = keyring_search_aux( 403 key_ref = keyring_search_aux(
424 make_key_ref(cred->tgcred->process_keyring, 1), 404 make_key_ref(cred->tgcred->process_keyring, 1),
425 context, type, description, match); 405 cred, type, description, match);
426 if (!IS_ERR(key_ref)) 406 if (!IS_ERR(key_ref))
427 goto found; 407 goto found;
428 408
@@ -446,7 +426,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
446 make_key_ref(rcu_dereference( 426 make_key_ref(rcu_dereference(
447 cred->tgcred->session_keyring), 427 cred->tgcred->session_keyring),
448 1), 428 1),
449 context, type, description, match); 429 cred, type, description, match);
450 rcu_read_unlock(); 430 rcu_read_unlock();
451 431
452 if (!IS_ERR(key_ref)) 432 if (!IS_ERR(key_ref))
@@ -468,7 +448,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
468 else if (cred->user->session_keyring) { 448 else if (cred->user->session_keyring) {
469 key_ref = keyring_search_aux( 449 key_ref = keyring_search_aux(
470 make_key_ref(cred->user->session_keyring, 1), 450 make_key_ref(cred->user->session_keyring, 1),
471 context, type, description, match); 451 cred, type, description, match);
472 if (!IS_ERR(key_ref)) 452 if (!IS_ERR(key_ref))
473 goto found; 453 goto found;
474 454
@@ -490,7 +470,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
490 * - we don't permit access to request_key auth keys via this method 470 * - we don't permit access to request_key auth keys via this method
491 */ 471 */
492 if (cred->request_key_auth && 472 if (cred->request_key_auth &&
493 context == current && 473 cred == current_cred() &&
494 type != &key_type_request_key_auth 474 type != &key_type_request_key_auth
495 ) { 475 ) {
496 /* defend against the auth key being revoked */ 476 /* defend against the auth key being revoked */
@@ -500,7 +480,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
500 rka = cred->request_key_auth->payload.data; 480 rka = cred->request_key_auth->payload.data;
501 481
502 key_ref = search_process_keyrings(type, description, 482 key_ref = search_process_keyrings(type, description,
503 match, rka->context); 483 match, rka->cred);
504 484
505 up_read(&cred->request_key_auth->sem); 485 up_read(&cred->request_key_auth->sem);
506 486
@@ -527,7 +507,6 @@ key_ref_t search_process_keyrings(struct key_type *type,
527 key_ref = ret ? ret : err; 507 key_ref = ret ? ret : err;
528 508
529found: 509found:
530 put_cred(cred);
531 return key_ref; 510 return key_ref;
532 511
533} /* end search_process_keyrings() */ 512} /* end search_process_keyrings() */
@@ -552,8 +531,7 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
552 key_perm_t perm) 531 key_perm_t perm)
553{ 532{
554 struct request_key_auth *rka; 533 struct request_key_auth *rka;
555 struct task_struct *t = current; 534 const struct cred *cred;
556 struct cred *cred;
557 struct key *key; 535 struct key *key;
558 key_ref_t key_ref, skey_ref; 536 key_ref_t key_ref, skey_ref;
559 int ret; 537 int ret;
@@ -608,6 +586,7 @@ try_again:
608 goto error; 586 goto error;
609 ret = install_session_keyring( 587 ret = install_session_keyring(
610 cred->user->session_keyring); 588 cred->user->session_keyring);
589
611 if (ret < 0) 590 if (ret < 0)
612 goto error; 591 goto error;
613 goto reget_creds; 592 goto reget_creds;
@@ -693,7 +672,7 @@ try_again:
693 /* check to see if we possess the key */ 672 /* check to see if we possess the key */
694 skey_ref = search_process_keyrings(key->type, key, 673 skey_ref = search_process_keyrings(key->type, key,
695 lookup_user_key_possessed, 674 lookup_user_key_possessed,
696 current); 675 cred);
697 676
698 if (!IS_ERR(skey_ref)) { 677 if (!IS_ERR(skey_ref)) {
699 key_put(key); 678 key_put(key);
@@ -725,7 +704,7 @@ try_again:
725 goto invalid_key; 704 goto invalid_key;
726 705
727 /* check the permissions */ 706 /* check the permissions */
728 ret = key_task_permission(key_ref, t, perm); 707 ret = key_task_permission(key_ref, cred, perm);
729 if (ret < 0) 708 if (ret < 0)
730 goto invalid_key; 709 goto invalid_key;
731 710
@@ -755,21 +734,33 @@ reget_creds:
755 */ 734 */
756long join_session_keyring(const char *name) 735long join_session_keyring(const char *name)
757{ 736{
758 struct task_struct *tsk = current; 737 const struct cred *old;
759 struct cred *cred = current->cred; 738 struct cred *new;
760 struct key *keyring; 739 struct key *keyring;
761 long ret; 740 long ret, serial;
741
742 /* only permit this if there's a single thread in the thread group -
743 * this avoids us having to adjust the creds on all threads and risking
744 * ENOMEM */
745 if (!is_single_threaded(current))
746 return -EMLINK;
747
748 new = prepare_creds();
749 if (!new)
750 return -ENOMEM;
751 old = current_cred();
762 752
763 /* if no name is provided, install an anonymous keyring */ 753 /* if no name is provided, install an anonymous keyring */
764 if (!name) { 754 if (!name) {
765 ret = install_session_keyring(NULL); 755 ret = install_session_keyring_to_cred(new, NULL);
766 if (ret < 0) 756 if (ret < 0)
767 goto error; 757 goto error;
768 758
769 rcu_read_lock(); 759 serial = new->tgcred->session_keyring->serial;
770 ret = rcu_dereference(cred->tgcred->session_keyring)->serial; 760 ret = commit_creds(new);
771 rcu_read_unlock(); 761 if (ret == 0)
772 goto error; 762 ret = serial;
763 goto okay;
773 } 764 }
774 765
775 /* allow the user to join or create a named keyring */ 766 /* allow the user to join or create a named keyring */
@@ -779,29 +770,33 @@ long join_session_keyring(const char *name)
779 keyring = find_keyring_by_name(name, false); 770 keyring = find_keyring_by_name(name, false);
780 if (PTR_ERR(keyring) == -ENOKEY) { 771 if (PTR_ERR(keyring) == -ENOKEY) {
781 /* not found - try and create a new one */ 772 /* not found - try and create a new one */
782 keyring = keyring_alloc(name, cred->uid, cred->gid, tsk, 773 keyring = keyring_alloc(name, old->uid, old->gid, old,
783 KEY_ALLOC_IN_QUOTA, NULL); 774 KEY_ALLOC_IN_QUOTA, NULL);
784 if (IS_ERR(keyring)) { 775 if (IS_ERR(keyring)) {
785 ret = PTR_ERR(keyring); 776 ret = PTR_ERR(keyring);
786 goto error2; 777 goto error2;
787 } 778 }
788 } 779 } else if (IS_ERR(keyring)) {
789 else if (IS_ERR(keyring)) {
790 ret = PTR_ERR(keyring); 780 ret = PTR_ERR(keyring);
791 goto error2; 781 goto error2;
792 } 782 }
793 783
794 /* we've got a keyring - now to install it */ 784 /* we've got a keyring - now to install it */
795 ret = install_session_keyring(keyring); 785 ret = install_session_keyring_to_cred(new, keyring);
796 if (ret < 0) 786 if (ret < 0)
797 goto error2; 787 goto error2;
798 788
789 commit_creds(new);
790 mutex_unlock(&key_session_mutex);
791
799 ret = keyring->serial; 792 ret = keyring->serial;
800 key_put(keyring); 793 key_put(keyring);
794okay:
795 return ret;
801 796
802error2: 797error2:
803 mutex_unlock(&key_session_mutex); 798 mutex_unlock(&key_session_mutex);
804error: 799error:
800 abort_creds(new);
805 return ret; 801 return ret;
806 802}
807} /* end join_session_keyring() */