aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cred.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:17 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:17 -0500
commitf1752eec6145c97163dbce62d17cf5d928e28a27 (patch)
tree16bc51166d38815092de36a461b845b0b4b522f9 /kernel/cred.c
parentb6dff3ec5e116e3af6f537d4caedcad6b9e5082a (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.c96
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 */
22struct 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 */
36static 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 */
56void __put_cred(struct cred *cred)
57{
58 call_rcu(&cred->rcu, put_cred_rcu);
59}
60EXPORT_SYMBOL(__put_cred);
61
62/*
63 * Copy credentials for the new process created by fork()
64 */
65int 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}