0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/errno.h>
0010 #include <linux/string.h>
0011 #include <linux/spinlock.h>
0012 #include <linux/slab.h>
0013
0014 #include "security.h"
0015 #include "conditional.h"
0016 #include "services.h"
0017
0018
0019
0020
0021
0022
0023
0024 static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
0025 {
0026 u32 i;
0027 int s[COND_EXPR_MAXDEPTH];
0028 int sp = -1;
0029
0030 if (expr->len == 0)
0031 return -1;
0032
0033 for (i = 0; i < expr->len; i++) {
0034 struct cond_expr_node *node = &expr->nodes[i];
0035
0036 switch (node->expr_type) {
0037 case COND_BOOL:
0038 if (sp == (COND_EXPR_MAXDEPTH - 1))
0039 return -1;
0040 sp++;
0041 s[sp] = p->bool_val_to_struct[node->bool - 1]->state;
0042 break;
0043 case COND_NOT:
0044 if (sp < 0)
0045 return -1;
0046 s[sp] = !s[sp];
0047 break;
0048 case COND_OR:
0049 if (sp < 1)
0050 return -1;
0051 sp--;
0052 s[sp] |= s[sp + 1];
0053 break;
0054 case COND_AND:
0055 if (sp < 1)
0056 return -1;
0057 sp--;
0058 s[sp] &= s[sp + 1];
0059 break;
0060 case COND_XOR:
0061 if (sp < 1)
0062 return -1;
0063 sp--;
0064 s[sp] ^= s[sp + 1];
0065 break;
0066 case COND_EQ:
0067 if (sp < 1)
0068 return -1;
0069 sp--;
0070 s[sp] = (s[sp] == s[sp + 1]);
0071 break;
0072 case COND_NEQ:
0073 if (sp < 1)
0074 return -1;
0075 sp--;
0076 s[sp] = (s[sp] != s[sp + 1]);
0077 break;
0078 default:
0079 return -1;
0080 }
0081 }
0082 return s[0];
0083 }
0084
0085
0086
0087
0088
0089
0090
0091
0092 static void evaluate_cond_node(struct policydb *p, struct cond_node *node)
0093 {
0094 struct avtab_node *avnode;
0095 int new_state;
0096 u32 i;
0097
0098 new_state = cond_evaluate_expr(p, &node->expr);
0099 if (new_state != node->cur_state) {
0100 node->cur_state = new_state;
0101 if (new_state == -1)
0102 pr_err("SELinux: expression result was undefined - disabling all rules.\n");
0103
0104 for (i = 0; i < node->true_list.len; i++) {
0105 avnode = node->true_list.nodes[i];
0106 if (new_state <= 0)
0107 avnode->key.specified &= ~AVTAB_ENABLED;
0108 else
0109 avnode->key.specified |= AVTAB_ENABLED;
0110 }
0111
0112 for (i = 0; i < node->false_list.len; i++) {
0113 avnode = node->false_list.nodes[i];
0114
0115 if (new_state)
0116 avnode->key.specified &= ~AVTAB_ENABLED;
0117 else
0118 avnode->key.specified |= AVTAB_ENABLED;
0119 }
0120 }
0121 }
0122
0123 void evaluate_cond_nodes(struct policydb *p)
0124 {
0125 u32 i;
0126
0127 for (i = 0; i < p->cond_list_len; i++)
0128 evaluate_cond_node(p, &p->cond_list[i]);
0129 }
0130
0131 void cond_policydb_init(struct policydb *p)
0132 {
0133 p->bool_val_to_struct = NULL;
0134 p->cond_list = NULL;
0135 p->cond_list_len = 0;
0136
0137 avtab_init(&p->te_cond_avtab);
0138 }
0139
0140 static void cond_node_destroy(struct cond_node *node)
0141 {
0142 kfree(node->expr.nodes);
0143
0144 kfree(node->true_list.nodes);
0145 kfree(node->false_list.nodes);
0146 }
0147
0148 static void cond_list_destroy(struct policydb *p)
0149 {
0150 u32 i;
0151
0152 for (i = 0; i < p->cond_list_len; i++)
0153 cond_node_destroy(&p->cond_list[i]);
0154 kfree(p->cond_list);
0155 p->cond_list = NULL;
0156 p->cond_list_len = 0;
0157 }
0158
0159 void cond_policydb_destroy(struct policydb *p)
0160 {
0161 kfree(p->bool_val_to_struct);
0162 avtab_destroy(&p->te_cond_avtab);
0163 cond_list_destroy(p);
0164 }
0165
0166 int cond_init_bool_indexes(struct policydb *p)
0167 {
0168 kfree(p->bool_val_to_struct);
0169 p->bool_val_to_struct = kmalloc_array(p->p_bools.nprim,
0170 sizeof(*p->bool_val_to_struct),
0171 GFP_KERNEL);
0172 if (!p->bool_val_to_struct)
0173 return -ENOMEM;
0174 return 0;
0175 }
0176
0177 int cond_destroy_bool(void *key, void *datum, void *p)
0178 {
0179 kfree(key);
0180 kfree(datum);
0181 return 0;
0182 }
0183
0184 int cond_index_bool(void *key, void *datum, void *datap)
0185 {
0186 struct policydb *p;
0187 struct cond_bool_datum *booldatum;
0188
0189 booldatum = datum;
0190 p = datap;
0191
0192 if (!booldatum->value || booldatum->value > p->p_bools.nprim)
0193 return -EINVAL;
0194
0195 p->sym_val_to_name[SYM_BOOLS][booldatum->value - 1] = key;
0196 p->bool_val_to_struct[booldatum->value - 1] = booldatum;
0197
0198 return 0;
0199 }
0200
0201 static int bool_isvalid(struct cond_bool_datum *b)
0202 {
0203 if (!(b->state == 0 || b->state == 1))
0204 return 0;
0205 return 1;
0206 }
0207
0208 int cond_read_bool(struct policydb *p, struct symtab *s, void *fp)
0209 {
0210 char *key = NULL;
0211 struct cond_bool_datum *booldatum;
0212 __le32 buf[3];
0213 u32 len;
0214 int rc;
0215
0216 booldatum = kzalloc(sizeof(*booldatum), GFP_KERNEL);
0217 if (!booldatum)
0218 return -ENOMEM;
0219
0220 rc = next_entry(buf, fp, sizeof(buf));
0221 if (rc)
0222 goto err;
0223
0224 booldatum->value = le32_to_cpu(buf[0]);
0225 booldatum->state = le32_to_cpu(buf[1]);
0226
0227 rc = -EINVAL;
0228 if (!bool_isvalid(booldatum))
0229 goto err;
0230
0231 len = le32_to_cpu(buf[2]);
0232 if (((len == 0) || (len == (u32)-1)))
0233 goto err;
0234
0235 rc = -ENOMEM;
0236 key = kmalloc(len + 1, GFP_KERNEL);
0237 if (!key)
0238 goto err;
0239 rc = next_entry(key, fp, len);
0240 if (rc)
0241 goto err;
0242 key[len] = '\0';
0243 rc = symtab_insert(s, key, booldatum);
0244 if (rc)
0245 goto err;
0246
0247 return 0;
0248 err:
0249 cond_destroy_bool(key, booldatum, NULL);
0250 return rc;
0251 }
0252
0253 struct cond_insertf_data {
0254 struct policydb *p;
0255 struct avtab_node **dst;
0256 struct cond_av_list *other;
0257 };
0258
0259 static int cond_insertf(struct avtab *a, const struct avtab_key *k,
0260 const struct avtab_datum *d, void *ptr)
0261 {
0262 struct cond_insertf_data *data = ptr;
0263 struct policydb *p = data->p;
0264 struct cond_av_list *other = data->other;
0265 struct avtab_node *node_ptr;
0266 u32 i;
0267 bool found;
0268
0269
0270
0271
0272
0273
0274 if (k->specified & AVTAB_TYPE) {
0275 if (avtab_search(&p->te_avtab, k)) {
0276 pr_err("SELinux: type rule already exists outside of a conditional.\n");
0277 return -EINVAL;
0278 }
0279
0280
0281
0282
0283
0284
0285
0286
0287 if (other) {
0288 node_ptr = avtab_search_node(&p->te_cond_avtab, k);
0289 if (node_ptr) {
0290 if (avtab_search_node_next(node_ptr, k->specified)) {
0291 pr_err("SELinux: too many conflicting type rules.\n");
0292 return -EINVAL;
0293 }
0294 found = false;
0295 for (i = 0; i < other->len; i++) {
0296 if (other->nodes[i] == node_ptr) {
0297 found = true;
0298 break;
0299 }
0300 }
0301 if (!found) {
0302 pr_err("SELinux: conflicting type rules.\n");
0303 return -EINVAL;
0304 }
0305 }
0306 } else {
0307 if (avtab_search(&p->te_cond_avtab, k)) {
0308 pr_err("SELinux: conflicting type rules when adding type rule for true.\n");
0309 return -EINVAL;
0310 }
0311 }
0312 }
0313
0314 node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
0315 if (!node_ptr) {
0316 pr_err("SELinux: could not insert rule.\n");
0317 return -ENOMEM;
0318 }
0319
0320 *data->dst = node_ptr;
0321 return 0;
0322 }
0323
0324 static int cond_read_av_list(struct policydb *p, void *fp,
0325 struct cond_av_list *list,
0326 struct cond_av_list *other)
0327 {
0328 int rc;
0329 __le32 buf[1];
0330 u32 i, len;
0331 struct cond_insertf_data data;
0332
0333 rc = next_entry(buf, fp, sizeof(u32));
0334 if (rc)
0335 return rc;
0336
0337 len = le32_to_cpu(buf[0]);
0338 if (len == 0)
0339 return 0;
0340
0341 list->nodes = kcalloc(len, sizeof(*list->nodes), GFP_KERNEL);
0342 if (!list->nodes)
0343 return -ENOMEM;
0344
0345 data.p = p;
0346 data.other = other;
0347 for (i = 0; i < len; i++) {
0348 data.dst = &list->nodes[i];
0349 rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
0350 &data);
0351 if (rc) {
0352 kfree(list->nodes);
0353 list->nodes = NULL;
0354 return rc;
0355 }
0356 }
0357
0358 list->len = len;
0359 return 0;
0360 }
0361
0362 static int expr_node_isvalid(struct policydb *p, struct cond_expr_node *expr)
0363 {
0364 if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
0365 pr_err("SELinux: conditional expressions uses unknown operator.\n");
0366 return 0;
0367 }
0368
0369 if (expr->bool > p->p_bools.nprim) {
0370 pr_err("SELinux: conditional expressions uses unknown bool.\n");
0371 return 0;
0372 }
0373 return 1;
0374 }
0375
0376 static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
0377 {
0378 __le32 buf[2];
0379 u32 i, len;
0380 int rc;
0381
0382 rc = next_entry(buf, fp, sizeof(u32) * 2);
0383 if (rc)
0384 return rc;
0385
0386 node->cur_state = le32_to_cpu(buf[0]);
0387
0388
0389 len = le32_to_cpu(buf[1]);
0390 node->expr.nodes = kcalloc(len, sizeof(*node->expr.nodes), GFP_KERNEL);
0391 if (!node->expr.nodes)
0392 return -ENOMEM;
0393
0394 node->expr.len = len;
0395
0396 for (i = 0; i < len; i++) {
0397 struct cond_expr_node *expr = &node->expr.nodes[i];
0398
0399 rc = next_entry(buf, fp, sizeof(u32) * 2);
0400 if (rc)
0401 return rc;
0402
0403 expr->expr_type = le32_to_cpu(buf[0]);
0404 expr->bool = le32_to_cpu(buf[1]);
0405
0406 if (!expr_node_isvalid(p, expr))
0407 return -EINVAL;
0408 }
0409
0410 rc = cond_read_av_list(p, fp, &node->true_list, NULL);
0411 if (rc)
0412 return rc;
0413 return cond_read_av_list(p, fp, &node->false_list, &node->true_list);
0414 }
0415
0416 int cond_read_list(struct policydb *p, void *fp)
0417 {
0418 __le32 buf[1];
0419 u32 i, len;
0420 int rc;
0421
0422 rc = next_entry(buf, fp, sizeof(buf));
0423 if (rc)
0424 return rc;
0425
0426 len = le32_to_cpu(buf[0]);
0427
0428 p->cond_list = kcalloc(len, sizeof(*p->cond_list), GFP_KERNEL);
0429 if (!p->cond_list)
0430 return -ENOMEM;
0431
0432 rc = avtab_alloc(&(p->te_cond_avtab), p->te_avtab.nel);
0433 if (rc)
0434 goto err;
0435
0436 p->cond_list_len = len;
0437
0438 for (i = 0; i < len; i++) {
0439 rc = cond_read_node(p, &p->cond_list[i], fp);
0440 if (rc)
0441 goto err;
0442 }
0443 return 0;
0444 err:
0445 cond_list_destroy(p);
0446 return rc;
0447 }
0448
0449 int cond_write_bool(void *vkey, void *datum, void *ptr)
0450 {
0451 char *key = vkey;
0452 struct cond_bool_datum *booldatum = datum;
0453 struct policy_data *pd = ptr;
0454 void *fp = pd->fp;
0455 __le32 buf[3];
0456 u32 len;
0457 int rc;
0458
0459 len = strlen(key);
0460 buf[0] = cpu_to_le32(booldatum->value);
0461 buf[1] = cpu_to_le32(booldatum->state);
0462 buf[2] = cpu_to_le32(len);
0463 rc = put_entry(buf, sizeof(u32), 3, fp);
0464 if (rc)
0465 return rc;
0466 rc = put_entry(key, 1, len, fp);
0467 if (rc)
0468 return rc;
0469 return 0;
0470 }
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481 static int cond_write_av_list(struct policydb *p,
0482 struct cond_av_list *list, struct policy_file *fp)
0483 {
0484 __le32 buf[1];
0485 u32 i;
0486 int rc;
0487
0488 buf[0] = cpu_to_le32(list->len);
0489 rc = put_entry(buf, sizeof(u32), 1, fp);
0490 if (rc)
0491 return rc;
0492
0493 for (i = 0; i < list->len; i++) {
0494 rc = avtab_write_item(p, list->nodes[i], fp);
0495 if (rc)
0496 return rc;
0497 }
0498
0499 return 0;
0500 }
0501
0502 static int cond_write_node(struct policydb *p, struct cond_node *node,
0503 struct policy_file *fp)
0504 {
0505 __le32 buf[2];
0506 int rc;
0507 u32 i;
0508
0509 buf[0] = cpu_to_le32(node->cur_state);
0510 rc = put_entry(buf, sizeof(u32), 1, fp);
0511 if (rc)
0512 return rc;
0513
0514 buf[0] = cpu_to_le32(node->expr.len);
0515 rc = put_entry(buf, sizeof(u32), 1, fp);
0516 if (rc)
0517 return rc;
0518
0519 for (i = 0; i < node->expr.len; i++) {
0520 buf[0] = cpu_to_le32(node->expr.nodes[i].expr_type);
0521 buf[1] = cpu_to_le32(node->expr.nodes[i].bool);
0522 rc = put_entry(buf, sizeof(u32), 2, fp);
0523 if (rc)
0524 return rc;
0525 }
0526
0527 rc = cond_write_av_list(p, &node->true_list, fp);
0528 if (rc)
0529 return rc;
0530 rc = cond_write_av_list(p, &node->false_list, fp);
0531 if (rc)
0532 return rc;
0533
0534 return 0;
0535 }
0536
0537 int cond_write_list(struct policydb *p, void *fp)
0538 {
0539 u32 i;
0540 __le32 buf[1];
0541 int rc;
0542
0543 buf[0] = cpu_to_le32(p->cond_list_len);
0544 rc = put_entry(buf, sizeof(u32), 1, fp);
0545 if (rc)
0546 return rc;
0547
0548 for (i = 0; i < p->cond_list_len; i++) {
0549 rc = cond_write_node(p, &p->cond_list[i], fp);
0550 if (rc)
0551 return rc;
0552 }
0553
0554 return 0;
0555 }
0556
0557 void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key,
0558 struct extended_perms_decision *xpermd)
0559 {
0560 struct avtab_node *node;
0561
0562 if (!ctab || !key || !xpermd)
0563 return;
0564
0565 for (node = avtab_search_node(ctab, key); node;
0566 node = avtab_search_node_next(node, key->specified)) {
0567 if (node->key.specified & AVTAB_ENABLED)
0568 services_compute_xperms_decision(xpermd, node);
0569 }
0570 }
0571
0572
0573
0574 void cond_compute_av(struct avtab *ctab, struct avtab_key *key,
0575 struct av_decision *avd, struct extended_perms *xperms)
0576 {
0577 struct avtab_node *node;
0578
0579 if (!ctab || !key || !avd)
0580 return;
0581
0582 for (node = avtab_search_node(ctab, key); node;
0583 node = avtab_search_node_next(node, key->specified)) {
0584 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) ==
0585 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
0586 avd->allowed |= node->datum.u.data;
0587 if ((u16)(AVTAB_AUDITDENY|AVTAB_ENABLED) ==
0588 (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
0589
0590
0591
0592
0593
0594 avd->auditdeny &= node->datum.u.data;
0595 if ((u16)(AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
0596 (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
0597 avd->auditallow |= node->datum.u.data;
0598 if (xperms && (node->key.specified & AVTAB_ENABLED) &&
0599 (node->key.specified & AVTAB_XPERMS))
0600 services_compute_xperms_drivers(xperms, node);
0601 }
0602 }
0603
0604 static int cond_dup_av_list(struct cond_av_list *new,
0605 struct cond_av_list *orig,
0606 struct avtab *avtab)
0607 {
0608 u32 i;
0609
0610 memset(new, 0, sizeof(*new));
0611
0612 new->nodes = kcalloc(orig->len, sizeof(*new->nodes), GFP_KERNEL);
0613 if (!new->nodes)
0614 return -ENOMEM;
0615
0616 for (i = 0; i < orig->len; i++) {
0617 new->nodes[i] = avtab_insert_nonunique(avtab,
0618 &orig->nodes[i]->key,
0619 &orig->nodes[i]->datum);
0620 if (!new->nodes[i])
0621 return -ENOMEM;
0622 new->len++;
0623 }
0624
0625 return 0;
0626 }
0627
0628 static int duplicate_policydb_cond_list(struct policydb *newp,
0629 struct policydb *origp)
0630 {
0631 int rc;
0632 u32 i;
0633
0634 rc = avtab_alloc_dup(&newp->te_cond_avtab, &origp->te_cond_avtab);
0635 if (rc)
0636 return rc;
0637
0638 newp->cond_list_len = 0;
0639 newp->cond_list = kcalloc(origp->cond_list_len,
0640 sizeof(*newp->cond_list),
0641 GFP_KERNEL);
0642 if (!newp->cond_list)
0643 goto error;
0644
0645 for (i = 0; i < origp->cond_list_len; i++) {
0646 struct cond_node *newn = &newp->cond_list[i];
0647 struct cond_node *orign = &origp->cond_list[i];
0648
0649 newp->cond_list_len++;
0650
0651 newn->cur_state = orign->cur_state;
0652 newn->expr.nodes = kmemdup(orign->expr.nodes,
0653 orign->expr.len * sizeof(*orign->expr.nodes),
0654 GFP_KERNEL);
0655 if (!newn->expr.nodes)
0656 goto error;
0657
0658 newn->expr.len = orign->expr.len;
0659
0660 rc = cond_dup_av_list(&newn->true_list, &orign->true_list,
0661 &newp->te_cond_avtab);
0662 if (rc)
0663 goto error;
0664
0665 rc = cond_dup_av_list(&newn->false_list, &orign->false_list,
0666 &newp->te_cond_avtab);
0667 if (rc)
0668 goto error;
0669 }
0670
0671 return 0;
0672
0673 error:
0674 avtab_destroy(&newp->te_cond_avtab);
0675 cond_list_destroy(newp);
0676 return -ENOMEM;
0677 }
0678
0679 static int cond_bools_destroy(void *key, void *datum, void *args)
0680 {
0681
0682 kfree(datum);
0683 return 0;
0684 }
0685
0686 static int cond_bools_copy(struct hashtab_node *new, struct hashtab_node *orig, void *args)
0687 {
0688 struct cond_bool_datum *datum;
0689
0690 datum = kmemdup(orig->datum, sizeof(struct cond_bool_datum),
0691 GFP_KERNEL);
0692 if (!datum)
0693 return -ENOMEM;
0694
0695 new->key = orig->key;
0696 new->datum = datum;
0697 return 0;
0698 }
0699
0700 static int cond_bools_index(void *key, void *datum, void *args)
0701 {
0702 struct cond_bool_datum *booldatum, **cond_bool_array;
0703
0704 booldatum = datum;
0705 cond_bool_array = args;
0706 cond_bool_array[booldatum->value - 1] = booldatum;
0707
0708 return 0;
0709 }
0710
0711 static int duplicate_policydb_bools(struct policydb *newdb,
0712 struct policydb *orig)
0713 {
0714 struct cond_bool_datum **cond_bool_array;
0715 int rc;
0716
0717 cond_bool_array = kmalloc_array(orig->p_bools.nprim,
0718 sizeof(*orig->bool_val_to_struct),
0719 GFP_KERNEL);
0720 if (!cond_bool_array)
0721 return -ENOMEM;
0722
0723 rc = hashtab_duplicate(&newdb->p_bools.table, &orig->p_bools.table,
0724 cond_bools_copy, cond_bools_destroy, NULL);
0725 if (rc) {
0726 kfree(cond_bool_array);
0727 return -ENOMEM;
0728 }
0729
0730 hashtab_map(&newdb->p_bools.table, cond_bools_index, cond_bool_array);
0731 newdb->bool_val_to_struct = cond_bool_array;
0732
0733 newdb->p_bools.nprim = orig->p_bools.nprim;
0734
0735 return 0;
0736 }
0737
0738 void cond_policydb_destroy_dup(struct policydb *p)
0739 {
0740 hashtab_map(&p->p_bools.table, cond_bools_destroy, NULL);
0741 hashtab_destroy(&p->p_bools.table);
0742 cond_policydb_destroy(p);
0743 }
0744
0745 int cond_policydb_dup(struct policydb *new, struct policydb *orig)
0746 {
0747 cond_policydb_init(new);
0748
0749 if (duplicate_policydb_bools(new, orig))
0750 return -ENOMEM;
0751
0752 if (duplicate_policydb_cond_list(new, orig)) {
0753 cond_policydb_destroy_dup(new);
0754 return -ENOMEM;
0755 }
0756
0757 return 0;
0758 }