blob: 3f97268dc4dd48f6e6ccb6d2451db52ee8e88566 [file] [log] [blame]
dcashman2e00e632016-10-12 14:58:09 -07001/*
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>
dcashman2e00e632016-10-12 14:58:09 -070012
13void __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/*
27 * read_cil_file - Initialize db and parse CIL input file.
28 */
29static int read_cil_file(struct cil_db **db, char *path) {
30 int rc = SEPOL_ERR;
31 FILE *file;
32 struct stat filedata;
33 uint32_t file_size;
34 char *buff = NULL;
35
36 cil_db_init(db);
37 file = fopen(path, "re");
38 if (!file) {
39 fprintf(stderr, "Could not open file: %s\n", path);
40 goto file_err;
41 }
42 rc = stat(path, &filedata);
43 if (rc == -1) {
44 fprintf(stderr, "Could not stat file: %s - %s\n", path, strerror(errno));
45 goto err;
46 }
47 file_size = filedata.st_size;
48 buff = malloc(file_size);
49 if (buff == NULL) {
50 fprintf(stderr, "OOM!\n");
51 rc = SEPOL_ERR;
52 goto err;
53 }
54 rc = fread(buff, file_size, 1, file);
55 if (rc != 1) {
56 fprintf(stderr, "Failure reading file: %s\n", path);
57 rc = SEPOL_ERR;
58 goto err;
59 }
60 fclose(file);
61 file = NULL;
62
63 /* creates parse_tree */
64 rc = cil_add_file(*db, path, buff, file_size);
65 if (rc != SEPOL_OK) {
66 fprintf(stderr, "Failure adding %s to parse tree\n", path);
liwugang85ce1532019-07-01 14:52:18 +080067 goto parse_err;
dcashman2e00e632016-10-12 14:58:09 -070068 }
69 free(buff);
70
71 return SEPOL_OK;
72err:
dcashman2e00e632016-10-12 14:58:09 -070073 fclose(file);
liwugang85ce1532019-07-01 14:52:18 +080074parse_err:
75 free(buff);
dcashman2e00e632016-10-12 14:58:09 -070076file_err:
77 cil_db_destroy(db);
78 return rc;
79}
80
81int 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;
Sandeep Patil42f95982017-04-07 14:18:48 -070090 char *dot;
dcashman2e00e632016-10-12 14:58:09 -070091 char *output = NULL;
Thiébaud Weksteen8e057d12021-09-15 10:56:34 +020092 FILE *output_file = NULL;
dcashman2e00e632016-10-12 14:58:09 -070093 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
Sandeep Patil42f95982017-04-07 14:18:48 -0700143 /* 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
dcashman2e00e632016-10-12 14:58:09 -0700150 if (mapping && tgt_policy) {
151 fprintf(stderr, "Please select only one mode between --mapping and --tgt_policy\n");
152 usage(argv[0]);
153 }
154
Nick Kralevich5fe07c72018-09-21 10:31:54 -0700155 /* gimme only the important details */
156 cil_set_log_level(CIL_WARN);
dcashman2e00e632016-10-12 14:58:09 -0700157
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 }
Thiébaud Weksteen8e057d12021-09-15 10:56:34 +0200180
181 output_file = fopen(output, "we");
182 if (!output_file) {
183 fprintf(stderr, "Could not open file: %s\n", output);
dcashman2e00e632016-10-12 14:58:09 -0700184 goto exit;
185 }
186
Thiébaud Weksteen8e057d12021-09-15 10:56:34 +0200187 rc = cil_write_build_ast(output_file, out_db);
188 if (rc != SEPOL_OK) {
189 fprintf(stderr, "Failed to write AST\n");
190 goto build_err;
191 }
192
193build_err:
194 fclose(output_file);
dcashman2e00e632016-10-12 14:58:09 -0700195exit:
196 free(base);
197 free(tgt_policy);
198 free(num);
199 free(output);
200 cil_db_destroy(&base_db);
201 cil_db_destroy(&out_db);
202 return rc;
203}