aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/avtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/ss/avtab.c')
-rw-r--r--security/selinux/ss/avtab.c192
1 files changed, 123 insertions, 69 deletions
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index f238c034c44e..2e71af67b5d8 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -58,6 +58,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
58{ 58{
59 int hvalue; 59 int hvalue;
60 struct avtab_node *prev, *cur, *newnode; 60 struct avtab_node *prev, *cur, *newnode;
61 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
61 62
62 if (!h) 63 if (!h)
63 return -EINVAL; 64 return -EINVAL;
@@ -69,7 +70,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
69 if (key->source_type == cur->key.source_type && 70 if (key->source_type == cur->key.source_type &&
70 key->target_type == cur->key.target_type && 71 key->target_type == cur->key.target_type &&
71 key->target_class == cur->key.target_class && 72 key->target_class == cur->key.target_class &&
72 (datum->specified & cur->datum.specified)) 73 (specified & cur->key.specified))
73 return -EEXIST; 74 return -EEXIST;
74 if (key->source_type < cur->key.source_type) 75 if (key->source_type < cur->key.source_type)
75 break; 76 break;
@@ -98,6 +99,7 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da
98{ 99{
99 int hvalue; 100 int hvalue;
100 struct avtab_node *prev, *cur, *newnode; 101 struct avtab_node *prev, *cur, *newnode;
102 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
101 103
102 if (!h) 104 if (!h)
103 return NULL; 105 return NULL;
@@ -108,7 +110,7 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da
108 if (key->source_type == cur->key.source_type && 110 if (key->source_type == cur->key.source_type &&
109 key->target_type == cur->key.target_type && 111 key->target_type == cur->key.target_type &&
110 key->target_class == cur->key.target_class && 112 key->target_class == cur->key.target_class &&
111 (datum->specified & cur->datum.specified)) 113 (specified & cur->key.specified))
112 break; 114 break;
113 if (key->source_type < cur->key.source_type) 115 if (key->source_type < cur->key.source_type)
114 break; 116 break;
@@ -125,10 +127,11 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da
125 return newnode; 127 return newnode;
126} 128}
127 129
128struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int specified) 130struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
129{ 131{
130 int hvalue; 132 int hvalue;
131 struct avtab_node *cur; 133 struct avtab_node *cur;
134 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
132 135
133 if (!h) 136 if (!h)
134 return NULL; 137 return NULL;
@@ -138,7 +141,7 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int spe
138 if (key->source_type == cur->key.source_type && 141 if (key->source_type == cur->key.source_type &&
139 key->target_type == cur->key.target_type && 142 key->target_type == cur->key.target_type &&
140 key->target_class == cur->key.target_class && 143 key->target_class == cur->key.target_class &&
141 (specified & cur->datum.specified)) 144 (specified & cur->key.specified))
142 return &cur->datum; 145 return &cur->datum;
143 146
144 if (key->source_type < cur->key.source_type) 147 if (key->source_type < cur->key.source_type)
@@ -159,10 +162,11 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int spe
159 * conjunction with avtab_search_next_node() 162 * conjunction with avtab_search_next_node()
160 */ 163 */
161struct avtab_node* 164struct avtab_node*
162avtab_search_node(struct avtab *h, struct avtab_key *key, int specified) 165avtab_search_node(struct avtab *h, struct avtab_key *key)
163{ 166{
164 int hvalue; 167 int hvalue;
165 struct avtab_node *cur; 168 struct avtab_node *cur;
169 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
166 170
167 if (!h) 171 if (!h)
168 return NULL; 172 return NULL;
@@ -172,7 +176,7 @@ avtab_search_node(struct avtab *h, struct avtab_key *key, int specified)
172 if (key->source_type == cur->key.source_type && 176 if (key->source_type == cur->key.source_type &&
173 key->target_type == cur->key.target_type && 177 key->target_type == cur->key.target_type &&
174 key->target_class == cur->key.target_class && 178 key->target_class == cur->key.target_class &&
175 (specified & cur->datum.specified)) 179 (specified & cur->key.specified))
176 return cur; 180 return cur;
177 181
178 if (key->source_type < cur->key.source_type) 182 if (key->source_type < cur->key.source_type)
@@ -196,11 +200,12 @@ avtab_search_node_next(struct avtab_node *node, int specified)
196 if (!node) 200 if (!node)
197 return NULL; 201 return NULL;
198 202
203 specified &= ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
199 for (cur = node->next; cur; cur = cur->next) { 204 for (cur = node->next; cur; cur = cur->next) {
200 if (node->key.source_type == cur->key.source_type && 205 if (node->key.source_type == cur->key.source_type &&
201 node->key.target_type == cur->key.target_type && 206 node->key.target_type == cur->key.target_type &&
202 node->key.target_class == cur->key.target_class && 207 node->key.target_class == cur->key.target_class &&
203 (specified & cur->datum.specified)) 208 (specified & cur->key.specified))
204 return cur; 209 return cur;
205 210
206 if (node->key.source_type < cur->key.source_type) 211 if (node->key.source_type < cur->key.source_type)
@@ -278,75 +283,126 @@ void avtab_hash_eval(struct avtab *h, char *tag)
278 max_chain_len); 283 max_chain_len);
279} 284}
280 285
281int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey) 286static uint16_t spec_order[] = {
287 AVTAB_ALLOWED,
288 AVTAB_AUDITDENY,
289 AVTAB_AUDITALLOW,
290 AVTAB_TRANSITION,
291 AVTAB_CHANGE,
292 AVTAB_MEMBER
293};
294
295int avtab_read_item(void *fp, u32 vers, struct avtab *a,
296 int (*insertf)(struct avtab *a, struct avtab_key *k,
297 struct avtab_datum *d, void *p),
298 void *p)
282{ 299{
283 u32 buf[7]; 300 u16 buf16[4], enabled;
284 u32 items, items2; 301 u32 buf32[7], items, items2, val;
285 int rc; 302 struct avtab_key key;
303 struct avtab_datum datum;
304 int i, rc;
305
306 memset(&key, 0, sizeof(struct avtab_key));
307 memset(&datum, 0, sizeof(struct avtab_datum));
308
309 if (vers < POLICYDB_VERSION_AVTAB) {
310 rc = next_entry(buf32, fp, sizeof(u32));
311 if (rc < 0) {
312 printk(KERN_ERR "security: avtab: truncated entry\n");
313 return -1;
314 }
315 items2 = le32_to_cpu(buf32[0]);
316 if (items2 > ARRAY_SIZE(buf32)) {
317 printk(KERN_ERR "security: avtab: entry overflow\n");
318 return -1;
286 319
287 memset(avkey, 0, sizeof(struct avtab_key)); 320 }
288 memset(avdatum, 0, sizeof(struct avtab_datum)); 321 rc = next_entry(buf32, fp, sizeof(u32)*items2);
322 if (rc < 0) {
323 printk(KERN_ERR "security: avtab: truncated entry\n");
324 return -1;
325 }
326 items = 0;
289 327
290 rc = next_entry(buf, fp, sizeof(u32)); 328 val = le32_to_cpu(buf32[items++]);
291 if (rc < 0) { 329 key.source_type = (u16)val;
292 printk(KERN_ERR "security: avtab: truncated entry\n"); 330 if (key.source_type != val) {
293 goto bad; 331 printk("security: avtab: truncated source type\n");
294 } 332 return -1;
295 items2 = le32_to_cpu(buf[0]); 333 }
296 if (items2 > ARRAY_SIZE(buf)) { 334 val = le32_to_cpu(buf32[items++]);
297 printk(KERN_ERR "security: avtab: entry overflow\n"); 335 key.target_type = (u16)val;
298 goto bad; 336 if (key.target_type != val) {
337 printk("security: avtab: truncated target type\n");
338 return -1;
339 }
340 val = le32_to_cpu(buf32[items++]);
341 key.target_class = (u16)val;
342 if (key.target_class != val) {
343 printk("security: avtab: truncated target class\n");
344 return -1;
345 }
346
347 val = le32_to_cpu(buf32[items++]);
348 enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
349
350 if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
351 printk("security: avtab: null entry\n");
352 return -1;
353 }
354 if ((val & AVTAB_AV) &&
355 (val & AVTAB_TYPE)) {
356 printk("security: avtab: entry has both access vectors and types\n");
357 return -1;
358 }
359
360 for (i = 0; i < sizeof(spec_order)/sizeof(u16); i++) {
361 if (val & spec_order[i]) {
362 key.specified = spec_order[i] | enabled;
363 datum.data = le32_to_cpu(buf32[items++]);
364 rc = insertf(a, &key, &datum, p);
365 if (rc) return rc;
366 }
367 }
368
369 if (items != items2) {
370 printk("security: avtab: entry only had %d items, expected %d\n", items2, items);
371 return -1;
372 }
373 return 0;
299 } 374 }
300 rc = next_entry(buf, fp, sizeof(u32)*items2); 375
376 rc = next_entry(buf16, fp, sizeof(u16)*4);
301 if (rc < 0) { 377 if (rc < 0) {
302 printk(KERN_ERR "security: avtab: truncated entry\n"); 378 printk("security: avtab: truncated entry\n");
303 goto bad; 379 return -1;
304 } 380 }
381
305 items = 0; 382 items = 0;
306 avkey->source_type = le32_to_cpu(buf[items++]); 383 key.source_type = le16_to_cpu(buf16[items++]);
307 avkey->target_type = le32_to_cpu(buf[items++]); 384 key.target_type = le16_to_cpu(buf16[items++]);
308 avkey->target_class = le32_to_cpu(buf[items++]); 385 key.target_class = le16_to_cpu(buf16[items++]);
309 avdatum->specified = le32_to_cpu(buf[items++]); 386 key.specified = le16_to_cpu(buf16[items++]);
310 if (!(avdatum->specified & (AVTAB_AV | AVTAB_TYPE))) { 387
311 printk(KERN_ERR "security: avtab: null entry\n"); 388 rc = next_entry(buf32, fp, sizeof(u32));
312 goto bad; 389 if (rc < 0) {
313 } 390 printk("security: avtab: truncated entry\n");
314 if ((avdatum->specified & AVTAB_AV) && 391 return -1;
315 (avdatum->specified & AVTAB_TYPE)) {
316 printk(KERN_ERR "security: avtab: entry has both access vectors and types\n");
317 goto bad;
318 }
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++]);
326 } else {
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++]);
333 }
334 if (items != items2) {
335 printk(KERN_ERR "security: avtab: entry only had %d items, expected %d\n",
336 items2, items);
337 goto bad;
338 } 392 }
393 datum.data = le32_to_cpu(*buf32);
394 return insertf(a, &key, &datum, p);
395}
339 396
340 return 0; 397static int avtab_insertf(struct avtab *a, struct avtab_key *k,
341bad: 398 struct avtab_datum *d, void *p)
342 return -1; 399{
400 return avtab_insert(a, k, d);
343} 401}
344 402
345int avtab_read(struct avtab *a, void *fp, u32 config) 403int avtab_read(struct avtab *a, void *fp, u32 vers)
346{ 404{
347 int rc; 405 int rc;
348 struct avtab_key avkey;
349 struct avtab_datum avdatum;
350 u32 buf[1]; 406 u32 buf[1];
351 u32 nel, i; 407 u32 nel, i;
352 408
@@ -363,16 +419,14 @@ int avtab_read(struct avtab *a, void *fp, u32 config)
363 goto bad; 419 goto bad;
364 } 420 }
365 for (i = 0; i < nel; i++) { 421 for (i = 0; i < nel; i++) {
366 if (avtab_read_item(fp, &avdatum, &avkey)) { 422 rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL);
367 rc = -EINVAL;
368 goto bad;
369 }
370 rc = avtab_insert(a, &avkey, &avdatum);
371 if (rc) { 423 if (rc) {
372 if (rc == -ENOMEM) 424 if (rc == -ENOMEM)
373 printk(KERN_ERR "security: avtab: out of memory\n"); 425 printk(KERN_ERR "security: avtab: out of memory\n");
374 if (rc == -EEXIST) 426 else if (rc == -EEXIST)
375 printk(KERN_ERR "security: avtab: duplicate entry\n"); 427 printk(KERN_ERR "security: avtab: duplicate entry\n");
428 else
429 rc = -EINVAL;
376 goto bad; 430 goto bad;
377 } 431 }
378 } 432 }