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