1 /* Authors: Karl MacMillan <kmacmillan@tresys.com>
2 *
3 * Copyright (C) 2004 Tresys Technology, LLC
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 2.
7 */
8
9 #include <sepol/module.h>
10 #include <getopt.h>
11 #include <fcntl.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/mman.h>
19 #include <fcntl.h>
20 #include <errno.h>
21
22 char *progname = NULL;
23 extern char *optarg;
24
usage(const char * prog)25 static __attribute__((__noreturn__)) void usage(const char *prog)
26 {
27 printf("usage: %s -o <output file> -m <module> [-f <file contexts>]\n",
28 prog);
29 printf("Options:\n");
30 printf(" -o --outfile Output file (required)\n");
31 printf(" -m --module Module file (required)\n");
32 printf(" -f --fc File contexts file\n");
33 printf(" -s --seuser Seusers file (only valid in base)\n");
34 printf
35 (" -u --user_extra user_extra file (only valid in base)\n");
36 printf(" -n --nc Netfilter contexts file\n");
37 exit(1);
38 }
39
file_to_policy_file(const char * filename,struct sepol_policy_file ** pf,const char * mode)40 static int file_to_policy_file(const char *filename, struct sepol_policy_file **pf,
41 const char *mode)
42 {
43 FILE *f;
44
45 if (sepol_policy_file_create(pf)) {
46 fprintf(stderr, "%s: Out of memory\n", progname);
47 return -1;
48 }
49
50 f = fopen(filename, mode);
51 if (!f) {
52 fprintf(stderr, "%s: Could not open file %s: %s\n", progname,
53 strerror(errno), filename);
54 return -1;
55 }
56 sepol_policy_file_set_fp(*pf, f);
57 return 0;
58 }
59
file_to_data(const char * path,char ** data,size_t * len)60 static int file_to_data(const char *path, char **data, size_t * len)
61 {
62 int fd;
63 struct stat sb;
64 fd = open(path, O_RDONLY);
65 if (fd < 0) {
66 fprintf(stderr, "%s: Failed to open %s: %s\n", progname, path,
67 strerror(errno));
68 return -1;
69 }
70 if (fstat(fd, &sb) < 0) {
71 fprintf(stderr, "%s: Failed to fstat %s: %s\n", progname,
72 path, strerror(errno));
73 goto err;
74 }
75 if (!sb.st_size) {
76 close(fd);
77 *len = 0;
78 return 0;
79 }
80
81 *data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
82 if (*data == MAP_FAILED) {
83 fprintf(stderr, "%s: Failed to mmap %s: %s\n", progname, path,
84 strerror(errno));
85 goto err;
86 }
87 *len = sb.st_size;
88 close(fd);
89 return 0;
90 err:
91 close(fd);
92 return -1;
93 }
94
main(int argc,char ** argv)95 int main(int argc, char **argv)
96 {
97 struct sepol_module_package *pkg;
98 struct sepol_policy_file *mod, *out;
99 char *module = NULL, *file_contexts = NULL, *seusers =
100 NULL, *user_extra = NULL;
101 char *fcdata = NULL, *outfile = NULL, *seusersdata =
102 NULL, *user_extradata = NULL;
103 char *netfilter_contexts = NULL, *ncdata = NULL;
104 size_t fclen = 0, seuserslen = 0, user_extralen = 0, nclen = 0;
105 int i;
106
107 static struct option opts[] = {
108 {"module", required_argument, NULL, 'm'},
109 {"fc", required_argument, NULL, 'f'},
110 {"seuser", required_argument, NULL, 's'},
111 {"user_extra", required_argument, NULL, 'u'},
112 {"nc", required_argument, NULL, 'n'},
113 {"outfile", required_argument, NULL, 'o'},
114 {"help", 0, NULL, 'h'},
115 {NULL, 0, NULL, 0}
116 };
117
118 while ((i = getopt_long(argc, argv, "m:f:s:u:o:n:h", opts, NULL)) != -1) {
119 switch (i) {
120 case 'h':
121 usage(argv[0]);
122 exit(0);
123 case 'm':
124 if (module) {
125 fprintf(stderr,
126 "May not specify more than one module\n");
127 exit(1);
128 }
129 module = strdup(optarg);
130 if (!module)
131 exit(1);
132 break;
133 case 'f':
134 if (file_contexts) {
135 fprintf(stderr,
136 "May not specify more than one file context file\n");
137 exit(1);
138 }
139 file_contexts = strdup(optarg);
140 if (!file_contexts)
141 exit(1);
142 break;
143 case 'o':
144 if (outfile) {
145 fprintf(stderr,
146 "May not specify more than one output file\n");
147 exit(1);
148 }
149 outfile = strdup(optarg);
150 if (!outfile)
151 exit(1);
152 break;
153 case 's':
154 if (seusers) {
155 fprintf(stderr,
156 "May not specify more than one seuser file\n");
157 exit(1);
158 }
159 seusers = strdup(optarg);
160 if (!seusers)
161 exit(1);
162 break;
163 case 'u':
164 if (user_extra) {
165 fprintf(stderr,
166 "May not specify more than one user_extra file\n");
167 exit(1);
168 }
169 user_extra = strdup(optarg);
170 if (!user_extra)
171 exit(1);
172 break;
173 case 'n':
174 if (netfilter_contexts) {
175 fprintf(stderr,
176 "May not specify more than one netfilter contexts file\n");
177 exit(1);
178 }
179 netfilter_contexts = strdup(optarg);
180 if (!netfilter_contexts)
181 exit(1);
182 break;
183 }
184 }
185
186 progname = argv[0];
187
188 if (!module || !outfile) {
189 usage(argv[0]);
190 exit(0);
191 }
192
193 if (file_contexts) {
194 if (file_to_data(file_contexts, &fcdata, &fclen))
195 exit(1);
196 }
197
198 if (seusers) {
199 if (file_to_data(seusers, &seusersdata, &seuserslen))
200 exit(1);
201 }
202
203 if (user_extra) {
204 if (file_to_data(user_extra, &user_extradata, &user_extralen))
205 exit(1);
206 }
207
208 if (netfilter_contexts) {
209 if (file_to_data(netfilter_contexts, &ncdata, &nclen))
210 exit(1);
211 }
212
213 if (file_to_policy_file(module, &mod, "r"))
214 exit(1);
215
216 if (sepol_module_package_create(&pkg)) {
217 fprintf(stderr, "%s: Out of memory\n", argv[0]);
218 exit(1);
219 }
220
221 if (sepol_policydb_read(sepol_module_package_get_policy(pkg), mod)) {
222 fprintf(stderr,
223 "%s: Error while reading policy module from %s\n",
224 argv[0], module);
225 exit(1);
226 }
227
228 if (fclen)
229 sepol_module_package_set_file_contexts(pkg, fcdata, fclen);
230
231 if (seuserslen)
232 sepol_module_package_set_seusers(pkg, seusersdata, seuserslen);
233
234 if (user_extra)
235 sepol_module_package_set_user_extra(pkg, user_extradata,
236 user_extralen);
237
238 if (nclen)
239 sepol_module_package_set_netfilter_contexts(pkg, ncdata, nclen);
240
241 if (file_to_policy_file(outfile, &out, "w"))
242 exit(1);
243
244 if (sepol_module_package_write(pkg, out)) {
245 fprintf(stderr,
246 "%s: Error while writing module package to %s\n",
247 argv[0], argv[1]);
248 exit(1);
249 }
250
251 if (fclen)
252 munmap(fcdata, fclen);
253 if (nclen)
254 munmap(ncdata, nclen);
255 sepol_policy_file_free(mod);
256 sepol_policy_file_free(out);
257 sepol_module_package_free(pkg);
258 free(file_contexts);
259 free(outfile);
260 free(module);
261 free(seusers);
262 free(user_extra);
263 exit(0);
264 }
265