2 * Implementation of the access vector table type.
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
7 /* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
9 * Added conditional policy language extensions
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.
17 #include <linux/kernel.h>
18 #include <linux/slab.h>
19 #include <linux/vmalloc.h>
20 #include <linux/errno.h>
25 #define AVTAB_HASH(keyp) \
26 ((keyp->target_class + \
27 (keyp->target_type << 2) + \
28 (keyp->source_type << 9)) & \
31 static kmem_cache_t
*avtab_node_cachep
;
33 static struct avtab_node
*
34 avtab_insert_node(struct avtab
*h
, int hvalue
,
35 struct avtab_node
* prev
, struct avtab_node
* cur
,
36 struct avtab_key
*key
, struct avtab_datum
*datum
)
38 struct avtab_node
* newnode
;
39 newnode
= kmem_cache_alloc(avtab_node_cachep
, SLAB_KERNEL
);
42 memset(newnode
, 0, sizeof(struct avtab_node
));
44 newnode
->datum
= *datum
;
46 newnode
->next
= prev
->next
;
49 newnode
->next
= h
->htable
[hvalue
];
50 h
->htable
[hvalue
] = newnode
;
57 static int avtab_insert(struct avtab
*h
, struct avtab_key
*key
, struct avtab_datum
*datum
)
60 struct avtab_node
*prev
, *cur
, *newnode
;
65 hvalue
= AVTAB_HASH(key
);
66 for (prev
= NULL
, cur
= h
->htable
[hvalue
];
68 prev
= cur
, cur
= cur
->next
) {
69 if (key
->source_type
== cur
->key
.source_type
&&
70 key
->target_type
== cur
->key
.target_type
&&
71 key
->target_class
== cur
->key
.target_class
&&
72 (datum
->specified
& cur
->datum
.specified
))
74 if (key
->source_type
< cur
->key
.source_type
)
76 if (key
->source_type
== cur
->key
.source_type
&&
77 key
->target_type
< cur
->key
.target_type
)
79 if (key
->source_type
== cur
->key
.source_type
&&
80 key
->target_type
== cur
->key
.target_type
&&
81 key
->target_class
< cur
->key
.target_class
)
85 newnode
= avtab_insert_node(h
, hvalue
, prev
, cur
, key
, datum
);
92 /* Unlike avtab_insert(), this function allow multiple insertions of the same
93 * key/specified mask into the table, as needed by the conditional avtab.
94 * It also returns a pointer to the node inserted.
97 avtab_insert_nonunique(struct avtab
* h
, struct avtab_key
* key
, struct avtab_datum
* datum
)
100 struct avtab_node
*prev
, *cur
, *newnode
;
104 hvalue
= AVTAB_HASH(key
);
105 for (prev
= NULL
, cur
= h
->htable
[hvalue
];
107 prev
= cur
, cur
= cur
->next
) {
108 if (key
->source_type
== cur
->key
.source_type
&&
109 key
->target_type
== cur
->key
.target_type
&&
110 key
->target_class
== cur
->key
.target_class
&&
111 (datum
->specified
& cur
->datum
.specified
))
113 if (key
->source_type
< cur
->key
.source_type
)
115 if (key
->source_type
== cur
->key
.source_type
&&
116 key
->target_type
< cur
->key
.target_type
)
118 if (key
->source_type
== cur
->key
.source_type
&&
119 key
->target_type
== cur
->key
.target_type
&&
120 key
->target_class
< cur
->key
.target_class
)
123 newnode
= avtab_insert_node(h
, hvalue
, prev
, cur
, key
, datum
);
128 struct avtab_datum
*avtab_search(struct avtab
*h
, struct avtab_key
*key
, int specified
)
131 struct avtab_node
*cur
;
136 hvalue
= AVTAB_HASH(key
);
137 for (cur
= h
->htable
[hvalue
]; cur
; cur
= cur
->next
) {
138 if (key
->source_type
== cur
->key
.source_type
&&
139 key
->target_type
== cur
->key
.target_type
&&
140 key
->target_class
== cur
->key
.target_class
&&
141 (specified
& cur
->datum
.specified
))
144 if (key
->source_type
< cur
->key
.source_type
)
146 if (key
->source_type
== cur
->key
.source_type
&&
147 key
->target_type
< cur
->key
.target_type
)
149 if (key
->source_type
== cur
->key
.source_type
&&
150 key
->target_type
== cur
->key
.target_type
&&
151 key
->target_class
< cur
->key
.target_class
)
158 /* This search function returns a node pointer, and can be used in
159 * conjunction with avtab_search_next_node()
162 avtab_search_node(struct avtab
*h
, struct avtab_key
*key
, int specified
)
165 struct avtab_node
*cur
;
170 hvalue
= AVTAB_HASH(key
);
171 for (cur
= h
->htable
[hvalue
]; cur
; cur
= cur
->next
) {
172 if (key
->source_type
== cur
->key
.source_type
&&
173 key
->target_type
== cur
->key
.target_type
&&
174 key
->target_class
== cur
->key
.target_class
&&
175 (specified
& cur
->datum
.specified
))
178 if (key
->source_type
< cur
->key
.source_type
)
180 if (key
->source_type
== cur
->key
.source_type
&&
181 key
->target_type
< cur
->key
.target_type
)
183 if (key
->source_type
== cur
->key
.source_type
&&
184 key
->target_type
== cur
->key
.target_type
&&
185 key
->target_class
< cur
->key
.target_class
)
192 avtab_search_node_next(struct avtab_node
*node
, int specified
)
194 struct avtab_node
*cur
;
199 for (cur
= node
->next
; cur
; cur
= cur
->next
) {
200 if (node
->key
.source_type
== cur
->key
.source_type
&&
201 node
->key
.target_type
== cur
->key
.target_type
&&
202 node
->key
.target_class
== cur
->key
.target_class
&&
203 (specified
& cur
->datum
.specified
))
206 if (node
->key
.source_type
< cur
->key
.source_type
)
208 if (node
->key
.source_type
== cur
->key
.source_type
&&
209 node
->key
.target_type
< cur
->key
.target_type
)
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
)
219 void avtab_destroy(struct avtab
*h
)
222 struct avtab_node
*cur
, *temp
;
224 if (!h
|| !h
->htable
)
227 for (i
= 0; i
< AVTAB_SIZE
; i
++) {
229 while (cur
!= NULL
) {
232 kmem_cache_free(avtab_node_cachep
, temp
);
241 int avtab_init(struct avtab
*h
)
245 h
->htable
= vmalloc(sizeof(*(h
->htable
)) * AVTAB_SIZE
);
248 for (i
= 0; i
< AVTAB_SIZE
; i
++)
254 void avtab_hash_eval(struct avtab
*h
, char *tag
)
256 int i
, chain_len
, slots_used
, max_chain_len
;
257 struct avtab_node
*cur
;
261 for (i
= 0; i
< AVTAB_SIZE
; i
++) {
271 if (chain_len
> max_chain_len
)
272 max_chain_len
= chain_len
;
276 printk(KERN_INFO
"%s: %d entries and %d/%d buckets used, longest "
277 "chain length %d\n", tag
, h
->nel
, slots_used
, AVTAB_SIZE
,
281 int avtab_read_item(void *fp
, struct avtab_datum
*avdatum
, struct avtab_key
*avkey
)
287 memset(avkey
, 0, sizeof(struct avtab_key
));
288 memset(avdatum
, 0, sizeof(struct avtab_datum
));
290 rc
= next_entry(buf
, fp
, sizeof(u32
));
292 printk(KERN_ERR
"security: avtab: truncated entry\n");
295 items2
= le32_to_cpu(buf
[0]);
296 if (items2
> ARRAY_SIZE(buf
)) {
297 printk(KERN_ERR
"security: avtab: entry overflow\n");
300 rc
= next_entry(buf
, fp
, sizeof(u32
)*items2
);
302 printk(KERN_ERR
"security: avtab: truncated entry\n");
306 avkey
->source_type
= le32_to_cpu(buf
[items
++]);
307 avkey
->target_type
= le32_to_cpu(buf
[items
++]);
308 avkey
->target_class
= le32_to_cpu(buf
[items
++]);
309 avdatum
->specified
= le32_to_cpu(buf
[items
++]);
310 if (!(avdatum
->specified
& (AVTAB_AV
| AVTAB_TYPE
))) {
311 printk(KERN_ERR
"security: avtab: null entry\n");
314 if ((avdatum
->specified
& AVTAB_AV
) &&
315 (avdatum
->specified
& AVTAB_TYPE
)) {
316 printk(KERN_ERR
"security: avtab: entry has both access vectors and types\n");
319 if (avdatum
->specified
& AVTAB_AV
) {
320 if (avdatum
->specified
& AVTAB_ALLOWED
)
321 avtab_allowed(avdatum
) = le32_to_cpu(buf
[items
++]);
322 if (avdatum
->specified
& AVTAB_AUDITDENY
)
323 avtab_auditdeny(avdatum
) = le32_to_cpu(buf
[items
++]);
324 if (avdatum
->specified
& AVTAB_AUDITALLOW
)
325 avtab_auditallow(avdatum
) = le32_to_cpu(buf
[items
++]);
327 if (avdatum
->specified
& AVTAB_TRANSITION
)
328 avtab_transition(avdatum
) = le32_to_cpu(buf
[items
++]);
329 if (avdatum
->specified
& AVTAB_CHANGE
)
330 avtab_change(avdatum
) = le32_to_cpu(buf
[items
++]);
331 if (avdatum
->specified
& AVTAB_MEMBER
)
332 avtab_member(avdatum
) = le32_to_cpu(buf
[items
++]);
334 if (items
!= items2
) {
335 printk(KERN_ERR
"security: avtab: entry only had %d items, expected %d\n",
345 int avtab_read(struct avtab
*a
, void *fp
, u32 config
)
348 struct avtab_key avkey
;
349 struct avtab_datum avdatum
;
354 rc
= next_entry(buf
, fp
, sizeof(u32
));
356 printk(KERN_ERR
"security: avtab: truncated table\n");
359 nel
= le32_to_cpu(buf
[0]);
361 printk(KERN_ERR
"security: avtab: table is empty\n");
365 for (i
= 0; i
< nel
; i
++) {
366 if (avtab_read_item(fp
, &avdatum
, &avkey
)) {
370 rc
= avtab_insert(a
, &avkey
, &avdatum
);
373 printk(KERN_ERR
"security: avtab: out of memory\n");
375 printk(KERN_ERR
"security: avtab: duplicate entry\n");
389 void avtab_cache_init(void)
391 avtab_node_cachep
= kmem_cache_create("avtab_node",
392 sizeof(struct avtab_node
),
393 0, SLAB_PANIC
, NULL
, NULL
);
396 void avtab_cache_destroy(void)
398 kmem_cache_destroy (avtab_node_cachep
);