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 parse_err; 69 } 70 free(buff); 71 72 return SEPOL_OK; 73 err: 74 fclose(file); 75 parse_err: 76 free(buff); 77 file_err: 78 cil_db_destroy(db); 79 return rc; 80 } 81 82 int main(int argc, char *argv[]) 83 { 84 int opt_char; 85 int opt_index = 0; 86 int rc = SEPOL_ERR; 87 bool mapping = false; 88 char *base = NULL; 89 char *tgt_policy = NULL; 90 char *num = NULL; 91 char *dot; 92 char *output = NULL; 93 struct cil_db *base_db = NULL; 94 struct cil_db *out_db = NULL; 95 96 static struct option long_opts[] = { 97 {"help", no_argument, 0, 'h'}, 98 {"base", required_argument, 0, 'b'}, 99 {"mapping", no_argument, 0, 'm'}, 100 {"number", required_argument, 0, 'n'}, 101 {"output", required_argument, 0, 'o'}, 102 {"tgt_policy", required_argument, 0, 't'}, 103 {0, 0, 0, 0} 104 }; 105 106 while (1) { 107 opt_char = getopt_long(argc, argv, "b:mn:o:t:h", long_opts, &opt_index); 108 if (opt_char == -1) { 109 break; 110 } 111 switch (opt_char) { 112 case 'b': 113 base = strdup(optarg); 114 break; 115 case 'm': 116 mapping = true; 117 break; 118 case 'n': 119 num = strdup(optarg); 120 break; 121 case 'o': 122 output = strdup(optarg); 123 break; 124 case 't': 125 tgt_policy = strdup(optarg); 126 break; 127 case 'h': 128 usage(argv[0]); 129 default: 130 fprintf(stderr, "Unsupported option: %s\n", optarg); 131 usage(argv[0]); 132 } 133 } 134 if (optind < argc) { 135 fprintf(stderr, "Unknown arguments supplied\n"); 136 usage(argv[0]); 137 } 138 if (num == NULL || base == NULL || (mapping == false && tgt_policy == NULL)) { 139 fprintf(stderr, "Please specify required arguments\n"); 140 usage(argv[0]); 141 } 142 143 /* policy language doesn't like '.', so replace them with '_' in mapping version */ 144 dot = num; 145 while ((dot = strchr(dot, '.')) != NULL) { 146 *dot = '_'; 147 ++dot; 148 } 149 150 if (mapping && tgt_policy) { 151 fprintf(stderr, "Please select only one mode between --mapping and --tgt_policy\n"); 152 usage(argv[0]); 153 } 154 155 /* gimme only the important details */ 156 cil_set_log_level(CIL_WARN); 157 158 /* read platform policy */ 159 rc = read_cil_file(&base_db, base); 160 if (rc != SEPOL_OK) { 161 goto exit; 162 } 163 164 if (mapping) { 165 rc = cil_android_attrib_mapping(&out_db, base_db, num); 166 if (rc != SEPOL_OK) 167 goto exit; 168 } else { 169 /* read target policy, ready for manipulation */ 170 rc = read_cil_file(&out_db, tgt_policy); 171 if (rc != SEPOL_OK) { 172 goto exit; 173 } 174 /* attributize the target policy */ 175 rc = cil_android_attributize(out_db, base_db, num); 176 if (rc != SEPOL_OK) { 177 goto exit; 178 } 179 } 180 rc = cil_write_ast(out_db, output); 181 if (rc != SEPOL_OK) { 182 goto exit; 183 } 184 185 exit: 186 free(base); 187 free(tgt_policy); 188 free(num); 189 free(output); 190 cil_db_destroy(&base_db); 191 cil_db_destroy(&out_db); 192 return rc; 193 } 194