aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cred.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/cred.c')
-rw-r--r--kernel/cred.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/kernel/cred.c b/kernel/cred.c
index f9a0ce66c9c3..c0a4c12d38b2 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -144,7 +144,10 @@ void __put_cred(struct cred *cred)
144 BUG_ON(cred == current->cred); 144 BUG_ON(cred == current->cred);
145 BUG_ON(cred == current->real_cred); 145 BUG_ON(cred == current->real_cred);
146 146
147 call_rcu(&cred->rcu, put_cred_rcu); 147 if (cred->non_rcu)
148 put_cred_rcu(&cred->rcu);
149 else
150 call_rcu(&cred->rcu, put_cred_rcu);
148} 151}
149EXPORT_SYMBOL(__put_cred); 152EXPORT_SYMBOL(__put_cred);
150 153
@@ -261,6 +264,7 @@ struct cred *prepare_creds(void)
261 old = task->cred; 264 old = task->cred;
262 memcpy(new, old, sizeof(struct cred)); 265 memcpy(new, old, sizeof(struct cred));
263 266
267 new->non_rcu = 0;
264 atomic_set(&new->usage, 1); 268 atomic_set(&new->usage, 1);
265 set_cred_subscribers(new, 0); 269 set_cred_subscribers(new, 0);
266 get_group_info(new->group_info); 270 get_group_info(new->group_info);
@@ -544,7 +548,19 @@ const struct cred *override_creds(const struct cred *new)
544 548
545 validate_creds(old); 549 validate_creds(old);
546 validate_creds(new); 550 validate_creds(new);
547 get_cred(new); 551
552 /*
553 * NOTE! This uses 'get_new_cred()' rather than 'get_cred()'.
554 *
555 * That means that we do not clear the 'non_rcu' flag, since
556 * we are only installing the cred into the thread-synchronous
557 * '->cred' pointer, not the '->real_cred' pointer that is
558 * visible to other threads under RCU.
559 *
560 * Also note that we did validate_creds() manually, not depending
561 * on the validation in 'get_cred()'.
562 */
563 get_new_cred((struct cred *)new);
548 alter_cred_subscribers(new, 1); 564 alter_cred_subscribers(new, 1);
549 rcu_assign_pointer(current->cred, new); 565 rcu_assign_pointer(current->cred, new);
550 alter_cred_subscribers(old, -1); 566 alter_cred_subscribers(old, -1);
@@ -681,6 +697,7 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
681 validate_creds(old); 697 validate_creds(old);
682 698
683 *new = *old; 699 *new = *old;
700 new->non_rcu = 0;
684 atomic_set(&new->usage, 1); 701 atomic_set(&new->usage, 1);
685 set_cred_subscribers(new, 0); 702 set_cred_subscribers(new, 0);
686 get_uid(new->user); 703 get_uid(new->user);