1*2d543d20SAndroid Build Coastguard Worker /* Authors: Karl MacMillan <[email protected]>
2*2d543d20SAndroid Build Coastguard Worker * Joshua Brindle <[email protected]>
3*2d543d20SAndroid Build Coastguard Worker *
4*2d543d20SAndroid Build Coastguard Worker * Copyright (C) 2004 Tresys Technology, LLC
5*2d543d20SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
6*2d543d20SAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
7*2d543d20SAndroid Build Coastguard Worker * the Free Software Foundation, version 2.
8*2d543d20SAndroid Build Coastguard Worker */
9*2d543d20SAndroid Build Coastguard Worker
10*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb.h>
11*2d543d20SAndroid Build Coastguard Worker #include <sepol/module.h>
12*2d543d20SAndroid Build Coastguard Worker
13*2d543d20SAndroid Build Coastguard Worker #include <getopt.h>
14*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
15*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
16*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
17*2d543d20SAndroid Build Coastguard Worker #include <sys/mman.h>
18*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
19*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
20*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
21*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
22*2d543d20SAndroid Build Coastguard Worker #include <string.h>
23*2d543d20SAndroid Build Coastguard Worker
24*2d543d20SAndroid Build Coastguard Worker #define EXPANDPOLICY_VERSION "1.0"
25*2d543d20SAndroid Build Coastguard Worker
usage(const char * program_name)26*2d543d20SAndroid Build Coastguard Worker static void usage(const char *program_name)
27*2d543d20SAndroid Build Coastguard Worker {
28*2d543d20SAndroid Build Coastguard Worker printf("usage: %s [-h -V -a -c [version] -v] basemodpkg outputfile\n",
29*2d543d20SAndroid Build Coastguard Worker program_name);
30*2d543d20SAndroid Build Coastguard Worker }
31*2d543d20SAndroid Build Coastguard Worker
main(int argc,char ** argv)32*2d543d20SAndroid Build Coastguard Worker int main(int argc, char **argv)
33*2d543d20SAndroid Build Coastguard Worker {
34*2d543d20SAndroid Build Coastguard Worker const char *basename, *outname;
35*2d543d20SAndroid Build Coastguard Worker int ch, ret, show_version = 0, verbose = 0, policyvers = 0, check_assertions = 1;
36*2d543d20SAndroid Build Coastguard Worker struct sepol_policy_file *pf = NULL;
37*2d543d20SAndroid Build Coastguard Worker sepol_module_package_t *base = NULL;
38*2d543d20SAndroid Build Coastguard Worker sepol_policydb_t *out = NULL, *p;
39*2d543d20SAndroid Build Coastguard Worker FILE *fp = NULL, *outfile = NULL;
40*2d543d20SAndroid Build Coastguard Worker sepol_handle_t *handle = NULL;
41*2d543d20SAndroid Build Coastguard Worker
42*2d543d20SAndroid Build Coastguard Worker while ((ch = getopt(argc, argv, "c:Vvah")) != EOF) {
43*2d543d20SAndroid Build Coastguard Worker switch (ch) {
44*2d543d20SAndroid Build Coastguard Worker case 'V':
45*2d543d20SAndroid Build Coastguard Worker show_version = 1;
46*2d543d20SAndroid Build Coastguard Worker break;
47*2d543d20SAndroid Build Coastguard Worker case 'v':
48*2d543d20SAndroid Build Coastguard Worker verbose = 1;
49*2d543d20SAndroid Build Coastguard Worker break;
50*2d543d20SAndroid Build Coastguard Worker case 'h':
51*2d543d20SAndroid Build Coastguard Worker usage(argv[0]);
52*2d543d20SAndroid Build Coastguard Worker return EXIT_SUCCESS;
53*2d543d20SAndroid Build Coastguard Worker case 'c':{
54*2d543d20SAndroid Build Coastguard Worker long int n;
55*2d543d20SAndroid Build Coastguard Worker
56*2d543d20SAndroid Build Coastguard Worker errno = 0;
57*2d543d20SAndroid Build Coastguard Worker n = strtol(optarg, NULL, 10);
58*2d543d20SAndroid Build Coastguard Worker if (errno) {
59*2d543d20SAndroid Build Coastguard Worker fprintf(stderr,
60*2d543d20SAndroid Build Coastguard Worker "%s: Invalid policyvers specified: %s\n",
61*2d543d20SAndroid Build Coastguard Worker argv[0], optarg);
62*2d543d20SAndroid Build Coastguard Worker usage(argv[0]);
63*2d543d20SAndroid Build Coastguard Worker return EXIT_FAILURE;
64*2d543d20SAndroid Build Coastguard Worker }
65*2d543d20SAndroid Build Coastguard Worker if (n < sepol_policy_kern_vers_min()
66*2d543d20SAndroid Build Coastguard Worker || n > sepol_policy_kern_vers_max()) {
67*2d543d20SAndroid Build Coastguard Worker fprintf(stderr,
68*2d543d20SAndroid Build Coastguard Worker "%s: policyvers value %ld not in range %d-%d\n",
69*2d543d20SAndroid Build Coastguard Worker argv[0], n,
70*2d543d20SAndroid Build Coastguard Worker sepol_policy_kern_vers_min(),
71*2d543d20SAndroid Build Coastguard Worker sepol_policy_kern_vers_max());
72*2d543d20SAndroid Build Coastguard Worker usage(argv[0]);
73*2d543d20SAndroid Build Coastguard Worker return EXIT_FAILURE;
74*2d543d20SAndroid Build Coastguard Worker }
75*2d543d20SAndroid Build Coastguard Worker policyvers = n;
76*2d543d20SAndroid Build Coastguard Worker break;
77*2d543d20SAndroid Build Coastguard Worker }
78*2d543d20SAndroid Build Coastguard Worker case 'a':{
79*2d543d20SAndroid Build Coastguard Worker check_assertions = 0;
80*2d543d20SAndroid Build Coastguard Worker break;
81*2d543d20SAndroid Build Coastguard Worker }
82*2d543d20SAndroid Build Coastguard Worker default:
83*2d543d20SAndroid Build Coastguard Worker usage(argv[0]);
84*2d543d20SAndroid Build Coastguard Worker return EXIT_FAILURE;
85*2d543d20SAndroid Build Coastguard Worker }
86*2d543d20SAndroid Build Coastguard Worker }
87*2d543d20SAndroid Build Coastguard Worker
88*2d543d20SAndroid Build Coastguard Worker if (verbose) {
89*2d543d20SAndroid Build Coastguard Worker if (policyvers)
90*2d543d20SAndroid Build Coastguard Worker printf("Building version %d policy\n", policyvers);
91*2d543d20SAndroid Build Coastguard Worker }
92*2d543d20SAndroid Build Coastguard Worker
93*2d543d20SAndroid Build Coastguard Worker if (show_version) {
94*2d543d20SAndroid Build Coastguard Worker printf("%s\n", EXPANDPOLICY_VERSION);
95*2d543d20SAndroid Build Coastguard Worker return EXIT_SUCCESS;
96*2d543d20SAndroid Build Coastguard Worker }
97*2d543d20SAndroid Build Coastguard Worker
98*2d543d20SAndroid Build Coastguard Worker /* check args */
99*2d543d20SAndroid Build Coastguard Worker if (argc < 3 || argc - optind != 2) {
100*2d543d20SAndroid Build Coastguard Worker fprintf(stderr,
101*2d543d20SAndroid Build Coastguard Worker "%s: You must provide the base module package and output filename\n",
102*2d543d20SAndroid Build Coastguard Worker argv[0]);
103*2d543d20SAndroid Build Coastguard Worker usage(argv[0]);
104*2d543d20SAndroid Build Coastguard Worker return EXIT_FAILURE;
105*2d543d20SAndroid Build Coastguard Worker }
106*2d543d20SAndroid Build Coastguard Worker
107*2d543d20SAndroid Build Coastguard Worker basename = argv[optind++];
108*2d543d20SAndroid Build Coastguard Worker outname = argv[optind];
109*2d543d20SAndroid Build Coastguard Worker
110*2d543d20SAndroid Build Coastguard Worker handle = sepol_handle_create();
111*2d543d20SAndroid Build Coastguard Worker if (!handle) {
112*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "%s: Out of memory\n", argv[0]);
113*2d543d20SAndroid Build Coastguard Worker goto failure;
114*2d543d20SAndroid Build Coastguard Worker }
115*2d543d20SAndroid Build Coastguard Worker
116*2d543d20SAndroid Build Coastguard Worker if (sepol_policy_file_create(&pf)) {
117*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "%s: Out of memory\n", argv[0]);
118*2d543d20SAndroid Build Coastguard Worker goto failure;
119*2d543d20SAndroid Build Coastguard Worker }
120*2d543d20SAndroid Build Coastguard Worker
121*2d543d20SAndroid Build Coastguard Worker /* read the base module */
122*2d543d20SAndroid Build Coastguard Worker if (sepol_module_package_create(&base)) {
123*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "%s: Out of memory\n", argv[0]);
124*2d543d20SAndroid Build Coastguard Worker goto failure;
125*2d543d20SAndroid Build Coastguard Worker }
126*2d543d20SAndroid Build Coastguard Worker
127*2d543d20SAndroid Build Coastguard Worker fp = fopen(basename, "re");
128*2d543d20SAndroid Build Coastguard Worker if (!fp) {
129*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "%s: Can't open '%s': %s\n",
130*2d543d20SAndroid Build Coastguard Worker argv[0], basename, strerror(errno));
131*2d543d20SAndroid Build Coastguard Worker goto failure;
132*2d543d20SAndroid Build Coastguard Worker }
133*2d543d20SAndroid Build Coastguard Worker
134*2d543d20SAndroid Build Coastguard Worker sepol_policy_file_set_fp(pf, fp);
135*2d543d20SAndroid Build Coastguard Worker ret = sepol_module_package_read(base, pf, 0);
136*2d543d20SAndroid Build Coastguard Worker if (ret) {
137*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "%s: Error in reading package from %s\n",
138*2d543d20SAndroid Build Coastguard Worker argv[0], basename);
139*2d543d20SAndroid Build Coastguard Worker goto failure;
140*2d543d20SAndroid Build Coastguard Worker }
141*2d543d20SAndroid Build Coastguard Worker
142*2d543d20SAndroid Build Coastguard Worker fclose(fp);
143*2d543d20SAndroid Build Coastguard Worker fp = NULL;
144*2d543d20SAndroid Build Coastguard Worker
145*2d543d20SAndroid Build Coastguard Worker /* linking the base takes care of enabling optional avrules */
146*2d543d20SAndroid Build Coastguard Worker p = sepol_module_package_get_policy(base);
147*2d543d20SAndroid Build Coastguard Worker if (sepol_link_modules(handle, p, NULL, 0, 0)) {
148*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "%s: Error while enabling avrules\n", argv[0]);
149*2d543d20SAndroid Build Coastguard Worker goto failure;
150*2d543d20SAndroid Build Coastguard Worker }
151*2d543d20SAndroid Build Coastguard Worker
152*2d543d20SAndroid Build Coastguard Worker /* create the output policy */
153*2d543d20SAndroid Build Coastguard Worker
154*2d543d20SAndroid Build Coastguard Worker if (sepol_policydb_create(&out)) {
155*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "%s: Out of memory\n", argv[0]);
156*2d543d20SAndroid Build Coastguard Worker goto failure;
157*2d543d20SAndroid Build Coastguard Worker }
158*2d543d20SAndroid Build Coastguard Worker
159*2d543d20SAndroid Build Coastguard Worker sepol_set_expand_consume_base(handle, 1);
160*2d543d20SAndroid Build Coastguard Worker
161*2d543d20SAndroid Build Coastguard Worker if (sepol_expand_module(handle, p, out, verbose, check_assertions)) {
162*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "%s: Error while expanding policy\n", argv[0]);
163*2d543d20SAndroid Build Coastguard Worker goto failure;
164*2d543d20SAndroid Build Coastguard Worker }
165*2d543d20SAndroid Build Coastguard Worker
166*2d543d20SAndroid Build Coastguard Worker if (policyvers) {
167*2d543d20SAndroid Build Coastguard Worker if (sepol_policydb_set_vers(out, policyvers)) {
168*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "%s: Invalid version %d\n", argv[0],
169*2d543d20SAndroid Build Coastguard Worker policyvers);
170*2d543d20SAndroid Build Coastguard Worker goto failure;
171*2d543d20SAndroid Build Coastguard Worker }
172*2d543d20SAndroid Build Coastguard Worker }
173*2d543d20SAndroid Build Coastguard Worker
174*2d543d20SAndroid Build Coastguard Worker outfile = fopen(outname, "we");
175*2d543d20SAndroid Build Coastguard Worker if (!outfile) {
176*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "%s: Can't open '%s': %s\n",
177*2d543d20SAndroid Build Coastguard Worker argv[0], outname, strerror(errno));
178*2d543d20SAndroid Build Coastguard Worker goto failure;
179*2d543d20SAndroid Build Coastguard Worker }
180*2d543d20SAndroid Build Coastguard Worker
181*2d543d20SAndroid Build Coastguard Worker sepol_policy_file_set_fp(pf, outfile);
182*2d543d20SAndroid Build Coastguard Worker ret = sepol_policydb_write(out, pf);
183*2d543d20SAndroid Build Coastguard Worker if (ret) {
184*2d543d20SAndroid Build Coastguard Worker fprintf(stderr,
185*2d543d20SAndroid Build Coastguard Worker "%s: Error while writing expanded policy to %s\n",
186*2d543d20SAndroid Build Coastguard Worker argv[0], outname);
187*2d543d20SAndroid Build Coastguard Worker goto failure;
188*2d543d20SAndroid Build Coastguard Worker }
189*2d543d20SAndroid Build Coastguard Worker
190*2d543d20SAndroid Build Coastguard Worker ret = fclose(outfile);
191*2d543d20SAndroid Build Coastguard Worker outfile = NULL;
192*2d543d20SAndroid Build Coastguard Worker if (ret) {
193*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "%s: Error closing policy file %s: %s\n",
194*2d543d20SAndroid Build Coastguard Worker argv[0], outname, strerror(errno));
195*2d543d20SAndroid Build Coastguard Worker goto failure;
196*2d543d20SAndroid Build Coastguard Worker }
197*2d543d20SAndroid Build Coastguard Worker
198*2d543d20SAndroid Build Coastguard Worker ret = EXIT_SUCCESS;
199*2d543d20SAndroid Build Coastguard Worker goto cleanup;
200*2d543d20SAndroid Build Coastguard Worker
201*2d543d20SAndroid Build Coastguard Worker failure:
202*2d543d20SAndroid Build Coastguard Worker ret = EXIT_FAILURE;
203*2d543d20SAndroid Build Coastguard Worker
204*2d543d20SAndroid Build Coastguard Worker cleanup:
205*2d543d20SAndroid Build Coastguard Worker if (outfile)
206*2d543d20SAndroid Build Coastguard Worker fclose(outfile);
207*2d543d20SAndroid Build Coastguard Worker sepol_policydb_free(out);
208*2d543d20SAndroid Build Coastguard Worker if (fp)
209*2d543d20SAndroid Build Coastguard Worker fclose(fp);
210*2d543d20SAndroid Build Coastguard Worker sepol_module_package_free(base);
211*2d543d20SAndroid Build Coastguard Worker sepol_policy_file_free(pf);
212*2d543d20SAndroid Build Coastguard Worker sepol_handle_destroy(handle);
213*2d543d20SAndroid Build Coastguard Worker
214*2d543d20SAndroid Build Coastguard Worker return ret;
215*2d543d20SAndroid Build Coastguard Worker }
216