aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/process_keys.c
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2008-12-24 19:40:09 -0500
committerJames Morris <jmorris@namei.org>2008-12-24 19:40:09 -0500
commitcbacc2c7f066a1e01b33b0e27ae5efbf534bc2db (patch)
tree90d1093131d2a3543a8b3b1f3364e7c6f4081a93 /security/keys/process_keys.c
parent4a6908a3a050aacc9c3a2f36b276b46c0629ad91 (diff)
parent74192246910ff4fb95309ba1a683215644beeb62 (diff)
Merge branch 'next' into for-linus
Diffstat (limited to 'security/keys/process_keys.c')
-rw-r--r--security/keys/process_keys.c469
1 files changed, 215 insertions, 254 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 45b240af6dbe..2f5d89e92b85 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -40,13 +40,17 @@ struct key_user root_key_user = {
40/* 40/*
41 * install user and user session keyrings for a particular UID 41 * install user and user session keyrings for a particular UID
42 */ 42 */
43int install_user_keyrings(struct task_struct *tsk) 43int install_user_keyrings(void)
44{ 44{
45 struct user_struct *user = tsk->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(struct task_struct *tsk)
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 tsk, 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,7 +87,7 @@ int install_user_keyrings(struct task_struct *tsk)
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 tsk, KEY_ALLOC_IN_QUOTA, NULL); 90 cred, KEY_ALLOC_IN_QUOTA, NULL);
87 if (IS_ERR(session_keyring)) { 91 if (IS_ERR(session_keyring)) {
88 ret = PTR_ERR(session_keyring); 92 ret = PTR_ERR(session_keyring);
89 goto error_release; 93 goto error_release;
@@ -115,140 +119,128 @@ error:
115 return ret; 119 return ret;
116} 120}
117 121
118/*****************************************************************************/
119/* 122/*
120 * deal with the UID changing 123 * install a fresh thread keyring directly to new credentials
121 */ 124 */
122void switch_uid_keyring(struct user_struct *new_user) 125int install_thread_keyring_to_cred(struct cred *new)
123{ 126{
124#if 0 /* do nothing for now */ 127 struct key *keyring;
125 struct key *old;
126
127 /* switch to the new user's session keyring if we were running under
128 * root's default session keyring */
129 if (new_user->uid != 0 &&
130 current->session_keyring == &root_session_keyring
131 ) {
132 atomic_inc(&new_user->session_keyring->usage);
133
134 task_lock(current);
135 old = current->session_keyring;
136 current->session_keyring = new_user->session_keyring;
137 task_unlock(current);
138 128
139 key_put(old); 129 keyring = keyring_alloc("_tid", new->uid, new->gid, new,
140 } 130 KEY_ALLOC_QUOTA_OVERRUN, NULL);
141#endif 131 if (IS_ERR(keyring))
132 return PTR_ERR(keyring);
142 133
143} /* end switch_uid_keyring() */ 134 new->thread_keyring = keyring;
135 return 0;
136}
144 137
145/*****************************************************************************/
146/* 138/*
147 * install a fresh thread keyring, discarding the old one 139 * install a fresh thread keyring, discarding the old one
148 */ 140 */
149int install_thread_keyring(struct task_struct *tsk) 141static int install_thread_keyring(void)
150{ 142{
151 struct key *keyring, *old; 143 struct cred *new;
152 char buf[20];
153 int ret; 144 int ret;
154 145
155 sprintf(buf, "_tid.%u", tsk->pid); 146 new = prepare_creds();
147 if (!new)
148 return -ENOMEM;
156 149
157 keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 150 BUG_ON(new->thread_keyring);
158 KEY_ALLOC_QUOTA_OVERRUN, NULL); 151
159 if (IS_ERR(keyring)) { 152 ret = install_thread_keyring_to_cred(new);
160 ret = PTR_ERR(keyring); 153 if (ret < 0) {
161 goto error; 154 abort_creds(new);
155 return ret;
162 } 156 }
163 157
164 task_lock(tsk); 158 return commit_creds(new);
165 old = tsk->thread_keyring; 159}
166 tsk->thread_keyring = keyring;
167 task_unlock(tsk);
168 160
169 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;
170 170
171 key_put(old); 171 if (new->tgcred->process_keyring)
172error: 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);
173 return ret; 189 return ret;
190}
174 191
175} /* end install_thread_keyring() */
176
177/*****************************************************************************/
178/* 192/*
179 * make sure a process keyring is installed 193 * make sure a process keyring is installed
194 * - we
180 */ 195 */
181int install_process_keyring(struct task_struct *tsk) 196static int install_process_keyring(void)
182{ 197{
183 struct key *keyring; 198 struct cred *new;
184 char buf[20];
185 int ret; 199 int ret;
186 200
187 might_sleep(); 201 new = prepare_creds();
188 202 if (!new)
189 if (!tsk->signal->process_keyring) { 203 return -ENOMEM;
190 sprintf(buf, "_pid.%u", tsk->tgid);
191
192 keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
193 KEY_ALLOC_QUOTA_OVERRUN, NULL);
194 if (IS_ERR(keyring)) {
195 ret = PTR_ERR(keyring);
196 goto error;
197 }
198
199 /* attach keyring */
200 spin_lock_irq(&tsk->sighand->siglock);
201 if (!tsk->signal->process_keyring) {
202 tsk->signal->process_keyring = keyring;
203 keyring = NULL;
204 }
205 spin_unlock_irq(&tsk->sighand->siglock);
206 204
207 key_put(keyring); 205 ret = install_process_keyring_to_cred(new);
206 if (ret < 0) {
207 abort_creds(new);
208 return ret != -EEXIST ?: 0;
208 } 209 }
209 210
210 ret = 0; 211 return commit_creds(new);
211error: 212}
212 return ret;
213
214} /* end install_process_keyring() */
215 213
216/*****************************************************************************/
217/* 214/*
218 * install a session keyring, discarding the old one 215 * install a session keyring directly to a credentials struct
219 * - if a keyring is not supplied, an empty one is invented
220 */ 216 */
221static int install_session_keyring(struct task_struct *tsk, 217static int install_session_keyring_to_cred(struct cred *cred,
222 struct key *keyring) 218 struct key *keyring)
223{ 219{
224 unsigned long flags; 220 unsigned long flags;
225 struct key *old; 221 struct key *old;
226 char buf[20];
227 222
228 might_sleep(); 223 might_sleep();
229 224
230 /* create an empty session keyring */ 225 /* create an empty session keyring */
231 if (!keyring) { 226 if (!keyring) {
232 sprintf(buf, "_ses.%u", tsk->tgid);
233
234 flags = KEY_ALLOC_QUOTA_OVERRUN; 227 flags = KEY_ALLOC_QUOTA_OVERRUN;
235 if (tsk->signal->session_keyring) 228 if (cred->tgcred->session_keyring)
236 flags = KEY_ALLOC_IN_QUOTA; 229 flags = KEY_ALLOC_IN_QUOTA;
237 230
238 keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 231 keyring = keyring_alloc("_ses", cred->uid, cred->gid,
239 flags, NULL); 232 cred, flags, NULL);
240 if (IS_ERR(keyring)) 233 if (IS_ERR(keyring))
241 return PTR_ERR(keyring); 234 return PTR_ERR(keyring);
242 } 235 } else {
243 else {
244 atomic_inc(&keyring->usage); 236 atomic_inc(&keyring->usage);
245 } 237 }
246 238
247 /* install the keyring */ 239 /* install the keyring */
248 spin_lock_irq(&tsk->sighand->siglock); 240 spin_lock_irq(&cred->tgcred->lock);
249 old = tsk->signal->session_keyring; 241 old = cred->tgcred->session_keyring;
250 rcu_assign_pointer(tsk->signal->session_keyring, keyring); 242 rcu_assign_pointer(cred->tgcred->session_keyring, keyring);
251 spin_unlock_irq(&tsk->sighand->siglock); 243 spin_unlock_irq(&cred->tgcred->lock);
252 244
253 /* 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
254 * on it if it didn't previously point to anything */ 246 * on it if it didn't previously point to anything */
@@ -258,110 +250,29 @@ static int install_session_keyring(struct task_struct *tsk,
258 } 250 }
259 251
260 return 0; 252 return 0;
253}
261 254
262} /* end install_session_keyring() */
263
264/*****************************************************************************/
265/*
266 * copy the keys in a thread group for fork without CLONE_THREAD
267 */
268int copy_thread_group_keys(struct task_struct *tsk)
269{
270 key_check(current->thread_group->session_keyring);
271 key_check(current->thread_group->process_keyring);
272
273 /* no process keyring yet */
274 tsk->signal->process_keyring = NULL;
275
276 /* same session keyring */
277 rcu_read_lock();
278 tsk->signal->session_keyring =
279 key_get(rcu_dereference(current->signal->session_keyring));
280 rcu_read_unlock();
281
282 return 0;
283
284} /* end copy_thread_group_keys() */
285
286/*****************************************************************************/
287/*
288 * copy the keys for fork
289 */
290int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
291{
292 key_check(tsk->thread_keyring);
293 key_check(tsk->request_key_auth);
294
295 /* no thread keyring yet */
296 tsk->thread_keyring = NULL;
297
298 /* copy the request_key() authorisation for this thread */
299 key_get(tsk->request_key_auth);
300
301 return 0;
302
303} /* end copy_keys() */
304
305/*****************************************************************************/
306/*
307 * dispose of thread group keys upon thread group destruction
308 */
309void exit_thread_group_keys(struct signal_struct *tg)
310{
311 key_put(tg->session_keyring);
312 key_put(tg->process_keyring);
313
314} /* end exit_thread_group_keys() */
315
316/*****************************************************************************/
317/*
318 * dispose of per-thread keys upon thread exit
319 */
320void exit_keys(struct task_struct *tsk)
321{
322 key_put(tsk->thread_keyring);
323 key_put(tsk->request_key_auth);
324
325} /* end exit_keys() */
326
327/*****************************************************************************/
328/* 255/*
329 * deal with execve() 256 * install a session keyring, discarding the old one
257 * - if a keyring is not supplied, an empty one is invented
330 */ 258 */
331int exec_keys(struct task_struct *tsk) 259static int install_session_keyring(struct key *keyring)
332{ 260{
333 struct key *old; 261 struct cred *new;
334 262 int ret;
335 /* newly exec'd tasks don't get a thread keyring */
336 task_lock(tsk);
337 old = tsk->thread_keyring;
338 tsk->thread_keyring = NULL;
339 task_unlock(tsk);
340
341 key_put(old);
342
343 /* discard the process keyring from a newly exec'd task */
344 spin_lock_irq(&tsk->sighand->siglock);
345 old = tsk->signal->process_keyring;
346 tsk->signal->process_keyring = NULL;
347 spin_unlock_irq(&tsk->sighand->siglock);
348
349 key_put(old);
350
351 return 0;
352 263
353} /* end exec_keys() */ 264 new = prepare_creds();
265 if (!new)
266 return -ENOMEM;
354 267
355/*****************************************************************************/ 268 ret = install_session_keyring_to_cred(new, NULL);
356/* 269 if (ret < 0) {
357 * deal with SUID programs 270 abort_creds(new);
358 * - we might want to make this invent a new session keyring 271 return ret;
359 */ 272 }
360int suid_keys(struct task_struct *tsk)
361{
362 return 0;
363 273
364} /* end suid_keys() */ 274 return commit_creds(new);
275}
365 276
366/*****************************************************************************/ 277/*****************************************************************************/
367/* 278/*
@@ -370,10 +281,11 @@ int suid_keys(struct task_struct *tsk)
370void key_fsuid_changed(struct task_struct *tsk) 281void key_fsuid_changed(struct task_struct *tsk)
371{ 282{
372 /* update the ownership of the thread keyring */ 283 /* update the ownership of the thread keyring */
373 if (tsk->thread_keyring) { 284 BUG_ON(!tsk->cred);
374 down_write(&tsk->thread_keyring->sem); 285 if (tsk->cred->thread_keyring) {
375 tsk->thread_keyring->uid = tsk->fsuid; 286 down_write(&tsk->cred->thread_keyring->sem);
376 up_write(&tsk->thread_keyring->sem); 287 tsk->cred->thread_keyring->uid = tsk->cred->fsuid;
288 up_write(&tsk->cred->thread_keyring->sem);
377 } 289 }
378 290
379} /* end key_fsuid_changed() */ 291} /* end key_fsuid_changed() */
@@ -385,10 +297,11 @@ void key_fsuid_changed(struct task_struct *tsk)
385void key_fsgid_changed(struct task_struct *tsk) 297void key_fsgid_changed(struct task_struct *tsk)
386{ 298{
387 /* update the ownership of the thread keyring */ 299 /* update the ownership of the thread keyring */
388 if (tsk->thread_keyring) { 300 BUG_ON(!tsk->cred);
389 down_write(&tsk->thread_keyring->sem); 301 if (tsk->cred->thread_keyring) {
390 tsk->thread_keyring->gid = tsk->fsgid; 302 down_write(&tsk->cred->thread_keyring->sem);
391 up_write(&tsk->thread_keyring->sem); 303 tsk->cred->thread_keyring->gid = tsk->cred->fsgid;
304 up_write(&tsk->cred->thread_keyring->sem);
392 } 305 }
393 306
394} /* end key_fsgid_changed() */ 307} /* end key_fsgid_changed() */
@@ -404,7 +317,7 @@ void key_fsgid_changed(struct task_struct *tsk)
404key_ref_t search_process_keyrings(struct key_type *type, 317key_ref_t search_process_keyrings(struct key_type *type,
405 const void *description, 318 const void *description,
406 key_match_func_t match, 319 key_match_func_t match,
407 struct task_struct *context) 320 const struct cred *cred)
408{ 321{
409 struct request_key_auth *rka; 322 struct request_key_auth *rka;
410 key_ref_t key_ref, ret, err; 323 key_ref_t key_ref, ret, err;
@@ -423,10 +336,10 @@ key_ref_t search_process_keyrings(struct key_type *type,
423 err = ERR_PTR(-EAGAIN); 336 err = ERR_PTR(-EAGAIN);
424 337
425 /* search the thread keyring first */ 338 /* search the thread keyring first */
426 if (context->thread_keyring) { 339 if (cred->thread_keyring) {
427 key_ref = keyring_search_aux( 340 key_ref = keyring_search_aux(
428 make_key_ref(context->thread_keyring, 1), 341 make_key_ref(cred->thread_keyring, 1),
429 context, type, description, match); 342 cred, type, description, match);
430 if (!IS_ERR(key_ref)) 343 if (!IS_ERR(key_ref))
431 goto found; 344 goto found;
432 345
@@ -444,10 +357,10 @@ key_ref_t search_process_keyrings(struct key_type *type,
444 } 357 }
445 358
446 /* search the process keyring second */ 359 /* search the process keyring second */
447 if (context->signal->process_keyring) { 360 if (cred->tgcred->process_keyring) {
448 key_ref = keyring_search_aux( 361 key_ref = keyring_search_aux(
449 make_key_ref(context->signal->process_keyring, 1), 362 make_key_ref(cred->tgcred->process_keyring, 1),
450 context, type, description, match); 363 cred, type, description, match);
451 if (!IS_ERR(key_ref)) 364 if (!IS_ERR(key_ref))
452 goto found; 365 goto found;
453 366
@@ -465,13 +378,13 @@ key_ref_t search_process_keyrings(struct key_type *type,
465 } 378 }
466 379
467 /* search the session keyring */ 380 /* search the session keyring */
468 if (context->signal->session_keyring) { 381 if (cred->tgcred->session_keyring) {
469 rcu_read_lock(); 382 rcu_read_lock();
470 key_ref = keyring_search_aux( 383 key_ref = keyring_search_aux(
471 make_key_ref(rcu_dereference( 384 make_key_ref(rcu_dereference(
472 context->signal->session_keyring), 385 cred->tgcred->session_keyring),
473 1), 386 1),
474 context, type, description, match); 387 cred, type, description, match);
475 rcu_read_unlock(); 388 rcu_read_unlock();
476 389
477 if (!IS_ERR(key_ref)) 390 if (!IS_ERR(key_ref))
@@ -490,10 +403,10 @@ key_ref_t search_process_keyrings(struct key_type *type,
490 } 403 }
491 } 404 }
492 /* or search the user-session keyring */ 405 /* or search the user-session keyring */
493 else if (context->user->session_keyring) { 406 else if (cred->user->session_keyring) {
494 key_ref = keyring_search_aux( 407 key_ref = keyring_search_aux(
495 make_key_ref(context->user->session_keyring, 1), 408 make_key_ref(cred->user->session_keyring, 1),
496 context, type, description, match); 409 cred, type, description, match);
497 if (!IS_ERR(key_ref)) 410 if (!IS_ERR(key_ref))
498 goto found; 411 goto found;
499 412
@@ -514,20 +427,20 @@ key_ref_t search_process_keyrings(struct key_type *type,
514 * search the keyrings of the process mentioned there 427 * search the keyrings of the process mentioned there
515 * - we don't permit access to request_key auth keys via this method 428 * - we don't permit access to request_key auth keys via this method
516 */ 429 */
517 if (context->request_key_auth && 430 if (cred->request_key_auth &&
518 context == current && 431 cred == current_cred() &&
519 type != &key_type_request_key_auth 432 type != &key_type_request_key_auth
520 ) { 433 ) {
521 /* defend against the auth key being revoked */ 434 /* defend against the auth key being revoked */
522 down_read(&context->request_key_auth->sem); 435 down_read(&cred->request_key_auth->sem);
523 436
524 if (key_validate(context->request_key_auth) == 0) { 437 if (key_validate(cred->request_key_auth) == 0) {
525 rka = context->request_key_auth->payload.data; 438 rka = cred->request_key_auth->payload.data;
526 439
527 key_ref = search_process_keyrings(type, description, 440 key_ref = search_process_keyrings(type, description,
528 match, rka->context); 441 match, rka->cred);
529 442
530 up_read(&context->request_key_auth->sem); 443 up_read(&cred->request_key_auth->sem);
531 444
532 if (!IS_ERR(key_ref)) 445 if (!IS_ERR(key_ref))
533 goto found; 446 goto found;
@@ -544,7 +457,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
544 break; 457 break;
545 } 458 }
546 } else { 459 } else {
547 up_read(&context->request_key_auth->sem); 460 up_read(&cred->request_key_auth->sem);
548 } 461 }
549 } 462 }
550 463
@@ -572,93 +485,98 @@ static int lookup_user_key_possessed(const struct key *key, const void *target)
572 * - don't create special keyrings unless so requested 485 * - don't create special keyrings unless so requested
573 * - partially constructed keys aren't found unless requested 486 * - partially constructed keys aren't found unless requested
574 */ 487 */
575key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, 488key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
576 int create, int partial, key_perm_t perm) 489 key_perm_t perm)
577{ 490{
578 key_ref_t key_ref, skey_ref; 491 struct request_key_auth *rka;
492 const struct cred *cred;
579 struct key *key; 493 struct key *key;
494 key_ref_t key_ref, skey_ref;
580 int ret; 495 int ret;
581 496
582 if (!context) 497try_again:
583 context = current; 498 cred = get_current_cred();
584
585 key_ref = ERR_PTR(-ENOKEY); 499 key_ref = ERR_PTR(-ENOKEY);
586 500
587 switch (id) { 501 switch (id) {
588 case KEY_SPEC_THREAD_KEYRING: 502 case KEY_SPEC_THREAD_KEYRING:
589 if (!context->thread_keyring) { 503 if (!cred->thread_keyring) {
590 if (!create) 504 if (!create)
591 goto error; 505 goto error;
592 506
593 ret = install_thread_keyring(context); 507 ret = install_thread_keyring();
594 if (ret < 0) { 508 if (ret < 0) {
595 key = ERR_PTR(ret); 509 key = ERR_PTR(ret);
596 goto error; 510 goto error;
597 } 511 }
512 goto reget_creds;
598 } 513 }
599 514
600 key = context->thread_keyring; 515 key = cred->thread_keyring;
601 atomic_inc(&key->usage); 516 atomic_inc(&key->usage);
602 key_ref = make_key_ref(key, 1); 517 key_ref = make_key_ref(key, 1);
603 break; 518 break;
604 519
605 case KEY_SPEC_PROCESS_KEYRING: 520 case KEY_SPEC_PROCESS_KEYRING:
606 if (!context->signal->process_keyring) { 521 if (!cred->tgcred->process_keyring) {
607 if (!create) 522 if (!create)
608 goto error; 523 goto error;
609 524
610 ret = install_process_keyring(context); 525 ret = install_process_keyring();
611 if (ret < 0) { 526 if (ret < 0) {
612 key = ERR_PTR(ret); 527 key = ERR_PTR(ret);
613 goto error; 528 goto error;
614 } 529 }
530 goto reget_creds;
615 } 531 }
616 532
617 key = context->signal->process_keyring; 533 key = cred->tgcred->process_keyring;
618 atomic_inc(&key->usage); 534 atomic_inc(&key->usage);
619 key_ref = make_key_ref(key, 1); 535 key_ref = make_key_ref(key, 1);
620 break; 536 break;
621 537
622 case KEY_SPEC_SESSION_KEYRING: 538 case KEY_SPEC_SESSION_KEYRING:
623 if (!context->signal->session_keyring) { 539 if (!cred->tgcred->session_keyring) {
624 /* always install a session keyring upon access if one 540 /* always install a session keyring upon access if one
625 * doesn't exist yet */ 541 * doesn't exist yet */
626 ret = install_user_keyrings(context); 542 ret = install_user_keyrings();
627 if (ret < 0) 543 if (ret < 0)
628 goto error; 544 goto error;
629 ret = install_session_keyring( 545 ret = install_session_keyring(
630 context, context->user->session_keyring); 546 cred->user->session_keyring);
547
631 if (ret < 0) 548 if (ret < 0)
632 goto error; 549 goto error;
550 goto reget_creds;
633 } 551 }
634 552
635 rcu_read_lock(); 553 rcu_read_lock();
636 key = rcu_dereference(context->signal->session_keyring); 554 key = rcu_dereference(cred->tgcred->session_keyring);
637 atomic_inc(&key->usage); 555 atomic_inc(&key->usage);
638 rcu_read_unlock(); 556 rcu_read_unlock();
639 key_ref = make_key_ref(key, 1); 557 key_ref = make_key_ref(key, 1);
640 break; 558 break;
641 559
642 case KEY_SPEC_USER_KEYRING: 560 case KEY_SPEC_USER_KEYRING:
643 if (!context->user->uid_keyring) { 561 if (!cred->user->uid_keyring) {
644 ret = install_user_keyrings(context); 562 ret = install_user_keyrings();
645 if (ret < 0) 563 if (ret < 0)
646 goto error; 564 goto error;
647 } 565 }
648 566
649 key = context->user->uid_keyring; 567 key = cred->user->uid_keyring;
650 atomic_inc(&key->usage); 568 atomic_inc(&key->usage);
651 key_ref = make_key_ref(key, 1); 569 key_ref = make_key_ref(key, 1);
652 break; 570 break;
653 571
654 case KEY_SPEC_USER_SESSION_KEYRING: 572 case KEY_SPEC_USER_SESSION_KEYRING:
655 if (!context->user->session_keyring) { 573 if (!cred->user->session_keyring) {
656 ret = install_user_keyrings(context); 574 ret = install_user_keyrings();
657 if (ret < 0) 575 if (ret < 0)
658 goto error; 576 goto error;
659 } 577 }
660 578
661 key = context->user->session_keyring; 579 key = cred->user->session_keyring;
662 atomic_inc(&key->usage); 580 atomic_inc(&key->usage);
663 key_ref = make_key_ref(key, 1); 581 key_ref = make_key_ref(key, 1);
664 break; 582 break;
@@ -669,7 +587,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
669 goto error; 587 goto error;
670 588
671 case KEY_SPEC_REQKEY_AUTH_KEY: 589 case KEY_SPEC_REQKEY_AUTH_KEY:
672 key = context->request_key_auth; 590 key = cred->request_key_auth;
673 if (!key) 591 if (!key)
674 goto error; 592 goto error;
675 593
@@ -677,6 +595,25 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
677 key_ref = make_key_ref(key, 1); 595 key_ref = make_key_ref(key, 1);
678 break; 596 break;
679 597
598 case KEY_SPEC_REQUESTOR_KEYRING:
599 if (!cred->request_key_auth)
600 goto error;
601
602 down_read(&cred->request_key_auth->sem);
603 if (cred->request_key_auth->flags & KEY_FLAG_REVOKED) {
604 key_ref = ERR_PTR(-EKEYREVOKED);
605 key = NULL;
606 } else {
607 rka = cred->request_key_auth->payload.data;
608 key = rka->dest_keyring;
609 atomic_inc(&key->usage);
610 }
611 up_read(&cred->request_key_auth->sem);
612 if (!key)
613 goto error;
614 key_ref = make_key_ref(key, 1);
615 break;
616
680 default: 617 default:
681 key_ref = ERR_PTR(-EINVAL); 618 key_ref = ERR_PTR(-EINVAL);
682 if (id < 1) 619 if (id < 1)
@@ -693,7 +630,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
693 /* check to see if we possess the key */ 630 /* check to see if we possess the key */
694 skey_ref = search_process_keyrings(key->type, key, 631 skey_ref = search_process_keyrings(key->type, key,
695 lookup_user_key_possessed, 632 lookup_user_key_possessed,
696 current); 633 cred);
697 634
698 if (!IS_ERR(skey_ref)) { 635 if (!IS_ERR(skey_ref)) {
699 key_put(key); 636 key_put(key);
@@ -725,11 +662,12 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
725 goto invalid_key; 662 goto invalid_key;
726 663
727 /* check the permissions */ 664 /* check the permissions */
728 ret = key_task_permission(key_ref, context, perm); 665 ret = key_task_permission(key_ref, cred, perm);
729 if (ret < 0) 666 if (ret < 0)
730 goto invalid_key; 667 goto invalid_key;
731 668
732error: 669error:
670 put_cred(cred);
733 return key_ref; 671 return key_ref;
734 672
735invalid_key: 673invalid_key:
@@ -737,6 +675,12 @@ invalid_key:
737 key_ref = ERR_PTR(ret); 675 key_ref = ERR_PTR(ret);
738 goto error; 676 goto error;
739 677
678 /* if we attempted to install a keyring, then it may have caused new
679 * creds to be installed */
680reget_creds:
681 put_cred(cred);
682 goto try_again;
683
740} /* end lookup_user_key() */ 684} /* end lookup_user_key() */
741 685
742/*****************************************************************************/ 686/*****************************************************************************/
@@ -748,20 +692,33 @@ invalid_key:
748 */ 692 */
749long join_session_keyring(const char *name) 693long join_session_keyring(const char *name)
750{ 694{
751 struct task_struct *tsk = current; 695 const struct cred *old;
696 struct cred *new;
752 struct key *keyring; 697 struct key *keyring;
753 long ret; 698 long ret, serial;
699
700 /* only permit this if there's a single thread in the thread group -
701 * this avoids us having to adjust the creds on all threads and risking
702 * ENOMEM */
703 if (!is_single_threaded(current))
704 return -EMLINK;
705
706 new = prepare_creds();
707 if (!new)
708 return -ENOMEM;
709 old = current_cred();
754 710
755 /* if no name is provided, install an anonymous keyring */ 711 /* if no name is provided, install an anonymous keyring */
756 if (!name) { 712 if (!name) {
757 ret = install_session_keyring(tsk, NULL); 713 ret = install_session_keyring_to_cred(new, NULL);
758 if (ret < 0) 714 if (ret < 0)
759 goto error; 715 goto error;
760 716
761 rcu_read_lock(); 717 serial = new->tgcred->session_keyring->serial;
762 ret = rcu_dereference(tsk->signal->session_keyring)->serial; 718 ret = commit_creds(new);
763 rcu_read_unlock(); 719 if (ret == 0)
764 goto error; 720 ret = serial;
721 goto okay;
765 } 722 }
766 723
767 /* allow the user to join or create a named keyring */ 724 /* allow the user to join or create a named keyring */
@@ -771,29 +728,33 @@ long join_session_keyring(const char *name)
771 keyring = find_keyring_by_name(name, false); 728 keyring = find_keyring_by_name(name, false);
772 if (PTR_ERR(keyring) == -ENOKEY) { 729 if (PTR_ERR(keyring) == -ENOKEY) {
773 /* not found - try and create a new one */ 730 /* not found - try and create a new one */
774 keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 731 keyring = keyring_alloc(name, old->uid, old->gid, old,
775 KEY_ALLOC_IN_QUOTA, NULL); 732 KEY_ALLOC_IN_QUOTA, NULL);
776 if (IS_ERR(keyring)) { 733 if (IS_ERR(keyring)) {
777 ret = PTR_ERR(keyring); 734 ret = PTR_ERR(keyring);
778 goto error2; 735 goto error2;
779 } 736 }
780 } 737 } else if (IS_ERR(keyring)) {
781 else if (IS_ERR(keyring)) {
782 ret = PTR_ERR(keyring); 738 ret = PTR_ERR(keyring);
783 goto error2; 739 goto error2;
784 } 740 }
785 741
786 /* we've got a keyring - now to install it */ 742 /* we've got a keyring - now to install it */
787 ret = install_session_keyring(tsk, keyring); 743 ret = install_session_keyring_to_cred(new, keyring);
788 if (ret < 0) 744 if (ret < 0)
789 goto error2; 745 goto error2;
790 746
747 commit_creds(new);
748 mutex_unlock(&key_session_mutex);
749
791 ret = keyring->serial; 750 ret = keyring->serial;
792 key_put(keyring); 751 key_put(keyring);
752okay:
753 return ret;
793 754
794error2: 755error2:
795 mutex_unlock(&key_session_mutex); 756 mutex_unlock(&key_session_mutex);
796error: 757error:
758 abort_creds(new);
797 return ret; 759 return ret;
798 760}
799} /* end join_session_keyring() */