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