diff options
Diffstat (limited to 'kernel/cred.c')
| -rw-r--r-- | kernel/cred.c | 127 |
1 files changed, 15 insertions, 112 deletions
diff --git a/kernel/cred.c b/kernel/cred.c index 48cea3da6d05..8888afb846e9 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
| @@ -30,17 +30,6 @@ | |||
| 30 | static struct kmem_cache *cred_jar; | 30 | static 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 | ||
| 36 | static 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 | */ |
| 46 | struct cred init_cred = { | 35 | struct 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 | ||
| 73 | static inline void set_cred_subscribers(struct cred *cred, int n) | 59 | static 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 | ||
| 102 | static 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 | */ | ||
| 118 | static 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 | */ |
| 131 | static void put_cred_rcu(struct rcu_head *rcu) | 87 | static 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 | */ |
| 335 | struct cred *prepare_exec_creds(void) | 284 | struct 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 | */ |
| 384 | int copy_creds(struct task_struct *p, unsigned long clone_flags) | 314 | int 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 | */ |
| 644 | struct cred *prepare_kernel_cred(struct task_struct *daemon) | 561 | struct 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 | ||
