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
24 extern char *optarg;
25 extern int optind;
26
27 int policyvers = 0;
28
29 #define EXPANDPOLICY_VERSION "1.0"
30
usage(const char * program_name)31 static __attribute__((__noreturn__)) void usage(const char *program_name)
32 {
33 printf("usage: %s [-V -a -c [version]] basemodpkg outputfile\n",
34 program_name);
35 exit(1);
36 }
37
main(int argc,char ** argv)38 int 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