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