CRED: Detach the credentials from task_struct
[linux-flexiantxendom0-natty.git] / kernel / cred.c
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 }