debuggers.hg

view xen/xsm/flask/ss/sidtab.c @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children b22f9ab1716a ef3209bb5063
line source
1 /*
2 * Implementation of the SID table type.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
7 /* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
9 #include <xen/lib.h>
10 #include <xen/xmalloc.h>
11 #include <xen/errno.h>
12 #include <xen/spinlock.h>
13 #include "flask.h"
14 #include "security.h"
15 #include "sidtab.h"
17 #define SIDTAB_HASH(sid) (sid & SIDTAB_HASH_MASK)
19 #define INIT_SIDTAB_LOCK(s) spin_lock_init(&s->lock)
20 #define SIDTAB_LOCK(s, x) spin_lock_irqsave(&s->lock, x)
21 #define SIDTAB_UNLOCK(s, x) spin_unlock_irqrestore(&s->lock, x)
23 int sidtab_init(struct sidtab *s)
24 {
25 int i;
27 s->htable = (void *)xmalloc_array(struct sidtab_node, SIDTAB_SIZE);
28 if ( !s->htable )
29 return -ENOMEM;
30 for ( i = 0; i < SIDTAB_SIZE; i++ )
31 s->htable[i] = NULL;
32 s->nel = 0;
33 s->next_sid = 1;
34 s->shutdown = 0;
35 INIT_SIDTAB_LOCK(s);
36 return 0;
37 }
39 int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
40 {
41 int hvalue, rc = 0;
42 struct sidtab_node *prev, *cur, *newnode;
44 if ( !s )
45 {
46 rc = -ENOMEM;
47 goto out;
48 }
50 hvalue = SIDTAB_HASH(sid);
51 prev = NULL;
52 cur = s->htable[hvalue];
53 while ( cur != NULL && sid > cur->sid )
54 {
55 prev = cur;
56 cur = cur->next;
57 }
59 if ( cur && sid == cur->sid )
60 {
61 rc = -EEXIST;
62 goto out;
63 }
65 newnode = xmalloc(struct sidtab_node);
66 if ( newnode == NULL )
67 {
68 rc = -ENOMEM;
69 goto out;
70 }
71 newnode->sid = sid;
72 if ( context_cpy(&newnode->context, context) )
73 {
74 xfree(newnode);
75 rc = -ENOMEM;
76 goto out;
77 }
79 if ( prev )
80 {
81 newnode->next = prev->next;
82 wmb();
83 prev->next = newnode;
84 }
85 else
86 {
87 newnode->next = s->htable[hvalue];
88 wmb();
89 s->htable[hvalue] = newnode;
90 }
92 s->nel++;
93 if ( sid >= s->next_sid )
94 s->next_sid = sid + 1;
95 out:
96 return rc;
97 }
99 struct context *sidtab_search(struct sidtab *s, u32 sid)
100 {
101 int hvalue;
102 struct sidtab_node *cur;
104 if ( !s )
105 return NULL;
107 hvalue = SIDTAB_HASH(sid);
108 cur = s->htable[hvalue];
109 while ( cur != NULL && sid > cur->sid )
110 cur = cur->next;
112 if ( cur == NULL || sid != cur->sid )
113 {
114 /* Remap invalid SIDs to the unlabeled SID. */
115 sid = SECINITSID_UNLABELED;
116 hvalue = SIDTAB_HASH(sid);
117 cur = s->htable[hvalue];
118 while ( cur != NULL && sid > cur->sid )
119 cur = cur->next;
120 if ( !cur || sid != cur->sid )
121 return NULL;
122 }
124 return &cur->context;
125 }
127 int sidtab_map(struct sidtab *s,
128 int (*apply) (u32 sid, struct context *context, void *args), void *args)
129 {
130 int i, rc = 0;
131 struct sidtab_node *cur;
133 if ( !s )
134 goto out;
136 for ( i = 0; i < SIDTAB_SIZE; i++ )
137 {
138 cur = s->htable[i];
139 while ( cur != NULL )
140 {
141 rc = apply(cur->sid, &cur->context, args);
142 if ( rc )
143 goto out;
144 cur = cur->next;
145 }
146 }
147 out:
148 return rc;
149 }
151 void sidtab_map_remove_on_error(struct sidtab *s,
152 int (*apply) (u32 sid, struct context *context, void *args), void *args)
153 {
154 int i, ret;
155 struct sidtab_node *last, *cur, *temp;
157 if ( !s )
158 return;
160 for ( i = 0; i < SIDTAB_SIZE; i++ )
161 {
162 last = NULL;
163 cur = s->htable[i];
164 while ( cur != NULL )
165 {
166 ret = apply(cur->sid, &cur->context, args);
167 if ( ret )
168 {
169 if ( last )
170 {
171 last->next = cur->next;
172 }
173 else
174 {
175 s->htable[i] = cur->next;
176 }
178 temp = cur;
179 cur = cur->next;
180 context_destroy(&temp->context);
181 xfree(temp);
182 s->nel--;
183 }
184 else
185 {
186 last = cur;
187 cur = cur->next;
188 }
189 }
190 }
192 return;
193 }
195 static inline u32 sidtab_search_context(struct sidtab *s,
196 struct context *context)
197 {
198 int i;
199 struct sidtab_node *cur;
201 for ( i = 0; i < SIDTAB_SIZE; i++ )
202 {
203 cur = s->htable[i];
204 while ( cur != NULL )
205 {
206 if ( context_cmp(&cur->context, context) )
207 return cur->sid;
208 cur = cur->next;
209 }
210 }
211 return 0;
212 }
214 int sidtab_context_to_sid(struct sidtab *s, struct context *context,
215 u32 *out_sid)
216 {
217 u32 sid;
218 int ret = 0;
219 unsigned long flags;
221 *out_sid = SECSID_NULL;
223 sid = sidtab_search_context(s, context);
224 if ( !sid )
225 {
226 SIDTAB_LOCK(s, flags);
227 /* Rescan now that we hold the lock. */
228 sid = sidtab_search_context(s, context);
229 if ( sid )
230 goto unlock_out;
231 /* No SID exists for the context. Allocate a new one. */
232 if ( s->next_sid == UINT_MAX || s->shutdown )
233 {
234 ret = -ENOMEM;
235 goto unlock_out;
236 }
237 sid = s->next_sid++;
238 ret = sidtab_insert(s, sid, context);
239 if ( ret )
240 s->next_sid--;
241 unlock_out:
242 SIDTAB_UNLOCK(s, flags);
243 }
245 if ( ret )
246 return ret;
248 *out_sid = sid;
249 return 0;
250 }
252 void sidtab_hash_eval(struct sidtab *h, char *tag)
253 {
254 int i, chain_len, slots_used, max_chain_len;
255 struct sidtab_node *cur;
257 slots_used = 0;
258 max_chain_len = 0;
259 for ( i = 0; i < SIDTAB_SIZE; i++ )
260 {
261 cur = h->htable[i];
262 if ( cur )
263 {
264 slots_used++;
265 chain_len = 0;
266 while ( cur )
267 {
268 chain_len++;
269 cur = cur->next;
270 }
272 if ( chain_len > max_chain_len )
273 max_chain_len = chain_len;
274 }
275 }
277 printk(KERN_INFO "%s: %d entries and %d/%d buckets used, longest "
278 "chain length %d\n", tag, h->nel, slots_used, SIDTAB_SIZE,
279 max_chain_len);
280 }
282 void sidtab_destroy(struct sidtab *s)
283 {
284 int i;
285 struct sidtab_node *cur, *temp;
287 if ( !s )
288 return;
290 for ( i = 0; i < SIDTAB_SIZE; i++ )
291 {
292 cur = s->htable[i];
293 while ( cur != NULL )
294 {
295 temp = cur;
296 cur = cur->next;
297 context_destroy(&temp->context);
298 xfree(temp);
299 }
300 s->htable[i] = NULL;
301 }
302 xfree(s->htable);
303 s->htable = NULL;
304 s->nel = 0;
305 s->next_sid = 1;
306 }
308 void sidtab_set(struct sidtab *dst, struct sidtab *src)
309 {
310 unsigned long flags;
312 SIDTAB_LOCK(src, flags);
313 dst->htable = src->htable;
314 dst->nel = src->nel;
315 dst->next_sid = src->next_sid;
316 dst->shutdown = 0;
317 SIDTAB_UNLOCK(src, flags);
318 }
320 void sidtab_shutdown(struct sidtab *s)
321 {
322 unsigned long flags;
324 SIDTAB_LOCK(s, flags);
325 s->shutdown = 1;
326 SIDTAB_UNLOCK(s, flags);
327 }