debuggers.hg

view xen/xsm/flask/ss/avtab.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
line source
1 /*
2 * Implementation of the access vector table type.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
7 /* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
8 *
9 * Added conditional policy language extensions
10 *
11 * Copyright (C) 2003 Tresys Technology, LLC
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, version 2.
15 */
17 /* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
19 #include <xen/lib.h>
20 #include <asm/byteorder.h>
21 #include <xen/types.h>
22 #include <xen/xmalloc.h>
23 #include <xen/errno.h>
25 #include "avtab.h"
26 #include "policydb.h"
28 #define AVTAB_HASH(keyp) \
29 ((keyp->target_class + \
30 (keyp->target_type << 2) + \
31 (keyp->source_type << 9)) & \
32 AVTAB_HASH_MASK)
34 static struct avtab_node* avtab_insert_node(struct avtab *h, int hvalue,
35 struct avtab_node * prev, struct avtab_node * cur, struct avtab_key *key,
36 struct avtab_datum *datum)
37 {
38 struct avtab_node * newnode;
39 newnode = xmalloc(struct avtab_node);
40 if ( newnode == NULL )
41 return NULL;
42 memset(newnode, 0, sizeof(struct avtab_node));
43 newnode->key = *key;
44 newnode->datum = *datum;
45 if ( prev )
46 {
47 newnode->next = prev->next;
48 prev->next = newnode;
49 }
50 else
51 {
52 newnode->next = h->htable[hvalue];
53 h->htable[hvalue] = newnode;
54 }
56 h->nel++;
57 return newnode;
58 }
60 static int avtab_insert(struct avtab *h, struct avtab_key *key,
61 struct avtab_datum *datum)
62 {
63 int hvalue;
64 struct avtab_node *prev, *cur, *newnode;
65 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
67 if ( !h )
68 return -EINVAL;
70 hvalue = AVTAB_HASH(key);
71 for ( prev = NULL, cur = h->htable[hvalue]; cur;
72 prev = cur, cur = cur->next)
73 {
74 if ( key->source_type == cur->key.source_type &&
75 key->target_type == cur->key.target_type &&
76 key->target_class == cur->key.target_class &&
77 (specified & cur->key.specified) )
78 return -EEXIST;
79 if ( key->source_type < cur->key.source_type )
80 break;
81 if ( key->source_type == cur->key.source_type &&
82 key->target_type < cur->key.target_type )
83 break;
84 if ( key->source_type == cur->key.source_type &&
85 key->target_type == cur->key.target_type &&
86 key->target_class < cur->key.target_class )
87 break;
88 }
90 newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
91 if( !newnode )
92 return -ENOMEM;
94 return 0;
95 }
97 /* Unlike avtab_insert(), this function allow multiple insertions of the same
98 * key/specified mask into the table, as needed by the conditional avtab.
99 * It also returns a pointer to the node inserted.
100 */
101 struct avtab_node * avtab_insert_nonunique(struct avtab * h,
102 struct avtab_key * key, struct avtab_datum * datum)
103 {
104 int hvalue;
105 struct avtab_node *prev, *cur, *newnode;
106 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
108 if ( !h )
109 return NULL;
110 hvalue = AVTAB_HASH(key);
111 for ( prev = NULL, cur = h->htable[hvalue]; cur;
112 prev = cur, cur = cur->next )
113 {
114 if ( key->source_type == cur->key.source_type &&
115 key->target_type == cur->key.target_type &&
116 key->target_class == cur->key.target_class &&
117 (specified & cur->key.specified) )
118 break;
119 if ( key->source_type < cur->key.source_type )
120 break;
121 if ( key->source_type == cur->key.source_type &&
122 key->target_type < cur->key.target_type )
123 break;
124 if ( key->source_type == cur->key.source_type &&
125 key->target_type == cur->key.target_type &&
126 key->target_class < cur->key.target_class )
127 break;
128 }
129 newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
131 return newnode;
132 }
134 struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
135 {
136 int hvalue;
137 struct avtab_node *cur;
138 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
140 if ( !h )
141 return NULL;
143 hvalue = AVTAB_HASH(key);
144 for ( cur = h->htable[hvalue]; cur; cur = cur->next )
145 {
146 if ( key->source_type == cur->key.source_type &&
147 key->target_type == cur->key.target_type &&
148 key->target_class == cur->key.target_class &&
149 (specified & cur->key.specified) )
150 return &cur->datum;
152 if ( key->source_type < cur->key.source_type )
153 break;
154 if ( key->source_type == cur->key.source_type &&
155 key->target_type < cur->key.target_type )
156 break;
157 if ( key->source_type == cur->key.source_type &&
158 key->target_type == cur->key.target_type &&
159 key->target_class < cur->key.target_class )
160 break;
161 }
163 return NULL;
164 }
166 /* This search function returns a node pointer, and can be used in
167 * conjunction with avtab_search_next_node()
168 */
169 struct avtab_node* avtab_search_node(struct avtab *h, struct avtab_key *key)
170 {
171 int hvalue;
172 struct avtab_node *cur;
173 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
175 if ( !h )
176 return NULL;
178 hvalue = AVTAB_HASH(key);
179 for ( cur = h->htable[hvalue]; cur; cur = cur->next )
180 {
181 if ( key->source_type == cur->key.source_type &&
182 key->target_type == cur->key.target_type &&
183 key->target_class == cur->key.target_class &&
184 (specified & cur->key.specified) )
185 return cur;
187 if ( key->source_type < cur->key.source_type )
188 break;
189 if ( key->source_type == cur->key.source_type &&
190 key->target_type < cur->key.target_type )
191 break;
192 if ( key->source_type == cur->key.source_type &&
193 key->target_type == cur->key.target_type &&
194 key->target_class < cur->key.target_class )
195 break;
196 }
197 return NULL;
198 }
200 struct avtab_node* avtab_search_node_next(struct avtab_node *node,
201 int specified)
202 {
203 struct avtab_node *cur;
205 if ( !node )
206 return NULL;
208 specified &= ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
209 for ( cur = node->next; cur; cur = cur->next )
210 {
211 if ( node->key.source_type == cur->key.source_type &&
212 node->key.target_type == cur->key.target_type &&
213 node->key.target_class == cur->key.target_class &&
214 (specified & cur->key.specified) )
215 return cur;
217 if ( node->key.source_type < cur->key.source_type )
218 break;
219 if ( node->key.source_type == cur->key.source_type &&
220 node->key.target_type < cur->key.target_type )
221 break;
222 if ( node->key.source_type == cur->key.source_type &&
223 node->key.target_type == cur->key.target_type &&
224 node->key.target_class < cur->key.target_class )
225 break;
226 }
227 return NULL;
228 }
230 void avtab_destroy(struct avtab *h)
231 {
232 int i;
233 struct avtab_node *cur, *temp;
235 if ( !h || !h->htable )
236 return;
238 for ( i = 0; i < AVTAB_SIZE; i++ )
239 {
240 cur = h->htable[i];
241 while ( cur != NULL )
242 {
243 temp = cur;
244 cur = cur->next;
245 xfree(temp);
246 }
247 h->htable[i] = NULL;
248 }
249 xfree(h->htable);
250 h->htable = NULL;
251 }
254 int avtab_init(struct avtab *h)
255 {
256 int i;
258 h->htable = (void *)xmalloc_array(struct avtab_node, AVTAB_SIZE);
259 if ( !h->htable )
260 return -ENOMEM;
261 for ( i = 0; i < AVTAB_SIZE; i++ )
262 h->htable[i] = NULL;
263 h->nel = 0;
264 return 0;
265 }
267 void avtab_hash_eval(struct avtab *h, char *tag)
268 {
269 int i, chain_len, slots_used, max_chain_len;
270 struct avtab_node *cur;
272 slots_used = 0;
273 max_chain_len = 0;
274 for ( i = 0; i < AVTAB_SIZE; i++ )
275 {
276 cur = h->htable[i];
277 if ( cur )
278 {
279 slots_used++;
280 chain_len = 0;
281 while ( cur )
282 {
283 chain_len++;
284 cur = cur->next;
285 }
287 if ( chain_len > max_chain_len )
288 max_chain_len = chain_len;
289 }
290 }
292 printk(KERN_INFO "%s: %d entries and %d/%d buckets used, longest "
293 "chain length %d\n", tag, h->nel, slots_used, AVTAB_SIZE,
294 max_chain_len);
295 }
297 static uint16_t spec_order[] = {
298 AVTAB_ALLOWED,
299 AVTAB_AUDITDENY,
300 AVTAB_AUDITALLOW,
301 AVTAB_TRANSITION,
302 AVTAB_CHANGE,
303 AVTAB_MEMBER
304 };
306 int avtab_read_item(void *fp, u32 vers, struct avtab *a,
307 int (*insertf)(struct avtab *a, struct avtab_key *k,
308 struct avtab_datum *d, void *p), void *p)
309 {
310 __le16 buf16[4];
311 u16 enabled;
312 __le32 buf32[7];
313 u32 items, items2, val;
314 struct avtab_key key;
315 struct avtab_datum datum;
316 int i, rc;
318 memset(&key, 0, sizeof(struct avtab_key));
319 memset(&datum, 0, sizeof(struct avtab_datum));
321 if ( vers < POLICYDB_VERSION_AVTAB )
322 {
323 rc = next_entry(buf32, fp, sizeof(u32));
324 if ( rc < 0 )
325 {
326 printk(KERN_ERR "security: avtab: truncated entry\n");
327 return -1;
328 }
329 items2 = le32_to_cpu(buf32[0]);
330 if ( items2 > ARRAY_SIZE(buf32) )
331 {
332 printk(KERN_ERR "security: avtab: entry overflow\n");
333 return -1;
335 }
336 rc = next_entry(buf32, fp, sizeof(u32)*items2);
337 if ( rc < 0 )
338 {
339 printk(KERN_ERR "security: avtab: truncated entry\n");
340 return -1;
341 }
342 items = 0;
344 val = le32_to_cpu(buf32[items++]);
345 key.source_type = (u16)val;
346 if ( key.source_type != val )
347 {
348 printk("security: avtab: truncated source type\n");
349 return -1;
350 }
351 val = le32_to_cpu(buf32[items++]);
352 key.target_type = (u16)val;
353 if ( key.target_type != val )
354 {
355 printk("security: avtab: truncated target type\n");
356 return -1;
357 }
358 val = le32_to_cpu(buf32[items++]);
359 key.target_class = (u16)val;
360 if ( key.target_class != val )
361 {
362 printk("security: avtab: truncated target class\n");
363 return -1;
364 }
366 val = le32_to_cpu(buf32[items++]);
367 enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
369 if ( !(val & (AVTAB_AV | AVTAB_TYPE)) )
370 {
371 printk("security: avtab: null entry\n");
372 return -1;
373 }
374 if ( (val & AVTAB_AV) && (val & AVTAB_TYPE) )
375 {
376 printk("security: avtab: entry has both access vectors and types\n");
377 return -1;
378 }
380 for ( i = 0; i < sizeof(spec_order)/sizeof(u16); i++ )
381 {
382 if ( val & spec_order[i] )
383 {
384 key.specified = spec_order[i] | enabled;
385 datum.data = le32_to_cpu(buf32[items++]);
386 rc = insertf(a, &key, &datum, p);
387 if ( rc )
388 return rc;
389 }
390 }
392 if ( items != items2 ) {
393 printk("security: avtab: entry only had %d items, expected %d\n",
394 items2, items);
395 return -1;
396 }
397 return 0;
398 }
400 rc = next_entry(buf16, fp, sizeof(u16)*4);
401 if ( rc < 0 )
402 {
403 printk("security: avtab: truncated entry\n");
404 return -1;
405 }
407 items = 0;
408 key.source_type = le16_to_cpu(buf16[items++]);
409 key.target_type = le16_to_cpu(buf16[items++]);
410 key.target_class = le16_to_cpu(buf16[items++]);
411 key.specified = le16_to_cpu(buf16[items++]);
413 rc = next_entry(buf32, fp, sizeof(u32));
414 if ( rc < 0 )
415 {
416 printk("security: avtab: truncated entry\n");
417 return -1;
418 }
419 datum.data = le32_to_cpu(*buf32);
420 return insertf(a, &key, &datum, p);
421 }
423 static int avtab_insertf(struct avtab *a, struct avtab_key *k,
424 struct avtab_datum *d, void *p)
425 {
426 return avtab_insert(a, k, d);
427 }
429 int avtab_read(struct avtab *a, void *fp, u32 vers)
430 {
431 int rc;
432 __le32 buf[1];
433 u32 nel, i;
435 rc = next_entry(buf, fp, sizeof(u32));
436 if ( rc < 0 )
437 {
438 printk(KERN_ERR "security: avtab: truncated table\n");
439 goto bad;
440 }
441 nel = le32_to_cpu(buf[0]);
442 if ( !nel )
443 {
444 printk(KERN_ERR "security: avtab: table is empty\n");
445 rc = -EINVAL;
446 goto bad;
447 }
448 for ( i = 0; i < nel; i++ )
449 {
450 rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL);
451 if ( rc )
452 {
453 if ( rc == -ENOMEM )
454 printk(KERN_ERR "security: avtab: out of memory\n");
455 else if ( rc == -EEXIST )
456 printk(KERN_ERR "security: avtab: duplicate entry\n");
457 else
458 rc = -EINVAL;
459 goto bad;
460 }
461 }
463 rc = 0;
464 out:
465 return rc;
467 bad:
468 avtab_destroy(a);
469 goto out;
470 }