xref: /aosp_15_r20/external/selinux/semodule-utils/semodule_package/semodule_package.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1 /* Authors: Karl MacMillan <[email protected]>
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 
usage(const char * prog)22 static void usage(const char *prog)
23 {
24 	printf("usage: %s -o <output file> -m <module> [-f <file contexts>]\n",
25 	       prog);
26 	printf("Options:\n");
27 	printf("  -o --outfile		Output file (required)\n");
28 	printf("  -m --module		Module file (required)\n");
29 	printf("  -f --fc		File contexts file\n");
30 	printf("  -s --seuser		Seusers file (only valid in base)\n");
31 	printf
32 	    ("  -u --user_extra	user_extra file (only valid in base)\n");
33 	printf("  -n --nc		Netfilter contexts file\n");
34 	printf("  -h --help		Show this help message\n");
35 }
36 
file_to_data(const char * path,char ** data,size_t * len,const char * progname)37 static int file_to_data(const char *path, char **data, size_t * len, const char *progname)
38 {
39 	int fd;
40 	struct stat sb;
41 	fd = open(path, O_RDONLY | O_CLOEXEC);
42 	if (fd < 0) {
43 		fprintf(stderr, "%s:  Failed to open %s:  %s\n", progname, path,
44 			strerror(errno));
45 		return -1;
46 	}
47 	if (fstat(fd, &sb) < 0) {
48 		fprintf(stderr, "%s:  Failed to fstat %s:  %s\n", progname,
49 			path, strerror(errno));
50 		goto err;
51 	}
52 	if (!sb.st_size) {
53 		close(fd);
54 		*len = 0;
55 		return 0;
56 	}
57 
58 	*data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
59 	if (*data == MAP_FAILED) {
60 		fprintf(stderr, "%s:  Failed to mmap %s:  %s\n", progname, path,
61 			strerror(errno));
62 		goto err;
63 	}
64 	*len = sb.st_size;
65 	close(fd);
66 	return 0;
67       err:
68 	close(fd);
69 	return -1;
70 }
71 
main(int argc,char ** argv)72 int main(int argc, char **argv)
73 {
74 	struct sepol_module_package *pkg = NULL;
75 	struct sepol_policy_file *mod = NULL, *out = NULL;
76 	FILE *fp = NULL;
77 	char *module = NULL, *file_contexts = NULL, *seusers =
78 	    NULL, *user_extra = NULL;
79 	char *fcdata = NULL, *outfile = NULL, *seusersdata =
80 	    NULL, *user_extradata = NULL;
81 	char *netfilter_contexts = NULL, *ncdata = NULL;
82 	size_t fclen = 0, seuserslen = 0, user_extralen = 0, nclen = 0;
83 	int i, ret;
84 
85 	const struct option opts[] = {
86 		{"module", required_argument, NULL, 'm'},
87 		{"fc", required_argument, NULL, 'f'},
88 		{"seuser", required_argument, NULL, 's'},
89 		{"user_extra", required_argument, NULL, 'u'},
90 		{"nc", required_argument, NULL, 'n'},
91 		{"outfile", required_argument, NULL, 'o'},
92 		{"help", 0, NULL, 'h'},
93 		{NULL, 0, NULL, 0}
94 	};
95 
96 	while ((i = getopt_long(argc, argv, "m:f:s:u:o:n:h", opts, NULL)) != -1) {
97 		switch (i) {
98 		case 'h':
99 			usage(argv[0]);
100 			return EXIT_SUCCESS;
101 		case 'm':
102 			if (module) {
103 				fprintf(stderr,
104 					"May not specify more than one module\n");
105 				return EXIT_FAILURE;
106 			}
107 			module = strdup(optarg);
108 			if (!module) {
109 				fprintf(stderr, "%s:  Out of memory\n", argv[0]);
110 				return EXIT_FAILURE;
111 			}
112 			break;
113 		case 'f':
114 			if (file_contexts) {
115 				fprintf(stderr,
116 					"May not specify more than one file context file\n");
117 				return EXIT_FAILURE;
118 			}
119 			file_contexts = strdup(optarg);
120 			if (!file_contexts) {
121 				fprintf(stderr, "%s:  Out of memory\n", argv[0]);
122 				return EXIT_FAILURE;
123 			}
124 			break;
125 		case 'o':
126 			if (outfile) {
127 				fprintf(stderr,
128 					"May not specify more than one output file\n");
129 				return EXIT_FAILURE;
130 			}
131 			outfile = strdup(optarg);
132 			if (!outfile) {
133 				fprintf(stderr, "%s:  Out of memory\n", argv[0]);
134 				return EXIT_FAILURE;
135 			}
136 			break;
137 		case 's':
138 			if (seusers) {
139 				fprintf(stderr,
140 					"May not specify more than one seuser file\n");
141 				return EXIT_FAILURE;
142 			}
143 			seusers = strdup(optarg);
144 			if (!seusers) {
145 				fprintf(stderr, "%s:  Out of memory\n", argv[0]);
146 				return EXIT_FAILURE;
147 			}
148 			break;
149 		case 'u':
150 			if (user_extra) {
151 				fprintf(stderr,
152 					"May not specify more than one user_extra file\n");
153 				return EXIT_FAILURE;
154 			}
155 			user_extra = strdup(optarg);
156 			if (!user_extra) {
157 				fprintf(stderr, "%s:  Out of memory\n", argv[0]);
158 				return EXIT_FAILURE;
159 			}
160 			break;
161 		case 'n':
162 			if (netfilter_contexts) {
163 				fprintf(stderr,
164 					"May not specify more than one netfilter contexts file\n");
165 				return EXIT_FAILURE;
166 			}
167 			netfilter_contexts = strdup(optarg);
168 			if (!netfilter_contexts) {
169 				fprintf(stderr, "%s:  Out of memory\n", argv[0]);
170 				return EXIT_FAILURE;
171 			}
172 			break;
173 		default:
174 			usage(argv[0]);
175 			return EXIT_FAILURE;
176 		}
177 	}
178 
179 	if (optind < argc) {
180 		fprintf(stderr, "%s:  Superfluous command line arguments: ", argv[0]);
181 		while (optind < argc)
182 			 fprintf(stderr, "%s ", argv[optind++]);
183 		fprintf(stderr, "\n");
184 		usage(argv[0]);
185 		return EXIT_FAILURE;
186 	}
187 
188 	if (!module || !outfile) {
189 		usage(argv[0]);
190 		return EXIT_FAILURE;
191 	}
192 
193 	if (file_contexts && file_to_data(file_contexts, &fcdata, &fclen, argv[0]))
194 		goto failure;
195 
196 	if (seusers && file_to_data(seusers, &seusersdata, &seuserslen, argv[0]))
197 		goto failure;
198 
199 	if (user_extra && file_to_data(user_extra, &user_extradata, &user_extralen, argv[0]))
200 		goto failure;
201 
202 	if (netfilter_contexts && file_to_data(netfilter_contexts, &ncdata, &nclen, argv[0]))
203 		goto failure;
204 
205 	if (sepol_policy_file_create(&mod)) {
206 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
207 		goto failure;
208 	}
209 
210 	fp = fopen(module, "re");
211 	if (!fp) {
212 		fprintf(stderr, "%s:  Could not open file %s:  %s\n", argv[0],
213 			module, strerror(errno));
214 		goto failure;
215 	}
216 	sepol_policy_file_set_fp(mod, fp);
217 
218 	if (sepol_module_package_create(&pkg)) {
219 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
220 		goto failure;
221 	}
222 
223 	if (sepol_policydb_read(sepol_module_package_get_policy(pkg), mod)) {
224 		fprintf(stderr,
225 			"%s:  Error while reading policy module from %s\n",
226 			argv[0], module);
227 		goto failure;
228 	}
229 
230 	fclose(fp);
231 	fp = NULL;
232 
233 	if (fclen && sepol_module_package_set_file_contexts(pkg, fcdata, fclen)) {
234 		fprintf(stderr, "%s:  Error while setting file contexts\n", argv[0]);
235 		goto failure;
236 	}
237 
238 	if (seuserslen && sepol_module_package_set_seusers(pkg, seusersdata, seuserslen)) {
239 		fprintf(stderr, "%s:  Error while setting seusers\n", argv[0]);
240 		goto failure;
241 	}
242 
243 	if (user_extra && sepol_module_package_set_user_extra(pkg, user_extradata, user_extralen)) {
244 		fprintf(stderr, "%s:  Error while setting extra users\n", argv[0]);
245 		goto failure;
246 	}
247 
248 	if (nclen && sepol_module_package_set_netfilter_contexts(pkg, ncdata, nclen)) {
249 		fprintf(stderr, "%s:  Error while setting netfilter contexts\n", argv[0]);
250 		goto failure;
251 	}
252 
253 	if (sepol_policy_file_create(&out)) {
254 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
255 		goto failure;
256 	}
257 
258 	fp = fopen(outfile, "we");
259 	if (!fp) {
260 		fprintf(stderr, "%s:  Could not open file %s:  %s\n", argv[0],
261 			outfile, strerror(errno));
262 		goto failure;
263 	}
264 	sepol_policy_file_set_fp(out, fp);
265 
266 	if (sepol_module_package_write(pkg, out)) {
267 		fprintf(stderr,
268 			"%s:  Error while writing module package to %s\n",
269 			argv[0], argv[1]);
270 		goto failure;
271 	}
272 
273 	ret = fclose(fp);
274 	fp = NULL;
275 	if (ret) {
276 		fprintf(stderr, "%s:  Could not close file %s:  %s\n", argv[0],
277 			outfile, strerror(errno));
278 		goto failure;
279 	}
280 
281 	ret = EXIT_SUCCESS;
282 	goto cleanup;
283 
284 failure:
285 	ret = EXIT_FAILURE;
286 
287 cleanup:
288 	if (fp)
289 		fclose(fp);
290 	sepol_policy_file_free(out);
291 	if (nclen)
292 		munmap(ncdata, nclen);
293 	if (user_extradata)
294 		munmap(user_extradata, user_extralen);
295 	if (seuserslen)
296 		munmap(seusersdata, seuserslen);
297 	if (fclen)
298 		munmap(fcdata, fclen);
299 	sepol_module_package_free(pkg);
300 	sepol_policy_file_free(mod);
301 	free(netfilter_contexts);
302 	free(user_extra);
303 	free(seusers);
304 	free(outfile);
305 	free(file_contexts);
306 	free(module);
307 
308 	return ret;
309 }
310