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 struct avtab_node*
32 avtab_insert_node(struct avtab *h, int hvalue, struct avtab_node * prev, struct avtab_node * cur,
33 struct avtab_key *key, struct avtab_datum *datum)
35 struct avtab_node * newnode;
36 newnode = (struct avtab_node *) kmalloc(sizeof(struct avtab_node),GFP_KERNEL);
39 memset(newnode, 0, sizeof(struct avtab_node));
41 newnode->datum = *datum;
43 newnode->next = prev->next;
46 newnode->next = h->htable[hvalue];
47 h->htable[hvalue] = newnode;
54 int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
57 struct avtab_node *prev, *cur, *newnode;
62 hvalue = AVTAB_HASH(key);
63 for (prev = NULL, cur = h->htable[hvalue];
65 prev = cur, cur = cur->next) {
66 if (key->source_type == cur->key.source_type &&
67 key->target_type == cur->key.target_type &&
68 key->target_class == cur->key.target_class &&
69 (datum->specified & cur->datum.specified))
71 if (key->source_type < cur->key.source_type)
73 if (key->source_type == cur->key.source_type &&
74 key->target_type < cur->key.target_type)
76 if (key->source_type == cur->key.source_type &&
77 key->target_type == cur->key.target_type &&
78 key->target_class < cur->key.target_class)
82 newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
89 /* Unlike avtab_insert(), this function allow multiple insertions of the same
90 * key/specified mask into the table, as needed by the conditional avtab.
91 * It also returns a pointer to the node inserted.
94 avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_datum * datum)
97 struct avtab_node *prev, *cur, *newnode;
101 hvalue = AVTAB_HASH(key);
102 for (prev = NULL, cur = h->htable[hvalue];
104 prev = cur, cur = cur->next) {
105 if (key->source_type == cur->key.source_type &&
106 key->target_type == cur->key.target_type &&
107 key->target_class == cur->key.target_class &&
108 (datum->specified & cur->datum.specified))
110 if (key->source_type < cur->key.source_type)
112 if (key->source_type == cur->key.source_type &&
113 key->target_type < cur->key.target_type)
115 if (key->source_type == cur->key.source_type &&
116 key->target_type == cur->key.target_type &&
117 key->target_class < cur->key.target_class)
120 newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
125 struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int specified)
128 struct avtab_node *cur;
133 hvalue = AVTAB_HASH(key);
134 for (cur = h->htable[hvalue]; cur; cur = cur->next) {
135 if (key->source_type == cur->key.source_type &&
136 key->target_type == cur->key.target_type &&
137 key->target_class == cur->key.target_class &&
138 (specified & cur->datum.specified))
141 if (key->source_type < cur->key.source_type)
143 if (key->source_type == cur->key.source_type &&
144 key->target_type < cur->key.target_type)
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)
155 /* This search function returns a node pointer, and can be used in
156 * conjunction with avtab_search_next_node()
159 avtab_search_node(struct avtab *h, struct avtab_key *key, int specified)
162 struct avtab_node *cur;
167 hvalue = AVTAB_HASH(key);
168 for (cur = h->htable[hvalue]; cur; cur = cur->next) {
169 if (key->source_type == cur->key.source_type &&
170 key->target_type == cur->key.target_type &&
171 key->target_class == cur->key.target_class &&
172 (specified & cur->datum.specified))
175 if (key->source_type < cur->key.source_type)
177 if (key->source_type == cur->key.source_type &&
178 key->target_type < cur->key.target_type)
180 if (key->source_type == cur->key.source_type &&
181 key->target_type == cur->key.target_type &&
182 key->target_class < cur->key.target_class)
189 avtab_search_node_next(struct avtab_node *node, int specified)
191 struct avtab_node *cur;
196 for (cur = node->next; cur; cur = cur->next) {
197 if (node->key.source_type == cur->key.source_type &&
198 node->key.target_type == cur->key.target_type &&
199 node->key.target_class == cur->key.target_class &&
200 (specified & cur->datum.specified))
203 if (node->key.source_type < cur->key.source_type)
205 if (node->key.source_type == cur->key.source_type &&
206 node->key.target_type < cur->key.target_type)
208 if (node->key.source_type == cur->key.source_type &&
209 node->key.target_type == cur->key.target_type &&
210 node->key.target_class < cur->key.target_class)
216 void avtab_destroy(struct avtab *h)
219 struct avtab_node *cur, *temp;
221 if (!h || !h->htable)
224 for (i = 0; i < AVTAB_SIZE; i++) {
226 while (cur != NULL) {
238 int avtab_map(struct avtab *h,
239 int (*apply) (struct avtab_key *k,
240 struct avtab_datum *d,
245 struct avtab_node *cur;
250 for (i = 0; i < AVTAB_SIZE; i++) {
252 while (cur != NULL) {
253 ret = apply(&cur->key, &cur->datum, args);
262 int avtab_init(struct avtab *h)
266 h->htable = vmalloc(sizeof(*(h->htable)) * AVTAB_SIZE);
269 for (i = 0; i < AVTAB_SIZE; i++)
275 void avtab_hash_eval(struct avtab *h, char *tag)
277 int i, chain_len, slots_used, max_chain_len;
278 struct avtab_node *cur;
282 for (i = 0; i < AVTAB_SIZE; i++) {
292 if (chain_len > max_chain_len)
293 max_chain_len = chain_len;
297 printk(KERN_INFO "%s: %d entries and %d/%d buckets used, longest "
298 "chain length %d\n", tag, h->nel, slots_used, AVTAB_SIZE,
302 int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey)
307 memset(avkey, 0, sizeof(struct avtab_key));
308 memset(avdatum, 0, sizeof(struct avtab_datum));
310 buf = next_entry(fp, sizeof(__u32));
312 printk(KERN_ERR "security: avtab: truncated entry\n");
315 items2 = le32_to_cpu(buf[0]);
316 buf = next_entry(fp, sizeof(__u32)*items2);
318 printk(KERN_ERR "security: avtab: truncated entry\n");
322 avkey->source_type = le32_to_cpu(buf[items++]);
323 avkey->target_type = le32_to_cpu(buf[items++]);
324 avkey->target_class = le32_to_cpu(buf[items++]);
325 avdatum->specified = le32_to_cpu(buf[items++]);
326 if (!(avdatum->specified & (AVTAB_AV | AVTAB_TYPE))) {
327 printk(KERN_ERR "security: avtab: null entry\n");
330 if ((avdatum->specified & AVTAB_AV) &&
331 (avdatum->specified & AVTAB_TYPE)) {
332 printk(KERN_ERR "security: avtab: entry has both access vectors and types\n");
335 if (avdatum->specified & AVTAB_AV) {
336 if (avdatum->specified & AVTAB_ALLOWED)
337 avtab_allowed(avdatum) = le32_to_cpu(buf[items++]);
338 if (avdatum->specified & AVTAB_AUDITDENY)
339 avtab_auditdeny(avdatum) = le32_to_cpu(buf[items++]);
340 if (avdatum->specified & AVTAB_AUDITALLOW)
341 avtab_auditallow(avdatum) = le32_to_cpu(buf[items++]);
343 if (avdatum->specified & AVTAB_TRANSITION)
344 avtab_transition(avdatum) = le32_to_cpu(buf[items++]);
345 if (avdatum->specified & AVTAB_CHANGE)
346 avtab_change(avdatum) = le32_to_cpu(buf[items++]);
347 if (avdatum->specified & AVTAB_MEMBER)
348 avtab_member(avdatum) = le32_to_cpu(buf[items++]);
350 if (items != items2) {
351 printk(KERN_ERR "security: avtab: entry only had %d items, expected %d\n",
361 int avtab_read(struct avtab *a, void *fp, u32 config)
364 struct avtab_key avkey;
365 struct avtab_datum avdatum;
370 buf = next_entry(fp, sizeof(u32));
372 printk(KERN_ERR "security: avtab: truncated table\n");
375 nel = le32_to_cpu(buf[0]);
377 printk(KERN_ERR "security: avtab: table is empty\n");
380 for (i = 0; i < nel; i++) {
381 if (avtab_read_item(fp, &avdatum, &avkey))
383 rc = avtab_insert(a, &avkey, &avdatum);
386 printk(KERN_ERR "security: avtab: out of memory\n");
388 printk(KERN_ERR "security: avtab: duplicate entry\n");