69b2614965963f4dd660c3496710e8eb8ddec6a5
[openafs.git] / src / afs / LINUX / osi_cred.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * osi_cred.c - Linux cred handling routines.
12  *
13  */
14 #include <afsconfig.h>
15 #include "afs/param.h"
16
17
18 #include "afs/sysincludes.h"
19 #include "afsincludes.h"
20
21 /* Copy one credential structure to another, being careful about references */
22 static inline void
23 afs_copy_creds(cred_t *to_cred, const cred_t *from_cred) {
24     afs_set_cr_uid(to_cred, afs_cr_uid(from_cred));
25     afs_set_cr_gid(to_cred, afs_cr_gid(from_cred));
26     afs_set_cr_ruid(to_cred, afs_cr_ruid(from_cred));
27     afs_set_cr_rgid(to_cred, afs_cr_rgid(from_cred));
28     get_group_info(afs_cr_group_info(from_cred));
29     afs_set_cr_group_info(to_cred, afs_cr_group_info(from_cred));
30 }
31
32 cred_t *
33 crget(void)
34 {
35     cred_t *tmp;
36     
37 #if !defined(GFP_NOFS)
38 #define GFP_NOFS GFP_KERNEL
39 #endif
40     tmp = kmalloc(sizeof(cred_t), GFP_NOFS);
41     memset(tmp, 0, sizeof(cred_t));
42     if (!tmp)
43         osi_Panic("crget: No more memory for creds!\n");
44
45 #if defined(STRUCT_TASK_HAS_CRED)
46     get_cred(tmp);
47 #else
48     tmp->cr_ref = 1;
49 #endif
50     return tmp;
51 }
52
53 void
54 crfree(cred_t * cr)
55 {
56 #if defined(STRUCT_TASK_HAS_CRED)
57     put_cred(cr);
58 #else
59     if (cr->cr_ref > 1) {
60         cr->cr_ref--;
61         return;
62     }
63     put_group_info(afs_cr_group_info(cr));
64     kfree(cr);
65 #endif
66 }
67
68
69 /* Return a duplicate of the cred. */
70 cred_t *
71 crdup(cred_t * cr)
72 {
73     cred_t *tmp = crget();
74 #if defined(STRUCT_TASK_HAS_CRED)
75     afs_copy_creds(tmp, cr);
76 #else
77     afs_set_cr_uid(tmp, afs_cr_uid(cr));
78     afs_set_cr_ruid(tmp, afs_cr_ruid(cr));
79     afs_set_cr_gid(tmp, afs_cr_gid(cr));
80     afs_set_cr_rgid(tmp, afs_cr_rgid(cr));
81
82     get_group_info(afs_cr_group_info(cr));
83     afs_set_cr_group_info(tmp, afs_cr_group_info(cr));
84 #endif
85     return tmp;
86 }
87
88 cred_t *
89 crref(void)
90 {
91 #if defined(STRUCT_TASK_HAS_CRED)
92     return (cred_t *)get_current_cred();
93 #else
94     cred_t *cr = crget();
95
96     afs_set_cr_uid(cr, current_fsuid());
97     afs_set_cr_ruid(cr, current_uid());
98     afs_set_cr_gid(cr, current_fsgid());
99     afs_set_cr_rgid(cr, current_gid());
100
101     task_lock(current);
102     get_group_info(current_group_info());
103     afs_set_cr_group_info(cr, current_group_info());
104     task_unlock(current);
105
106     return cr;
107 #endif
108 }
109
110 /* Set the cred info into the current task */
111 void
112 crset(cred_t * cr)
113 {
114 #if defined(STRUCT_TASK_HAS_CRED)
115     struct cred *new_creds;
116
117     /* If our current task doesn't have identical real and effective
118      * credentials, commit_cred won't let us change them, so we just
119      * bail here.
120      */
121     if (current->cred != current->real_cred)
122         return;
123     new_creds = prepare_creds();
124     /* Drop the reference to group_info - we'll overwrite it in afs_copy_creds */
125     put_group_info(new_creds->group_info);
126     afs_copy_creds(new_creds, current_cred());
127
128     commit_creds(new_creds);
129 #else
130     struct group_info *old_info;
131
132     current->fsuid = afs_cr_uid(cr);
133     current->uid = afs_cr_ruid(cr);
134     current->fsgid = afs_cr_gid(cr);
135     current->gid = afs_cr_rgid(cr);
136
137     get_group_info(afs_cr_group_info(cr));
138     task_lock(current);
139     old_info = current->group_info;
140     current->group_info = afs_cr_group_info(cr);
141     task_unlock(current);
142     put_group_info(old_info);
143 #endif
144 }