32065f66ded5a3b8860eb27c4c80fba1f11e8106
[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 "../afs/param.h"
15 #include "../afs/sysincludes.h"
16 #include "../afs/afsincludes.h"
17
18 /* Setup a pool for creds. Allocate several at a time. */
19 #define CRED_ALLOC_STEP 29 /* at 140 bytes/cred = 4060 bytes. */
20
21
22 static cred_t *cred_pool = NULL;
23 int cred_allocs = 0;
24 int ncreds_inuse = 0;
25
26 /* Cred locking assumes current single threaded non-preemptive kernel.
27  * Also assuming a fast path through both down and up if no waiters. Otherwise,
28  * test if no creds in pool before grabbing lock in crfree().
29  */
30 static struct semaphore linux_cred_pool_lock = MUTEX;
31 #define CRED_LOCK() down(&linux_cred_pool_lock)
32 #define CRED_UNLOCK() up(&linux_cred_pool_lock)
33
34 cred_t *crget(void)
35 {
36     cred_t *tmp;
37     int i;
38
39     CRED_LOCK();
40     if (!cred_pool) {
41         cred_allocs++;
42         cred_pool = (cred_t*)osi_Alloc(CRED_ALLOC_STEP * sizeof(cred_t));
43         if (!cred_pool)
44             osi_Panic("crget: No more memory for creds!\n");
45         
46         for (i=0; i < CRED_ALLOC_STEP-1; i++)
47             cred_pool[i].cr_ref = (int)&cred_pool[i+1];
48         cred_pool[i].cr_ref = 0;
49     }
50     tmp = cred_pool;
51     cred_pool = (cred_t*)tmp->cr_ref;
52     ncreds_inuse++;
53     CRED_UNLOCK();
54
55     memset(tmp, 0, sizeof(cred_t));
56     tmp->cr_ref = 1;
57     return tmp;
58 }
59
60 void crfree(cred_t *cr)
61 {
62     if (cr->cr_ref > 1) {
63         cr->cr_ref--;
64         return;
65     }
66
67     CRED_LOCK();
68     cr->cr_ref = (int)cred_pool;
69     cred_pool = cr;
70     CRED_UNLOCK();
71     ncreds_inuse --;
72 }
73
74
75 /* Return a duplicate of the cred. */
76 cred_t *crdup(cred_t *cr)
77 {
78     cred_t *tmp = crget();
79     *tmp = *cr;
80     tmp->cr_ref = 1;
81     return tmp;
82 }
83
84 cred_t *crref(void)
85 {
86     cred_t *cr = crget();
87     cr->cr_uid = current->fsuid;
88     cr->cr_ruid = current->uid;
89     cr->cr_gid = current->fsgid;
90     cr->cr_rgid = current->gid;
91     memcpy(cr->cr_groups, current->groups, NGROUPS * sizeof(gid_t));
92     cr->cr_ngroups = current->ngroups;
93     return cr;
94 }
95
96
97 /* Set the cred info into the current task */
98 void crset(cred_t *cr)
99 {
100     current->fsuid = cr->cr_uid;
101     current->uid = cr->cr_ruid;
102     current->fsgid = cr->cr_gid;
103     current->gid = cr->cr_rgid;
104     memcpy(current->groups, cr->cr_groups, NGROUPS * sizeof(gid_t));
105     current->ngroups = cr->cr_ngroups;
106 }