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