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