aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/conditional.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/ss/conditional.c')
-rw-r--r--security/selinux/ss/conditional.c205
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
255static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, 255struct 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
263static 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
347err: 336err:
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
342static 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
353static int expr_isvalid(struct policydb *p, struct cond_expr *expr) 375static 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;
453err: 475err:
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}