version_policy.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * version_policy.c - Takes the given public platform policy, a private policy
  3. * and a version number to produced a combined "versioned" policy file.
  4. */
  5. #include <errno.h>
  6. #include <getopt.h>
  7. #include <stdbool.h>
  8. #include <stdio.h>
  9. #include <sys/stat.h>
  10. #include <cil/android.h>
  11. #include <cil/cil.h>
  12. #include <cil/cil_write_ast.h>
  13. void __attribute__ ((noreturn)) static usage(char *prog) {
  14. printf("Usage: %s [OPTION]...\n", prog);
  15. printf("\n");
  16. printf("Options:\n");
  17. printf(" -b, --base=<file> (req'd) base policy for versioning.\n");
  18. printf(" -m, --mapping generate cil version mapping from base policy\n");
  19. printf(" -n, --number (req'd) version number to use.\n");
  20. printf(" -o, --output=<file> write cil policy to <file>\n");
  21. printf(" -t, --tgt_policy policy to be versioned according to base policy\n");
  22. printf(" -h, --help display usage information\n");
  23. exit(1);
  24. }
  25. /*
  26. * read_cil_file - Initialize db and parse CIL input file.
  27. */
  28. static int read_cil_file(struct cil_db **db, char *path) {
  29. int rc = SEPOL_ERR;
  30. FILE *file;
  31. struct stat filedata;
  32. uint32_t file_size;
  33. char *buff = NULL;
  34. cil_db_init(db);
  35. file = fopen(path, "re");
  36. if (!file) {
  37. fprintf(stderr, "Could not open file: %s\n", path);
  38. goto file_err;
  39. }
  40. rc = stat(path, &filedata);
  41. if (rc == -1) {
  42. fprintf(stderr, "Could not stat file: %s - %s\n", path, strerror(errno));
  43. goto err;
  44. }
  45. file_size = filedata.st_size;
  46. buff = malloc(file_size);
  47. if (buff == NULL) {
  48. fprintf(stderr, "OOM!\n");
  49. rc = SEPOL_ERR;
  50. goto err;
  51. }
  52. rc = fread(buff, file_size, 1, file);
  53. if (rc != 1) {
  54. fprintf(stderr, "Failure reading file: %s\n", path);
  55. rc = SEPOL_ERR;
  56. goto err;
  57. }
  58. fclose(file);
  59. file = NULL;
  60. /* creates parse_tree */
  61. rc = cil_add_file(*db, path, buff, file_size);
  62. if (rc != SEPOL_OK) {
  63. fprintf(stderr, "Failure adding %s to parse tree\n", path);
  64. goto err;
  65. }
  66. free(buff);
  67. return SEPOL_OK;
  68. err:
  69. free(buff);
  70. fclose(file);
  71. file_err:
  72. cil_db_destroy(db);
  73. return rc;
  74. }
  75. int main(int argc, char *argv[])
  76. {
  77. int opt_char;
  78. int opt_index = 0;
  79. int rc = SEPOL_ERR;
  80. bool mapping = false;
  81. char *base = NULL;
  82. char *tgt_policy = NULL;
  83. char *num = NULL;
  84. char *dot;
  85. char *output = NULL;
  86. struct cil_db *base_db = NULL;
  87. struct cil_db *out_db = NULL;
  88. static struct option long_opts[] = {
  89. {"help", no_argument, 0, 'h'},
  90. {"base", required_argument, 0, 'b'},
  91. {"mapping", no_argument, 0, 'm'},
  92. {"number", required_argument, 0, 'n'},
  93. {"output", required_argument, 0, 'o'},
  94. {"tgt_policy", required_argument, 0, 't'},
  95. {0, 0, 0, 0}
  96. };
  97. while (1) {
  98. opt_char = getopt_long(argc, argv, "b:mn:o:t:h", long_opts, &opt_index);
  99. if (opt_char == -1) {
  100. break;
  101. }
  102. switch (opt_char) {
  103. case 'b':
  104. base = strdup(optarg);
  105. break;
  106. case 'm':
  107. mapping = true;
  108. break;
  109. case 'n':
  110. num = strdup(optarg);
  111. break;
  112. case 'o':
  113. output = strdup(optarg);
  114. break;
  115. case 't':
  116. tgt_policy = strdup(optarg);
  117. break;
  118. case 'h':
  119. usage(argv[0]);
  120. default:
  121. fprintf(stderr, "Unsupported option: %s\n", optarg);
  122. usage(argv[0]);
  123. }
  124. }
  125. if (optind < argc) {
  126. fprintf(stderr, "Unknown arguments supplied\n");
  127. usage(argv[0]);
  128. }
  129. if (num == NULL || base == NULL || (mapping == false && tgt_policy == NULL)) {
  130. fprintf(stderr, "Please specify required arguments\n");
  131. usage(argv[0]);
  132. }
  133. /* policy language doesn't like '.', so replace them with '_' in mapping version */
  134. dot = num;
  135. while ((dot = strchr(dot, '.')) != NULL) {
  136. *dot = '_';
  137. ++dot;
  138. }
  139. if (mapping && tgt_policy) {
  140. fprintf(stderr, "Please select only one mode between --mapping and --tgt_policy\n");
  141. usage(argv[0]);
  142. }
  143. /* gimme only the important details */
  144. cil_set_log_level(CIL_WARN);
  145. /* read platform policy */
  146. rc = read_cil_file(&base_db, base);
  147. if (rc != SEPOL_OK) {
  148. goto exit;
  149. }
  150. if (mapping) {
  151. rc = cil_android_attrib_mapping(&out_db, base_db, num);
  152. if (rc != SEPOL_OK)
  153. goto exit;
  154. } else {
  155. /* read target policy, ready for manipulation */
  156. rc = read_cil_file(&out_db, tgt_policy);
  157. if (rc != SEPOL_OK) {
  158. goto exit;
  159. }
  160. /* attributize the target policy */
  161. rc = cil_android_attributize(out_db, base_db, num);
  162. if (rc != SEPOL_OK) {
  163. goto exit;
  164. }
  165. }
  166. rc = cil_write_ast(out_db, output);
  167. if (rc != SEPOL_OK) {
  168. goto exit;
  169. }
  170. exit:
  171. free(base);
  172. free(tgt_policy);
  173. free(num);
  174. free(output);
  175. cil_db_destroy(&base_db);
  176. cil_db_destroy(&out_db);
  177. return rc;
  178. }