semodule_expand.c revision 13cd4c8960688af11ad23b4c946149015c80d54
1/* Authors: Karl MacMillan <kmacmillan@tresys.com>
2 * 	    Joshua Brindle <jbrindle@tresys.com>
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
24extern char *optarg;
25extern int optind;
26
27int policyvers = 0;
28
29#define EXPANDPOLICY_VERSION "1.0"
30
31static void usage(char *program_name)
32{
33	printf("usage: %s [-V -a -c [version]] basemodpkg outputfile\n",
34	       program_name);
35	exit(1);
36}
37
38int main(int argc, char **argv)
39{
40	char *basename, *outname;
41	int ch, ret, show_version = 0, verbose = 0;
42	struct sepol_policy_file *pf;
43	sepol_module_package_t *base;
44	sepol_policydb_t *out, *p;
45	FILE *fp, *outfile;
46	int check_assertions = 1;
47	sepol_handle_t *handle;
48
49	while ((ch = getopt(argc, argv, "c:Vva")) != EOF) {
50		switch (ch) {
51		case 'V':
52			show_version = 1;
53			break;
54		case 'v':
55			verbose = 1;
56			break;
57		case 'c':{
58				long int n = strtol(optarg, NULL, 10);
59				if (errno) {
60					fprintf(stderr,
61						"%s:  Invalid policyvers specified: %s\n",
62						argv[0], optarg);
63					usage(argv[0]);
64					exit(1);
65				}
66				if (n < sepol_policy_kern_vers_min()
67				    || n > sepol_policy_kern_vers_max()) {
68					fprintf(stderr,
69						"%s:  policyvers value %ld not in range %d-%d\n",
70						argv[0], n,
71						sepol_policy_kern_vers_min(),
72						sepol_policy_kern_vers_max());
73					usage(argv[0]);
74					exit(1);
75				}
76				policyvers = n;
77				break;
78			}
79		case 'a':{
80				check_assertions = 0;
81				break;
82			}
83		default:
84			usage(argv[0]);
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		exit(0);
96	}
97
98	/* check args */
99	if (argc < 3 || !(optind != (argc - 1))) {
100		fprintf(stderr,
101			"%s:  You must provide the base module package and output filename\n",
102			argv[0]);
103		usage(argv[0]);
104	}
105
106	basename = argv[optind++];
107	outname = argv[optind];
108
109	handle = sepol_handle_create();
110	if (!handle)
111		exit(1);
112
113	if (sepol_policy_file_create(&pf)) {
114		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
115		exit(1);
116	}
117
118	/* read the base module */
119	if (sepol_module_package_create(&base)) {
120		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
121		exit(1);
122	}
123	fp = fopen(basename, "r");
124	if (!fp) {
125		fprintf(stderr, "%s:  Can't open '%s':  %s\n",
126			argv[0], basename, strerror(errno));
127		exit(1);
128	}
129	sepol_policy_file_set_fp(pf, fp);
130	ret = sepol_module_package_read(base, pf, 0);
131	if (ret) {
132		fprintf(stderr, "%s:  Error in reading package from %s\n",
133			argv[0], basename);
134		exit(1);
135	}
136	fclose(fp);
137
138	/* linking the base takes care of enabling optional avrules */
139	p = sepol_module_package_get_policy(base);
140	if (sepol_link_modules(handle, p, NULL, 0, 0)) {
141		fprintf(stderr, "%s:  Error while enabling avrules\n", argv[0]);
142		exit(1);
143	}
144
145	/* create the output policy */
146
147	if (sepol_policydb_create(&out)) {
148		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
149		exit(1);
150	}
151
152	sepol_set_expand_consume_base(handle, 1);
153
154	if (sepol_expand_module(handle, p, out, verbose, check_assertions)) {
155		fprintf(stderr, "%s:  Error while expanding policy\n", argv[0]);
156		exit(1);
157	}
158
159	if (policyvers) {
160		if (sepol_policydb_set_vers(out, policyvers)) {
161			fprintf(stderr, "%s:  Invalid version %d\n", argv[0],
162				policyvers);
163			exit(1);
164		}
165	}
166
167	sepol_module_package_free(base);
168
169	outfile = fopen(outname, "w");
170	if (!outfile) {
171		perror(outname);
172		exit(1);
173	}
174
175	sepol_policy_file_set_fp(pf, outfile);
176	ret = sepol_policydb_write(out, pf);
177	if (ret) {
178		fprintf(stderr,
179			"%s:  Error while writing expanded policy to %s\n",
180			argv[0], outname);
181		exit(1);
182	}
183	fclose(outfile);
184	sepol_handle_destroy(handle);
185	sepol_policydb_free(out);
186	sepol_policy_file_free(pf);
187
188	return 0;
189}
190