aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2012-10-02 14:24:29 -0400
committerDavid Howells <dhowells@redhat.com>2012-10-02 14:24:29 -0400
commit3a50597de8635cd05133bd12c95681c82fe7b878 (patch)
treed81c3e46dcef80fbaf84fdf1e8f43676625bab8e
parenta84a921978b7d56e0e4b87ffaca6367429b4d8ff (diff)
KEYS: Make the session and process keyrings per-thread
Make the session keyring per-thread rather than per-process, but still inherited from the parent thread to solve a problem with PAM and gdm. The problem is that join_session_keyring() will reject attempts to change the session keyring of a multithreaded program but gdm is now multithreaded before it gets to the point of starting PAM and running pam_keyinit to create the session keyring. See: https://bugs.freedesktop.org/show_bug.cgi?id=49211 The reason that join_session_keyring() will only change the session keyring under a single-threaded environment is that it's hard to alter the other thread's credentials to effect the change in a multi-threaded program. The problems are such as: (1) How to prevent two threads both running join_session_keyring() from racing. (2) Another thread's credentials may not be modified directly by this process. (3) The number of threads is uncertain whilst we're not holding the appropriate spinlock, making preallocation slightly tricky. (4) We could use TIF_NOTIFY_RESUME and key_replace_session_keyring() to get another thread to replace its keyring, but that means preallocating for each thread. A reasonable way around this is to make the session keyring per-thread rather than per-process and just document that if you want a common session keyring, you must get it before you spawn any threads - which is the current situation anyway. Whilst we're at it, we can the process keyring behave in the same way. This means we can clean up some of the ickyness in the creds code. Basically, after this patch, the session, process and thread keyrings are about inheritance rules only and not about sharing changes of keyring. Reported-by: Mantas M. <grawity@gmail.com> Signed-off-by: David Howells <dhowells@redhat.com> Tested-by: Ray Strode <rstrode@redhat.com>
-rw-r--r--include/linux/cred.h17
-rw-r--r--kernel/cred.c127
-rw-r--r--security/keys/keyctl.c11
-rw-r--r--security/keys/process_keys.c66
-rw-r--r--security/keys/request_key.c10
5 files changed, 50 insertions, 181 deletions
diff --git a/include/linux/cred.h b/include/linux/cred.h
index ebbed2ce6637..0142aacb70b7 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -77,21 +77,6 @@ extern int in_group_p(kgid_t);
77extern int in_egroup_p(kgid_t); 77extern int in_egroup_p(kgid_t);
78 78
79/* 79/*
80 * The common credentials for a thread group
81 * - shared by CLONE_THREAD
82 */
83#ifdef CONFIG_KEYS
84struct thread_group_cred {
85 atomic_t usage;
86 pid_t tgid; /* thread group process ID */
87 spinlock_t lock;
88 struct key __rcu *session_keyring; /* keyring inherited over fork */
89 struct key *process_keyring; /* keyring private to this process */
90 struct rcu_head rcu; /* RCU deletion hook */
91};
92#endif
93
94/*
95 * The security context of a task 80 * The security context of a task
96 * 81 *
97 * The parts of the context break down into two categories: 82 * The parts of the context break down into two categories:
@@ -139,6 +124,8 @@ struct cred {
139#ifdef CONFIG_KEYS 124#ifdef CONFIG_KEYS
140 unsigned char jit_keyring; /* default keyring to attach requested 125 unsigned char jit_keyring; /* default keyring to attach requested
141 * keys to */ 126 * keys to */
127 struct key __rcu *session_keyring; /* keyring inherited over fork */
128 struct key *process_keyring; /* keyring private to this process */
142 struct key *thread_keyring; /* keyring private to this thread */ 129 struct key *thread_keyring; /* keyring private to this thread */
143 struct key *request_key_auth; /* assumed request_key authority */ 130 struct key *request_key_auth; /* assumed request_key authority */
144 struct thread_group_cred *tgcred; /* thread-group shared credentials */ 131 struct thread_group_cred *tgcred; /* thread-group shared credentials */
diff --git a/kernel/cred.c b/kernel/cred.c
index de728ac50d82..3f7ad1ec2ae4 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -30,17 +30,6 @@
30static struct kmem_cache *cred_jar; 30static struct kmem_cache *cred_jar;
31 31
32/* 32/*
33 * The common credentials for the initial task's thread group
34 */
35#ifdef CONFIG_KEYS
36static struct thread_group_cred init_tgcred = {
37 .usage = ATOMIC_INIT(2),
38 .tgid = 0,
39 .lock = __SPIN_LOCK_UNLOCKED(init_cred.tgcred.lock),
40};
41#endif
42
43/*
44 * The initial credentials for the initial task 33 * The initial credentials for the initial task
45 */ 34 */
46struct cred init_cred = { 35struct cred init_cred = {
@@ -65,9 +54,6 @@ struct cred init_cred = {
65 .user = INIT_USER, 54 .user = INIT_USER,
66 .user_ns = &init_user_ns, 55 .user_ns = &init_user_ns,
67 .group_info = &init_groups, 56 .group_info = &init_groups,
68#ifdef CONFIG_KEYS
69 .tgcred = &init_tgcred,
70#endif
71}; 57};
72 58
73static inline void set_cred_subscribers(struct cred *cred, int n) 59static inline void set_cred_subscribers(struct cred *cred, int n)
@@ -96,36 +82,6 @@ static inline void alter_cred_subscribers(const struct cred *_cred, int n)
96} 82}
97 83
98/* 84/*
99 * Dispose of the shared task group credentials
100 */
101#ifdef CONFIG_KEYS
102static void release_tgcred_rcu(struct rcu_head *rcu)
103{
104 struct thread_group_cred *tgcred =
105 container_of(rcu, struct thread_group_cred, rcu);
106
107 BUG_ON(atomic_read(&tgcred->usage) != 0);
108
109 key_put(tgcred->session_keyring);
110 key_put(tgcred->process_keyring);
111 kfree(tgcred);
112}
113#endif
114
115/*
116 * Release a set of thread group credentials.
117 */
118static void release_tgcred(struct cred *cred)
119{
120#ifdef CONFIG_KEYS
121 struct thread_group_cred *tgcred = cred->tgcred;
122
123 if (atomic_dec_and_test(&tgcred->usage))
124 call_rcu(&tgcred->rcu, release_tgcred_rcu);
125#endif
126}
127
128/*
129 * The RCU callback to actually dispose of a set of credentials 85 * The RCU callback to actually dispose of a set of credentials
130 */ 86 */
131static void put_cred_rcu(struct rcu_head *rcu) 87static void put_cred_rcu(struct rcu_head *rcu)
@@ -150,9 +106,10 @@ static void put_cred_rcu(struct rcu_head *rcu)
150#endif 106#endif
151 107
152 security_cred_free(cred); 108 security_cred_free(cred);
109 key_put(cred->session_keyring);
110 key_put(cred->process_keyring);
153 key_put(cred->thread_keyring); 111 key_put(cred->thread_keyring);
154 key_put(cred->request_key_auth); 112 key_put(cred->request_key_auth);
155 release_tgcred(cred);
156 if (cred->group_info) 113 if (cred->group_info)
157 put_group_info(cred->group_info); 114 put_group_info(cred->group_info);
158 free_uid(cred->user); 115 free_uid(cred->user);
@@ -246,15 +203,6 @@ struct cred *cred_alloc_blank(void)
246 if (!new) 203 if (!new)
247 return NULL; 204 return NULL;
248 205
249#ifdef CONFIG_KEYS
250 new->tgcred = kzalloc(sizeof(*new->tgcred), GFP_KERNEL);
251 if (!new->tgcred) {
252 kmem_cache_free(cred_jar, new);
253 return NULL;
254 }
255 atomic_set(&new->tgcred->usage, 1);
256#endif
257
258 atomic_set(&new->usage, 1); 206 atomic_set(&new->usage, 1);
259#ifdef CONFIG_DEBUG_CREDENTIALS 207#ifdef CONFIG_DEBUG_CREDENTIALS
260 new->magic = CRED_MAGIC; 208 new->magic = CRED_MAGIC;
@@ -308,9 +256,10 @@ struct cred *prepare_creds(void)
308 get_user_ns(new->user_ns); 256 get_user_ns(new->user_ns);
309 257
310#ifdef CONFIG_KEYS 258#ifdef CONFIG_KEYS
259 key_get(new->session_keyring);
260 key_get(new->process_keyring);
311 key_get(new->thread_keyring); 261 key_get(new->thread_keyring);
312 key_get(new->request_key_auth); 262 key_get(new->request_key_auth);
313 atomic_inc(&new->tgcred->usage);
314#endif 263#endif
315 264
316#ifdef CONFIG_SECURITY 265#ifdef CONFIG_SECURITY
@@ -334,39 +283,20 @@ EXPORT_SYMBOL(prepare_creds);
334 */ 283 */
335struct cred *prepare_exec_creds(void) 284struct cred *prepare_exec_creds(void)
336{ 285{
337 struct thread_group_cred *tgcred = NULL;
338 struct cred *new; 286 struct cred *new;
339 287
340#ifdef CONFIG_KEYS
341 tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
342 if (!tgcred)
343 return NULL;
344#endif
345
346 new = prepare_creds(); 288 new = prepare_creds();
347 if (!new) { 289 if (!new)
348 kfree(tgcred);
349 return new; 290 return new;
350 }
351 291
352#ifdef CONFIG_KEYS 292#ifdef CONFIG_KEYS
353 /* newly exec'd tasks don't get a thread keyring */ 293 /* newly exec'd tasks don't get a thread keyring */
354 key_put(new->thread_keyring); 294 key_put(new->thread_keyring);
355 new->thread_keyring = NULL; 295 new->thread_keyring = NULL;
356 296
357 /* create a new per-thread-group creds for all this set of threads to
358 * share */
359 memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred));
360
361 atomic_set(&tgcred->usage, 1);
362 spin_lock_init(&tgcred->lock);
363
364 /* inherit the session keyring; new process keyring */ 297 /* inherit the session keyring; new process keyring */
365 key_get(tgcred->session_keyring); 298 key_put(new->process_keyring);
366 tgcred->process_keyring = NULL; 299 new->process_keyring = NULL;
367
368 release_tgcred(new);
369 new->tgcred = tgcred;
370#endif 300#endif
371 301
372 return new; 302 return new;
@@ -383,9 +313,6 @@ struct cred *prepare_exec_creds(void)
383 */ 313 */
384int copy_creds(struct task_struct *p, unsigned long clone_flags) 314int copy_creds(struct task_struct *p, unsigned long clone_flags)
385{ 315{
386#ifdef CONFIG_KEYS
387 struct thread_group_cred *tgcred;
388#endif
389 struct cred *new; 316 struct cred *new;
390 int ret; 317 int ret;
391 318
@@ -425,22 +352,12 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
425 install_thread_keyring_to_cred(new); 352 install_thread_keyring_to_cred(new);
426 } 353 }
427 354
428 /* we share the process and session keyrings between all the threads in 355 /* The process keyring is only shared between the threads in a process;
429 * a process - this is slightly icky as we violate COW credentials a 356 * anything outside of those threads doesn't inherit.
430 * bit */ 357 */
431 if (!(clone_flags & CLONE_THREAD)) { 358 if (!(clone_flags & CLONE_THREAD)) {
432 tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL); 359 key_put(new->process_keyring);
433 if (!tgcred) { 360 new->process_keyring = NULL;
434 ret = -ENOMEM;
435 goto error_put;
436 }
437 atomic_set(&tgcred->usage, 1);
438 spin_lock_init(&tgcred->lock);
439 tgcred->process_keyring = NULL;
440 tgcred->session_keyring = key_get(new->tgcred->session_keyring);
441
442 release_tgcred(new);
443 new->tgcred = tgcred;
444 } 361 }
445#endif 362#endif
446 363
@@ -643,9 +560,6 @@ void __init cred_init(void)
643 */ 560 */
644struct cred *prepare_kernel_cred(struct task_struct *daemon) 561struct cred *prepare_kernel_cred(struct task_struct *daemon)
645{ 562{
646#ifdef CONFIG_KEYS
647 struct thread_group_cred *tgcred;
648#endif
649 const struct cred *old; 563 const struct cred *old;
650 struct cred *new; 564 struct cred *new;
651 565
@@ -653,14 +567,6 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
653 if (!new) 567 if (!new)
654 return NULL; 568 return NULL;
655 569
656#ifdef CONFIG_KEYS
657 tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
658 if (!tgcred) {
659 kmem_cache_free(cred_jar, new);
660 return NULL;
661 }
662#endif
663
664 kdebug("prepare_kernel_cred() alloc %p", new); 570 kdebug("prepare_kernel_cred() alloc %p", new);
665 571
666 if (daemon) 572 if (daemon)
@@ -678,13 +584,10 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
678 get_group_info(new->group_info); 584 get_group_info(new->group_info);
679 585
680#ifdef CONFIG_KEYS 586#ifdef CONFIG_KEYS
681 atomic_set(&tgcred->usage, 1); 587 new->session_keyring = NULL;
682 spin_lock_init(&tgcred->lock); 588 new->process_keyring = NULL;
683 tgcred->process_keyring = NULL;
684 tgcred->session_keyring = NULL;
685 new->tgcred = tgcred;
686 new->request_key_auth = NULL;
687 new->thread_keyring = NULL; 589 new->thread_keyring = NULL;
590 new->request_key_auth = NULL;
688 new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; 591 new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
689#endif 592#endif
690 593
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index a0d373f76815..65b38417c211 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1475,7 +1475,8 @@ long keyctl_session_to_parent(void)
1475 goto error_keyring; 1475 goto error_keyring;
1476 newwork = &cred->rcu; 1476 newwork = &cred->rcu;
1477 1477
1478 cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); 1478 cred->session_keyring = key_ref_to_ptr(keyring_r);
1479 keyring_r = NULL;
1479 init_task_work(newwork, key_change_session_keyring); 1480 init_task_work(newwork, key_change_session_keyring);
1480 1481
1481 me = current; 1482 me = current;
@@ -1500,7 +1501,7 @@ long keyctl_session_to_parent(void)
1500 mycred = current_cred(); 1501 mycred = current_cred();
1501 pcred = __task_cred(parent); 1502 pcred = __task_cred(parent);
1502 if (mycred == pcred || 1503 if (mycred == pcred ||
1503 mycred->tgcred->session_keyring == pcred->tgcred->session_keyring) { 1504 mycred->session_keyring == pcred->session_keyring) {
1504 ret = 0; 1505 ret = 0;
1505 goto unlock; 1506 goto unlock;
1506 } 1507 }
@@ -1516,9 +1517,9 @@ long keyctl_session_to_parent(void)
1516 goto unlock; 1517 goto unlock;
1517 1518
1518 /* the keyrings must have the same UID */ 1519 /* the keyrings must have the same UID */
1519 if ((pcred->tgcred->session_keyring && 1520 if ((pcred->session_keyring &&
1520 pcred->tgcred->session_keyring->uid != mycred->euid) || 1521 pcred->session_keyring->uid != mycred->euid) ||
1521 mycred->tgcred->session_keyring->uid != mycred->euid) 1522 mycred->session_keyring->uid != mycred->euid)
1522 goto unlock; 1523 goto unlock;
1523 1524
1524 /* cancel an already pending keyring replacement */ 1525 /* cancel an already pending keyring replacement */
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 178b8c3b130a..9de5dc598276 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -169,9 +169,8 @@ static int install_thread_keyring(void)
169int install_process_keyring_to_cred(struct cred *new) 169int install_process_keyring_to_cred(struct cred *new)
170{ 170{
171 struct key *keyring; 171 struct key *keyring;
172 int ret;
173 172
174 if (new->tgcred->process_keyring) 173 if (new->process_keyring)
175 return -EEXIST; 174 return -EEXIST;
176 175
177 keyring = keyring_alloc("_pid", new->uid, new->gid, 176 keyring = keyring_alloc("_pid", new->uid, new->gid,
@@ -179,17 +178,8 @@ int install_process_keyring_to_cred(struct cred *new)
179 if (IS_ERR(keyring)) 178 if (IS_ERR(keyring))
180 return PTR_ERR(keyring); 179 return PTR_ERR(keyring);
181 180
182 spin_lock_irq(&new->tgcred->lock); 181 new->process_keyring = keyring;
183 if (!new->tgcred->process_keyring) { 182 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} 183}
194 184
195/* 185/*
@@ -230,7 +220,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
230 /* create an empty session keyring */ 220 /* create an empty session keyring */
231 if (!keyring) { 221 if (!keyring) {
232 flags = KEY_ALLOC_QUOTA_OVERRUN; 222 flags = KEY_ALLOC_QUOTA_OVERRUN;
233 if (cred->tgcred->session_keyring) 223 if (cred->session_keyring)
234 flags = KEY_ALLOC_IN_QUOTA; 224 flags = KEY_ALLOC_IN_QUOTA;
235 225
236 keyring = keyring_alloc("_ses", cred->uid, cred->gid, 226 keyring = keyring_alloc("_ses", cred->uid, cred->gid,
@@ -242,17 +232,11 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
242 } 232 }
243 233
244 /* install the keyring */ 234 /* install the keyring */
245 spin_lock_irq(&cred->tgcred->lock); 235 old = cred->session_keyring;
246 old = cred->tgcred->session_keyring; 236 rcu_assign_pointer(cred->session_keyring, keyring);
247 rcu_assign_pointer(cred->tgcred->session_keyring, keyring); 237
248 spin_unlock_irq(&cred->tgcred->lock); 238 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); 239 key_put(old);
255 }
256 240
257 return 0; 241 return 0;
258} 242}
@@ -367,9 +351,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
367 } 351 }
368 352
369 /* search the process keyring second */ 353 /* search the process keyring second */
370 if (cred->tgcred->process_keyring) { 354 if (cred->process_keyring) {
371 key_ref = keyring_search_aux( 355 key_ref = keyring_search_aux(
372 make_key_ref(cred->tgcred->process_keyring, 1), 356 make_key_ref(cred->process_keyring, 1),
373 cred, type, description, match, no_state_check); 357 cred, type, description, match, no_state_check);
374 if (!IS_ERR(key_ref)) 358 if (!IS_ERR(key_ref))
375 goto found; 359 goto found;
@@ -388,12 +372,10 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
388 } 372 }
389 373
390 /* search the session keyring */ 374 /* search the session keyring */
391 if (cred->tgcred->session_keyring) { 375 if (cred->session_keyring) {
392 rcu_read_lock(); 376 rcu_read_lock();
393 key_ref = keyring_search_aux( 377 key_ref = keyring_search_aux(
394 make_key_ref(rcu_dereference( 378 make_key_ref(rcu_dereference(cred->session_keyring), 1),
395 cred->tgcred->session_keyring),
396 1),
397 cred, type, description, match, no_state_check); 379 cred, type, description, match, no_state_check);
398 rcu_read_unlock(); 380 rcu_read_unlock();
399 381
@@ -563,7 +545,7 @@ try_again:
563 break; 545 break;
564 546
565 case KEY_SPEC_PROCESS_KEYRING: 547 case KEY_SPEC_PROCESS_KEYRING:
566 if (!cred->tgcred->process_keyring) { 548 if (!cred->process_keyring) {
567 if (!(lflags & KEY_LOOKUP_CREATE)) 549 if (!(lflags & KEY_LOOKUP_CREATE))
568 goto error; 550 goto error;
569 551
@@ -575,13 +557,13 @@ try_again:
575 goto reget_creds; 557 goto reget_creds;
576 } 558 }
577 559
578 key = cred->tgcred->process_keyring; 560 key = cred->process_keyring;
579 atomic_inc(&key->usage); 561 atomic_inc(&key->usage);
580 key_ref = make_key_ref(key, 1); 562 key_ref = make_key_ref(key, 1);
581 break; 563 break;
582 564
583 case KEY_SPEC_SESSION_KEYRING: 565 case KEY_SPEC_SESSION_KEYRING:
584 if (!cred->tgcred->session_keyring) { 566 if (!cred->session_keyring) {
585 /* always install a session keyring upon access if one 567 /* always install a session keyring upon access if one
586 * doesn't exist yet */ 568 * doesn't exist yet */
587 ret = install_user_keyrings(); 569 ret = install_user_keyrings();
@@ -596,7 +578,7 @@ try_again:
596 if (ret < 0) 578 if (ret < 0)
597 goto error; 579 goto error;
598 goto reget_creds; 580 goto reget_creds;
599 } else if (cred->tgcred->session_keyring == 581 } else if (cred->session_keyring ==
600 cred->user->session_keyring && 582 cred->user->session_keyring &&
601 lflags & KEY_LOOKUP_CREATE) { 583 lflags & KEY_LOOKUP_CREATE) {
602 ret = join_session_keyring(NULL); 584 ret = join_session_keyring(NULL);
@@ -606,7 +588,7 @@ try_again:
606 } 588 }
607 589
608 rcu_read_lock(); 590 rcu_read_lock();
609 key = rcu_dereference(cred->tgcred->session_keyring); 591 key = rcu_dereference(cred->session_keyring);
610 atomic_inc(&key->usage); 592 atomic_inc(&key->usage);
611 rcu_read_unlock(); 593 rcu_read_unlock();
612 key_ref = make_key_ref(key, 1); 594 key_ref = make_key_ref(key, 1);
@@ -766,12 +748,6 @@ long join_session_keyring(const char *name)
766 struct key *keyring; 748 struct key *keyring;
767 long ret, serial; 749 long ret, serial;
768 750
769 /* only permit this if there's a single thread in the thread group -
770 * this avoids us having to adjust the creds on all threads and risking
771 * ENOMEM */
772 if (!current_is_single_threaded())
773 return -EMLINK;
774
775 new = prepare_creds(); 751 new = prepare_creds();
776 if (!new) 752 if (!new)
777 return -ENOMEM; 753 return -ENOMEM;
@@ -783,7 +759,7 @@ long join_session_keyring(const char *name)
783 if (ret < 0) 759 if (ret < 0)
784 goto error; 760 goto error;
785 761
786 serial = new->tgcred->session_keyring->serial; 762 serial = new->session_keyring->serial;
787 ret = commit_creds(new); 763 ret = commit_creds(new);
788 if (ret == 0) 764 if (ret == 0)
789 ret = serial; 765 ret = serial;
@@ -806,6 +782,9 @@ long join_session_keyring(const char *name)
806 } else if (IS_ERR(keyring)) { 782 } else if (IS_ERR(keyring)) {
807 ret = PTR_ERR(keyring); 783 ret = PTR_ERR(keyring);
808 goto error2; 784 goto error2;
785 } else if (keyring == new->session_keyring) {
786 ret = 0;
787 goto error2;
809 } 788 }
810 789
811 /* we've got a keyring - now to install it */ 790 /* we've got a keyring - now to install it */
@@ -862,8 +841,7 @@ void key_change_session_keyring(struct callback_head *twork)
862 841
863 new->jit_keyring = old->jit_keyring; 842 new->jit_keyring = old->jit_keyring;
864 new->thread_keyring = key_get(old->thread_keyring); 843 new->thread_keyring = key_get(old->thread_keyring);
865 new->tgcred->tgid = old->tgcred->tgid; 844 new->process_keyring = key_get(old->process_keyring);
866 new->tgcred->process_keyring = key_get(old->tgcred->process_keyring);
867 845
868 security_transfer_creds(new, old); 846 security_transfer_creds(new, old);
869 847
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 000e75017520..275c4f9e4b8c 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -150,12 +150,12 @@ static int call_sbin_request_key(struct key_construction *cons,
150 cred->thread_keyring ? cred->thread_keyring->serial : 0); 150 cred->thread_keyring ? cred->thread_keyring->serial : 0);
151 151
152 prkey = 0; 152 prkey = 0;
153 if (cred->tgcred->process_keyring) 153 if (cred->process_keyring)
154 prkey = cred->tgcred->process_keyring->serial; 154 prkey = cred->process_keyring->serial;
155 sprintf(keyring_str[1], "%d", prkey); 155 sprintf(keyring_str[1], "%d", prkey);
156 156
157 rcu_read_lock(); 157 rcu_read_lock();
158 session = rcu_dereference(cred->tgcred->session_keyring); 158 session = rcu_dereference(cred->session_keyring);
159 if (!session) 159 if (!session)
160 session = cred->user->session_keyring; 160 session = cred->user->session_keyring;
161 sskey = session->serial; 161 sskey = session->serial;
@@ -297,14 +297,14 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
297 break; 297 break;
298 298
299 case KEY_REQKEY_DEFL_PROCESS_KEYRING: 299 case KEY_REQKEY_DEFL_PROCESS_KEYRING:
300 dest_keyring = key_get(cred->tgcred->process_keyring); 300 dest_keyring = key_get(cred->process_keyring);
301 if (dest_keyring) 301 if (dest_keyring)
302 break; 302 break;
303 303
304 case KEY_REQKEY_DEFL_SESSION_KEYRING: 304 case KEY_REQKEY_DEFL_SESSION_KEYRING:
305 rcu_read_lock(); 305 rcu_read_lock();
306 dest_keyring = key_get( 306 dest_keyring = key_get(
307 rcu_dereference(cred->tgcred->session_keyring)); 307 rcu_dereference(cred->session_keyring));
308 rcu_read_unlock(); 308 rcu_read_unlock();
309 309
310 if (dest_keyring) 310 if (dest_keyring)