diff options
Diffstat (limited to 'security/selinux/ss/conditional.c')
-rw-r--r-- | security/selinux/ss/conditional.c | 205 |
1 files changed, 114 insertions, 91 deletions
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index e2057f5a411a..b81cd6688978 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 | } |
@@ -252,104 +252,126 @@ err: | |||
252 | return -1; | 252 | return -1; |
253 | } | 253 | } |
254 | 254 | ||
255 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, | 255 | struct cond_insertf_data |
256 | struct cond_av_list *other) | ||
257 | { | 256 | { |
258 | struct cond_av_list *list, *last = NULL, *cur; | 257 | struct policydb *p; |
259 | struct avtab_key key; | 258 | struct cond_av_list *other; |
260 | struct avtab_datum datum; | 259 | struct cond_av_list *head; |
260 | struct cond_av_list *tail; | ||
261 | }; | ||
262 | |||
263 | static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr) | ||
264 | { | ||
265 | struct cond_insertf_data *data = ptr; | ||
266 | struct policydb *p = data->p; | ||
267 | struct cond_av_list *other = data->other, *list, *cur; | ||
261 | struct avtab_node *node_ptr; | 268 | struct avtab_node *node_ptr; |
262 | int rc; | ||
263 | u32 buf[1], i, len; | ||
264 | u8 found; | 269 | u8 found; |
265 | 270 | ||
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 | 271 | ||
278 | for (i = 0; i < len; i++) { | 272 | /* |
279 | if (avtab_read_item(fp, &datum, &key)) | 273 | * For type rules we have to make certain there aren't any |
274 | * conflicting rules by searching the te_avtab and the | ||
275 | * cond_te_avtab. | ||
276 | */ | ||
277 | if (k->specified & AVTAB_TYPE) { | ||
278 | if (avtab_search(&p->te_avtab, k)) { | ||
279 | printk("security: type rule already exists outside of a conditional."); | ||
280 | goto err; | 280 | goto err; |
281 | 281 | } | |
282 | /* | 282 | /* |
283 | * For type rules we have to make certain there aren't any | 283 | * If we are reading the false list other will be a pointer to |
284 | * conflicting rules by searching the te_avtab and the | 284 | * the true list. We can have duplicate entries if there is only |
285 | * cond_te_avtab. | 285 | * 1 other entry and it is in our true list. |
286 | * | ||
287 | * If we are reading the true list (other == NULL) there shouldn't | ||
288 | * be any other entries. | ||
286 | */ | 289 | */ |
287 | if (datum.specified & AVTAB_TYPE) { | 290 | if (other) { |
288 | if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) { | 291 | node_ptr = avtab_search_node(&p->te_cond_avtab, k); |
289 | printk("security: type rule already exists outside of a conditional."); | 292 | if (node_ptr) { |
290 | goto err; | 293 | if (avtab_search_node_next(node_ptr, k->specified)) { |
291 | } | 294 | printk("security: too many conflicting type rules."); |
292 | /* | 295 | goto err; |
293 | * If we are reading the false list other will be a pointer to | 296 | } |
294 | * the true list. We can have duplicate entries if there is only | 297 | found = 0; |
295 | * 1 other entry and it is in our true list. | 298 | for (cur = other; cur != NULL; cur = cur->next) { |
296 | * | 299 | if (cur->node == node_ptr) { |
297 | * If we are reading the true list (other == NULL) there shouldn't | 300 | found = 1; |
298 | * be any other entries. | 301 | 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 | } | 302 | } |
318 | } | 303 | } |
319 | } else { | 304 | if (!found) { |
320 | if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) { | 305 | printk("security: conflicting type rules.\n"); |
321 | printk("security: conflicting type rules when adding type rule for true."); | ||
322 | goto err; | 306 | goto err; |
323 | } | 307 | } |
324 | } | 308 | } |
309 | } else { | ||
310 | if (avtab_search(&p->te_cond_avtab, k)) { | ||
311 | printk("security: conflicting type rules when adding type rule for true.\n"); | ||
312 | goto err; | ||
313 | } | ||
325 | } | 314 | } |
326 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum); | 315 | } |
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 | 316 | ||
317 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); | ||
318 | if (!node_ptr) { | ||
319 | printk("security: could not insert rule."); | ||
320 | goto err; | ||
344 | } | 321 | } |
345 | 322 | ||
323 | list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL); | ||
324 | if (!list) | ||
325 | goto err; | ||
326 | memset(list, 0, sizeof(*list)); | ||
327 | |||
328 | list->node = node_ptr; | ||
329 | if (!data->head) | ||
330 | data->head = list; | ||
331 | else | ||
332 | data->tail->next = list; | ||
333 | data->tail = list; | ||
346 | return 0; | 334 | return 0; |
335 | |||
347 | err: | 336 | err: |
348 | cond_av_list_destroy(*ret_list); | 337 | cond_av_list_destroy(data->head); |
349 | *ret_list = NULL; | 338 | data->head = NULL; |
350 | return -1; | 339 | return -1; |
351 | } | 340 | } |
352 | 341 | ||
342 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) | ||
343 | { | ||
344 | int i, rc; | ||
345 | u32 buf[1], len; | ||
346 | struct cond_insertf_data data; | ||
347 | |||
348 | *ret_list = NULL; | ||
349 | |||
350 | len = 0; | ||
351 | rc = next_entry(buf, fp, sizeof(u32)); | ||
352 | if (rc < 0) | ||
353 | return -1; | ||
354 | |||
355 | len = le32_to_cpu(buf[0]); | ||
356 | if (len == 0) { | ||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | data.p = p; | ||
361 | data.other = other; | ||
362 | data.head = NULL; | ||
363 | data.tail = NULL; | ||
364 | for (i = 0; i < len; i++) { | ||
365 | rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data); | ||
366 | if (rc) | ||
367 | return rc; | ||
368 | |||
369 | } | ||
370 | |||
371 | *ret_list = data.head; | ||
372 | return 0; | ||
373 | } | ||
374 | |||
353 | static int expr_isvalid(struct policydb *p, struct cond_expr *expr) | 375 | static int expr_isvalid(struct policydb *p, struct cond_expr *expr) |
354 | { | 376 | { |
355 | if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { | 377 | if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { |
@@ -452,6 +474,7 @@ int cond_read_list(struct policydb *p, void *fp) | |||
452 | return 0; | 474 | return 0; |
453 | err: | 475 | err: |
454 | cond_list_destroy(p->cond_list); | 476 | cond_list_destroy(p->cond_list); |
477 | p->cond_list = NULL; | ||
455 | return -1; | 478 | return -1; |
456 | } | 479 | } |
457 | 480 | ||
@@ -465,22 +488,22 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi | |||
465 | if(!ctab || !key || !avd) | 488 | if(!ctab || !key || !avd) |
466 | return; | 489 | return; |
467 | 490 | ||
468 | for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL; | 491 | for(node = avtab_search_node(ctab, key); node != NULL; |
469 | node = avtab_search_node_next(node, AVTAB_AV)) { | 492 | node = avtab_search_node_next(node, key->specified)) { |
470 | if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) == | 493 | if ( (u16) (AVTAB_ALLOWED|AVTAB_ENABLED) == |
471 | (node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) | 494 | (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) |
472 | avd->allowed |= avtab_allowed(&node->datum); | 495 | avd->allowed |= node->datum.data; |
473 | if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) == | 496 | if ( (u16) (AVTAB_AUDITDENY|AVTAB_ENABLED) == |
474 | (node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) | 497 | (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) |
475 | /* Since a '0' in an auditdeny mask represents a | 498 | /* Since a '0' in an auditdeny mask represents a |
476 | * permission we do NOT want to audit (dontaudit), we use | 499 | * permission we do NOT want to audit (dontaudit), we use |
477 | * the '&' operand to ensure that all '0's in the mask | 500 | * the '&' operand to ensure that all '0's in the mask |
478 | * are retained (much unlike the allow and auditallow cases). | 501 | * are retained (much unlike the allow and auditallow cases). |
479 | */ | 502 | */ |
480 | avd->auditdeny &= avtab_auditdeny(&node->datum); | 503 | avd->auditdeny &= node->datum.data; |
481 | if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == | 504 | if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == |
482 | (node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) | 505 | (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) |
483 | avd->auditallow |= avtab_auditallow(&node->datum); | 506 | avd->auditallow |= node->datum.data; |
484 | } | 507 | } |
485 | return; | 508 | return; |
486 | } | 509 | } |