• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
usage(char * prog)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  */
read_cil_file(struct cil_db ** db,char * path)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 
main(int argc,char * argv[])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