xref: /aosp_15_r20/external/selinux/libsepol/src/module.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /* Author: Karl MacMillan <[email protected]>
2*2d543d20SAndroid Build Coastguard Worker  *         Jason Tang     <[email protected]>
3*2d543d20SAndroid Build Coastguard Worker  *         Chris PeBenito <[email protected]>
4*2d543d20SAndroid Build Coastguard Worker  *
5*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2004-2005 Tresys Technology, LLC
6*2d543d20SAndroid Build Coastguard Worker  *
7*2d543d20SAndroid Build Coastguard Worker  *  This library is free software; you can redistribute it and/or
8*2d543d20SAndroid Build Coastguard Worker  *  modify it under the terms of the GNU Lesser General Public
9*2d543d20SAndroid Build Coastguard Worker  *  License as published by the Free Software Foundation; either
10*2d543d20SAndroid Build Coastguard Worker  *  version 2.1 of the License, or (at your option) any later version.
11*2d543d20SAndroid Build Coastguard Worker  *
12*2d543d20SAndroid Build Coastguard Worker  *  This library is distributed in the hope that it will be useful,
13*2d543d20SAndroid Build Coastguard Worker  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14*2d543d20SAndroid Build Coastguard Worker  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15*2d543d20SAndroid Build Coastguard Worker  *  Lesser General Public License for more details.
16*2d543d20SAndroid Build Coastguard Worker  *
17*2d543d20SAndroid Build Coastguard Worker  *  You should have received a copy of the GNU Lesser General Public
18*2d543d20SAndroid Build Coastguard Worker  *  License along with this library; if not, write to the Free Software
19*2d543d20SAndroid Build Coastguard Worker  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20*2d543d20SAndroid Build Coastguard Worker  */
21*2d543d20SAndroid Build Coastguard Worker 
22*2d543d20SAndroid Build Coastguard Worker #include "policydb_internal.h"
23*2d543d20SAndroid Build Coastguard Worker #include "module_internal.h"
24*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/link.h>
25*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/expand.h>
26*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/module.h>
27*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
28*2d543d20SAndroid Build Coastguard Worker #include "private.h"
29*2d543d20SAndroid Build Coastguard Worker 
30*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
31*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
32*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
33*2d543d20SAndroid Build Coastguard Worker #include <inttypes.h>
34*2d543d20SAndroid Build Coastguard Worker 
35*2d543d20SAndroid Build Coastguard Worker #define SEPOL_PACKAGE_SECTION_FC 0xf97cff90
36*2d543d20SAndroid Build Coastguard Worker #define SEPOL_PACKAGE_SECTION_SEUSER 0x97cff91
37*2d543d20SAndroid Build Coastguard Worker #define SEPOL_PACKAGE_SECTION_USER_EXTRA 0x97cff92
38*2d543d20SAndroid Build Coastguard Worker #define SEPOL_PACKAGE_SECTION_NETFILTER 0x97cff93
39*2d543d20SAndroid Build Coastguard Worker 
policy_file_seek(struct policy_file * fp,size_t offset)40*2d543d20SAndroid Build Coastguard Worker static int policy_file_seek(struct policy_file *fp, size_t offset)
41*2d543d20SAndroid Build Coastguard Worker {
42*2d543d20SAndroid Build Coastguard Worker 	switch (fp->type) {
43*2d543d20SAndroid Build Coastguard Worker 	case PF_USE_STDIO:
44*2d543d20SAndroid Build Coastguard Worker 		if (offset > LONG_MAX) {
45*2d543d20SAndroid Build Coastguard Worker 			errno = EFAULT;
46*2d543d20SAndroid Build Coastguard Worker 			return -1;
47*2d543d20SAndroid Build Coastguard Worker 		}
48*2d543d20SAndroid Build Coastguard Worker 		return fseek(fp->fp, (long)offset, SEEK_SET);
49*2d543d20SAndroid Build Coastguard Worker 	case PF_USE_MEMORY:
50*2d543d20SAndroid Build Coastguard Worker 		if (offset > fp->size) {
51*2d543d20SAndroid Build Coastguard Worker 			errno = EFAULT;
52*2d543d20SAndroid Build Coastguard Worker 			return -1;
53*2d543d20SAndroid Build Coastguard Worker 		}
54*2d543d20SAndroid Build Coastguard Worker 		fp->data -= fp->size - fp->len;
55*2d543d20SAndroid Build Coastguard Worker 		fp->data += offset;
56*2d543d20SAndroid Build Coastguard Worker 		fp->len = fp->size - offset;
57*2d543d20SAndroid Build Coastguard Worker 		return 0;
58*2d543d20SAndroid Build Coastguard Worker 	default:
59*2d543d20SAndroid Build Coastguard Worker 		return 0;
60*2d543d20SAndroid Build Coastguard Worker 	}
61*2d543d20SAndroid Build Coastguard Worker }
62*2d543d20SAndroid Build Coastguard Worker 
policy_file_length(struct policy_file * fp,size_t * out)63*2d543d20SAndroid Build Coastguard Worker static int policy_file_length(struct policy_file *fp, size_t *out)
64*2d543d20SAndroid Build Coastguard Worker {
65*2d543d20SAndroid Build Coastguard Worker 	long prev_offset, end_offset;
66*2d543d20SAndroid Build Coastguard Worker 	int rc;
67*2d543d20SAndroid Build Coastguard Worker 	switch (fp->type) {
68*2d543d20SAndroid Build Coastguard Worker 	case PF_USE_STDIO:
69*2d543d20SAndroid Build Coastguard Worker 		prev_offset = ftell(fp->fp);
70*2d543d20SAndroid Build Coastguard Worker 		if (prev_offset < 0)
71*2d543d20SAndroid Build Coastguard Worker 			return prev_offset;
72*2d543d20SAndroid Build Coastguard Worker 		rc = fseek(fp->fp, 0L, SEEK_END);
73*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0)
74*2d543d20SAndroid Build Coastguard Worker 			return rc;
75*2d543d20SAndroid Build Coastguard Worker 		end_offset = ftell(fp->fp);
76*2d543d20SAndroid Build Coastguard Worker 		if (end_offset < 0)
77*2d543d20SAndroid Build Coastguard Worker 			return end_offset;
78*2d543d20SAndroid Build Coastguard Worker 		rc = fseek(fp->fp, prev_offset, SEEK_SET);
79*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0)
80*2d543d20SAndroid Build Coastguard Worker 			return rc;
81*2d543d20SAndroid Build Coastguard Worker 		*out = end_offset;
82*2d543d20SAndroid Build Coastguard Worker 		break;
83*2d543d20SAndroid Build Coastguard Worker 	case PF_USE_MEMORY:
84*2d543d20SAndroid Build Coastguard Worker 		*out = fp->size;
85*2d543d20SAndroid Build Coastguard Worker 		break;
86*2d543d20SAndroid Build Coastguard Worker 	default:
87*2d543d20SAndroid Build Coastguard Worker 		*out = 0;
88*2d543d20SAndroid Build Coastguard Worker 		break;
89*2d543d20SAndroid Build Coastguard Worker 	}
90*2d543d20SAndroid Build Coastguard Worker 	return 0;
91*2d543d20SAndroid Build Coastguard Worker }
92*2d543d20SAndroid Build Coastguard Worker 
module_package_init(sepol_module_package_t * p)93*2d543d20SAndroid Build Coastguard Worker static int module_package_init(sepol_module_package_t * p)
94*2d543d20SAndroid Build Coastguard Worker {
95*2d543d20SAndroid Build Coastguard Worker 	memset(p, 0, sizeof(sepol_module_package_t));
96*2d543d20SAndroid Build Coastguard Worker 	if (sepol_policydb_create(&p->policy))
97*2d543d20SAndroid Build Coastguard Worker 		return -1;
98*2d543d20SAndroid Build Coastguard Worker 
99*2d543d20SAndroid Build Coastguard Worker 	p->version = 1;
100*2d543d20SAndroid Build Coastguard Worker 	return 0;
101*2d543d20SAndroid Build Coastguard Worker }
102*2d543d20SAndroid Build Coastguard Worker 
set_char(char ** field,char * data,size_t len)103*2d543d20SAndroid Build Coastguard Worker static int set_char(char **field, char *data, size_t len)
104*2d543d20SAndroid Build Coastguard Worker {
105*2d543d20SAndroid Build Coastguard Worker 	if (*field) {
106*2d543d20SAndroid Build Coastguard Worker 		free(*field);
107*2d543d20SAndroid Build Coastguard Worker 		*field = NULL;
108*2d543d20SAndroid Build Coastguard Worker 	}
109*2d543d20SAndroid Build Coastguard Worker 	if (len) {
110*2d543d20SAndroid Build Coastguard Worker 		*field = malloc(len);
111*2d543d20SAndroid Build Coastguard Worker 		if (!*field)
112*2d543d20SAndroid Build Coastguard Worker 			return -1;
113*2d543d20SAndroid Build Coastguard Worker 		memcpy(*field, data, len);
114*2d543d20SAndroid Build Coastguard Worker 	}
115*2d543d20SAndroid Build Coastguard Worker 	return 0;
116*2d543d20SAndroid Build Coastguard Worker }
117*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_create(sepol_module_package_t ** p)118*2d543d20SAndroid Build Coastguard Worker int sepol_module_package_create(sepol_module_package_t ** p)
119*2d543d20SAndroid Build Coastguard Worker {
120*2d543d20SAndroid Build Coastguard Worker 	int rc;
121*2d543d20SAndroid Build Coastguard Worker 
122*2d543d20SAndroid Build Coastguard Worker 	*p = calloc(1, sizeof(sepol_module_package_t));
123*2d543d20SAndroid Build Coastguard Worker 	if (!(*p))
124*2d543d20SAndroid Build Coastguard Worker 		return -1;
125*2d543d20SAndroid Build Coastguard Worker 
126*2d543d20SAndroid Build Coastguard Worker 	rc = module_package_init(*p);
127*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0) {
128*2d543d20SAndroid Build Coastguard Worker 		free(*p);
129*2d543d20SAndroid Build Coastguard Worker 		*p = NULL;
130*2d543d20SAndroid Build Coastguard Worker 	}
131*2d543d20SAndroid Build Coastguard Worker 
132*2d543d20SAndroid Build Coastguard Worker 	return rc;
133*2d543d20SAndroid Build Coastguard Worker }
134*2d543d20SAndroid Build Coastguard Worker 
135*2d543d20SAndroid Build Coastguard Worker 
136*2d543d20SAndroid Build Coastguard Worker /* Deallocates all memory associated with a module package, including
137*2d543d20SAndroid Build Coastguard Worker  * the pointer itself.  Does nothing if p is NULL.
138*2d543d20SAndroid Build Coastguard Worker  */
sepol_module_package_free(sepol_module_package_t * p)139*2d543d20SAndroid Build Coastguard Worker void sepol_module_package_free(sepol_module_package_t * p)
140*2d543d20SAndroid Build Coastguard Worker {
141*2d543d20SAndroid Build Coastguard Worker 	if (p == NULL)
142*2d543d20SAndroid Build Coastguard Worker 		return;
143*2d543d20SAndroid Build Coastguard Worker 
144*2d543d20SAndroid Build Coastguard Worker 	sepol_policydb_free(p->policy);
145*2d543d20SAndroid Build Coastguard Worker 	free(p->file_contexts);
146*2d543d20SAndroid Build Coastguard Worker 	free(p->seusers);
147*2d543d20SAndroid Build Coastguard Worker 	free(p->user_extra);
148*2d543d20SAndroid Build Coastguard Worker 	free(p->netfilter_contexts);
149*2d543d20SAndroid Build Coastguard Worker 	free(p);
150*2d543d20SAndroid Build Coastguard Worker }
151*2d543d20SAndroid Build Coastguard Worker 
152*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_get_file_contexts(sepol_module_package_t * p)153*2d543d20SAndroid Build Coastguard Worker char *sepol_module_package_get_file_contexts(sepol_module_package_t * p)
154*2d543d20SAndroid Build Coastguard Worker {
155*2d543d20SAndroid Build Coastguard Worker 	return p->file_contexts;
156*2d543d20SAndroid Build Coastguard Worker }
157*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_get_file_contexts_len(sepol_module_package_t * p)158*2d543d20SAndroid Build Coastguard Worker size_t sepol_module_package_get_file_contexts_len(sepol_module_package_t * p)
159*2d543d20SAndroid Build Coastguard Worker {
160*2d543d20SAndroid Build Coastguard Worker 	return p->file_contexts_len;
161*2d543d20SAndroid Build Coastguard Worker }
162*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_get_seusers(sepol_module_package_t * p)163*2d543d20SAndroid Build Coastguard Worker char *sepol_module_package_get_seusers(sepol_module_package_t * p)
164*2d543d20SAndroid Build Coastguard Worker {
165*2d543d20SAndroid Build Coastguard Worker 	return p->seusers;
166*2d543d20SAndroid Build Coastguard Worker }
167*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_get_seusers_len(sepol_module_package_t * p)168*2d543d20SAndroid Build Coastguard Worker size_t sepol_module_package_get_seusers_len(sepol_module_package_t * p)
169*2d543d20SAndroid Build Coastguard Worker {
170*2d543d20SAndroid Build Coastguard Worker 	return p->seusers_len;
171*2d543d20SAndroid Build Coastguard Worker }
172*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_get_user_extra(sepol_module_package_t * p)173*2d543d20SAndroid Build Coastguard Worker char *sepol_module_package_get_user_extra(sepol_module_package_t * p)
174*2d543d20SAndroid Build Coastguard Worker {
175*2d543d20SAndroid Build Coastguard Worker 	return p->user_extra;
176*2d543d20SAndroid Build Coastguard Worker }
177*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_get_user_extra_len(sepol_module_package_t * p)178*2d543d20SAndroid Build Coastguard Worker size_t sepol_module_package_get_user_extra_len(sepol_module_package_t * p)
179*2d543d20SAndroid Build Coastguard Worker {
180*2d543d20SAndroid Build Coastguard Worker 	return p->user_extra_len;
181*2d543d20SAndroid Build Coastguard Worker }
182*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_get_netfilter_contexts(sepol_module_package_t * p)183*2d543d20SAndroid Build Coastguard Worker char *sepol_module_package_get_netfilter_contexts(sepol_module_package_t * p)
184*2d543d20SAndroid Build Coastguard Worker {
185*2d543d20SAndroid Build Coastguard Worker 	return p->netfilter_contexts;
186*2d543d20SAndroid Build Coastguard Worker }
187*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_get_netfilter_contexts_len(sepol_module_package_t * p)188*2d543d20SAndroid Build Coastguard Worker size_t sepol_module_package_get_netfilter_contexts_len(sepol_module_package_t *
189*2d543d20SAndroid Build Coastguard Worker 						       p)
190*2d543d20SAndroid Build Coastguard Worker {
191*2d543d20SAndroid Build Coastguard Worker 	return p->netfilter_contexts_len;
192*2d543d20SAndroid Build Coastguard Worker }
193*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_set_file_contexts(sepol_module_package_t * p,char * data,size_t len)194*2d543d20SAndroid Build Coastguard Worker int sepol_module_package_set_file_contexts(sepol_module_package_t * p,
195*2d543d20SAndroid Build Coastguard Worker 					   char *data, size_t len)
196*2d543d20SAndroid Build Coastguard Worker {
197*2d543d20SAndroid Build Coastguard Worker 	if (set_char(&p->file_contexts, data, len))
198*2d543d20SAndroid Build Coastguard Worker 		return -1;
199*2d543d20SAndroid Build Coastguard Worker 
200*2d543d20SAndroid Build Coastguard Worker 	p->file_contexts_len = len;
201*2d543d20SAndroid Build Coastguard Worker 	return 0;
202*2d543d20SAndroid Build Coastguard Worker }
203*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_set_seusers(sepol_module_package_t * p,char * data,size_t len)204*2d543d20SAndroid Build Coastguard Worker int sepol_module_package_set_seusers(sepol_module_package_t * p,
205*2d543d20SAndroid Build Coastguard Worker 				     char *data, size_t len)
206*2d543d20SAndroid Build Coastguard Worker {
207*2d543d20SAndroid Build Coastguard Worker 	if (set_char(&p->seusers, data, len))
208*2d543d20SAndroid Build Coastguard Worker 		return -1;
209*2d543d20SAndroid Build Coastguard Worker 
210*2d543d20SAndroid Build Coastguard Worker 	p->seusers_len = len;
211*2d543d20SAndroid Build Coastguard Worker 	return 0;
212*2d543d20SAndroid Build Coastguard Worker }
213*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_set_user_extra(sepol_module_package_t * p,char * data,size_t len)214*2d543d20SAndroid Build Coastguard Worker int sepol_module_package_set_user_extra(sepol_module_package_t * p,
215*2d543d20SAndroid Build Coastguard Worker 					char *data, size_t len)
216*2d543d20SAndroid Build Coastguard Worker {
217*2d543d20SAndroid Build Coastguard Worker 	if (set_char(&p->user_extra, data, len))
218*2d543d20SAndroid Build Coastguard Worker 		return -1;
219*2d543d20SAndroid Build Coastguard Worker 
220*2d543d20SAndroid Build Coastguard Worker 	p->user_extra_len = len;
221*2d543d20SAndroid Build Coastguard Worker 	return 0;
222*2d543d20SAndroid Build Coastguard Worker }
223*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_set_netfilter_contexts(sepol_module_package_t * p,char * data,size_t len)224*2d543d20SAndroid Build Coastguard Worker int sepol_module_package_set_netfilter_contexts(sepol_module_package_t * p,
225*2d543d20SAndroid Build Coastguard Worker 						char *data, size_t len)
226*2d543d20SAndroid Build Coastguard Worker {
227*2d543d20SAndroid Build Coastguard Worker 	if (set_char(&p->netfilter_contexts, data, len))
228*2d543d20SAndroid Build Coastguard Worker 		return -1;
229*2d543d20SAndroid Build Coastguard Worker 
230*2d543d20SAndroid Build Coastguard Worker 	p->netfilter_contexts_len = len;
231*2d543d20SAndroid Build Coastguard Worker 	return 0;
232*2d543d20SAndroid Build Coastguard Worker }
233*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_get_policy(sepol_module_package_t * p)234*2d543d20SAndroid Build Coastguard Worker sepol_policydb_t *sepol_module_package_get_policy(sepol_module_package_t * p)
235*2d543d20SAndroid Build Coastguard Worker {
236*2d543d20SAndroid Build Coastguard Worker 	return p->policy;
237*2d543d20SAndroid Build Coastguard Worker }
238*2d543d20SAndroid Build Coastguard Worker 
239*2d543d20SAndroid Build Coastguard Worker /* Append each of the file contexts from each module to the base
240*2d543d20SAndroid Build Coastguard Worker  * policy's file context.  'base_context' will be reallocated to a
241*2d543d20SAndroid Build Coastguard Worker  * larger size (and thus it is an in/out reference
242*2d543d20SAndroid Build Coastguard Worker  * variable). 'base_fc_len' is the length of base's file context; it
243*2d543d20SAndroid Build Coastguard Worker  * too is a reference variable.  Return 0 on success, -1 if out of
244*2d543d20SAndroid Build Coastguard Worker  * memory. */
link_file_contexts(sepol_module_package_t * base,sepol_module_package_t ** modules,int num_modules)245*2d543d20SAndroid Build Coastguard Worker static int link_file_contexts(sepol_module_package_t * base,
246*2d543d20SAndroid Build Coastguard Worker 			      sepol_module_package_t ** modules,
247*2d543d20SAndroid Build Coastguard Worker 			      int num_modules)
248*2d543d20SAndroid Build Coastguard Worker {
249*2d543d20SAndroid Build Coastguard Worker 	size_t fc_len;
250*2d543d20SAndroid Build Coastguard Worker 	int i;
251*2d543d20SAndroid Build Coastguard Worker 	char *s;
252*2d543d20SAndroid Build Coastguard Worker 
253*2d543d20SAndroid Build Coastguard Worker 	fc_len = base->file_contexts_len;
254*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < num_modules; i++) {
255*2d543d20SAndroid Build Coastguard Worker 		fc_len += modules[i]->file_contexts_len;
256*2d543d20SAndroid Build Coastguard Worker 	}
257*2d543d20SAndroid Build Coastguard Worker 
258*2d543d20SAndroid Build Coastguard Worker 	if ((s = (char *)realloc(base->file_contexts, fc_len)) == NULL) {
259*2d543d20SAndroid Build Coastguard Worker 		return -1;
260*2d543d20SAndroid Build Coastguard Worker 	}
261*2d543d20SAndroid Build Coastguard Worker 	base->file_contexts = s;
262*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < num_modules; i++) {
263*2d543d20SAndroid Build Coastguard Worker 		memcpy(base->file_contexts + base->file_contexts_len,
264*2d543d20SAndroid Build Coastguard Worker 		       modules[i]->file_contexts,
265*2d543d20SAndroid Build Coastguard Worker 		       modules[i]->file_contexts_len);
266*2d543d20SAndroid Build Coastguard Worker 		base->file_contexts_len += modules[i]->file_contexts_len;
267*2d543d20SAndroid Build Coastguard Worker 	}
268*2d543d20SAndroid Build Coastguard Worker 	return 0;
269*2d543d20SAndroid Build Coastguard Worker }
270*2d543d20SAndroid Build Coastguard Worker 
271*2d543d20SAndroid Build Coastguard Worker /* Append each of the netfilter contexts from each module to the base
272*2d543d20SAndroid Build Coastguard Worker  * policy's netfilter context.  'base_context' will be reallocated to a
273*2d543d20SAndroid Build Coastguard Worker  * larger size (and thus it is an in/out reference
274*2d543d20SAndroid Build Coastguard Worker  * variable). 'base_nc_len' is the length of base's netfilter contexts; it
275*2d543d20SAndroid Build Coastguard Worker  * too is a reference variable.  Return 0 on success, -1 if out of
276*2d543d20SAndroid Build Coastguard Worker  * memory. */
link_netfilter_contexts(sepol_module_package_t * base,sepol_module_package_t ** modules,int num_modules)277*2d543d20SAndroid Build Coastguard Worker static int link_netfilter_contexts(sepol_module_package_t * base,
278*2d543d20SAndroid Build Coastguard Worker 				   sepol_module_package_t ** modules,
279*2d543d20SAndroid Build Coastguard Worker 				   int num_modules)
280*2d543d20SAndroid Build Coastguard Worker {
281*2d543d20SAndroid Build Coastguard Worker 	size_t base_nc_len;
282*2d543d20SAndroid Build Coastguard Worker 	int i;
283*2d543d20SAndroid Build Coastguard Worker 	char *base_context;
284*2d543d20SAndroid Build Coastguard Worker 
285*2d543d20SAndroid Build Coastguard Worker 	base_nc_len = base->netfilter_contexts_len;
286*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < num_modules; i++) {
287*2d543d20SAndroid Build Coastguard Worker 		base_nc_len += modules[i]->netfilter_contexts_len;
288*2d543d20SAndroid Build Coastguard Worker 	}
289*2d543d20SAndroid Build Coastguard Worker 
290*2d543d20SAndroid Build Coastguard Worker 	if ((base_context =
291*2d543d20SAndroid Build Coastguard Worker 	     (char *)realloc(base->netfilter_contexts, base_nc_len)) == NULL) {
292*2d543d20SAndroid Build Coastguard Worker 		return -1;
293*2d543d20SAndroid Build Coastguard Worker 	}
294*2d543d20SAndroid Build Coastguard Worker 	base->netfilter_contexts = base_context;
295*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < num_modules; i++) {
296*2d543d20SAndroid Build Coastguard Worker 		if (modules[i]->netfilter_contexts_len > 0) {
297*2d543d20SAndroid Build Coastguard Worker 			memcpy(base->netfilter_contexts + base->netfilter_contexts_len,
298*2d543d20SAndroid Build Coastguard Worker 			       modules[i]->netfilter_contexts,
299*2d543d20SAndroid Build Coastguard Worker 			       modules[i]->netfilter_contexts_len);
300*2d543d20SAndroid Build Coastguard Worker 			base->netfilter_contexts_len +=
301*2d543d20SAndroid Build Coastguard Worker 			    modules[i]->netfilter_contexts_len;
302*2d543d20SAndroid Build Coastguard Worker 		}
303*2d543d20SAndroid Build Coastguard Worker 
304*2d543d20SAndroid Build Coastguard Worker 	}
305*2d543d20SAndroid Build Coastguard Worker 	return 0;
306*2d543d20SAndroid Build Coastguard Worker }
307*2d543d20SAndroid Build Coastguard Worker 
308*2d543d20SAndroid Build Coastguard Worker /* Links the module packages into the base.  Returns 0 on success, -1
309*2d543d20SAndroid Build Coastguard Worker  * if a requirement was not met, or -2 for all other errors. */
sepol_link_packages(sepol_handle_t * handle,sepol_module_package_t * base,sepol_module_package_t ** modules,int num_modules,int verbose)310*2d543d20SAndroid Build Coastguard Worker int sepol_link_packages(sepol_handle_t * handle,
311*2d543d20SAndroid Build Coastguard Worker 			sepol_module_package_t * base,
312*2d543d20SAndroid Build Coastguard Worker 			sepol_module_package_t ** modules, int num_modules,
313*2d543d20SAndroid Build Coastguard Worker 			int verbose)
314*2d543d20SAndroid Build Coastguard Worker {
315*2d543d20SAndroid Build Coastguard Worker 	policydb_t **mod_pols = NULL;
316*2d543d20SAndroid Build Coastguard Worker 	int i, retval;
317*2d543d20SAndroid Build Coastguard Worker 
318*2d543d20SAndroid Build Coastguard Worker 	if ((mod_pols = calloc(num_modules, sizeof(*mod_pols))) == NULL) {
319*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "Out of memory!");
320*2d543d20SAndroid Build Coastguard Worker 		return -2;
321*2d543d20SAndroid Build Coastguard Worker 	}
322*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < num_modules; i++) {
323*2d543d20SAndroid Build Coastguard Worker 		mod_pols[i] = &modules[i]->policy->p;
324*2d543d20SAndroid Build Coastguard Worker 	}
325*2d543d20SAndroid Build Coastguard Worker 
326*2d543d20SAndroid Build Coastguard Worker 	retval = link_modules(handle, &base->policy->p, mod_pols, num_modules,
327*2d543d20SAndroid Build Coastguard Worker 			      verbose);
328*2d543d20SAndroid Build Coastguard Worker 	free(mod_pols);
329*2d543d20SAndroid Build Coastguard Worker 	if (retval == -3) {
330*2d543d20SAndroid Build Coastguard Worker 		return -1;
331*2d543d20SAndroid Build Coastguard Worker 	} else if (retval < 0) {
332*2d543d20SAndroid Build Coastguard Worker 		return -2;
333*2d543d20SAndroid Build Coastguard Worker 	}
334*2d543d20SAndroid Build Coastguard Worker 
335*2d543d20SAndroid Build Coastguard Worker 	if (link_file_contexts(base, modules, num_modules) == -1) {
336*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "Out of memory!");
337*2d543d20SAndroid Build Coastguard Worker 		return -2;
338*2d543d20SAndroid Build Coastguard Worker 	}
339*2d543d20SAndroid Build Coastguard Worker 
340*2d543d20SAndroid Build Coastguard Worker 	if (link_netfilter_contexts(base, modules, num_modules) == -1) {
341*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "Out of memory!");
342*2d543d20SAndroid Build Coastguard Worker 		return -2;
343*2d543d20SAndroid Build Coastguard Worker 	}
344*2d543d20SAndroid Build Coastguard Worker 
345*2d543d20SAndroid Build Coastguard Worker 	return 0;
346*2d543d20SAndroid Build Coastguard Worker }
347*2d543d20SAndroid Build Coastguard Worker 
348*2d543d20SAndroid Build Coastguard Worker /* buf must be large enough - no checks are performed */
349*2d543d20SAndroid Build Coastguard Worker #define _read_helper_bufsize BUFSIZ
read_helper(char * buf,struct policy_file * file,uint32_t bytes)350*2d543d20SAndroid Build Coastguard Worker static int read_helper(char *buf, struct policy_file *file, uint32_t bytes)
351*2d543d20SAndroid Build Coastguard Worker {
352*2d543d20SAndroid Build Coastguard Worker 	uint32_t offset, nel, read_len;
353*2d543d20SAndroid Build Coastguard Worker 	int rc;
354*2d543d20SAndroid Build Coastguard Worker 
355*2d543d20SAndroid Build Coastguard Worker 	offset = 0;
356*2d543d20SAndroid Build Coastguard Worker 	nel = bytes;
357*2d543d20SAndroid Build Coastguard Worker 
358*2d543d20SAndroid Build Coastguard Worker 	while (nel) {
359*2d543d20SAndroid Build Coastguard Worker 		if (nel < _read_helper_bufsize)
360*2d543d20SAndroid Build Coastguard Worker 			read_len = nel;
361*2d543d20SAndroid Build Coastguard Worker 		else
362*2d543d20SAndroid Build Coastguard Worker 			read_len = _read_helper_bufsize;
363*2d543d20SAndroid Build Coastguard Worker 		rc = next_entry(&buf[offset], file, read_len);
364*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0)
365*2d543d20SAndroid Build Coastguard Worker 			return -1;
366*2d543d20SAndroid Build Coastguard Worker 		offset += read_len;
367*2d543d20SAndroid Build Coastguard Worker 		nel -= read_len;
368*2d543d20SAndroid Build Coastguard Worker 	}
369*2d543d20SAndroid Build Coastguard Worker 	return 0;
370*2d543d20SAndroid Build Coastguard Worker }
371*2d543d20SAndroid Build Coastguard Worker 
372*2d543d20SAndroid Build Coastguard Worker #define MAXSECTIONS 100
373*2d543d20SAndroid Build Coastguard Worker 
374*2d543d20SAndroid Build Coastguard Worker /* Get the section offsets from a package file, offsets will be malloc'd to
375*2d543d20SAndroid Build Coastguard Worker  * the appropriate size and the caller must free() them */
module_package_read_offsets(sepol_module_package_t * mod,struct policy_file * file,size_t ** offsets,uint32_t * sections)376*2d543d20SAndroid Build Coastguard Worker static int module_package_read_offsets(sepol_module_package_t * mod,
377*2d543d20SAndroid Build Coastguard Worker 				       struct policy_file *file,
378*2d543d20SAndroid Build Coastguard Worker 				       size_t ** offsets, uint32_t * sections)
379*2d543d20SAndroid Build Coastguard Worker {
380*2d543d20SAndroid Build Coastguard Worker 	uint32_t *buf = NULL, nsec;
381*2d543d20SAndroid Build Coastguard Worker 	unsigned i;
382*2d543d20SAndroid Build Coastguard Worker 	size_t *off = NULL;
383*2d543d20SAndroid Build Coastguard Worker 	int rc;
384*2d543d20SAndroid Build Coastguard Worker 
385*2d543d20SAndroid Build Coastguard Worker 	buf = malloc(sizeof(uint32_t)*3);
386*2d543d20SAndroid Build Coastguard Worker 	if (!buf) {
387*2d543d20SAndroid Build Coastguard Worker 		ERR(file->handle, "out of memory");
388*2d543d20SAndroid Build Coastguard Worker 		goto err;
389*2d543d20SAndroid Build Coastguard Worker 	}
390*2d543d20SAndroid Build Coastguard Worker 
391*2d543d20SAndroid Build Coastguard Worker 	rc = next_entry(buf, file, sizeof(uint32_t) * 3);
392*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0) {
393*2d543d20SAndroid Build Coastguard Worker 		ERR(file->handle, "module package header truncated");
394*2d543d20SAndroid Build Coastguard Worker 		goto err;
395*2d543d20SAndroid Build Coastguard Worker 	}
396*2d543d20SAndroid Build Coastguard Worker 	if (le32_to_cpu(buf[0]) != SEPOL_MODULE_PACKAGE_MAGIC) {
397*2d543d20SAndroid Build Coastguard Worker 		ERR(file->handle,
398*2d543d20SAndroid Build Coastguard Worker 		    "wrong magic number for module package:  expected %#08x, got %#08x",
399*2d543d20SAndroid Build Coastguard Worker 		    SEPOL_MODULE_PACKAGE_MAGIC, le32_to_cpu(buf[0]));
400*2d543d20SAndroid Build Coastguard Worker 		goto err;
401*2d543d20SAndroid Build Coastguard Worker 	}
402*2d543d20SAndroid Build Coastguard Worker 
403*2d543d20SAndroid Build Coastguard Worker 	mod->version = le32_to_cpu(buf[1]);
404*2d543d20SAndroid Build Coastguard Worker 	nsec = *sections = le32_to_cpu(buf[2]);
405*2d543d20SAndroid Build Coastguard Worker 
406*2d543d20SAndroid Build Coastguard Worker 	if (nsec > MAXSECTIONS) {
407*2d543d20SAndroid Build Coastguard Worker 		ERR(file->handle, "too many sections (%u) in module package",
408*2d543d20SAndroid Build Coastguard Worker 		    nsec);
409*2d543d20SAndroid Build Coastguard Worker 		goto err;
410*2d543d20SAndroid Build Coastguard Worker 	}
411*2d543d20SAndroid Build Coastguard Worker 
412*2d543d20SAndroid Build Coastguard Worker 	off = (size_t *) calloc(nsec + 1, sizeof(size_t));
413*2d543d20SAndroid Build Coastguard Worker 	if (!off) {
414*2d543d20SAndroid Build Coastguard Worker 		ERR(file->handle, "out of memory");
415*2d543d20SAndroid Build Coastguard Worker 		goto err;
416*2d543d20SAndroid Build Coastguard Worker 	}
417*2d543d20SAndroid Build Coastguard Worker 
418*2d543d20SAndroid Build Coastguard Worker 	free(buf);
419*2d543d20SAndroid Build Coastguard Worker 	buf = calloc(nsec, sizeof(uint32_t));
420*2d543d20SAndroid Build Coastguard Worker 	if (!buf) {
421*2d543d20SAndroid Build Coastguard Worker 		ERR(file->handle, "out of memory");
422*2d543d20SAndroid Build Coastguard Worker 		goto err;
423*2d543d20SAndroid Build Coastguard Worker 	}
424*2d543d20SAndroid Build Coastguard Worker 	rc = next_entry(buf, file, sizeof(uint32_t) * nsec);
425*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0) {
426*2d543d20SAndroid Build Coastguard Worker 		ERR(file->handle, "module package offset array truncated");
427*2d543d20SAndroid Build Coastguard Worker 		goto err;
428*2d543d20SAndroid Build Coastguard Worker 	}
429*2d543d20SAndroid Build Coastguard Worker 
430*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < nsec; i++) {
431*2d543d20SAndroid Build Coastguard Worker 		off[i] = le32_to_cpu(buf[i]);
432*2d543d20SAndroid Build Coastguard Worker 		if (i && off[i] < off[i - 1]) {
433*2d543d20SAndroid Build Coastguard Worker 			ERR(file->handle, "offsets are not increasing (at %u, "
434*2d543d20SAndroid Build Coastguard Worker 			    "offset %zu -> %zu", i, off[i - 1],
435*2d543d20SAndroid Build Coastguard Worker 			    off[i]);
436*2d543d20SAndroid Build Coastguard Worker 			goto err;
437*2d543d20SAndroid Build Coastguard Worker 		}
438*2d543d20SAndroid Build Coastguard Worker 	}
439*2d543d20SAndroid Build Coastguard Worker 
440*2d543d20SAndroid Build Coastguard Worker 	rc = policy_file_length(file, &off[nsec]);
441*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0)
442*2d543d20SAndroid Build Coastguard Worker 		goto err;
443*2d543d20SAndroid Build Coastguard Worker 
444*2d543d20SAndroid Build Coastguard Worker 	if (nsec && off[nsec] < off[nsec-1]) {
445*2d543d20SAndroid Build Coastguard Worker 		ERR(file->handle, "offset greater than file size (at %u, "
446*2d543d20SAndroid Build Coastguard Worker 		    "offset %zu -> %zu", nsec, off[nsec - 1],
447*2d543d20SAndroid Build Coastguard Worker 		    off[nsec]);
448*2d543d20SAndroid Build Coastguard Worker 		goto err;
449*2d543d20SAndroid Build Coastguard Worker 	}
450*2d543d20SAndroid Build Coastguard Worker 	*offsets = off;
451*2d543d20SAndroid Build Coastguard Worker 	free(buf);
452*2d543d20SAndroid Build Coastguard Worker 	return 0;
453*2d543d20SAndroid Build Coastguard Worker 
454*2d543d20SAndroid Build Coastguard Worker err:
455*2d543d20SAndroid Build Coastguard Worker 	free(buf);
456*2d543d20SAndroid Build Coastguard Worker 	free(off);
457*2d543d20SAndroid Build Coastguard Worker 	return -1;
458*2d543d20SAndroid Build Coastguard Worker }
459*2d543d20SAndroid Build Coastguard Worker 
460*2d543d20SAndroid Build Coastguard Worker /* Flags for which sections have been seen during parsing of module package. */
461*2d543d20SAndroid Build Coastguard Worker #define SEEN_MOD 1
462*2d543d20SAndroid Build Coastguard Worker #define SEEN_FC  2
463*2d543d20SAndroid Build Coastguard Worker #define SEEN_SEUSER 4
464*2d543d20SAndroid Build Coastguard Worker #define SEEN_USER_EXTRA 8
465*2d543d20SAndroid Build Coastguard Worker #define SEEN_NETFILTER 16
466*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_read(sepol_module_package_t * mod,struct sepol_policy_file * spf,int verbose)467*2d543d20SAndroid Build Coastguard Worker int sepol_module_package_read(sepol_module_package_t * mod,
468*2d543d20SAndroid Build Coastguard Worker 			      struct sepol_policy_file *spf, int verbose)
469*2d543d20SAndroid Build Coastguard Worker {
470*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *file = &spf->pf;
471*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[1], nsec;
472*2d543d20SAndroid Build Coastguard Worker 	size_t *offsets, len;
473*2d543d20SAndroid Build Coastguard Worker 	int rc;
474*2d543d20SAndroid Build Coastguard Worker 	unsigned i, seen = 0;
475*2d543d20SAndroid Build Coastguard Worker 
476*2d543d20SAndroid Build Coastguard Worker 	if (module_package_read_offsets(mod, file, &offsets, &nsec))
477*2d543d20SAndroid Build Coastguard Worker 		return -1;
478*2d543d20SAndroid Build Coastguard Worker 
479*2d543d20SAndroid Build Coastguard Worker 	/* we know the section offsets, seek to them and read in the data */
480*2d543d20SAndroid Build Coastguard Worker 
481*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < nsec; i++) {
482*2d543d20SAndroid Build Coastguard Worker 
483*2d543d20SAndroid Build Coastguard Worker 		if (policy_file_seek(file, offsets[i])) {
484*2d543d20SAndroid Build Coastguard Worker 			ERR(file->handle, "error seeking to offset %zu for "
485*2d543d20SAndroid Build Coastguard Worker 			    "module package section %u", offsets[i], i);
486*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
487*2d543d20SAndroid Build Coastguard Worker 		}
488*2d543d20SAndroid Build Coastguard Worker 
489*2d543d20SAndroid Build Coastguard Worker 		len = offsets[i + 1] - offsets[i];
490*2d543d20SAndroid Build Coastguard Worker 
491*2d543d20SAndroid Build Coastguard Worker 		if (len < sizeof(uint32_t)) {
492*2d543d20SAndroid Build Coastguard Worker 			ERR(file->handle, "module package section %u "
493*2d543d20SAndroid Build Coastguard Worker 			    "has too small length %zu", i, len);
494*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
495*2d543d20SAndroid Build Coastguard Worker 		}
496*2d543d20SAndroid Build Coastguard Worker 
497*2d543d20SAndroid Build Coastguard Worker 		/* read the magic number, so that we know which function to call */
498*2d543d20SAndroid Build Coastguard Worker 		rc = next_entry(buf, file, sizeof(uint32_t));
499*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
500*2d543d20SAndroid Build Coastguard Worker 			ERR(file->handle,
501*2d543d20SAndroid Build Coastguard Worker 			    "module package section %u truncated, lacks magic number",
502*2d543d20SAndroid Build Coastguard Worker 			    i);
503*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
504*2d543d20SAndroid Build Coastguard Worker 		}
505*2d543d20SAndroid Build Coastguard Worker 
506*2d543d20SAndroid Build Coastguard Worker 		switch (le32_to_cpu(buf[0])) {
507*2d543d20SAndroid Build Coastguard Worker 		case SEPOL_PACKAGE_SECTION_FC:
508*2d543d20SAndroid Build Coastguard Worker 			if (seen & SEEN_FC) {
509*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
510*2d543d20SAndroid Build Coastguard Worker 				    "found multiple file contexts sections in module package (at section %u)",
511*2d543d20SAndroid Build Coastguard Worker 				    i);
512*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
513*2d543d20SAndroid Build Coastguard Worker 			}
514*2d543d20SAndroid Build Coastguard Worker 
515*2d543d20SAndroid Build Coastguard Worker 			mod->file_contexts_len = len - sizeof(uint32_t);
516*2d543d20SAndroid Build Coastguard Worker 			mod->file_contexts =
517*2d543d20SAndroid Build Coastguard Worker 			    (char *)malloc(mod->file_contexts_len);
518*2d543d20SAndroid Build Coastguard Worker 			if (!mod->file_contexts) {
519*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle, "out of memory");
520*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
521*2d543d20SAndroid Build Coastguard Worker 			}
522*2d543d20SAndroid Build Coastguard Worker 			if (read_helper
523*2d543d20SAndroid Build Coastguard Worker 			    (mod->file_contexts, file,
524*2d543d20SAndroid Build Coastguard Worker 			     mod->file_contexts_len)) {
525*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
526*2d543d20SAndroid Build Coastguard Worker 				    "invalid file contexts section at section %u",
527*2d543d20SAndroid Build Coastguard Worker 				    i);
528*2d543d20SAndroid Build Coastguard Worker 				free(mod->file_contexts);
529*2d543d20SAndroid Build Coastguard Worker 				mod->file_contexts = NULL;
530*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
531*2d543d20SAndroid Build Coastguard Worker 			}
532*2d543d20SAndroid Build Coastguard Worker 			seen |= SEEN_FC;
533*2d543d20SAndroid Build Coastguard Worker 			break;
534*2d543d20SAndroid Build Coastguard Worker 		case SEPOL_PACKAGE_SECTION_SEUSER:
535*2d543d20SAndroid Build Coastguard Worker 			if (seen & SEEN_SEUSER) {
536*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
537*2d543d20SAndroid Build Coastguard Worker 				    "found multiple seuser sections in module package (at section %u)",
538*2d543d20SAndroid Build Coastguard Worker 				    i);
539*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
540*2d543d20SAndroid Build Coastguard Worker 			}
541*2d543d20SAndroid Build Coastguard Worker 
542*2d543d20SAndroid Build Coastguard Worker 			mod->seusers_len = len - sizeof(uint32_t);
543*2d543d20SAndroid Build Coastguard Worker 			mod->seusers = (char *)malloc(mod->seusers_len);
544*2d543d20SAndroid Build Coastguard Worker 			if (!mod->seusers) {
545*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle, "out of memory");
546*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
547*2d543d20SAndroid Build Coastguard Worker 			}
548*2d543d20SAndroid Build Coastguard Worker 			if (read_helper(mod->seusers, file, mod->seusers_len)) {
549*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
550*2d543d20SAndroid Build Coastguard Worker 				    "invalid seuser section at section %u", i);
551*2d543d20SAndroid Build Coastguard Worker 				free(mod->seusers);
552*2d543d20SAndroid Build Coastguard Worker 				mod->seusers = NULL;
553*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
554*2d543d20SAndroid Build Coastguard Worker 			}
555*2d543d20SAndroid Build Coastguard Worker 			seen |= SEEN_SEUSER;
556*2d543d20SAndroid Build Coastguard Worker 			break;
557*2d543d20SAndroid Build Coastguard Worker 		case SEPOL_PACKAGE_SECTION_USER_EXTRA:
558*2d543d20SAndroid Build Coastguard Worker 			if (seen & SEEN_USER_EXTRA) {
559*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
560*2d543d20SAndroid Build Coastguard Worker 				    "found multiple user_extra sections in module package (at section %u)",
561*2d543d20SAndroid Build Coastguard Worker 				    i);
562*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
563*2d543d20SAndroid Build Coastguard Worker 			}
564*2d543d20SAndroid Build Coastguard Worker 
565*2d543d20SAndroid Build Coastguard Worker 			mod->user_extra_len = len - sizeof(uint32_t);
566*2d543d20SAndroid Build Coastguard Worker 			mod->user_extra = (char *)malloc(mod->user_extra_len);
567*2d543d20SAndroid Build Coastguard Worker 			if (!mod->user_extra) {
568*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle, "out of memory");
569*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
570*2d543d20SAndroid Build Coastguard Worker 			}
571*2d543d20SAndroid Build Coastguard Worker 			if (read_helper
572*2d543d20SAndroid Build Coastguard Worker 			    (mod->user_extra, file, mod->user_extra_len)) {
573*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
574*2d543d20SAndroid Build Coastguard Worker 				    "invalid user_extra section at section %u",
575*2d543d20SAndroid Build Coastguard Worker 				    i);
576*2d543d20SAndroid Build Coastguard Worker 				free(mod->user_extra);
577*2d543d20SAndroid Build Coastguard Worker 				mod->user_extra = NULL;
578*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
579*2d543d20SAndroid Build Coastguard Worker 			}
580*2d543d20SAndroid Build Coastguard Worker 			seen |= SEEN_USER_EXTRA;
581*2d543d20SAndroid Build Coastguard Worker 			break;
582*2d543d20SAndroid Build Coastguard Worker 		case SEPOL_PACKAGE_SECTION_NETFILTER:
583*2d543d20SAndroid Build Coastguard Worker 			if (seen & SEEN_NETFILTER) {
584*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
585*2d543d20SAndroid Build Coastguard Worker 				    "found multiple netfilter contexts sections in module package (at section %u)",
586*2d543d20SAndroid Build Coastguard Worker 				    i);
587*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
588*2d543d20SAndroid Build Coastguard Worker 			}
589*2d543d20SAndroid Build Coastguard Worker 
590*2d543d20SAndroid Build Coastguard Worker 			mod->netfilter_contexts_len = len - sizeof(uint32_t);
591*2d543d20SAndroid Build Coastguard Worker 			mod->netfilter_contexts =
592*2d543d20SAndroid Build Coastguard Worker 			    (char *)malloc(mod->netfilter_contexts_len);
593*2d543d20SAndroid Build Coastguard Worker 			if (!mod->netfilter_contexts) {
594*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle, "out of memory");
595*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
596*2d543d20SAndroid Build Coastguard Worker 			}
597*2d543d20SAndroid Build Coastguard Worker 			if (read_helper
598*2d543d20SAndroid Build Coastguard Worker 			    (mod->netfilter_contexts, file,
599*2d543d20SAndroid Build Coastguard Worker 			     mod->netfilter_contexts_len)) {
600*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
601*2d543d20SAndroid Build Coastguard Worker 				    "invalid netfilter contexts section at section %u",
602*2d543d20SAndroid Build Coastguard Worker 				    i);
603*2d543d20SAndroid Build Coastguard Worker 				free(mod->netfilter_contexts);
604*2d543d20SAndroid Build Coastguard Worker 				mod->netfilter_contexts = NULL;
605*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
606*2d543d20SAndroid Build Coastguard Worker 			}
607*2d543d20SAndroid Build Coastguard Worker 			seen |= SEEN_NETFILTER;
608*2d543d20SAndroid Build Coastguard Worker 			break;
609*2d543d20SAndroid Build Coastguard Worker 		case POLICYDB_MOD_MAGIC:
610*2d543d20SAndroid Build Coastguard Worker 			if (seen & SEEN_MOD) {
611*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
612*2d543d20SAndroid Build Coastguard Worker 				    "found multiple module sections in module package (at section %u)",
613*2d543d20SAndroid Build Coastguard Worker 				    i);
614*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
615*2d543d20SAndroid Build Coastguard Worker 			}
616*2d543d20SAndroid Build Coastguard Worker 
617*2d543d20SAndroid Build Coastguard Worker 			/* seek back to where the magic number was */
618*2d543d20SAndroid Build Coastguard Worker 			if (policy_file_seek(file, offsets[i]))
619*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
620*2d543d20SAndroid Build Coastguard Worker 
621*2d543d20SAndroid Build Coastguard Worker 			rc = policydb_read(&mod->policy->p, file, verbose);
622*2d543d20SAndroid Build Coastguard Worker 			if (rc < 0) {
623*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
624*2d543d20SAndroid Build Coastguard Worker 				    "invalid module in module package (at section %u)",
625*2d543d20SAndroid Build Coastguard Worker 				    i);
626*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
627*2d543d20SAndroid Build Coastguard Worker 			}
628*2d543d20SAndroid Build Coastguard Worker 			seen |= SEEN_MOD;
629*2d543d20SAndroid Build Coastguard Worker 			break;
630*2d543d20SAndroid Build Coastguard Worker 		default:
631*2d543d20SAndroid Build Coastguard Worker 			/* unknown section, ignore */
632*2d543d20SAndroid Build Coastguard Worker 			ERR(file->handle,
633*2d543d20SAndroid Build Coastguard Worker 			    "unknown magic number at section %u, offset: %zx, number: %x ",
634*2d543d20SAndroid Build Coastguard Worker 			    i, offsets[i], le32_to_cpu(buf[0]));
635*2d543d20SAndroid Build Coastguard Worker 			break;
636*2d543d20SAndroid Build Coastguard Worker 		}
637*2d543d20SAndroid Build Coastguard Worker 	}
638*2d543d20SAndroid Build Coastguard Worker 
639*2d543d20SAndroid Build Coastguard Worker 	if ((seen & SEEN_MOD) == 0) {
640*2d543d20SAndroid Build Coastguard Worker 		ERR(file->handle, "missing module in module package");
641*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
642*2d543d20SAndroid Build Coastguard Worker 	}
643*2d543d20SAndroid Build Coastguard Worker 
644*2d543d20SAndroid Build Coastguard Worker 	free(offsets);
645*2d543d20SAndroid Build Coastguard Worker 	return 0;
646*2d543d20SAndroid Build Coastguard Worker 
647*2d543d20SAndroid Build Coastguard Worker       cleanup:
648*2d543d20SAndroid Build Coastguard Worker 	free(offsets);
649*2d543d20SAndroid Build Coastguard Worker 	return -1;
650*2d543d20SAndroid Build Coastguard Worker }
651*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_info(struct sepol_policy_file * spf,int * type,char ** name,char ** version)652*2d543d20SAndroid Build Coastguard Worker int sepol_module_package_info(struct sepol_policy_file *spf, int *type,
653*2d543d20SAndroid Build Coastguard Worker 			      char **name, char **version)
654*2d543d20SAndroid Build Coastguard Worker {
655*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *file = &spf->pf;
656*2d543d20SAndroid Build Coastguard Worker 	sepol_module_package_t *mod = NULL;
657*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[5], len, nsec;
658*2d543d20SAndroid Build Coastguard Worker 	size_t *offsets = NULL;
659*2d543d20SAndroid Build Coastguard Worker 	unsigned i, seen = 0;
660*2d543d20SAndroid Build Coastguard Worker 	char *id;
661*2d543d20SAndroid Build Coastguard Worker 	int rc;
662*2d543d20SAndroid Build Coastguard Worker 
663*2d543d20SAndroid Build Coastguard Worker 	if (sepol_module_package_create(&mod))
664*2d543d20SAndroid Build Coastguard Worker 		return -1;
665*2d543d20SAndroid Build Coastguard Worker 
666*2d543d20SAndroid Build Coastguard Worker 	if (module_package_read_offsets(mod, file, &offsets, &nsec)) {
667*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
668*2d543d20SAndroid Build Coastguard Worker 	}
669*2d543d20SAndroid Build Coastguard Worker 
670*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < nsec; i++) {
671*2d543d20SAndroid Build Coastguard Worker 
672*2d543d20SAndroid Build Coastguard Worker 		if (policy_file_seek(file, offsets[i])) {
673*2d543d20SAndroid Build Coastguard Worker 			ERR(file->handle, "error seeking to offset "
674*2d543d20SAndroid Build Coastguard Worker 			    "%zu for module package section %u", offsets[i], i);
675*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
676*2d543d20SAndroid Build Coastguard Worker 		}
677*2d543d20SAndroid Build Coastguard Worker 
678*2d543d20SAndroid Build Coastguard Worker 		len = offsets[i + 1] - offsets[i];
679*2d543d20SAndroid Build Coastguard Worker 
680*2d543d20SAndroid Build Coastguard Worker 		if (len < sizeof(uint32_t)) {
681*2d543d20SAndroid Build Coastguard Worker 			ERR(file->handle,
682*2d543d20SAndroid Build Coastguard Worker 			    "module package section %u has too small length %u",
683*2d543d20SAndroid Build Coastguard Worker 			    i, len);
684*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
685*2d543d20SAndroid Build Coastguard Worker 		}
686*2d543d20SAndroid Build Coastguard Worker 
687*2d543d20SAndroid Build Coastguard Worker 		/* read the magic number, so that we know which function to call */
688*2d543d20SAndroid Build Coastguard Worker 		rc = next_entry(buf, file, sizeof(uint32_t) * 2);
689*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
690*2d543d20SAndroid Build Coastguard Worker 			ERR(file->handle,
691*2d543d20SAndroid Build Coastguard Worker 			    "module package section %u truncated, lacks magic number",
692*2d543d20SAndroid Build Coastguard Worker 			    i);
693*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
694*2d543d20SAndroid Build Coastguard Worker 		}
695*2d543d20SAndroid Build Coastguard Worker 
696*2d543d20SAndroid Build Coastguard Worker 		switch (le32_to_cpu(buf[0])) {
697*2d543d20SAndroid Build Coastguard Worker 		case SEPOL_PACKAGE_SECTION_FC:
698*2d543d20SAndroid Build Coastguard Worker 			/* skip file contexts */
699*2d543d20SAndroid Build Coastguard Worker 			if (seen & SEEN_FC) {
700*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
701*2d543d20SAndroid Build Coastguard Worker 				    "found multiple file contexts sections in module package (at section %u)",
702*2d543d20SAndroid Build Coastguard Worker 				    i);
703*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
704*2d543d20SAndroid Build Coastguard Worker 			}
705*2d543d20SAndroid Build Coastguard Worker 			seen |= SEEN_FC;
706*2d543d20SAndroid Build Coastguard Worker 			break;
707*2d543d20SAndroid Build Coastguard Worker 		case SEPOL_PACKAGE_SECTION_SEUSER:
708*2d543d20SAndroid Build Coastguard Worker 			/* skip seuser */
709*2d543d20SAndroid Build Coastguard Worker 			if (seen & SEEN_SEUSER) {
710*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
711*2d543d20SAndroid Build Coastguard Worker 				    "found seuser sections in module package (at section %u)",
712*2d543d20SAndroid Build Coastguard Worker 				    i);
713*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
714*2d543d20SAndroid Build Coastguard Worker 			}
715*2d543d20SAndroid Build Coastguard Worker 			seen |= SEEN_SEUSER;
716*2d543d20SAndroid Build Coastguard Worker 			break;
717*2d543d20SAndroid Build Coastguard Worker 		case SEPOL_PACKAGE_SECTION_USER_EXTRA:
718*2d543d20SAndroid Build Coastguard Worker 			/* skip user_extra */
719*2d543d20SAndroid Build Coastguard Worker 			if (seen & SEEN_USER_EXTRA) {
720*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
721*2d543d20SAndroid Build Coastguard Worker 				    "found user_extra sections in module package (at section %u)",
722*2d543d20SAndroid Build Coastguard Worker 				    i);
723*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
724*2d543d20SAndroid Build Coastguard Worker 			}
725*2d543d20SAndroid Build Coastguard Worker 			seen |= SEEN_USER_EXTRA;
726*2d543d20SAndroid Build Coastguard Worker 			break;
727*2d543d20SAndroid Build Coastguard Worker 		case SEPOL_PACKAGE_SECTION_NETFILTER:
728*2d543d20SAndroid Build Coastguard Worker 			/* skip netfilter contexts */
729*2d543d20SAndroid Build Coastguard Worker 			if (seen & SEEN_NETFILTER) {
730*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
731*2d543d20SAndroid Build Coastguard Worker 				    "found multiple netfilter contexts sections in module package (at section %u)",
732*2d543d20SAndroid Build Coastguard Worker 				    i);
733*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
734*2d543d20SAndroid Build Coastguard Worker 			}
735*2d543d20SAndroid Build Coastguard Worker 			seen |= SEEN_NETFILTER;
736*2d543d20SAndroid Build Coastguard Worker 			break;
737*2d543d20SAndroid Build Coastguard Worker 		case POLICYDB_MOD_MAGIC:
738*2d543d20SAndroid Build Coastguard Worker 			if (seen & SEEN_MOD) {
739*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
740*2d543d20SAndroid Build Coastguard Worker 				    "found multiple module sections in module package (at section %u)",
741*2d543d20SAndroid Build Coastguard Worker 				    i);
742*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
743*2d543d20SAndroid Build Coastguard Worker 			}
744*2d543d20SAndroid Build Coastguard Worker 			len = le32_to_cpu(buf[1]);
745*2d543d20SAndroid Build Coastguard Worker 			if (len != strlen(POLICYDB_MOD_STRING)) {
746*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
747*2d543d20SAndroid Build Coastguard Worker 				    "module string length is wrong (at section %u)",
748*2d543d20SAndroid Build Coastguard Worker 				    i);
749*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
750*2d543d20SAndroid Build Coastguard Worker 			}
751*2d543d20SAndroid Build Coastguard Worker 
752*2d543d20SAndroid Build Coastguard Worker 			/* skip id */
753*2d543d20SAndroid Build Coastguard Worker 			id = malloc(len + 1);
754*2d543d20SAndroid Build Coastguard Worker 			if (!id) {
755*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
756*2d543d20SAndroid Build Coastguard Worker 				    "out of memory (at section %u)",
757*2d543d20SAndroid Build Coastguard Worker 				    i);
758*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
759*2d543d20SAndroid Build Coastguard Worker 			}
760*2d543d20SAndroid Build Coastguard Worker 			rc = next_entry(id, file, len);
761*2d543d20SAndroid Build Coastguard Worker 			free(id);
762*2d543d20SAndroid Build Coastguard Worker 			if (rc < 0) {
763*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
764*2d543d20SAndroid Build Coastguard Worker 				    "cannot get module string (at section %u)",
765*2d543d20SAndroid Build Coastguard Worker 				    i);
766*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
767*2d543d20SAndroid Build Coastguard Worker 			}
768*2d543d20SAndroid Build Coastguard Worker 
769*2d543d20SAndroid Build Coastguard Worker 			rc = next_entry(buf, file, sizeof(uint32_t) * 5);
770*2d543d20SAndroid Build Coastguard Worker 			if (rc < 0) {
771*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
772*2d543d20SAndroid Build Coastguard Worker 				    "cannot get module header (at section %u)",
773*2d543d20SAndroid Build Coastguard Worker 				    i);
774*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
775*2d543d20SAndroid Build Coastguard Worker 			}
776*2d543d20SAndroid Build Coastguard Worker 
777*2d543d20SAndroid Build Coastguard Worker 			*type = le32_to_cpu(buf[0]);
778*2d543d20SAndroid Build Coastguard Worker 			/* if base - we're done */
779*2d543d20SAndroid Build Coastguard Worker 			if (*type == POLICY_BASE) {
780*2d543d20SAndroid Build Coastguard Worker 				*name = NULL;
781*2d543d20SAndroid Build Coastguard Worker 				*version = NULL;
782*2d543d20SAndroid Build Coastguard Worker 				seen |= SEEN_MOD;
783*2d543d20SAndroid Build Coastguard Worker 				break;
784*2d543d20SAndroid Build Coastguard Worker 			} else if (*type != POLICY_MOD) {
785*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
786*2d543d20SAndroid Build Coastguard Worker 				    "module has invalid type %d (at section %u)",
787*2d543d20SAndroid Build Coastguard Worker 				    *type, i);
788*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
789*2d543d20SAndroid Build Coastguard Worker 			}
790*2d543d20SAndroid Build Coastguard Worker 
791*2d543d20SAndroid Build Coastguard Worker 			/* read the name and version */
792*2d543d20SAndroid Build Coastguard Worker 			rc = next_entry(buf, file, sizeof(uint32_t));
793*2d543d20SAndroid Build Coastguard Worker 			if (rc < 0) {
794*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
795*2d543d20SAndroid Build Coastguard Worker 				    "cannot get module name len (at section %u)",
796*2d543d20SAndroid Build Coastguard Worker 				    i);
797*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
798*2d543d20SAndroid Build Coastguard Worker 			}
799*2d543d20SAndroid Build Coastguard Worker 
800*2d543d20SAndroid Build Coastguard Worker 			len = le32_to_cpu(buf[0]);
801*2d543d20SAndroid Build Coastguard Worker 			if (str_read(name, file, len)) {
802*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
803*2d543d20SAndroid Build Coastguard Worker 				    "cannot read module name (at section %u): %m",
804*2d543d20SAndroid Build Coastguard Worker 				    i);
805*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
806*2d543d20SAndroid Build Coastguard Worker 			}
807*2d543d20SAndroid Build Coastguard Worker 
808*2d543d20SAndroid Build Coastguard Worker 			rc = next_entry(buf, file, sizeof(uint32_t));
809*2d543d20SAndroid Build Coastguard Worker 			if (rc < 0) {
810*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
811*2d543d20SAndroid Build Coastguard Worker 				    "cannot get module version len (at section %u)",
812*2d543d20SAndroid Build Coastguard Worker 				    i);
813*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
814*2d543d20SAndroid Build Coastguard Worker 			}
815*2d543d20SAndroid Build Coastguard Worker 			len = le32_to_cpu(buf[0]);
816*2d543d20SAndroid Build Coastguard Worker 			if (str_read(version, file, len)) {
817*2d543d20SAndroid Build Coastguard Worker 				ERR(file->handle,
818*2d543d20SAndroid Build Coastguard Worker 				    "cannot read module version (at section %u): %m",
819*2d543d20SAndroid Build Coastguard Worker 				i);
820*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
821*2d543d20SAndroid Build Coastguard Worker 			}
822*2d543d20SAndroid Build Coastguard Worker 			seen |= SEEN_MOD;
823*2d543d20SAndroid Build Coastguard Worker 			break;
824*2d543d20SAndroid Build Coastguard Worker 		default:
825*2d543d20SAndroid Build Coastguard Worker 			break;
826*2d543d20SAndroid Build Coastguard Worker 		}
827*2d543d20SAndroid Build Coastguard Worker 
828*2d543d20SAndroid Build Coastguard Worker 	}
829*2d543d20SAndroid Build Coastguard Worker 
830*2d543d20SAndroid Build Coastguard Worker 	if ((seen & SEEN_MOD) == 0) {
831*2d543d20SAndroid Build Coastguard Worker 		ERR(file->handle, "missing module in module package");
832*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
833*2d543d20SAndroid Build Coastguard Worker 	}
834*2d543d20SAndroid Build Coastguard Worker 
835*2d543d20SAndroid Build Coastguard Worker 	sepol_module_package_free(mod);
836*2d543d20SAndroid Build Coastguard Worker 	free(offsets);
837*2d543d20SAndroid Build Coastguard Worker 	return 0;
838*2d543d20SAndroid Build Coastguard Worker 
839*2d543d20SAndroid Build Coastguard Worker       cleanup:
840*2d543d20SAndroid Build Coastguard Worker 	sepol_module_package_free(mod);
841*2d543d20SAndroid Build Coastguard Worker 	free(offsets);
842*2d543d20SAndroid Build Coastguard Worker 	return -1;
843*2d543d20SAndroid Build Coastguard Worker }
844*2d543d20SAndroid Build Coastguard Worker 
write_helper(char * data,size_t len,struct policy_file * file)845*2d543d20SAndroid Build Coastguard Worker static int write_helper(char *data, size_t len, struct policy_file *file)
846*2d543d20SAndroid Build Coastguard Worker {
847*2d543d20SAndroid Build Coastguard Worker 	int idx = 0;
848*2d543d20SAndroid Build Coastguard Worker 	size_t len2;
849*2d543d20SAndroid Build Coastguard Worker 
850*2d543d20SAndroid Build Coastguard Worker 	while (len) {
851*2d543d20SAndroid Build Coastguard Worker 		if (len > BUFSIZ)
852*2d543d20SAndroid Build Coastguard Worker 			len2 = BUFSIZ;
853*2d543d20SAndroid Build Coastguard Worker 		else
854*2d543d20SAndroid Build Coastguard Worker 			len2 = len;
855*2d543d20SAndroid Build Coastguard Worker 
856*2d543d20SAndroid Build Coastguard Worker 		if (put_entry(&data[idx], 1, len2, file) != len2) {
857*2d543d20SAndroid Build Coastguard Worker 			return -1;
858*2d543d20SAndroid Build Coastguard Worker 		}
859*2d543d20SAndroid Build Coastguard Worker 		len -= len2;
860*2d543d20SAndroid Build Coastguard Worker 		idx += len2;
861*2d543d20SAndroid Build Coastguard Worker 	}
862*2d543d20SAndroid Build Coastguard Worker 	return 0;
863*2d543d20SAndroid Build Coastguard Worker }
864*2d543d20SAndroid Build Coastguard Worker 
sepol_module_package_write(sepol_module_package_t * p,struct sepol_policy_file * spf)865*2d543d20SAndroid Build Coastguard Worker int sepol_module_package_write(sepol_module_package_t * p,
866*2d543d20SAndroid Build Coastguard Worker 			       struct sepol_policy_file *spf)
867*2d543d20SAndroid Build Coastguard Worker {
868*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *file = &spf->pf;
869*2d543d20SAndroid Build Coastguard Worker 	policy_file_t polfile;
870*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[5], offsets[5], len, nsec = 0;
871*2d543d20SAndroid Build Coastguard Worker 	int i;
872*2d543d20SAndroid Build Coastguard Worker 
873*2d543d20SAndroid Build Coastguard Worker 	if (p->policy) {
874*2d543d20SAndroid Build Coastguard Worker 		/* compute policy length */
875*2d543d20SAndroid Build Coastguard Worker 		policy_file_init(&polfile);
876*2d543d20SAndroid Build Coastguard Worker 		polfile.type = PF_LEN;
877*2d543d20SAndroid Build Coastguard Worker 		polfile.handle = file->handle;
878*2d543d20SAndroid Build Coastguard Worker 		if (policydb_write(&p->policy->p, &polfile))
879*2d543d20SAndroid Build Coastguard Worker 			return -1;
880*2d543d20SAndroid Build Coastguard Worker 		len = polfile.len;
881*2d543d20SAndroid Build Coastguard Worker 		if (!polfile.len)
882*2d543d20SAndroid Build Coastguard Worker 			return -1;
883*2d543d20SAndroid Build Coastguard Worker 		nsec++;
884*2d543d20SAndroid Build Coastguard Worker 
885*2d543d20SAndroid Build Coastguard Worker 	} else {
886*2d543d20SAndroid Build Coastguard Worker 		/* We don't support writing a package without a module at this point */
887*2d543d20SAndroid Build Coastguard Worker 		return -1;
888*2d543d20SAndroid Build Coastguard Worker 	}
889*2d543d20SAndroid Build Coastguard Worker 
890*2d543d20SAndroid Build Coastguard Worker 	/* seusers and user_extra only supported in base at the moment */
891*2d543d20SAndroid Build Coastguard Worker 	if ((p->seusers || p->user_extra)
892*2d543d20SAndroid Build Coastguard Worker 	    && (p->policy->p.policy_type != SEPOL_POLICY_BASE)) {
893*2d543d20SAndroid Build Coastguard Worker 		ERR(file->handle,
894*2d543d20SAndroid Build Coastguard Worker 		    "seuser and user_extra sections only supported in base");
895*2d543d20SAndroid Build Coastguard Worker 		return -1;
896*2d543d20SAndroid Build Coastguard Worker 	}
897*2d543d20SAndroid Build Coastguard Worker 
898*2d543d20SAndroid Build Coastguard Worker 	if (p->file_contexts)
899*2d543d20SAndroid Build Coastguard Worker 		nsec++;
900*2d543d20SAndroid Build Coastguard Worker 
901*2d543d20SAndroid Build Coastguard Worker 	if (p->seusers)
902*2d543d20SAndroid Build Coastguard Worker 		nsec++;
903*2d543d20SAndroid Build Coastguard Worker 
904*2d543d20SAndroid Build Coastguard Worker 	if (p->user_extra)
905*2d543d20SAndroid Build Coastguard Worker 		nsec++;
906*2d543d20SAndroid Build Coastguard Worker 
907*2d543d20SAndroid Build Coastguard Worker 	if (p->netfilter_contexts)
908*2d543d20SAndroid Build Coastguard Worker 		nsec++;
909*2d543d20SAndroid Build Coastguard Worker 
910*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(SEPOL_MODULE_PACKAGE_MAGIC);
911*2d543d20SAndroid Build Coastguard Worker 	buf[1] = cpu_to_le32(p->version);
912*2d543d20SAndroid Build Coastguard Worker 	buf[2] = cpu_to_le32(nsec);
913*2d543d20SAndroid Build Coastguard Worker 	if (put_entry(buf, sizeof(uint32_t), 3, file) != 3)
914*2d543d20SAndroid Build Coastguard Worker 		return -1;
915*2d543d20SAndroid Build Coastguard Worker 
916*2d543d20SAndroid Build Coastguard Worker 	/* calculate offsets */
917*2d543d20SAndroid Build Coastguard Worker 	offsets[0] = (nsec + 3) * sizeof(uint32_t);
918*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(offsets[0]);
919*2d543d20SAndroid Build Coastguard Worker 
920*2d543d20SAndroid Build Coastguard Worker 	i = 1;
921*2d543d20SAndroid Build Coastguard Worker 	if (p->file_contexts) {
922*2d543d20SAndroid Build Coastguard Worker 		offsets[i] = offsets[i - 1] + len;
923*2d543d20SAndroid Build Coastguard Worker 		buf[i] = cpu_to_le32(offsets[i]);
924*2d543d20SAndroid Build Coastguard Worker 		/* add a uint32_t to compensate for the magic number */
925*2d543d20SAndroid Build Coastguard Worker 		len = p->file_contexts_len + sizeof(uint32_t);
926*2d543d20SAndroid Build Coastguard Worker 		i++;
927*2d543d20SAndroid Build Coastguard Worker 	}
928*2d543d20SAndroid Build Coastguard Worker 	if (p->seusers) {
929*2d543d20SAndroid Build Coastguard Worker 		offsets[i] = offsets[i - 1] + len;
930*2d543d20SAndroid Build Coastguard Worker 		buf[i] = cpu_to_le32(offsets[i]);
931*2d543d20SAndroid Build Coastguard Worker 		len = p->seusers_len + sizeof(uint32_t);
932*2d543d20SAndroid Build Coastguard Worker 		i++;
933*2d543d20SAndroid Build Coastguard Worker 	}
934*2d543d20SAndroid Build Coastguard Worker 	if (p->user_extra) {
935*2d543d20SAndroid Build Coastguard Worker 		offsets[i] = offsets[i - 1] + len;
936*2d543d20SAndroid Build Coastguard Worker 		buf[i] = cpu_to_le32(offsets[i]);
937*2d543d20SAndroid Build Coastguard Worker 		len = p->user_extra_len + sizeof(uint32_t);
938*2d543d20SAndroid Build Coastguard Worker 		i++;
939*2d543d20SAndroid Build Coastguard Worker 	}
940*2d543d20SAndroid Build Coastguard Worker 	if (p->netfilter_contexts) {
941*2d543d20SAndroid Build Coastguard Worker 		offsets[i] = offsets[i - 1] + len;
942*2d543d20SAndroid Build Coastguard Worker 		buf[i] = cpu_to_le32(offsets[i]);
943*2d543d20SAndroid Build Coastguard Worker 		len = p->netfilter_contexts_len + sizeof(uint32_t);
944*2d543d20SAndroid Build Coastguard Worker 		i++;
945*2d543d20SAndroid Build Coastguard Worker 	}
946*2d543d20SAndroid Build Coastguard Worker 	if (put_entry(buf, sizeof(uint32_t), nsec, file) != nsec)
947*2d543d20SAndroid Build Coastguard Worker 		return -1;
948*2d543d20SAndroid Build Coastguard Worker 
949*2d543d20SAndroid Build Coastguard Worker 	/* write sections */
950*2d543d20SAndroid Build Coastguard Worker 
951*2d543d20SAndroid Build Coastguard Worker 	if (policydb_write(&p->policy->p, file))
952*2d543d20SAndroid Build Coastguard Worker 		return -1;
953*2d543d20SAndroid Build Coastguard Worker 
954*2d543d20SAndroid Build Coastguard Worker 	if (p->file_contexts) {
955*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_FC);
956*2d543d20SAndroid Build Coastguard Worker 		if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
957*2d543d20SAndroid Build Coastguard Worker 			return -1;
958*2d543d20SAndroid Build Coastguard Worker 		if (write_helper(p->file_contexts, p->file_contexts_len, file))
959*2d543d20SAndroid Build Coastguard Worker 			return -1;
960*2d543d20SAndroid Build Coastguard Worker 	}
961*2d543d20SAndroid Build Coastguard Worker 	if (p->seusers) {
962*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_SEUSER);
963*2d543d20SAndroid Build Coastguard Worker 		if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
964*2d543d20SAndroid Build Coastguard Worker 			return -1;
965*2d543d20SAndroid Build Coastguard Worker 		if (write_helper(p->seusers, p->seusers_len, file))
966*2d543d20SAndroid Build Coastguard Worker 			return -1;
967*2d543d20SAndroid Build Coastguard Worker 
968*2d543d20SAndroid Build Coastguard Worker 	}
969*2d543d20SAndroid Build Coastguard Worker 	if (p->user_extra) {
970*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_USER_EXTRA);
971*2d543d20SAndroid Build Coastguard Worker 		if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
972*2d543d20SAndroid Build Coastguard Worker 			return -1;
973*2d543d20SAndroid Build Coastguard Worker 		if (write_helper(p->user_extra, p->user_extra_len, file))
974*2d543d20SAndroid Build Coastguard Worker 			return -1;
975*2d543d20SAndroid Build Coastguard Worker 	}
976*2d543d20SAndroid Build Coastguard Worker 	if (p->netfilter_contexts) {
977*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_NETFILTER);
978*2d543d20SAndroid Build Coastguard Worker 		if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
979*2d543d20SAndroid Build Coastguard Worker 			return -1;
980*2d543d20SAndroid Build Coastguard Worker 		if (write_helper
981*2d543d20SAndroid Build Coastguard Worker 		    (p->netfilter_contexts, p->netfilter_contexts_len, file))
982*2d543d20SAndroid Build Coastguard Worker 			return -1;
983*2d543d20SAndroid Build Coastguard Worker 	}
984*2d543d20SAndroid Build Coastguard Worker 	return 0;
985*2d543d20SAndroid Build Coastguard Worker }
986*2d543d20SAndroid Build Coastguard Worker 
sepol_link_modules(sepol_handle_t * handle,sepol_policydb_t * base,sepol_policydb_t ** modules,size_t len,int verbose)987*2d543d20SAndroid Build Coastguard Worker int sepol_link_modules(sepol_handle_t * handle,
988*2d543d20SAndroid Build Coastguard Worker 		       sepol_policydb_t * base,
989*2d543d20SAndroid Build Coastguard Worker 		       sepol_policydb_t ** modules, size_t len, int verbose)
990*2d543d20SAndroid Build Coastguard Worker {
991*2d543d20SAndroid Build Coastguard Worker 	return link_modules(handle, &base->p, (policydb_t **) modules, len,
992*2d543d20SAndroid Build Coastguard Worker 			    verbose);
993*2d543d20SAndroid Build Coastguard Worker }
994*2d543d20SAndroid Build Coastguard Worker 
sepol_expand_module(sepol_handle_t * handle,sepol_policydb_t * base,sepol_policydb_t * out,int verbose,int check)995*2d543d20SAndroid Build Coastguard Worker int sepol_expand_module(sepol_handle_t * handle,
996*2d543d20SAndroid Build Coastguard Worker 			sepol_policydb_t * base,
997*2d543d20SAndroid Build Coastguard Worker 			sepol_policydb_t * out, int verbose, int check)
998*2d543d20SAndroid Build Coastguard Worker {
999*2d543d20SAndroid Build Coastguard Worker 	return expand_module(handle, &base->p, &out->p, verbose, check);
1000*2d543d20SAndroid Build Coastguard Worker }
1001