diff options
author | David Howells <dhowells@redhat.com> | 2008-11-13 18:39:17 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-11-13 18:39:17 -0500 |
commit | f1752eec6145c97163dbce62d17cf5d928e28a27 (patch) | |
tree | 16bc51166d38815092de36a461b845b0b4b522f9 /kernel/cred.c | |
parent | b6dff3ec5e116e3af6f537d4caedcad6b9e5082a (diff) |
CRED: Detach the credentials from task_struct
Detach the credentials from task_struct, duplicating them in copy_process()
and releasing them in __put_task_struct().
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'kernel/cred.c')
-rw-r--r-- | kernel/cred.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/kernel/cred.c b/kernel/cred.c new file mode 100644 index 000000000000..833244a7cb05 --- /dev/null +++ b/kernel/cred.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* Task credentials management | ||
2 | * | ||
3 | * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/cred.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/key.h> | ||
15 | #include <linux/keyctl.h> | ||
16 | #include <linux/init_task.h> | ||
17 | #include <linux/security.h> | ||
18 | |||
19 | /* | ||
20 | * The initial credentials for the initial task | ||
21 | */ | ||
22 | struct cred init_cred = { | ||
23 | .usage = ATOMIC_INIT(3), | ||
24 | .securebits = SECUREBITS_DEFAULT, | ||
25 | .cap_inheritable = CAP_INIT_INH_SET, | ||
26 | .cap_permitted = CAP_FULL_SET, | ||
27 | .cap_effective = CAP_INIT_EFF_SET, | ||
28 | .cap_bset = CAP_INIT_BSET, | ||
29 | .user = INIT_USER, | ||
30 | .group_info = &init_groups, | ||
31 | }; | ||
32 | |||
33 | /* | ||
34 | * The RCU callback to actually dispose of a set of credentials | ||
35 | */ | ||
36 | static void put_cred_rcu(struct rcu_head *rcu) | ||
37 | { | ||
38 | struct cred *cred = container_of(rcu, struct cred, rcu); | ||
39 | |||
40 | BUG_ON(atomic_read(&cred->usage) != 0); | ||
41 | |||
42 | key_put(cred->thread_keyring); | ||
43 | key_put(cred->request_key_auth); | ||
44 | put_group_info(cred->group_info); | ||
45 | free_uid(cred->user); | ||
46 | security_cred_free(cred); | ||
47 | kfree(cred); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * __put_cred - Destroy a set of credentials | ||
52 | * @sec: The record to release | ||
53 | * | ||
54 | * Destroy a set of credentials on which no references remain. | ||
55 | */ | ||
56 | void __put_cred(struct cred *cred) | ||
57 | { | ||
58 | call_rcu(&cred->rcu, put_cred_rcu); | ||
59 | } | ||
60 | EXPORT_SYMBOL(__put_cred); | ||
61 | |||
62 | /* | ||
63 | * Copy credentials for the new process created by fork() | ||
64 | */ | ||
65 | int copy_creds(struct task_struct *p, unsigned long clone_flags) | ||
66 | { | ||
67 | struct cred *pcred; | ||
68 | int ret; | ||
69 | |||
70 | pcred = kmemdup(p->cred, sizeof(*p->cred), GFP_KERNEL); | ||
71 | if (!pcred) | ||
72 | return -ENOMEM; | ||
73 | |||
74 | #ifdef CONFIG_SECURITY | ||
75 | pcred->security = NULL; | ||
76 | #endif | ||
77 | |||
78 | ret = security_cred_alloc(pcred); | ||
79 | if (ret < 0) { | ||
80 | kfree(pcred); | ||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | atomic_set(&pcred->usage, 1); | ||
85 | get_group_info(pcred->group_info); | ||
86 | get_uid(pcred->user); | ||
87 | key_get(pcred->thread_keyring); | ||
88 | key_get(pcred->request_key_auth); | ||
89 | |||
90 | atomic_inc(&pcred->user->processes); | ||
91 | |||
92 | /* RCU assignment is unneeded here as no-one can have accessed this | ||
93 | * pointer yet, barring us */ | ||
94 | p->cred = pcred; | ||
95 | return 0; | ||
96 | } | ||