diff options
author | Steve French <sfrench@us.ibm.com> | 2005-09-06 18:47:31 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2005-09-06 18:47:31 -0400 |
commit | c08319a9d50b5c9cb4fdb33728bd16497cf4ddd3 (patch) | |
tree | 5fbec9030029da1ec387c18b85f26f19ee50da44 /security/selinux/ss/conditional.c | |
parent | bfa0d75a1eee59f0577e3c1697ff570b77581a35 (diff) | |
parent | 4706df3d3c42af802597d82c8b1542c3d52eab23 (diff) |
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'security/selinux/ss/conditional.c')
-rw-r--r-- | security/selinux/ss/conditional.c | 215 |
1 files changed, 121 insertions, 94 deletions
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index e2057f5a411a..daf288007460 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c | |||
@@ -100,18 +100,18 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node) | |||
100 | /* turn the rules on or off */ | 100 | /* turn the rules on or off */ |
101 | for (cur = node->true_list; cur != NULL; cur = cur->next) { | 101 | for (cur = node->true_list; cur != NULL; cur = cur->next) { |
102 | if (new_state <= 0) { | 102 | if (new_state <= 0) { |
103 | cur->node->datum.specified &= ~AVTAB_ENABLED; | 103 | cur->node->key.specified &= ~AVTAB_ENABLED; |
104 | } else { | 104 | } else { |
105 | cur->node->datum.specified |= AVTAB_ENABLED; | 105 | cur->node->key.specified |= AVTAB_ENABLED; |
106 | } | 106 | } |
107 | } | 107 | } |
108 | 108 | ||
109 | for (cur = node->false_list; cur != NULL; cur = cur->next) { | 109 | for (cur = node->false_list; cur != NULL; cur = cur->next) { |
110 | /* -1 or 1 */ | 110 | /* -1 or 1 */ |
111 | if (new_state) { | 111 | if (new_state) { |
112 | cur->node->datum.specified &= ~AVTAB_ENABLED; | 112 | cur->node->key.specified &= ~AVTAB_ENABLED; |
113 | } else { | 113 | } else { |
114 | cur->node->datum.specified |= AVTAB_ENABLED; | 114 | cur->node->key.specified |= AVTAB_ENABLED; |
115 | } | 115 | } |
116 | } | 116 | } |
117 | } | 117 | } |
@@ -216,7 +216,8 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) | |||
216 | { | 216 | { |
217 | char *key = NULL; | 217 | char *key = NULL; |
218 | struct cond_bool_datum *booldatum; | 218 | struct cond_bool_datum *booldatum; |
219 | u32 buf[3], len; | 219 | __le32 buf[3]; |
220 | u32 len; | ||
220 | int rc; | 221 | int rc; |
221 | 222 | ||
222 | booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); | 223 | booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); |
@@ -252,104 +253,127 @@ err: | |||
252 | return -1; | 253 | return -1; |
253 | } | 254 | } |
254 | 255 | ||
255 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, | 256 | struct cond_insertf_data |
256 | struct cond_av_list *other) | ||
257 | { | 257 | { |
258 | struct cond_av_list *list, *last = NULL, *cur; | 258 | struct policydb *p; |
259 | struct avtab_key key; | 259 | struct cond_av_list *other; |
260 | struct avtab_datum datum; | 260 | struct cond_av_list *head; |
261 | struct cond_av_list *tail; | ||
262 | }; | ||
263 | |||
264 | static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr) | ||
265 | { | ||
266 | struct cond_insertf_data *data = ptr; | ||
267 | struct policydb *p = data->p; | ||
268 | struct cond_av_list *other = data->other, *list, *cur; | ||
261 | struct avtab_node *node_ptr; | 269 | struct avtab_node *node_ptr; |
262 | int rc; | ||
263 | u32 buf[1], i, len; | ||
264 | u8 found; | 270 | u8 found; |
265 | 271 | ||
266 | *ret_list = NULL; | ||
267 | |||
268 | len = 0; | ||
269 | rc = next_entry(buf, fp, sizeof buf); | ||
270 | if (rc < 0) | ||
271 | return -1; | ||
272 | |||
273 | len = le32_to_cpu(buf[0]); | ||
274 | if (len == 0) { | ||
275 | return 0; | ||
276 | } | ||
277 | 272 | ||
278 | for (i = 0; i < len; i++) { | 273 | /* |
279 | if (avtab_read_item(fp, &datum, &key)) | 274 | * For type rules we have to make certain there aren't any |
275 | * conflicting rules by searching the te_avtab and the | ||
276 | * cond_te_avtab. | ||
277 | */ | ||
278 | if (k->specified & AVTAB_TYPE) { | ||
279 | if (avtab_search(&p->te_avtab, k)) { | ||
280 | printk("security: type rule already exists outside of a conditional."); | ||
280 | goto err; | 281 | goto err; |
281 | 282 | } | |
282 | /* | 283 | /* |
283 | * For type rules we have to make certain there aren't any | 284 | * If we are reading the false list other will be a pointer to |
284 | * conflicting rules by searching the te_avtab and the | 285 | * the true list. We can have duplicate entries if there is only |
285 | * cond_te_avtab. | 286 | * 1 other entry and it is in our true list. |
287 | * | ||
288 | * If we are reading the true list (other == NULL) there shouldn't | ||
289 | * be any other entries. | ||
286 | */ | 290 | */ |
287 | if (datum.specified & AVTAB_TYPE) { | 291 | if (other) { |
288 | if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) { | 292 | node_ptr = avtab_search_node(&p->te_cond_avtab, k); |
289 | printk("security: type rule already exists outside of a conditional."); | 293 | if (node_ptr) { |
290 | goto err; | 294 | if (avtab_search_node_next(node_ptr, k->specified)) { |
291 | } | 295 | printk("security: too many conflicting type rules."); |
292 | /* | 296 | goto err; |
293 | * If we are reading the false list other will be a pointer to | 297 | } |
294 | * the true list. We can have duplicate entries if there is only | 298 | found = 0; |
295 | * 1 other entry and it is in our true list. | 299 | for (cur = other; cur != NULL; cur = cur->next) { |
296 | * | 300 | if (cur->node == node_ptr) { |
297 | * If we are reading the true list (other == NULL) there shouldn't | 301 | found = 1; |
298 | * be any other entries. | 302 | break; |
299 | */ | ||
300 | if (other) { | ||
301 | node_ptr = avtab_search_node(&p->te_cond_avtab, &key, AVTAB_TYPE); | ||
302 | if (node_ptr) { | ||
303 | if (avtab_search_node_next(node_ptr, AVTAB_TYPE)) { | ||
304 | printk("security: too many conflicting type rules."); | ||
305 | goto err; | ||
306 | } | ||
307 | found = 0; | ||
308 | for (cur = other; cur != NULL; cur = cur->next) { | ||
309 | if (cur->node == node_ptr) { | ||
310 | found = 1; | ||
311 | break; | ||
312 | } | ||
313 | } | ||
314 | if (!found) { | ||
315 | printk("security: conflicting type rules."); | ||
316 | goto err; | ||
317 | } | 303 | } |
318 | } | 304 | } |
319 | } else { | 305 | if (!found) { |
320 | if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) { | 306 | printk("security: conflicting type rules.\n"); |
321 | printk("security: conflicting type rules when adding type rule for true."); | ||
322 | goto err; | 307 | goto err; |
323 | } | 308 | } |
324 | } | 309 | } |
310 | } else { | ||
311 | if (avtab_search(&p->te_cond_avtab, k)) { | ||
312 | printk("security: conflicting type rules when adding type rule for true.\n"); | ||
313 | goto err; | ||
314 | } | ||
325 | } | 315 | } |
326 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum); | 316 | } |
327 | if (!node_ptr) { | ||
328 | printk("security: could not insert rule."); | ||
329 | goto err; | ||
330 | } | ||
331 | |||
332 | list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL); | ||
333 | if (!list) | ||
334 | goto err; | ||
335 | memset(list, 0, sizeof(struct cond_av_list)); | ||
336 | |||
337 | list->node = node_ptr; | ||
338 | if (i == 0) | ||
339 | *ret_list = list; | ||
340 | else | ||
341 | last->next = list; | ||
342 | last = list; | ||
343 | 317 | ||
318 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); | ||
319 | if (!node_ptr) { | ||
320 | printk("security: could not insert rule."); | ||
321 | goto err; | ||
344 | } | 322 | } |
345 | 323 | ||
324 | list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL); | ||
325 | if (!list) | ||
326 | goto err; | ||
327 | memset(list, 0, sizeof(*list)); | ||
328 | |||
329 | list->node = node_ptr; | ||
330 | if (!data->head) | ||
331 | data->head = list; | ||
332 | else | ||
333 | data->tail->next = list; | ||
334 | data->tail = list; | ||
346 | return 0; | 335 | return 0; |
336 | |||
347 | err: | 337 | err: |
348 | cond_av_list_destroy(*ret_list); | 338 | cond_av_list_destroy(data->head); |
349 | *ret_list = NULL; | 339 | data->head = NULL; |
350 | return -1; | 340 | return -1; |
351 | } | 341 | } |
352 | 342 | ||
343 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) | ||
344 | { | ||
345 | int i, rc; | ||
346 | __le32 buf[1]; | ||
347 | u32 len; | ||
348 | struct cond_insertf_data data; | ||
349 | |||
350 | *ret_list = NULL; | ||
351 | |||
352 | len = 0; | ||
353 | rc = next_entry(buf, fp, sizeof(u32)); | ||
354 | if (rc < 0) | ||
355 | return -1; | ||
356 | |||
357 | len = le32_to_cpu(buf[0]); | ||
358 | if (len == 0) { | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | data.p = p; | ||
363 | data.other = other; | ||
364 | data.head = NULL; | ||
365 | data.tail = NULL; | ||
366 | for (i = 0; i < len; i++) { | ||
367 | rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data); | ||
368 | if (rc) | ||
369 | return rc; | ||
370 | |||
371 | } | ||
372 | |||
373 | *ret_list = data.head; | ||
374 | return 0; | ||
375 | } | ||
376 | |||
353 | static int expr_isvalid(struct policydb *p, struct cond_expr *expr) | 377 | static int expr_isvalid(struct policydb *p, struct cond_expr *expr) |
354 | { | 378 | { |
355 | if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { | 379 | if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { |
@@ -366,7 +390,8 @@ static int expr_isvalid(struct policydb *p, struct cond_expr *expr) | |||
366 | 390 | ||
367 | static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) | 391 | static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) |
368 | { | 392 | { |
369 | u32 buf[2], len, i; | 393 | __le32 buf[2]; |
394 | u32 len, i; | ||
370 | int rc; | 395 | int rc; |
371 | struct cond_expr *expr = NULL, *last = NULL; | 396 | struct cond_expr *expr = NULL, *last = NULL; |
372 | 397 | ||
@@ -424,7 +449,8 @@ err: | |||
424 | int cond_read_list(struct policydb *p, void *fp) | 449 | int cond_read_list(struct policydb *p, void *fp) |
425 | { | 450 | { |
426 | struct cond_node *node, *last = NULL; | 451 | struct cond_node *node, *last = NULL; |
427 | u32 buf[1], i, len; | 452 | __le32 buf[1]; |
453 | u32 i, len; | ||
428 | int rc; | 454 | int rc; |
429 | 455 | ||
430 | rc = next_entry(buf, fp, sizeof buf); | 456 | rc = next_entry(buf, fp, sizeof buf); |
@@ -452,6 +478,7 @@ int cond_read_list(struct policydb *p, void *fp) | |||
452 | return 0; | 478 | return 0; |
453 | err: | 479 | err: |
454 | cond_list_destroy(p->cond_list); | 480 | cond_list_destroy(p->cond_list); |
481 | p->cond_list = NULL; | ||
455 | return -1; | 482 | return -1; |
456 | } | 483 | } |
457 | 484 | ||
@@ -465,22 +492,22 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi | |||
465 | if(!ctab || !key || !avd) | 492 | if(!ctab || !key || !avd) |
466 | return; | 493 | return; |
467 | 494 | ||
468 | for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL; | 495 | for(node = avtab_search_node(ctab, key); node != NULL; |
469 | node = avtab_search_node_next(node, AVTAB_AV)) { | 496 | node = avtab_search_node_next(node, key->specified)) { |
470 | if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) == | 497 | if ( (u16) (AVTAB_ALLOWED|AVTAB_ENABLED) == |
471 | (node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) | 498 | (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) |
472 | avd->allowed |= avtab_allowed(&node->datum); | 499 | avd->allowed |= node->datum.data; |
473 | if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) == | 500 | if ( (u16) (AVTAB_AUDITDENY|AVTAB_ENABLED) == |
474 | (node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) | 501 | (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) |
475 | /* Since a '0' in an auditdeny mask represents a | 502 | /* Since a '0' in an auditdeny mask represents a |
476 | * permission we do NOT want to audit (dontaudit), we use | 503 | * permission we do NOT want to audit (dontaudit), we use |
477 | * the '&' operand to ensure that all '0's in the mask | 504 | * the '&' operand to ensure that all '0's in the mask |
478 | * are retained (much unlike the allow and auditallow cases). | 505 | * are retained (much unlike the allow and auditallow cases). |
479 | */ | 506 | */ |
480 | avd->auditdeny &= avtab_auditdeny(&node->datum); | 507 | avd->auditdeny &= node->datum.data; |
481 | if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == | 508 | if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == |
482 | (node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) | 509 | (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) |
483 | avd->auditallow |= avtab_auditallow(&node->datum); | 510 | avd->auditallow |= node->datum.data; |
484 | } | 511 | } |
485 | return; | 512 | return; |
486 | } | 513 | } |