1 #include <stdlib.h> 2 3 #include "cil_flavor.h" 4 #include "cil_internal.h" 5 #include "cil_log.h" 6 #include "cil_tree.h" 7 8 struct cil_args_write { 9 FILE *cil_out; 10 struct cil_db *db; 11 }; 12 13 static int cil_unfill_expr(struct cil_list *expr_str, char **out_str, int paren); 14 static int cil_unfill_classperms_list(struct cil_list *classperms, char **out_str, int paren); 15 static int __cil_write_first_child_helper(struct cil_tree_node *node, void *extra_args); 16 static int __cil_write_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args); 17 static int __cil_write_last_child_helper(struct cil_tree_node *node, void *extra_args); 18 19 static int __cil_strlist_concat(struct cil_list *str_list, char **out_str, int paren) { 20 size_t len = paren ? 3 : 1; 21 size_t num_elems = 0; 22 char *p = NULL; 23 struct cil_list_item *curr; 24 25 /* get buffer size */ 26 cil_list_for_each(curr, str_list) { 27 len += strlen((char *)curr->data); 28 num_elems++; 29 } 30 if (num_elems != 0) { 31 /* add spaces between elements */ 32 len += num_elems - 1; 33 } 34 *out_str = cil_malloc(len); 35 p = *out_str; 36 if (paren) 37 *p++ = '('; 38 cil_list_for_each(curr, str_list) { 39 size_t src_len = strlen((char *)curr->data); 40 memcpy(p, curr->data, src_len); 41 p += src_len; 42 if (curr->next != NULL) 43 *p++ = ' '; 44 } 45 if (paren) 46 *p++ = ')'; 47 *p++ = '\0'; 48 return SEPOL_OK; 49 } 50 51 static int __cil_unfill_expr_helper(struct cil_list_item *curr, 52 struct cil_list_item **next, char **out_str, int paren) { 53 int rc = SEPOL_ERR; 54 char *str = NULL; 55 char *operand1 = NULL; 56 char *operand2 = NULL; 57 58 switch(curr->flavor) { 59 case CIL_LIST: 60 rc = cil_unfill_expr((struct cil_list *)curr->data, &str, paren); 61 if (rc != SEPOL_OK) 62 goto exit; 63 *out_str = str; 64 *next = curr->next; 65 break; 66 case CIL_STRING: 67 str = strdup((char *)curr->data); 68 if (!str) { 69 cil_log(CIL_ERR, "OOM. Unable to copy string.\n"); 70 rc = SEPOL_ERR; 71 goto exit; 72 } 73 *out_str = str; 74 *next = curr->next; 75 break; 76 case CIL_DATUM: 77 str = strdup(((struct cil_symtab_datum *)curr->data)->name); 78 if (!str) { 79 cil_log(CIL_ERR, "OOM. Unable to copy string.\n"); 80 rc = SEPOL_ERR; 81 goto exit; 82 } 83 *out_str = str; 84 *next = curr->next; 85 break; 86 case CIL_OP: { 87 char *op_str = NULL; 88 size_t len = 0; 89 enum cil_flavor op_flavor = (enum cil_flavor)curr->data; 90 switch (op_flavor) { 91 case CIL_AND: 92 op_str = CIL_KEY_AND; 93 break; 94 case CIL_OR: 95 op_str = CIL_KEY_OR; 96 break; 97 case CIL_NOT: 98 op_str = CIL_KEY_NOT; 99 break; 100 case CIL_ALL: 101 op_str = CIL_KEY_ALL; 102 break; 103 case CIL_EQ: 104 op_str = CIL_KEY_EQ; 105 break; 106 case CIL_NEQ: 107 op_str = CIL_KEY_NEQ; 108 break; 109 case CIL_RANGE: 110 op_str = CIL_KEY_RANGE; 111 break; 112 case CIL_XOR: 113 op_str = CIL_KEY_XOR; 114 break; 115 case CIL_CONS_DOM: 116 op_str = CIL_KEY_CONS_DOM; 117 break; 118 case CIL_CONS_DOMBY: 119 op_str = CIL_KEY_CONS_DOMBY; 120 break; 121 case CIL_CONS_INCOMP: 122 op_str = CIL_KEY_CONS_INCOMP; 123 break; 124 default: 125 cil_log(CIL_ERR, "Unknown operator in expression: %d\n", op_flavor); 126 goto exit; 127 break; 128 } 129 /* all operands take two args except for 'all' and 'not', which take 130 * one and two, respectively */ 131 len = strlen(op_str) + 3; 132 if (op_flavor == CIL_ALL) { 133 *out_str = cil_malloc(len); 134 sprintf(*out_str, "(%s)", op_str); 135 *next = curr->next; 136 } else if (op_flavor == CIL_NOT) { 137 rc = __cil_unfill_expr_helper(curr->next, next, &operand1, paren); 138 if (rc != SEPOL_OK) 139 goto exit; 140 len += strlen(operand1) + 1; 141 *out_str = cil_malloc(len); 142 sprintf(*out_str, "(%s %s)", op_str, operand1); 143 // *next already set by recursive call 144 } else { 145 rc = __cil_unfill_expr_helper(curr->next, next, &operand1, paren); 146 if (rc != SEPOL_OK) 147 goto exit; 148 len += strlen(operand1) + 1; 149 // *next contains operand2, but keep track of next after that 150 rc = __cil_unfill_expr_helper(*next, next, &operand2, paren); 151 if (rc != SEPOL_OK) 152 goto exit; 153 len += strlen(operand2) + 1; 154 *out_str = cil_malloc(len); 155 sprintf(*out_str, "(%s %s %s)", op_str, operand1, operand2); 156 // *next already set by recursive call 157 } 158 } 159 break; 160 case CIL_CONS_OPERAND: { 161 enum cil_flavor operand_flavor = (enum cil_flavor)curr->data; 162 char *operand_str = NULL; 163 switch (operand_flavor) { 164 case CIL_CONS_U1: 165 operand_str = CIL_KEY_CONS_U1; 166 break; 167 case CIL_CONS_U2: 168 operand_str = CIL_KEY_CONS_U2; 169 break; 170 case CIL_CONS_U3: 171 operand_str = CIL_KEY_CONS_U3; 172 break; 173 case CIL_CONS_T1: 174 operand_str = CIL_KEY_CONS_T1; 175 break; 176 case CIL_CONS_T2: 177 operand_str = CIL_KEY_CONS_T2; 178 break; 179 case CIL_CONS_T3: 180 operand_str = CIL_KEY_CONS_T3; 181 break; 182 case CIL_CONS_R1: 183 operand_str = CIL_KEY_CONS_R1; 184 break; 185 case CIL_CONS_R2: 186 operand_str = CIL_KEY_CONS_R2; 187 break; 188 case CIL_CONS_R3: 189 operand_str = CIL_KEY_CONS_R3; 190 break; 191 case CIL_CONS_L1: 192 operand_str = CIL_KEY_CONS_L1; 193 break; 194 case CIL_CONS_L2: 195 operand_str = CIL_KEY_CONS_L2; 196 break; 197 case CIL_CONS_H1: 198 operand_str = CIL_KEY_CONS_H1; 199 break; 200 case CIL_CONS_H2: 201 operand_str = CIL_KEY_CONS_H2; 202 break; 203 default: 204 cil_log(CIL_ERR, "Unknown operand in expression\n"); 205 goto exit; 206 break; 207 } 208 str = strdup(operand_str); 209 if (!str) { 210 cil_log(CIL_ERR, "OOM. Unable to copy string.\n"); 211 rc = SEPOL_ERR; 212 goto exit; 213 } 214 *out_str = str; 215 *next = curr->next; 216 } 217 break; 218 default: 219 cil_log(CIL_ERR, "Unknown flavor in expression\n"); 220 goto exit; 221 break; 222 } 223 rc = SEPOL_OK; 224 exit: 225 free(operand1); 226 free(operand2); 227 return rc; 228 } 229 230 static int cil_unfill_expr(struct cil_list *expr_str, char **out_str, int paren) { 231 int rc = SEPOL_ERR; 232 233 /* reuse cil_list to keep track of strings */ 234 struct cil_list *str_list = NULL; 235 struct cil_list_item *curr = NULL; 236 237 cil_list_init(&str_list, CIL_NONE); 238 239 /* iterate through cil_list, grabbing elements as needed */ 240 curr = expr_str->head; 241 while(curr != NULL) { 242 char *str = NULL; 243 struct cil_list_item *next = NULL; 244 245 rc = __cil_unfill_expr_helper(curr, &next, &str, paren); 246 if (rc != SEPOL_OK) 247 goto exit; 248 cil_list_append(str_list, CIL_STRING, (void *) str); 249 str = NULL; 250 curr = next; 251 } 252 rc = __cil_strlist_concat(str_list, out_str, paren); 253 if (rc != SEPOL_OK) 254 goto exit; 255 rc = SEPOL_OK; 256 exit: 257 cil_list_for_each(curr, str_list) { 258 free(curr->data); 259 } 260 cil_list_destroy(&str_list, 0); 261 return rc; 262 } 263 264 static int cil_unfill_cats(struct cil_cats *cats, char **out_str) { 265 return cil_unfill_expr(cats->str_expr, out_str, 0); 266 } 267 268 static int cil_unfill_level(struct cil_level *lvl, char **out_str) { 269 int rc = SEPOL_ERR; 270 size_t len = 0; 271 char *sens, *cats = NULL; 272 sens = lvl->sens_str; 273 len = strlen(sens) + 3; // '()\0' 274 if (lvl->cats != NULL) { 275 rc = cil_unfill_cats(lvl->cats, &cats); 276 if (rc != SEPOL_OK) 277 goto exit; 278 len += strlen(cats) + 1; 279 } 280 *out_str = cil_malloc(len); 281 if (cats == NULL) { 282 if (sprintf(*out_str, "(%s)", sens) < 0) { 283 cil_log(CIL_ERR, "Error unpacking and writing level\n"); 284 rc = SEPOL_ERR; 285 goto exit; 286 } 287 } else { 288 if (sprintf(*out_str, "(%s %s)", sens, cats) < 0) { 289 cil_log(CIL_ERR, "Error unpacking and writing level\n"); 290 rc = SEPOL_ERR; 291 goto exit; 292 } 293 } 294 rc = SEPOL_OK; 295 exit: 296 free(cats); 297 return rc; 298 } 299 300 static int cil_unfill_levelrange(struct cil_levelrange *lvlrnge, char **out_str) { 301 int rc = SEPOL_ERR; 302 size_t len = 0; 303 char *low = NULL, *high = NULL; 304 if (lvlrnge->low_str != NULL) { 305 low = strdup(lvlrnge->low_str); 306 if (low == NULL) { 307 cil_log(CIL_ERR, "OOM. Unable to copy level string.\n"); 308 rc = SEPOL_ERR; 309 goto exit; 310 } 311 } else { 312 rc = cil_unfill_level(lvlrnge->low, &low); 313 if (rc != SEPOL_OK) 314 goto exit; 315 } 316 if (lvlrnge->high_str != NULL) { 317 high = strdup(lvlrnge->high_str); 318 if (high == NULL) { 319 cil_log(CIL_ERR, "OOM. Unable to copy level string.\n"); 320 rc = SEPOL_ERR; 321 goto exit; 322 } 323 } else { 324 rc = cil_unfill_level(lvlrnge->high, &high); 325 if (rc != SEPOL_OK) 326 goto exit; 327 } 328 len = strlen(low) + strlen(high) + 4; 329 *out_str = cil_malloc(len); 330 if (sprintf(*out_str, "(%s %s)", low, high) < 0) { 331 cil_log(CIL_ERR, "Error unpacking and writing levelrange\n"); 332 rc = SEPOL_ERR; 333 goto exit; 334 } 335 rc = SEPOL_OK; 336 exit: 337 free(low); 338 free(high); 339 return rc; 340 } 341 342 static int cil_unfill_context(struct cil_context *context, char **out_str) { 343 int rc = SEPOL_ERR; 344 size_t len = 0; 345 char *user_str, *role_str, *type_str; 346 char *range_str = NULL; 347 348 user_str = context->user_str; 349 role_str = context->role_str; 350 type_str = context->type_str; 351 if (context->range_str != NULL) { 352 range_str = strdup(context->range_str); 353 if (range_str == NULL) { 354 cil_log(CIL_ERR, "OOM. Unable to copy range string.\n"); 355 rc = SEPOL_ERR; 356 goto exit; 357 } 358 } else { 359 rc = cil_unfill_levelrange(context->range, &range_str); 360 if (rc != SEPOL_OK) 361 goto exit; 362 } 363 len = strlen(user_str) + strlen(role_str) + strlen(type_str) 364 + strlen(range_str) + 6; 365 *out_str = cil_malloc(len); 366 if (sprintf(*out_str, "(%s %s %s %s)", user_str, role_str, type_str, range_str) < 0) { 367 cil_log(CIL_ERR, "Error unpacking and writing context\n"); 368 rc = SEPOL_ERR; 369 goto exit; 370 } 371 rc = SEPOL_OK; 372 exit: 373 free(range_str); 374 return rc; 375 } 376 377 static int cil_unfill_permx(struct cil_permissionx *permx, char **out_str) { 378 size_t len = 3; 379 int rc = SEPOL_ERR; 380 char *kind, *obj; 381 char *expr = NULL; 382 383 switch (permx->kind) { 384 case CIL_PERMX_KIND_IOCTL: 385 kind = CIL_KEY_IOCTL; 386 break; 387 default: 388 cil_log(CIL_ERR, "Unknown permissionx kind: %d\n", permx->kind); 389 rc = SEPOL_ERR; 390 goto exit; 391 break; 392 } 393 obj = permx->obj_str; 394 rc = cil_unfill_expr(permx->expr_str, &expr, 1); 395 if (rc != SEPOL_OK) 396 goto exit; 397 len += strlen(kind) + strlen(obj) + strlen(expr) + 2; 398 *out_str = cil_malloc(len); 399 if (sprintf(*out_str, "(%s %s %s)", kind, obj, expr) < 0) { 400 cil_log(CIL_ERR, "Error writing xperm\n"); 401 rc = SEPOL_ERR; 402 goto exit; 403 } 404 rc = SEPOL_OK; 405 exit: 406 free(expr); 407 return rc; 408 } 409 410 #define cil_write_unsupported(flavor) _cil_write_unsupported(flavor, __LINE__) 411 static int _cil_write_unsupported(const char *flavor, int line) { 412 cil_log(CIL_ERR, 413 "flavor \"%s\" is not supported, look in file \"%s\"" 414 " on line %d to add support.\n", flavor, __FILE__, line); 415 return SEPOL_ENOTSUP; 416 } 417 418 static int cil_write_policycap(struct cil_tree_node *node, FILE *cil_out) { 419 struct cil_policycap *polcap = (struct cil_policycap *)node->data; 420 fprintf(cil_out, "(%s %s)\n", CIL_KEY_POLICYCAP, polcap->datum.name); 421 return SEPOL_OK; 422 } 423 424 static int cil_write_perm(struct cil_tree_node *node, FILE *cil_out) { 425 struct cil_perm *perm = (struct cil_perm *)node->data; 426 fprintf(cil_out, "%s", perm->datum.name); 427 if (node->next != NULL) 428 fprintf(cil_out, " "); 429 return SEPOL_OK; 430 } 431 432 433 static int cil_write_class(struct cil_tree_node *node, uint32_t *finished, 434 struct cil_args_write *extra_args) { 435 int rc = SEPOL_ERR; 436 FILE *cil_out = extra_args->cil_out; 437 struct cil_symtab_datum *datum = (struct cil_symtab_datum *)node->data; 438 char *class_type = (node->flavor == CIL_CLASS) ? CIL_KEY_CLASS : CIL_KEY_COMMON; 439 440 /* print preamble */ 441 fprintf(cil_out, "(%s %s ", class_type, datum->name); 442 443 if (node->cl_head == NULL) { 444 /* no associated perms in this part of tree */ 445 fprintf(cil_out, "()"); 446 } else { 447 448 /* visit subtree (perms) */ 449 rc = cil_tree_walk(node, __cil_write_node_helper, 450 __cil_write_first_child_helper, 451 __cil_write_last_child_helper, 452 extra_args); 453 if (rc != SEPOL_OK) 454 goto exit; 455 } 456 457 /* postamble (trailing paren) */ 458 fprintf(cil_out, ")\n"); 459 *finished = CIL_TREE_SKIP_HEAD; 460 rc = SEPOL_OK; 461 exit: 462 return rc; 463 } 464 465 static int cil_write_classorder(struct cil_tree_node *node, FILE *cil_out) { 466 int rc = SEPOL_ERR; 467 char *ord_str = NULL; 468 struct cil_classorder *classord = (struct cil_classorder *)node->data; 469 470 /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */ 471 rc = cil_unfill_expr(classord->class_list_str, &ord_str, 1); 472 if (rc != SEPOL_OK) 473 goto exit; 474 fprintf(cil_out, "(%s %s)\n", CIL_KEY_CLASSORDER, ord_str); 475 rc = SEPOL_OK; 476 exit: 477 free(ord_str); 478 return rc; 479 } 480 481 static int cil_write_classcommon(struct cil_tree_node *node, FILE *cil_out) { 482 struct cil_classcommon *classcommon = (struct cil_classcommon *)node->data; 483 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_CLASSCOMMON, classcommon->class_str, 484 classcommon->common_str); 485 return SEPOL_OK; 486 } 487 488 static int cil_write_sid(struct cil_tree_node *node, FILE *cil_out) { 489 struct cil_sid *sid = (struct cil_sid *)node->data; 490 fprintf(cil_out, "(%s %s)\n", CIL_KEY_SID, sid->datum.name); 491 return SEPOL_OK; 492 } 493 494 static int cil_write_sidcontext(struct cil_tree_node *node, FILE *cil_out) { 495 int rc = SEPOL_ERR; 496 char *sid; 497 char *ctx_str = NULL; 498 struct cil_sidcontext *sidcon = (struct cil_sidcontext *)node->data; 499 500 sid = sidcon->sid_str; 501 if (sidcon->context_str != NULL) { 502 ctx_str = strdup(sidcon->context_str); 503 if (ctx_str == NULL) { 504 cil_log(CIL_ERR, "OOM. Unable to copy context string.\n"); 505 rc = SEPOL_ERR; 506 goto exit; 507 } 508 } else { 509 rc = cil_unfill_context(sidcon->context, &ctx_str); 510 if (rc != SEPOL_OK) 511 goto exit; 512 } 513 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_SIDCONTEXT, sid, ctx_str); 514 rc = SEPOL_OK; 515 exit: 516 free(ctx_str); 517 return rc; 518 } 519 520 static int cil_write_sidorder(struct cil_tree_node *node, FILE *cil_out) { 521 int rc = SEPOL_ERR; 522 char *ord_str = NULL; 523 struct cil_sidorder *sidord = (struct cil_sidorder *)node->data; 524 525 /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */ 526 rc = cil_unfill_expr(sidord->sid_list_str, &ord_str, 1); 527 if (rc != SEPOL_OK) 528 goto exit; 529 fprintf(cil_out, "(%s %s)\n", CIL_KEY_SIDORDER, ord_str); 530 rc = SEPOL_OK; 531 exit: 532 free(ord_str); 533 return rc; 534 } 535 536 static int cil_write_user(struct cil_tree_node *node, FILE *cil_out) { 537 struct cil_user *user = (struct cil_user *)node->data; 538 fprintf(cil_out, "(%s %s)\n", CIL_KEY_USER, user->datum.name); 539 return SEPOL_OK; 540 } 541 542 static int cil_write_userrole(struct cil_tree_node *node, FILE *cil_out) { 543 struct cil_userrole *userrole = (struct cil_userrole *)node->data; 544 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_USERROLE, userrole->user_str, 545 userrole->role_str); 546 return SEPOL_OK; 547 } 548 549 static int cil_write_userlevel(struct cil_tree_node *node, FILE *cil_out) { 550 struct cil_userlevel *usrlvl = (struct cil_userlevel *)node->data; 551 int rc = SEPOL_ERR; 552 char *usr; 553 char *lvl = NULL; 554 555 usr = usrlvl->user_str; 556 if (usrlvl->level_str != NULL) { 557 lvl = strdup(usrlvl->level_str); 558 if (lvl == NULL) { 559 cil_log(CIL_ERR, "OOM. Unable to copy level string.\n"); 560 rc = SEPOL_ERR; 561 goto exit; 562 } 563 } else { 564 rc = cil_unfill_level(usrlvl->level, &lvl); 565 if (rc != SEPOL_OK) 566 goto exit; 567 } 568 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_USERLEVEL, usr, lvl); 569 rc = SEPOL_OK; 570 exit: 571 free(lvl); 572 return rc; 573 } 574 575 static int cil_write_userrange(struct cil_tree_node *node, FILE *cil_out) { 576 struct cil_userrange *usrrng = (struct cil_userrange *)node->data; 577 int rc = SEPOL_ERR; 578 char *usr; 579 char *range = NULL; 580 581 usr = usrrng->user_str; 582 if (usrrng->range_str != NULL) { 583 range = strdup(usrrng->range_str); 584 if (range == NULL) { 585 cil_log(CIL_ERR, "OOM. Unable to copy levelrange string.\n"); 586 rc = SEPOL_ERR; 587 goto exit; 588 } 589 } else { 590 rc = cil_unfill_levelrange(usrrng->range, &range); 591 if (rc != SEPOL_OK) 592 goto exit; 593 } 594 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_USERRANGE, usr, range); 595 rc = SEPOL_OK; 596 exit: 597 free(range); 598 return rc; 599 } 600 601 static int cil_write_role(struct cil_tree_node *node, FILE *cil_out) { 602 struct cil_role *role = (struct cil_role *)node->data; 603 fprintf(cil_out, "(%s %s)\n", CIL_KEY_ROLE, role->datum.name); 604 return SEPOL_OK; 605 } 606 607 static int cil_write_roletype(struct cil_tree_node *node, FILE *cil_out) { 608 struct cil_roletype *roletype = (struct cil_roletype *)node->data; 609 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_ROLETYPE, roletype->role_str, roletype->type_str); 610 return SEPOL_OK; 611 } 612 613 static int cil_write_roleattribute(struct cil_tree_node *node, FILE *cil_out) { 614 struct cil_roleattribute *roleattr = (struct cil_roleattribute *)node->data; 615 fprintf(cil_out, "(%s %s)\n", CIL_KEY_ROLEATTRIBUTE, roleattr->datum.name); 616 return SEPOL_OK; 617 } 618 619 static int cil_write_type(struct cil_tree_node *node, FILE *cil_out) { 620 struct cil_type *type = (struct cil_type *)node->data; 621 fprintf(cil_out, "(%s %s)\n", CIL_KEY_TYPE, type->datum.name); 622 return SEPOL_OK; 623 } 624 625 static int cil_write_typepermissive(struct cil_tree_node *node, FILE *cil_out) { 626 struct cil_typepermissive *type = (struct cil_typepermissive *)node->data; 627 fprintf(cil_out, "(%s %s)\n", CIL_KEY_TYPEPERMISSIVE, type->type_str); 628 return SEPOL_OK; 629 } 630 631 static int cil_write_typeattribute(struct cil_tree_node *node, FILE *cil_out) { 632 struct cil_typeattribute *typeattr = (struct cil_typeattribute *)node->data; 633 fprintf(cil_out, "(%s %s)\n", CIL_KEY_TYPEATTRIBUTE, typeattr->datum.name); 634 return SEPOL_OK; 635 } 636 637 static int cil_write_typeattributeset(struct cil_tree_node *node, FILE *cil_out) { 638 int rc = SEPOL_ERR; 639 char *typeattr; 640 char *set_str = NULL; 641 struct cil_typeattributeset *typeattrset = (struct cil_typeattributeset *)node->data; 642 643 typeattr = typeattrset->attr_str; 644 rc = cil_unfill_expr(typeattrset->str_expr, &set_str, 1); 645 if (rc != SEPOL_OK) 646 goto exit; 647 648 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_TYPEATTRIBUTESET, typeattr, set_str); 649 rc = SEPOL_OK; 650 exit: 651 free(set_str); 652 return rc; 653 } 654 655 static int cil_write_expandtypeattribute(struct cil_tree_node *node, FILE *cil_out) 656 { 657 int rc = SEPOL_ERR; 658 char *attr_strs = NULL; 659 struct cil_expandtypeattribute *expandattr = (struct cil_expandtypeattribute *)node->data; 660 661 rc = cil_unfill_expr(expandattr->attr_strs, &attr_strs, 1); 662 if (rc != SEPOL_OK) 663 goto exit; 664 665 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_EXPANDTYPEATTRIBUTE, attr_strs, 666 expandattr->expand ? CIL_KEY_CONDTRUE : CIL_KEY_CONDFALSE); 667 rc = SEPOL_OK; 668 exit: 669 free(attr_strs); 670 return rc; 671 } 672 673 static int cil_write_alias(struct cil_tree_node *node, FILE *cil_out) { 674 int rc = SEPOL_ERR; 675 char *type; 676 struct cil_alias *alias = (struct cil_alias *)node->data; 677 678 switch (node->flavor) { 679 case CIL_TYPEALIAS: 680 type = CIL_KEY_TYPEALIAS; 681 break; 682 case CIL_SENSALIAS: 683 type = CIL_KEY_SENSALIAS; 684 break; 685 case CIL_CATALIAS: 686 type = CIL_KEY_CATALIAS; 687 break; 688 default: 689 cil_log(CIL_ERR, "Unknown alias type: %d\n", node->flavor); 690 rc = SEPOL_ERR; 691 goto exit; 692 break; 693 } 694 fprintf(cil_out, "(%s %s)\n", type, alias->datum.name); 695 rc = SEPOL_OK; 696 exit: 697 return rc; 698 } 699 700 static int cil_write_aliasactual(struct cil_tree_node *node, FILE *cil_out) { 701 int rc = SEPOL_ERR; 702 char *type, *alias, *actual; 703 struct cil_aliasactual *aliasact = (struct cil_aliasactual *)node->data; 704 705 switch (node->flavor) { 706 case CIL_TYPEALIASACTUAL: 707 type = CIL_KEY_TYPEALIASACTUAL; 708 break; 709 case CIL_SENSALIASACTUAL: 710 type = CIL_KEY_SENSALIASACTUAL; 711 break; 712 case CIL_CATALIASACTUAL: 713 type = CIL_KEY_CATALIASACTUAL; 714 break; 715 default: 716 cil_log(CIL_ERR, "Unknown alias type: %d\n", node->flavor); 717 rc = SEPOL_ERR; 718 goto exit; 719 break; 720 } 721 alias = aliasact->alias_str; 722 actual = aliasact->actual_str; 723 fprintf(cil_out, "(%s %s %s)\n", type, alias, actual); 724 rc = SEPOL_OK; 725 exit: 726 return rc; 727 } 728 729 static int cil_write_nametypetransition(struct cil_tree_node *node, FILE *cil_out) { 730 char *src, *tgt, *obj, *res, *name; 731 struct cil_nametypetransition *ntrans = (struct cil_nametypetransition *)node->data; 732 733 src = ntrans->src_str; 734 tgt = ntrans->tgt_str; 735 obj = ntrans->obj_str; 736 res = ntrans->result_str; 737 name = ntrans->name_str; 738 fprintf(cil_out, "(%s %s %s %s \"%s\" %s)\n", CIL_KEY_TYPETRANSITION, 739 src, tgt, obj, name, res); 740 return SEPOL_OK; 741 } 742 743 static int cil_write_avrule_x(struct cil_avrule *avrule, FILE *cil_out) { 744 int rc = SEPOL_ERR; 745 char *rulekind, *src, *tgt; 746 char *xperms = NULL; 747 748 switch (avrule->rule_kind) { 749 case CIL_AVRULE_ALLOWED: 750 rulekind = CIL_KEY_ALLOWX; 751 break; 752 case CIL_AVRULE_AUDITALLOW: 753 rulekind = CIL_KEY_AUDITALLOWX; 754 break; 755 case CIL_AVRULE_DONTAUDIT: 756 rulekind = CIL_KEY_DONTAUDITX; 757 break; 758 case CIL_AVRULE_NEVERALLOW: 759 rulekind = CIL_KEY_NEVERALLOWX; 760 break; 761 default: 762 cil_log(CIL_ERR, "Unknown AVRULE type: %d\n", avrule->rule_kind); 763 rc = SEPOL_ERR; 764 goto exit; 765 break; 766 } 767 src = avrule->src_str; 768 tgt = avrule->tgt_str; 769 770 if (avrule->perms.x.permx_str != NULL) { 771 xperms = strdup(avrule->perms.x.permx_str); 772 if (xperms == NULL) { 773 cil_log(CIL_ERR, "OOM. Unable to copy xperms string.\n"); 774 rc = SEPOL_ERR; 775 goto exit; 776 } 777 } else { 778 rc = cil_unfill_permx(avrule->perms.x.permx, &xperms); 779 if (rc != SEPOL_OK) 780 goto exit; 781 } 782 fprintf(cil_out, "(%s %s %s %s)\n", rulekind, src, tgt, xperms); 783 rc = SEPOL_OK; 784 exit: 785 free(xperms); 786 return rc; 787 } 788 789 static int cil_write_avrule_orig(struct cil_avrule *avrule, FILE *cil_out) { 790 int rc = SEPOL_ERR; 791 char *rulekind, *src, *tgt; 792 char *classperms = NULL; 793 794 switch (avrule->rule_kind) { 795 case CIL_AVRULE_ALLOWED: 796 rulekind = CIL_KEY_ALLOW; 797 break; 798 case CIL_AVRULE_AUDITALLOW: 799 rulekind = CIL_KEY_AUDITALLOW; 800 break; 801 case CIL_AVRULE_DONTAUDIT: 802 rulekind = CIL_KEY_DONTAUDIT; 803 break; 804 case CIL_AVRULE_NEVERALLOW: 805 rulekind = CIL_KEY_NEVERALLOW; 806 break; 807 default: 808 cil_log(CIL_ERR, "Unknown AVRULE type: %d\n", avrule->rule_kind); 809 rc = SEPOL_ERR; 810 goto exit; 811 break; 812 } 813 src = avrule->src_str; 814 tgt = avrule->tgt_str; 815 816 rc = cil_unfill_classperms_list(avrule->perms.classperms, &classperms, 0); 817 if (rc != SEPOL_OK) 818 goto exit; 819 fprintf(cil_out, "(%s %s %s %s)\n", rulekind, src, tgt, classperms); 820 rc = SEPOL_OK; 821 exit: 822 free(classperms); 823 return rc; 824 } 825 826 static int cil_write_avrule(struct cil_tree_node *node, FILE *cil_out) { 827 int rc = SEPOL_ERR; 828 struct cil_avrule *avrule = (struct cil_avrule *)node->data; 829 830 if (avrule->is_extended) 831 rc = cil_write_avrule_x(avrule, cil_out); 832 else 833 rc = cil_write_avrule_orig(avrule, cil_out); 834 return rc; 835 } 836 837 static int cil_write_type_rule(struct cil_tree_node *node, FILE *cil_out) { 838 int rc = SEPOL_ERR; 839 char *type, *src, *tgt, *obj, *res; 840 struct cil_type_rule *typerule = (struct cil_type_rule *)node->data; 841 842 switch (typerule->rule_kind) { 843 case CIL_TYPE_TRANSITION: 844 type = CIL_KEY_TYPETRANSITION; 845 break; 846 case CIL_TYPE_MEMBER: 847 type = CIL_KEY_TYPEMEMBER; 848 break; 849 case CIL_TYPE_CHANGE: 850 type = CIL_KEY_TYPECHANGE; 851 break; 852 default: 853 cil_log(CIL_ERR, "Unknown TYPERULE type: %d\n", typerule->rule_kind); 854 rc = SEPOL_ERR; 855 goto exit; 856 break; 857 } 858 src = typerule->src_str; 859 tgt = typerule->tgt_str; 860 obj = typerule->obj_str; 861 res = typerule->result_str; 862 fprintf(cil_out, "(%s %s %s %s %s)\n", type, src, tgt, obj, res); 863 rc = SEPOL_OK; 864 exit: 865 return rc; 866 } 867 868 static int cil_write_sens(struct cil_tree_node *node, FILE *cil_out) { 869 struct cil_sens *sens = (struct cil_sens *)node->data; 870 fprintf(cil_out, "(%s %s)\n", CIL_KEY_SENSITIVITY, sens->datum.name); 871 return SEPOL_OK; 872 } 873 874 static int cil_write_cat(struct cil_tree_node *node, FILE *cil_out) { 875 struct cil_cat *cat = (struct cil_cat *)node->data; 876 fprintf(cil_out, "(%s %s)\n", CIL_KEY_CATEGORY, cat->datum.name); 877 return SEPOL_OK; 878 } 879 880 static int cil_write_senscat(struct cil_tree_node *node, FILE *cil_out) { 881 int rc = SEPOL_ERR; 882 char *sens; 883 char *cats = NULL; 884 struct cil_senscat *senscat = (struct cil_senscat *)node->data; 885 886 sens = senscat->sens_str; 887 rc = cil_unfill_cats(senscat->cats, &cats); 888 if (rc != SEPOL_OK) 889 goto exit; 890 /* TODO: deal with extra/missing parens */ 891 fprintf(cil_out, "(%s %s (%s))\n", CIL_KEY_SENSCAT, sens, cats); 892 rc = SEPOL_OK; 893 exit: 894 free(cats); 895 return rc; 896 } 897 898 static int cil_write_catorder(struct cil_tree_node *node, FILE *cil_out) { 899 int rc = SEPOL_ERR; 900 char *ord_str = NULL; 901 struct cil_catorder *catord = (struct cil_catorder *)node->data; 902 903 /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */ 904 rc = cil_unfill_expr(catord->cat_list_str, &ord_str, 1); 905 if (rc != SEPOL_OK) 906 goto exit; 907 fprintf(cil_out, "(%s %s)\n", CIL_KEY_CATORDER, ord_str); 908 rc = SEPOL_OK; 909 exit: 910 free(ord_str); 911 return rc; 912 } 913 914 static int cil_write_sensorder(struct cil_tree_node *node, FILE *cil_out) { 915 int rc = SEPOL_ERR; 916 char *ord_str = NULL; 917 struct cil_sensorder *sensord = (struct cil_sensorder *)node->data; 918 919 /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */ 920 rc = cil_unfill_expr(sensord->sens_list_str, &ord_str, 1); 921 if (rc != SEPOL_OK) 922 goto exit; 923 fprintf(cil_out, "(%s %s)\n", CIL_KEY_SENSITIVITYORDER, ord_str); 924 rc = SEPOL_OK; 925 exit: 926 free(ord_str); 927 return rc; 928 } 929 930 static int cil_write_genfscon(struct cil_tree_node *node, FILE *cil_out) { 931 int rc = SEPOL_ERR; 932 char *ctx_str = NULL; 933 934 struct cil_genfscon *genfscon = (struct cil_genfscon *)node->data; 935 if (genfscon->context_str != NULL) { 936 ctx_str = strdup(genfscon->context_str); 937 if (ctx_str == NULL) { 938 cil_log(CIL_ERR, "OOM. Unable to copy context string.\n"); 939 rc = SEPOL_ERR; 940 goto exit; 941 } 942 } else { 943 rc = cil_unfill_context(genfscon->context, &ctx_str); 944 if (rc != SEPOL_OK) 945 goto exit; 946 } 947 fprintf(cil_out, "(%s %s %s %s)\n", CIL_KEY_GENFSCON, genfscon->fs_str, 948 genfscon->path_str, ctx_str); 949 rc = SEPOL_OK; 950 exit: 951 free(ctx_str); 952 return rc; 953 } 954 955 static int cil_unfill_classperms(struct cil_list_item *curr, char **out_str) { 956 int rc = SEPOL_ERR; 957 size_t len = 3; 958 char *class_str; 959 char *perms_str = NULL; 960 struct cil_classperms *cp = (struct cil_classperms *)curr->data; 961 962 class_str = cp->class_str; 963 len += strlen(class_str) + 1; 964 965 /* fill_perms just calls gen_expr */ 966 rc = cil_unfill_expr(cp->perm_strs, &perms_str, 1); 967 if (rc != SEPOL_OK) 968 goto exit; 969 len += strlen(perms_str); 970 *out_str = cil_malloc(len); 971 sprintf(*out_str, "(%s %s)", class_str, perms_str); 972 rc = SEPOL_OK; 973 exit: 974 free(perms_str); 975 return rc; 976 } 977 978 static int cil_unfill_classperms_list(struct cil_list *classperms, char **out_str, int paren) { 979 int rc = SEPOL_ERR; 980 struct cil_list_item *curr; 981 char *str = NULL; 982 983 /* reuse cil_list to keep track of strings */ 984 struct cil_list *str_list = NULL; 985 cil_list_init(&str_list, CIL_NONE); 986 cil_list_for_each(curr, classperms) { 987 switch (curr->flavor) { 988 case CIL_CLASSPERMS_SET: 989 str = strdup(((struct cil_classperms_set *)curr->data)->set_str); 990 if (str == NULL) { 991 cil_log(CIL_ERR, "OOM. Unable to copy classpermset.\n"); 992 rc = SEPOL_ERR; 993 goto exit; 994 } 995 break; 996 case CIL_CLASSPERMS: 997 rc = cil_unfill_classperms(curr, &str); 998 if (rc != SEPOL_OK) 999 goto exit; 1000 break; 1001 default: 1002 cil_log(CIL_ERR, "Unrecognized classperms flavor\n."); 1003 goto exit; 1004 } 1005 cil_list_append(str_list, CIL_STRING, (void *) str); 1006 str = NULL; 1007 } 1008 rc = __cil_strlist_concat(str_list, out_str, paren); 1009 if (rc != SEPOL_OK) 1010 goto exit; 1011 rc = SEPOL_OK; 1012 exit: 1013 cil_list_for_each(curr, str_list) { 1014 free(curr->data); 1015 } 1016 cil_list_destroy(&str_list, 0); 1017 return rc; 1018 } 1019 1020 static int cil_write_fsuse(struct cil_tree_node *node, FILE *cil_out) { 1021 int rc = SEPOL_ERR; 1022 struct cil_fsuse *fsuse = (struct cil_fsuse *)node->data; 1023 char *type, *fsname; 1024 char *ctx_str = NULL; 1025 1026 switch(fsuse->type) { 1027 case CIL_FSUSE_XATTR: 1028 type = CIL_KEY_XATTR; 1029 break; 1030 case CIL_FSUSE_TASK: 1031 type = CIL_KEY_TASK; 1032 break; 1033 case CIL_FSUSE_TRANS: 1034 type = CIL_KEY_TRANS; 1035 break; 1036 default: 1037 cil_log(CIL_ERR, "Unrecognized fsuse type\n"); 1038 rc = SEPOL_ERR; 1039 goto exit; 1040 break; 1041 } 1042 1043 fsname = fsuse->fs_str; 1044 if (fsuse->context_str != NULL) { 1045 ctx_str = strdup(fsuse->context_str); 1046 if (ctx_str == NULL) { 1047 cil_log(CIL_ERR, "OOM. Unable to copy context string.\n"); 1048 rc = SEPOL_ERR; 1049 goto exit; 1050 } 1051 } else { 1052 rc = cil_unfill_context(fsuse->context, &ctx_str); 1053 if (rc != SEPOL_OK) 1054 goto exit; 1055 } 1056 fprintf(cil_out, "(%s %s %s %s)\n", CIL_KEY_FSUSE, type, fsname, ctx_str); 1057 exit: 1058 free(ctx_str); 1059 return rc; 1060 } 1061 1062 static int cil_write_constrain(struct cil_tree_node *node, FILE *cil_out) { 1063 int rc = SEPOL_ERR; 1064 struct cil_constrain *cons = (struct cil_constrain *)node->data; 1065 char *flav; 1066 char *classperms = NULL; 1067 char *expr = NULL; 1068 1069 flav = (node->flavor == CIL_CONSTRAIN) ? CIL_KEY_CONSTRAIN : CIL_KEY_MLSCONSTRAIN; 1070 1071 rc = cil_unfill_classperms_list(cons->classperms, &classperms, 0); 1072 if (rc != SEPOL_OK) 1073 goto exit; 1074 1075 rc = cil_unfill_expr(cons->str_expr, &expr, 0); 1076 if (rc != SEPOL_OK) 1077 goto exit; 1078 1079 fprintf(cil_out, "(%s %s %s)\n", flav, classperms, expr); 1080 exit: 1081 free(classperms); 1082 free(expr); 1083 return rc; 1084 } 1085 1086 static int cil_write_handleunknown(struct cil_tree_node *node, FILE *cil_out) { 1087 int rc = SEPOL_OK; 1088 struct cil_handleunknown *handunknown = (struct cil_handleunknown *)node->data; 1089 char *val = NULL; 1090 switch (handunknown->handle_unknown) { 1091 case SEPOL_ALLOW_UNKNOWN: 1092 val = CIL_KEY_HANDLEUNKNOWN_ALLOW; 1093 break; 1094 case SEPOL_DENY_UNKNOWN: 1095 val = CIL_KEY_HANDLEUNKNOWN_DENY; 1096 break; 1097 case SEPOL_REJECT_UNKNOWN: 1098 val = CIL_KEY_HANDLEUNKNOWN_REJECT; 1099 break; 1100 default: 1101 cil_log(CIL_ERR, "Unknown handleunknown value: %d.\n", 1102 handunknown->handle_unknown); 1103 rc = SEPOL_ERR; 1104 goto exit; 1105 break; 1106 } 1107 fprintf(cil_out, "(%s %s)\n", CIL_KEY_HANDLEUNKNOWN, val); 1108 exit: 1109 return rc; 1110 } 1111 1112 static int cil_write_mls(struct cil_tree_node *node, FILE *cil_out) { 1113 int rc = SEPOL_OK; 1114 struct cil_mls *mls = (struct cil_mls *)node->data; 1115 char *val = NULL; 1116 switch (mls->value) { 1117 case CIL_TRUE: 1118 val = CIL_KEY_CONDTRUE; 1119 break; 1120 case CIL_FALSE: 1121 val = CIL_KEY_CONDFALSE; 1122 break; 1123 default: 1124 cil_log(CIL_ERR, "Unknown mls value: %d.\n", mls->value); 1125 rc = SEPOL_ERR; 1126 goto exit; 1127 break; 1128 } 1129 fprintf(cil_out, "(%s %s)\n", CIL_KEY_MLS, val); 1130 exit: 1131 return rc; 1132 } 1133 1134 static int __cil_write_first_child_helper(struct cil_tree_node *node, void *extra_args) 1135 { 1136 int rc = SEPOL_ERR; 1137 struct cil_args_write *args = (struct cil_args_write *) extra_args; 1138 FILE *cil_out = NULL; 1139 1140 if (node == NULL || extra_args == NULL) { 1141 goto exit; 1142 } 1143 1144 cil_out = args->cil_out; 1145 1146 if (node->parent && node->parent->flavor != CIL_ROOT && node->parent->flavor != CIL_SRC_INFO) 1147 fprintf(cil_out,"("); 1148 rc = SEPOL_OK; 1149 exit: 1150 return rc; 1151 } 1152 1153 static int __cil_write_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) 1154 { 1155 int rc = SEPOL_OK; 1156 struct cil_args_write *args = NULL; 1157 FILE *cil_out = NULL; 1158 1159 if (node == NULL || extra_args == NULL) { 1160 goto exit; 1161 } 1162 1163 args = extra_args; 1164 cil_out = args->cil_out; 1165 1166 switch (node->flavor) { 1167 case CIL_BLOCK: 1168 rc = cil_write_unsupported("CIL_BLOCK"); 1169 break; 1170 case CIL_BLOCKABSTRACT: 1171 rc = cil_write_unsupported("CIL_BLOCKABSTRACT"); 1172 break; 1173 case CIL_BLOCKINHERIT: 1174 rc = cil_write_unsupported("CIL_BLOCKINHERIT"); 1175 break; 1176 case CIL_IN: 1177 rc = cil_write_unsupported("CIL_IN"); 1178 break; 1179 case CIL_POLICYCAP: 1180 cil_write_policycap(node, cil_out); 1181 break; 1182 case CIL_PERM: 1183 rc = cil_write_perm(node, cil_out); 1184 break; 1185 case CIL_MAP_PERM: 1186 rc = cil_write_unsupported("CIL_MAP_PERM"); 1187 break; 1188 case CIL_CLASSMAPPING: 1189 rc = cil_write_unsupported("CIL_CLASSMAPPING"); 1190 break; 1191 case CIL_CLASS: 1192 rc = cil_write_class(node, finished, extra_args); 1193 break; 1194 case CIL_COMMON: 1195 rc = cil_write_class(node, finished, extra_args); 1196 break; 1197 case CIL_MAP_CLASS: 1198 rc = cil_write_unsupported("CIL_MAP_CLASS"); 1199 break; 1200 case CIL_CLASSORDER: 1201 rc = cil_write_classorder(node, cil_out); 1202 break; 1203 case CIL_CLASSPERMISSION: 1204 rc = cil_write_unsupported("CIL_CLASSPERMISSION"); 1205 break; 1206 case CIL_CLASSPERMISSIONSET: 1207 rc = cil_write_unsupported("CIL_CLASSPERMISSIONSET"); 1208 break; 1209 case CIL_CLASSCOMMON: 1210 rc = cil_write_classcommon(node, cil_out); 1211 break; 1212 case CIL_SID: 1213 rc = cil_write_sid(node, cil_out); 1214 break; 1215 case CIL_SIDCONTEXT: 1216 rc = cil_write_sidcontext(node, cil_out); 1217 break; 1218 case CIL_SIDORDER: 1219 rc = cil_write_sidorder(node, cil_out); 1220 break; 1221 case CIL_USER: 1222 rc = cil_write_user(node, cil_out); 1223 break; 1224 case CIL_USERATTRIBUTE: 1225 rc = cil_write_unsupported("CIL_USERATTRIBUTE"); 1226 break; 1227 case CIL_USERATTRIBUTESET: 1228 rc = cil_write_unsupported("CIL_USERATTRIBUTESET"); 1229 break; 1230 case CIL_USERROLE: 1231 rc = cil_write_userrole(node, cil_out); 1232 break; 1233 case CIL_USERLEVEL: 1234 rc = cil_write_userlevel(node, cil_out); 1235 break; 1236 case CIL_USERRANGE: 1237 rc = cil_write_userrange(node, cil_out); 1238 break; 1239 case CIL_USERBOUNDS: 1240 rc = cil_write_unsupported("CIL_USERBOUNDS"); 1241 break; 1242 case CIL_USERPREFIX: 1243 rc = cil_write_unsupported("CIL_USERPREFIX"); 1244 break; 1245 case CIL_ROLE: 1246 rc = cil_write_role(node, cil_out); 1247 break; 1248 case CIL_ROLETYPE: 1249 rc = cil_write_roletype(node, cil_out); 1250 break; 1251 case CIL_ROLEBOUNDS: 1252 rc = cil_write_unsupported("CIL_ROLEBOUNDS"); 1253 break; 1254 case CIL_ROLEATTRIBUTE: 1255 cil_write_roleattribute(node, cil_out); 1256 break; 1257 case CIL_ROLEATTRIBUTESET: 1258 rc = cil_write_unsupported("CIL_ROLEATTRIBUTESET"); 1259 break; 1260 case CIL_ROLEALLOW: 1261 rc = cil_write_unsupported("CIL_ROLEALLOW"); 1262 break; 1263 case CIL_TYPE: 1264 rc = cil_write_type(node, cil_out); 1265 break; 1266 case CIL_TYPEBOUNDS: 1267 rc = cil_write_unsupported("CIL_TYPEBOUNDS"); 1268 break; 1269 case CIL_TYPEPERMISSIVE: 1270 rc = cil_write_typepermissive(node, cil_out); 1271 break; 1272 case CIL_TYPEATTRIBUTE: 1273 rc = cil_write_typeattribute(node, cil_out); 1274 break; 1275 case CIL_TYPEATTRIBUTESET: 1276 rc = cil_write_typeattributeset(node, cil_out); 1277 break; 1278 case CIL_EXPANDTYPEATTRIBUTE: 1279 rc = cil_write_expandtypeattribute(node, cil_out); 1280 break; 1281 case CIL_TYPEALIAS: 1282 rc = cil_write_alias(node, cil_out); 1283 break; 1284 case CIL_TYPEALIASACTUAL: 1285 rc = cil_write_aliasactual(node, cil_out); 1286 break; 1287 case CIL_ROLETRANSITION: 1288 rc = cil_write_unsupported("CIL_ROLETRANSITION"); 1289 break; 1290 case CIL_NAMETYPETRANSITION: 1291 rc = cil_write_nametypetransition(node, cil_out); 1292 break; 1293 case CIL_RANGETRANSITION: 1294 rc = cil_write_unsupported("CIL_RANGETRANSITION"); 1295 break; 1296 case CIL_TUNABLE: 1297 rc = cil_write_unsupported("CIL_TUNABLE"); 1298 break; 1299 case CIL_BOOL: 1300 rc = cil_write_unsupported("CIL_BOOL"); 1301 break; 1302 case CIL_AVRULE: 1303 case CIL_AVRULEX: 1304 rc = cil_write_avrule(node, cil_out); 1305 break; 1306 case CIL_PERMISSIONX: 1307 rc = cil_write_unsupported("CIL_PERMISSIONX"); 1308 break; 1309 case CIL_TYPE_RULE: 1310 cil_write_type_rule(node, cil_out); 1311 break; 1312 case CIL_SENS: 1313 rc = cil_write_sens(node, cil_out); 1314 break; 1315 case CIL_SENSALIAS: 1316 rc = cil_write_alias(node, cil_out); 1317 break; 1318 case CIL_SENSALIASACTUAL: 1319 rc = cil_write_aliasactual(node, cil_out); 1320 break; 1321 case CIL_CAT: 1322 rc = cil_write_cat(node, cil_out); 1323 break; 1324 case CIL_CATALIAS: 1325 rc = cil_write_alias(node, cil_out); 1326 break; 1327 case CIL_CATALIASACTUAL: 1328 rc = cil_write_aliasactual(node, cil_out); 1329 break; 1330 case CIL_CATSET: 1331 rc = cil_write_unsupported("CIL_CATSET"); 1332 break; 1333 case CIL_SENSCAT: 1334 rc = cil_write_senscat(node, cil_out); 1335 break; 1336 case CIL_CATORDER: 1337 rc = cil_write_catorder(node, cil_out); 1338 break; 1339 case CIL_SENSITIVITYORDER: 1340 rc = cil_write_sensorder(node, cil_out); 1341 break; 1342 case CIL_LEVEL: 1343 rc = cil_write_unsupported("CIL_LEVEL"); 1344 break; 1345 case CIL_LEVELRANGE: 1346 rc = cil_write_unsupported("CIL_LEVELRANGE"); 1347 break; 1348 case CIL_CONTEXT: 1349 rc = cil_write_unsupported("CIL_CONTEXT"); 1350 break; 1351 case CIL_NETIFCON: 1352 rc = cil_write_unsupported("CIL_NETIFCON"); 1353 break; 1354 case CIL_GENFSCON: 1355 rc = cil_write_genfscon(node, cil_out); 1356 break; 1357 case CIL_FILECON: 1358 rc = cil_write_unsupported("CIL_FILECON"); 1359 break; 1360 case CIL_NODECON: 1361 rc = cil_write_unsupported("CIL_NODECON"); 1362 break; 1363 case CIL_PORTCON: 1364 rc = cil_write_unsupported("CIL_PORTCON"); 1365 break; 1366 case CIL_PIRQCON: 1367 rc = cil_write_unsupported("CIL_PIRQCON"); 1368 break; 1369 case CIL_IOMEMCON: 1370 rc = cil_write_unsupported("CIL_IOMEMCON"); 1371 break; 1372 case CIL_IOPORTCON: 1373 rc = cil_write_unsupported("CIL_IOPORTCON"); 1374 break; 1375 case CIL_PCIDEVICECON: 1376 rc = cil_write_unsupported("CIL_PCIDEVICECON"); 1377 break; 1378 case CIL_DEVICETREECON: 1379 rc = cil_write_unsupported("CIL_DEVICETREECON"); 1380 break; 1381 case CIL_FSUSE: 1382 rc = cil_write_fsuse(node, cil_out); 1383 break; 1384 case CIL_CONSTRAIN: 1385 rc = cil_write_unsupported("CIL_CONSTRAIN"); 1386 break; 1387 case CIL_MLSCONSTRAIN: 1388 rc = cil_write_constrain(node, cil_out); 1389 break; 1390 case CIL_VALIDATETRANS: 1391 rc = cil_write_unsupported("CIL_VALIDATETRANS"); 1392 break; 1393 case CIL_MLSVALIDATETRANS: 1394 rc = cil_write_unsupported("CIL_MLSVALIDATETRANS"); 1395 break; 1396 case CIL_CALL: 1397 rc = cil_write_unsupported("CIL_CALL"); 1398 break; 1399 case CIL_MACRO: 1400 rc = cil_write_unsupported("CIL_MACRO"); 1401 break; 1402 case CIL_NODE: 1403 rc = cil_write_unsupported("CIL_NODE"); 1404 break; 1405 case CIL_OPTIONAL: 1406 rc = cil_write_unsupported("CIL_OPTIONAL"); 1407 break; 1408 case CIL_IPADDR: 1409 rc = cil_write_unsupported("CIL_IPADDR"); 1410 break; 1411 case CIL_CONDBLOCK: 1412 rc = cil_write_unsupported("CIL_CONDBLOCK"); 1413 break; 1414 case CIL_BOOLEANIF: 1415 rc = cil_write_unsupported("CIL_BOOLEANIF"); 1416 break; 1417 case CIL_TUNABLEIF: 1418 rc = cil_write_unsupported("CIL_TUNABLEIF"); 1419 break; 1420 case CIL_DEFAULTUSER: 1421 rc = cil_write_unsupported("CIL_DEFAULTUSER"); 1422 break; 1423 case CIL_DEFAULTROLE: 1424 rc = cil_write_unsupported("CIL_DEFAULTROLE"); 1425 break; 1426 case CIL_DEFAULTTYPE: 1427 rc = cil_write_unsupported("CIL_DEFAULTTYPE"); 1428 break; 1429 case CIL_DEFAULTRANGE: 1430 rc = cil_write_unsupported("CIL_DEFAULTRANGE"); 1431 break; 1432 case CIL_SELINUXUSER: 1433 rc = cil_write_unsupported("CIL_SELINUXUSER"); 1434 break; 1435 case CIL_SELINUXUSERDEFAULT: 1436 rc = cil_write_unsupported("CIL_SELINUXUSERDEFAULT"); 1437 break; 1438 case CIL_HANDLEUNKNOWN: 1439 rc = cil_write_handleunknown(node, cil_out); 1440 break; 1441 case CIL_MLS: 1442 rc = cil_write_mls(node, cil_out); 1443 break; 1444 case CIL_SRC_INFO: 1445 break; 1446 case CIL_NONE: 1447 // TODO: add proper removal support 1448 *finished = CIL_TREE_SKIP_HEAD; 1449 break; 1450 default: 1451 cil_log(CIL_ERR, "Unknown AST flavor: %d.\n", node->flavor); 1452 rc = SEPOL_ERR; 1453 goto exit; 1454 break; 1455 } 1456 exit: 1457 return rc; 1458 } 1459 1460 static int __cil_write_last_child_helper(struct cil_tree_node *node, void *extra_args) 1461 { 1462 int rc = SEPOL_ERR; 1463 struct cil_args_write *args = NULL; 1464 FILE *cil_out = NULL; 1465 1466 if (node == NULL || extra_args == NULL) { 1467 goto exit; 1468 } 1469 1470 args = extra_args; 1471 cil_out = args->cil_out; 1472 1473 if (node->parent && node->parent->flavor != CIL_ROOT && node->parent->flavor != CIL_SRC_INFO) { 1474 fprintf(cil_out,")"); 1475 } 1476 rc = SEPOL_OK; 1477 exit: 1478 return rc; 1479 } 1480 1481 /* main exported function */ 1482 int cil_write_ast(struct cil_db *db, const char* path) { 1483 int rc = SEPOL_ERR; 1484 struct cil_args_write extra_args; 1485 FILE *cil_out = NULL; 1486 1487 cil_out = fopen(path, "we"); 1488 if (cil_out == NULL) { 1489 cil_log(CIL_ERR, "Failure opening output file for writing AST\n"); 1490 rc = SEPOL_ERR; 1491 goto exit; 1492 } 1493 1494 extra_args.cil_out = cil_out; 1495 extra_args.db = db; 1496 rc = cil_tree_walk(db->ast->root, __cil_write_node_helper, 1497 __cil_write_first_child_helper, 1498 __cil_write_last_child_helper, 1499 &extra_args); 1500 if (rc != SEPOL_OK) { 1501 cil_log(CIL_INFO, "cil_tree_walk failed, rc: %d\n", rc); 1502 goto exit; 1503 } 1504 1505 exit: 1506 fclose(cil_out); 1507 cil_out = NULL; 1508 return rc; 1509 } 1510