diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-16 18:40:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-16 18:40:50 -0500 |
commit | 2a74dbb9a86e8102dcd07d284135b4530a84826e (patch) | |
tree | a54403e312b6062dfb57bd904ba8b8ce3b11e720 /kernel/cred.c | |
parent | 770b6cb4d21fb3e3df2a7a51e186a3c14db1ec30 (diff) | |
parent | e93072374112db9dc86635934ee761249be28370 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
"A quiet cycle for the security subsystem with just a few maintenance
updates."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
Smack: create a sysfs mount point for smackfs
Smack: use select not depends in Kconfig
Yama: remove locking from delete path
Yama: add RCU to drop read locking
drivers/char/tpm: remove tasklet and cleanup
KEYS: Use keyring_alloc() to create special keyrings
KEYS: Reduce initial permissions on keys
KEYS: Make the session and process keyrings per-thread
seccomp: Make syscall skipping and nr changes more consistent
key: Fix resource leak
keys: Fix unreachable code
KEYS: Add payload preparsing opportunity prior to key instantiate or update
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 | ||