1 /*
2 * Authors: Joshua Brindle <jbrindle@tresys.com>
3 * Karl MacMillan <kmacmillan@tresys.com>
4 * Jason Tang <jtang@tresys.com>
5 *
6 *
7 * Copyright (C) 2004-5 Tresys Technology, LLC
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, version 2.
11 */
12
13 #include <getopt.h>
14 #include <unistd.h>
15 #include <stdlib.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <stdio.h>
20 #include <errno.h>
21 #include <sys/mman.h>
22
23 #include <sepol/module_to_cil.h>
24 #include <sepol/policydb/policydb.h>
25 #include <sepol/policydb/services.h>
26 #include <sepol/policydb/conditional.h>
27 #include <sepol/policydb/flask.h>
28 #include <sepol/policydb/hierarchy.h>
29 #include <sepol/policydb/expand.h>
30 #include <sepol/policydb/link.h>
31 #include <sepol/policydb/sidtab.h>
32
33 #include "queue.h"
34 #include "checkpolicy.h"
35 #include "parse_util.h"
36
37 extern char *optarg;
38 extern int optind;
39
40 static sidtab_t sidtab;
41
42 extern int mlspol;
43
44 static int handle_unknown = SEPOL_DENY_UNKNOWN;
45 static const char *txtfile = "policy.conf";
46 static const char *binfile = "policy";
47
48 unsigned int policy_type = POLICY_BASE;
49 unsigned int policyvers = MOD_POLICYDB_VERSION_MAX;
50
read_binary_policy(policydb_t * p,const char * file,const char * progname)51 static int read_binary_policy(policydb_t * p, const char *file, const char *progname)
52 {
53 int fd;
54 struct stat sb;
55 void *map;
56 struct policy_file f, *fp;
57
58 fd = open(file, O_RDONLY);
59 if (fd < 0) {
60 fprintf(stderr, "Can't open '%s': %s\n",
61 file, strerror(errno));
62 return -1;
63 }
64 if (fstat(fd, &sb) < 0) {
65 fprintf(stderr, "Can't stat '%s': %s\n",
66 file, strerror(errno));
67 close(fd);
68 return -1;
69 }
70 map =
71 mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
72 close(fd);
73 if (map == MAP_FAILED) {
74 fprintf(stderr, "Can't map '%s': %s\n", file, strerror(errno));
75 return -1;
76 }
77 policy_file_init(&f);
78 f.type = PF_USE_MEMORY;
79 f.data = map;
80 f.len = sb.st_size;
81 fp = &f;
82
83 if (policydb_init(p)) {
84 fprintf(stderr, "%s: policydb_init: Out of memory!\n",
85 progname);
86 return -1;
87 }
88 if (policydb_read(p, fp, 1)) {
89 fprintf(stderr,
90 "%s: error(s) encountered while parsing configuration\n",
91 progname);
92 return -1;
93 }
94
95 /* Check Policy Consistency */
96 if (p->mls) {
97 if (!mlspol) {
98 fprintf(stderr, "%s: MLS policy, but non-MLS"
99 " is specified\n", progname);
100 return -1;
101 }
102 } else {
103 if (mlspol) {
104 fprintf(stderr, "%s: non-MLS policy, but MLS"
105 " is specified\n", progname);
106 return -1;
107 }
108 }
109 return 0;
110 }
111
write_binary_policy(policydb_t * p,FILE * outfp)112 static int write_binary_policy(policydb_t * p, FILE *outfp)
113 {
114 struct policy_file pf;
115
116 p->policy_type = policy_type;
117 p->policyvers = policyvers;
118 p->handle_unknown = handle_unknown;
119
120 policy_file_init(&pf);
121 pf.type = PF_USE_STDIO;
122 pf.fp = outfp;
123 return policydb_write(p, &pf);
124 }
125
usage(char * progname)126 static void usage(char *progname)
127 {
128 printf("usage: %s [-h] [-V] [-b] [-C] [-U handle_unknown] [-m] [-M] [-o FILE] [INPUT]\n", progname);
129 printf("Build base and policy modules.\n");
130 printf("Options:\n");
131 printf(" INPUT build module from INPUT (else read from \"%s\")\n",
132 txtfile);
133 printf(" -V show policy versions created by this program\n");
134 printf(" -b treat input as a binary policy file\n");
135 printf(" -C output CIL policy instead of binary policy\n");
136 printf(" -h print usage\n");
137 printf(" -U OPTION How to handle unknown classes and permissions\n");
138 printf(" deny: Deny unknown kernel checks\n");
139 printf(" reject: Reject loading of policy with unknowns\n");
140 printf(" allow: Allow unknown kernel checks\n");
141 printf(" -m build a policy module instead of a base module\n");
142 printf(" -M enable MLS policy\n");
143 printf(" -o FILE write module to FILE (else just check syntax)\n");
144 exit(1);
145 }
146
main(int argc,char ** argv)147 int main(int argc, char **argv)
148 {
149 const char *file = txtfile, *outfile = NULL;
150 unsigned int binary = 0, cil = 0;
151 int ch;
152 int show_version = 0;
153 policydb_t modpolicydb;
154 struct option long_options[] = {
155 {"help", no_argument, NULL, 'h'},
156 {"output", required_argument, NULL, 'o'},
157 {"binary", no_argument, NULL, 'b'},
158 {"version", no_argument, NULL, 'V'},
159 {"handle-unknown", required_argument, NULL, 'U'},
160 {"mls", no_argument, NULL, 'M'},
161 {"cil", no_argument, NULL, 'C'},
162 {NULL, 0, NULL, 0}
163 };
164
165 while ((ch = getopt_long(argc, argv, "ho:bVU:mMC", long_options, NULL)) != -1) {
166 switch (ch) {
167 case 'h':
168 usage(argv[0]);
169 break;
170 case 'o':
171 outfile = optarg;
172 break;
173 case 'b':
174 binary = 1;
175 file = binfile;
176 break;
177 case 'V':
178 show_version = 1;
179 break;
180 case 'U':
181 if (!strcasecmp(optarg, "deny")) {
182 handle_unknown = DENY_UNKNOWN;
183 break;
184 }
185 if (!strcasecmp(optarg, "reject")) {
186 handle_unknown = REJECT_UNKNOWN;
187 break;
188 }
189 if (!strcasecmp(optarg, "allow")) {
190 handle_unknown = ALLOW_UNKNOWN;
191 break;
192 }
193 usage(argv[0]);
194 case 'm':
195 policy_type = POLICY_MOD;
196 policyvers = MOD_POLICYDB_VERSION_MAX;
197 break;
198 case 'M':
199 mlspol = 1;
200 break;
201 case 'C':
202 cil = 1;
203 break;
204 default:
205 usage(argv[0]);
206 }
207 }
208
209 if (show_version) {
210 printf("Module versions %d-%d\n",
211 MOD_POLICYDB_VERSION_MIN, MOD_POLICYDB_VERSION_MAX);
212 exit(0);
213 }
214
215 if (handle_unknown && (policy_type != POLICY_BASE)) {
216 fprintf(stderr, "%s: Handling of unknown classes and permissions is only valid in the base module.\n", argv[0]);
217 exit(1);
218 }
219
220 if (binary && (policy_type != POLICY_BASE)) {
221 fprintf(stderr, "%s: -b and -m are incompatible with each other.\n", argv[0]);
222 exit(1);
223 }
224
225 if (optind != argc) {
226 file = argv[optind++];
227 if (optind != argc)
228 usage(argv[0]);
229 }
230 printf("%s: loading policy configuration from %s\n", argv[0], file);
231
232 /* Set policydb and sidtab used by libsepol service functions
233 to my structures, so that I can directly populate and
234 manipulate them. */
235 sepol_set_policydb(&modpolicydb);
236 sepol_set_sidtab(&sidtab);
237
238 if (binary) {
239 if (read_binary_policy(&modpolicydb, file, argv[0]) == -1) {
240 exit(1);
241 }
242 } else {
243 if (policydb_init(&modpolicydb)) {
244 fprintf(stderr, "%s: out of memory!\n", argv[0]);
245 return -1;
246 }
247
248 modpolicydb.policy_type = policy_type;
249 modpolicydb.mls = mlspol;
250 modpolicydb.handle_unknown = handle_unknown;
251
252 if (read_source_policy(&modpolicydb, file, argv[0]) == -1) {
253 exit(1);
254 }
255
256 if (hierarchy_check_constraints(NULL, &modpolicydb)) {
257 return -1;
258 }
259 }
260
261 if (modpolicydb.policy_type == POLICY_BASE && !cil) {
262 /* Verify that we can successfully expand the base module. */
263 policydb_t kernpolicydb;
264
265 if (policydb_init(&kernpolicydb)) {
266 fprintf(stderr, "%s: policydb_init failed\n", argv[0]);
267 exit(1);
268 }
269 if (link_modules(NULL, &modpolicydb, NULL, 0, 0)) {
270 fprintf(stderr, "%s: link modules failed\n", argv[0]);
271 exit(1);
272 }
273 if (expand_module(NULL, &modpolicydb, &kernpolicydb, 0, 1)) {
274 fprintf(stderr, "%s: expand module failed\n", argv[0]);
275 exit(1);
276 }
277 policydb_destroy(&kernpolicydb);
278 }
279
280 if (policydb_load_isids(&modpolicydb, &sidtab))
281 exit(1);
282
283 sepol_sidtab_destroy(&sidtab);
284
285 printf("%s: policy configuration loaded\n", argv[0]);
286
287 if (outfile) {
288 FILE *outfp = fopen(outfile, "w");
289
290 if (!outfp) {
291 perror(outfile);
292 exit(1);
293 }
294
295 if (!cil) {
296 printf("%s: writing binary representation (version %d) to %s\n",
297 argv[0], policyvers, file);
298
299 if (write_binary_policy(&modpolicydb, outfp) != 0) {
300 fprintf(stderr, "%s: error writing %s\n", argv[0], outfile);
301 exit(1);
302 }
303 } else {
304 printf("%s: writing CIL to %s\n",argv[0], outfile);
305
306 if (sepol_module_policydb_to_cil(outfp, &modpolicydb, 0) != 0) {
307 fprintf(stderr, "%s: error writing %s\n", argv[0], outfile);
308 exit(1);
309 }
310 }
311
312 fclose(outfp);
313 } else if (cil) {
314 fprintf(stderr, "%s: No file to write CIL was specified\n", argv[0]);
315 exit(1);
316 }
317
318 policydb_destroy(&modpolicydb);
319
320 return 0;
321 }
322
323 /* FLASK */
324