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