1255e72915d4cbddceb435e13d81601755714e9fSE Android/* Author: Karl MacMillan <kmacmillan@tresys.com>
2255e72915d4cbddceb435e13d81601755714e9fSE Android *         Jason Tang     <jtang@tresys.com>
3255e72915d4cbddceb435e13d81601755714e9fSE Android *         Chris PeBenito <cpebenito@tresys.com>
4255e72915d4cbddceb435e13d81601755714e9fSE Android *
5255e72915d4cbddceb435e13d81601755714e9fSE Android * Copyright (C) 2004-2005 Tresys Technology, LLC
6255e72915d4cbddceb435e13d81601755714e9fSE Android *
7255e72915d4cbddceb435e13d81601755714e9fSE Android *  This library is free software; you can redistribute it and/or
8255e72915d4cbddceb435e13d81601755714e9fSE Android *  modify it under the terms of the GNU Lesser General Public
9255e72915d4cbddceb435e13d81601755714e9fSE Android *  License as published by the Free Software Foundation; either
10255e72915d4cbddceb435e13d81601755714e9fSE Android *  version 2.1 of the License, or (at your option) any later version.
11255e72915d4cbddceb435e13d81601755714e9fSE Android *
12255e72915d4cbddceb435e13d81601755714e9fSE Android *  This library is distributed in the hope that it will be useful,
13255e72915d4cbddceb435e13d81601755714e9fSE Android *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14255e72915d4cbddceb435e13d81601755714e9fSE Android *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15255e72915d4cbddceb435e13d81601755714e9fSE Android *  Lesser General Public License for more details.
16255e72915d4cbddceb435e13d81601755714e9fSE Android *
17255e72915d4cbddceb435e13d81601755714e9fSE Android *  You should have received a copy of the GNU Lesser General Public
18255e72915d4cbddceb435e13d81601755714e9fSE Android *  License along with this library; if not, write to the Free Software
19255e72915d4cbddceb435e13d81601755714e9fSE Android *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20255e72915d4cbddceb435e13d81601755714e9fSE Android */
21255e72915d4cbddceb435e13d81601755714e9fSE Android
22255e72915d4cbddceb435e13d81601755714e9fSE Android#include "policydb_internal.h"
23255e72915d4cbddceb435e13d81601755714e9fSE Android#include "module_internal.h"
24255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/link.h>
25255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/expand.h>
26255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/module.h>
27255e72915d4cbddceb435e13d81601755714e9fSE Android#include "debug.h"
28255e72915d4cbddceb435e13d81601755714e9fSE Android#include "private.h"
29255e72915d4cbddceb435e13d81601755714e9fSE Android
30255e72915d4cbddceb435e13d81601755714e9fSE Android#include <stdio.h>
31255e72915d4cbddceb435e13d81601755714e9fSE Android#include <stdlib.h>
32255e72915d4cbddceb435e13d81601755714e9fSE Android#include <limits.h>
33255e72915d4cbddceb435e13d81601755714e9fSE Android
34255e72915d4cbddceb435e13d81601755714e9fSE Android#define SEPOL_PACKAGE_SECTION_FC 0xf97cff90
35255e72915d4cbddceb435e13d81601755714e9fSE Android#define SEPOL_PACKAGE_SECTION_SEUSER 0x97cff91
36255e72915d4cbddceb435e13d81601755714e9fSE Android#define SEPOL_PACKAGE_SECTION_USER_EXTRA 0x97cff92
37255e72915d4cbddceb435e13d81601755714e9fSE Android#define SEPOL_PACKAGE_SECTION_NETFILTER 0x97cff93
38255e72915d4cbddceb435e13d81601755714e9fSE Android
39255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int policy_file_seek(struct policy_file *fp, size_t offset)
40255e72915d4cbddceb435e13d81601755714e9fSE Android{
41255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (fp->type) {
42255e72915d4cbddceb435e13d81601755714e9fSE Android	case PF_USE_STDIO:
43255e72915d4cbddceb435e13d81601755714e9fSE Android		if (offset > LONG_MAX) {
44255e72915d4cbddceb435e13d81601755714e9fSE Android			errno = EFAULT;
45255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
46255e72915d4cbddceb435e13d81601755714e9fSE Android		}
47255e72915d4cbddceb435e13d81601755714e9fSE Android		return fseek(fp->fp, (long)offset, SEEK_SET);
48255e72915d4cbddceb435e13d81601755714e9fSE Android	case PF_USE_MEMORY:
49255e72915d4cbddceb435e13d81601755714e9fSE Android		if (offset > fp->size) {
50255e72915d4cbddceb435e13d81601755714e9fSE Android			errno = EFAULT;
51255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
52255e72915d4cbddceb435e13d81601755714e9fSE Android		}
53255e72915d4cbddceb435e13d81601755714e9fSE Android		fp->data -= fp->size - fp->len;
54255e72915d4cbddceb435e13d81601755714e9fSE Android		fp->data += offset;
55255e72915d4cbddceb435e13d81601755714e9fSE Android		fp->len = fp->size - offset;
56255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
57255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
58255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
59255e72915d4cbddceb435e13d81601755714e9fSE Android	}
60255e72915d4cbddceb435e13d81601755714e9fSE Android}
61255e72915d4cbddceb435e13d81601755714e9fSE Android
62255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic size_t policy_file_length(struct policy_file *fp)
63255e72915d4cbddceb435e13d81601755714e9fSE Android{
64255e72915d4cbddceb435e13d81601755714e9fSE Android	long prev_offset, end_offset;
65255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (fp->type) {
66255e72915d4cbddceb435e13d81601755714e9fSE Android	case PF_USE_STDIO:
67255e72915d4cbddceb435e13d81601755714e9fSE Android		prev_offset = ftell(fp->fp);
68255e72915d4cbddceb435e13d81601755714e9fSE Android		fseek(fp->fp, 0L, SEEK_END);
69255e72915d4cbddceb435e13d81601755714e9fSE Android		end_offset = ftell(fp->fp);
70255e72915d4cbddceb435e13d81601755714e9fSE Android		fseek(fp->fp, prev_offset, SEEK_SET);
71255e72915d4cbddceb435e13d81601755714e9fSE Android		return end_offset;
72255e72915d4cbddceb435e13d81601755714e9fSE Android	case PF_USE_MEMORY:
73255e72915d4cbddceb435e13d81601755714e9fSE Android		return fp->size;
74255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
75255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
76255e72915d4cbddceb435e13d81601755714e9fSE Android	}
77255e72915d4cbddceb435e13d81601755714e9fSE Android}
78255e72915d4cbddceb435e13d81601755714e9fSE Android
79255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int module_package_init(sepol_module_package_t * p)
80255e72915d4cbddceb435e13d81601755714e9fSE Android{
81255e72915d4cbddceb435e13d81601755714e9fSE Android	memset(p, 0, sizeof(sepol_module_package_t));
82255e72915d4cbddceb435e13d81601755714e9fSE Android	if (sepol_policydb_create(&p->policy))
83255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
84255e72915d4cbddceb435e13d81601755714e9fSE Android
85255e72915d4cbddceb435e13d81601755714e9fSE Android	p->version = 1;
86255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
87255e72915d4cbddceb435e13d81601755714e9fSE Android}
88255e72915d4cbddceb435e13d81601755714e9fSE Android
89255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int set_char(char **field, char *data, size_t len)
90255e72915d4cbddceb435e13d81601755714e9fSE Android{
91255e72915d4cbddceb435e13d81601755714e9fSE Android	if (*field) {
92255e72915d4cbddceb435e13d81601755714e9fSE Android		free(*field);
93255e72915d4cbddceb435e13d81601755714e9fSE Android		*field = NULL;
94255e72915d4cbddceb435e13d81601755714e9fSE Android	}
95255e72915d4cbddceb435e13d81601755714e9fSE Android	if (len) {
96255e72915d4cbddceb435e13d81601755714e9fSE Android		*field = malloc(len);
97255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!*field)
98255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
99255e72915d4cbddceb435e13d81601755714e9fSE Android		memcpy(*field, data, len);
100255e72915d4cbddceb435e13d81601755714e9fSE Android	}
101255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
102255e72915d4cbddceb435e13d81601755714e9fSE Android}
103255e72915d4cbddceb435e13d81601755714e9fSE Android
104255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_module_package_create(sepol_module_package_t ** p)
105255e72915d4cbddceb435e13d81601755714e9fSE Android{
106255e72915d4cbddceb435e13d81601755714e9fSE Android	*p = calloc(1, sizeof(sepol_module_package_t));
107255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!(*p))
108255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
109255e72915d4cbddceb435e13d81601755714e9fSE Android	return module_package_init(*p);
110255e72915d4cbddceb435e13d81601755714e9fSE Android}
111255e72915d4cbddceb435e13d81601755714e9fSE Android
112255e72915d4cbddceb435e13d81601755714e9fSE Androidhidden_def(sepol_module_package_create)
113255e72915d4cbddceb435e13d81601755714e9fSE Android
114255e72915d4cbddceb435e13d81601755714e9fSE Android/* Deallocates all memory associated with a module package, including
115255e72915d4cbddceb435e13d81601755714e9fSE Android * the pointer itself.  Does nothing if p is NULL.
116255e72915d4cbddceb435e13d81601755714e9fSE Android */
117255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid sepol_module_package_free(sepol_module_package_t * p)
118255e72915d4cbddceb435e13d81601755714e9fSE Android{
119255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p == NULL)
120255e72915d4cbddceb435e13d81601755714e9fSE Android		return;
121255e72915d4cbddceb435e13d81601755714e9fSE Android
122255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_policydb_free(p->policy);
123255e72915d4cbddceb435e13d81601755714e9fSE Android	free(p->file_contexts);
124255e72915d4cbddceb435e13d81601755714e9fSE Android	free(p->seusers);
125255e72915d4cbddceb435e13d81601755714e9fSE Android	free(p->user_extra);
126255e72915d4cbddceb435e13d81601755714e9fSE Android	free(p->netfilter_contexts);
127255e72915d4cbddceb435e13d81601755714e9fSE Android	free(p);
128255e72915d4cbddceb435e13d81601755714e9fSE Android}
129255e72915d4cbddceb435e13d81601755714e9fSE Android
130255e72915d4cbddceb435e13d81601755714e9fSE Androidhidden_def(sepol_module_package_free)
131255e72915d4cbddceb435e13d81601755714e9fSE Android
132255e72915d4cbddceb435e13d81601755714e9fSE Androidchar *sepol_module_package_get_file_contexts(sepol_module_package_t * p)
133255e72915d4cbddceb435e13d81601755714e9fSE Android{
134255e72915d4cbddceb435e13d81601755714e9fSE Android	return p->file_contexts;
135255e72915d4cbddceb435e13d81601755714e9fSE Android}
136255e72915d4cbddceb435e13d81601755714e9fSE Android
137255e72915d4cbddceb435e13d81601755714e9fSE Androidsize_t sepol_module_package_get_file_contexts_len(sepol_module_package_t * p)
138255e72915d4cbddceb435e13d81601755714e9fSE Android{
139255e72915d4cbddceb435e13d81601755714e9fSE Android	return p->file_contexts_len;
140255e72915d4cbddceb435e13d81601755714e9fSE Android}
141255e72915d4cbddceb435e13d81601755714e9fSE Android
142255e72915d4cbddceb435e13d81601755714e9fSE Androidchar *sepol_module_package_get_seusers(sepol_module_package_t * p)
143255e72915d4cbddceb435e13d81601755714e9fSE Android{
144255e72915d4cbddceb435e13d81601755714e9fSE Android	return p->seusers;
145255e72915d4cbddceb435e13d81601755714e9fSE Android}
146255e72915d4cbddceb435e13d81601755714e9fSE Android
147255e72915d4cbddceb435e13d81601755714e9fSE Androidsize_t sepol_module_package_get_seusers_len(sepol_module_package_t * p)
148255e72915d4cbddceb435e13d81601755714e9fSE Android{
149255e72915d4cbddceb435e13d81601755714e9fSE Android	return p->seusers_len;
150255e72915d4cbddceb435e13d81601755714e9fSE Android}
151255e72915d4cbddceb435e13d81601755714e9fSE Android
152255e72915d4cbddceb435e13d81601755714e9fSE Androidchar *sepol_module_package_get_user_extra(sepol_module_package_t * p)
153255e72915d4cbddceb435e13d81601755714e9fSE Android{
154255e72915d4cbddceb435e13d81601755714e9fSE Android	return p->user_extra;
155255e72915d4cbddceb435e13d81601755714e9fSE Android}
156255e72915d4cbddceb435e13d81601755714e9fSE Android
157255e72915d4cbddceb435e13d81601755714e9fSE Androidsize_t sepol_module_package_get_user_extra_len(sepol_module_package_t * p)
158255e72915d4cbddceb435e13d81601755714e9fSE Android{
159255e72915d4cbddceb435e13d81601755714e9fSE Android	return p->user_extra_len;
160255e72915d4cbddceb435e13d81601755714e9fSE Android}
161255e72915d4cbddceb435e13d81601755714e9fSE Android
162255e72915d4cbddceb435e13d81601755714e9fSE Androidchar *sepol_module_package_get_netfilter_contexts(sepol_module_package_t * p)
163255e72915d4cbddceb435e13d81601755714e9fSE Android{
164255e72915d4cbddceb435e13d81601755714e9fSE Android	return p->netfilter_contexts;
165255e72915d4cbddceb435e13d81601755714e9fSE Android}
166255e72915d4cbddceb435e13d81601755714e9fSE Android
167255e72915d4cbddceb435e13d81601755714e9fSE Androidsize_t sepol_module_package_get_netfilter_contexts_len(sepol_module_package_t *
168255e72915d4cbddceb435e13d81601755714e9fSE Android						       p)
169255e72915d4cbddceb435e13d81601755714e9fSE Android{
170255e72915d4cbddceb435e13d81601755714e9fSE Android	return p->netfilter_contexts_len;
171255e72915d4cbddceb435e13d81601755714e9fSE Android}
172255e72915d4cbddceb435e13d81601755714e9fSE Android
173255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_module_package_set_file_contexts(sepol_module_package_t * p,
174255e72915d4cbddceb435e13d81601755714e9fSE Android					   char *data, size_t len)
175255e72915d4cbddceb435e13d81601755714e9fSE Android{
176255e72915d4cbddceb435e13d81601755714e9fSE Android	if (set_char(&p->file_contexts, data, len))
177255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
178255e72915d4cbddceb435e13d81601755714e9fSE Android
179255e72915d4cbddceb435e13d81601755714e9fSE Android	p->file_contexts_len = len;
180255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
181255e72915d4cbddceb435e13d81601755714e9fSE Android}
182255e72915d4cbddceb435e13d81601755714e9fSE Android
183255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_module_package_set_seusers(sepol_module_package_t * p,
184255e72915d4cbddceb435e13d81601755714e9fSE Android				     char *data, size_t len)
185255e72915d4cbddceb435e13d81601755714e9fSE Android{
186255e72915d4cbddceb435e13d81601755714e9fSE Android	if (set_char(&p->seusers, data, len))
187255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
188255e72915d4cbddceb435e13d81601755714e9fSE Android
189255e72915d4cbddceb435e13d81601755714e9fSE Android	p->seusers_len = len;
190255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
191255e72915d4cbddceb435e13d81601755714e9fSE Android}
192255e72915d4cbddceb435e13d81601755714e9fSE Android
193255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_module_package_set_user_extra(sepol_module_package_t * p,
194255e72915d4cbddceb435e13d81601755714e9fSE Android					char *data, size_t len)
195255e72915d4cbddceb435e13d81601755714e9fSE Android{
196255e72915d4cbddceb435e13d81601755714e9fSE Android	if (set_char(&p->user_extra, data, len))
197255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
198255e72915d4cbddceb435e13d81601755714e9fSE Android
199255e72915d4cbddceb435e13d81601755714e9fSE Android	p->user_extra_len = len;
200255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
201255e72915d4cbddceb435e13d81601755714e9fSE Android}
202255e72915d4cbddceb435e13d81601755714e9fSE Android
203255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_module_package_set_netfilter_contexts(sepol_module_package_t * p,
204255e72915d4cbddceb435e13d81601755714e9fSE Android						char *data, size_t len)
205255e72915d4cbddceb435e13d81601755714e9fSE Android{
206255e72915d4cbddceb435e13d81601755714e9fSE Android	if (set_char(&p->netfilter_contexts, data, len))
207255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
208255e72915d4cbddceb435e13d81601755714e9fSE Android
209255e72915d4cbddceb435e13d81601755714e9fSE Android	p->netfilter_contexts_len = len;
210255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
211255e72915d4cbddceb435e13d81601755714e9fSE Android}
212255e72915d4cbddceb435e13d81601755714e9fSE Android
213255e72915d4cbddceb435e13d81601755714e9fSE Androidsepol_policydb_t *sepol_module_package_get_policy(sepol_module_package_t * p)
214255e72915d4cbddceb435e13d81601755714e9fSE Android{
215255e72915d4cbddceb435e13d81601755714e9fSE Android	return p->policy;
216255e72915d4cbddceb435e13d81601755714e9fSE Android}
217255e72915d4cbddceb435e13d81601755714e9fSE Android
218255e72915d4cbddceb435e13d81601755714e9fSE Android/* Append each of the file contexts from each module to the base
219255e72915d4cbddceb435e13d81601755714e9fSE Android * policy's file context.  'base_context' will be reallocated to a
220255e72915d4cbddceb435e13d81601755714e9fSE Android * larger size (and thus it is an in/out reference
221255e72915d4cbddceb435e13d81601755714e9fSE Android * variable). 'base_fc_len' is the length of base's file context; it
222255e72915d4cbddceb435e13d81601755714e9fSE Android * too is a reference variable.  Return 0 on success, -1 if out of
223255e72915d4cbddceb435e13d81601755714e9fSE Android * memory. */
224255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int link_file_contexts(sepol_module_package_t * base,
225255e72915d4cbddceb435e13d81601755714e9fSE Android			      sepol_module_package_t ** modules,
226255e72915d4cbddceb435e13d81601755714e9fSE Android			      int num_modules)
227255e72915d4cbddceb435e13d81601755714e9fSE Android{
228255e72915d4cbddceb435e13d81601755714e9fSE Android	size_t fc_len;
229255e72915d4cbddceb435e13d81601755714e9fSE Android	int i;
230255e72915d4cbddceb435e13d81601755714e9fSE Android	char *s;
231255e72915d4cbddceb435e13d81601755714e9fSE Android
232255e72915d4cbddceb435e13d81601755714e9fSE Android	fc_len = base->file_contexts_len;
233255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < num_modules; i++) {
234255e72915d4cbddceb435e13d81601755714e9fSE Android		fc_len += modules[i]->file_contexts_len;
235255e72915d4cbddceb435e13d81601755714e9fSE Android	}
236255e72915d4cbddceb435e13d81601755714e9fSE Android
237255e72915d4cbddceb435e13d81601755714e9fSE Android	if ((s = (char *)realloc(base->file_contexts, fc_len)) == NULL) {
238255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
239255e72915d4cbddceb435e13d81601755714e9fSE Android	}
240255e72915d4cbddceb435e13d81601755714e9fSE Android	base->file_contexts = s;
241255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < num_modules; i++) {
242255e72915d4cbddceb435e13d81601755714e9fSE Android		memcpy(base->file_contexts + base->file_contexts_len,
243255e72915d4cbddceb435e13d81601755714e9fSE Android		       modules[i]->file_contexts,
244255e72915d4cbddceb435e13d81601755714e9fSE Android		       modules[i]->file_contexts_len);
245255e72915d4cbddceb435e13d81601755714e9fSE Android		base->file_contexts_len += modules[i]->file_contexts_len;
246255e72915d4cbddceb435e13d81601755714e9fSE Android	}
247255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
248255e72915d4cbddceb435e13d81601755714e9fSE Android}
249255e72915d4cbddceb435e13d81601755714e9fSE Android
250255e72915d4cbddceb435e13d81601755714e9fSE Android/* Append each of the netfilter contexts from each module to the base
251255e72915d4cbddceb435e13d81601755714e9fSE Android * policy's netfilter context.  'base_context' will be reallocated to a
252255e72915d4cbddceb435e13d81601755714e9fSE Android * larger size (and thus it is an in/out reference
253255e72915d4cbddceb435e13d81601755714e9fSE Android * variable). 'base_nc_len' is the length of base's netfilter contexts; it
254255e72915d4cbddceb435e13d81601755714e9fSE Android * too is a reference variable.  Return 0 on success, -1 if out of
255255e72915d4cbddceb435e13d81601755714e9fSE Android * memory. */
256255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int link_netfilter_contexts(sepol_module_package_t * base,
257255e72915d4cbddceb435e13d81601755714e9fSE Android				   sepol_module_package_t ** modules,
258255e72915d4cbddceb435e13d81601755714e9fSE Android				   int num_modules)
259255e72915d4cbddceb435e13d81601755714e9fSE Android{
260255e72915d4cbddceb435e13d81601755714e9fSE Android	size_t base_nc_len;
261255e72915d4cbddceb435e13d81601755714e9fSE Android	int i;
262255e72915d4cbddceb435e13d81601755714e9fSE Android	char *base_context;
263255e72915d4cbddceb435e13d81601755714e9fSE Android
264255e72915d4cbddceb435e13d81601755714e9fSE Android	base_nc_len = base->netfilter_contexts_len;
265255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < num_modules; i++) {
266255e72915d4cbddceb435e13d81601755714e9fSE Android		base_nc_len += modules[i]->netfilter_contexts_len;
267255e72915d4cbddceb435e13d81601755714e9fSE Android	}
268255e72915d4cbddceb435e13d81601755714e9fSE Android
269255e72915d4cbddceb435e13d81601755714e9fSE Android	if ((base_context =
270255e72915d4cbddceb435e13d81601755714e9fSE Android	     (char *)realloc(base->netfilter_contexts, base_nc_len)) == NULL) {
271255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
272255e72915d4cbddceb435e13d81601755714e9fSE Android	}
273255e72915d4cbddceb435e13d81601755714e9fSE Android	base->netfilter_contexts = base_context;
274255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < num_modules; i++) {
275255e72915d4cbddceb435e13d81601755714e9fSE Android		memcpy(base->netfilter_contexts + base->netfilter_contexts_len,
276255e72915d4cbddceb435e13d81601755714e9fSE Android		       modules[i]->netfilter_contexts,
277255e72915d4cbddceb435e13d81601755714e9fSE Android		       modules[i]->netfilter_contexts_len);
278255e72915d4cbddceb435e13d81601755714e9fSE Android		base->netfilter_contexts_len +=
279255e72915d4cbddceb435e13d81601755714e9fSE Android		    modules[i]->netfilter_contexts_len;
280255e72915d4cbddceb435e13d81601755714e9fSE Android	}
281255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
282255e72915d4cbddceb435e13d81601755714e9fSE Android}
283255e72915d4cbddceb435e13d81601755714e9fSE Android
284255e72915d4cbddceb435e13d81601755714e9fSE Android/* Links the module packages into the base.  Returns 0 on success, -1
285255e72915d4cbddceb435e13d81601755714e9fSE Android * if a requirement was not met, or -2 for all other errors. */
286255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_link_packages(sepol_handle_t * handle,
287255e72915d4cbddceb435e13d81601755714e9fSE Android			sepol_module_package_t * base,
288255e72915d4cbddceb435e13d81601755714e9fSE Android			sepol_module_package_t ** modules, int num_modules,
289255e72915d4cbddceb435e13d81601755714e9fSE Android			int verbose)
290255e72915d4cbddceb435e13d81601755714e9fSE Android{
291255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb_t **mod_pols = NULL;
292255e72915d4cbddceb435e13d81601755714e9fSE Android	int i, retval;
293255e72915d4cbddceb435e13d81601755714e9fSE Android
294255e72915d4cbddceb435e13d81601755714e9fSE Android	if ((mod_pols = calloc(num_modules, sizeof(*mod_pols))) == NULL) {
295255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "Out of memory!");
296255e72915d4cbddceb435e13d81601755714e9fSE Android		return -2;
297255e72915d4cbddceb435e13d81601755714e9fSE Android	}
298255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < num_modules; i++) {
299255e72915d4cbddceb435e13d81601755714e9fSE Android		mod_pols[i] = &modules[i]->policy->p;
300255e72915d4cbddceb435e13d81601755714e9fSE Android	}
301255e72915d4cbddceb435e13d81601755714e9fSE Android
302255e72915d4cbddceb435e13d81601755714e9fSE Android	retval = link_modules(handle, &base->policy->p, mod_pols, num_modules,
303255e72915d4cbddceb435e13d81601755714e9fSE Android			      verbose);
304255e72915d4cbddceb435e13d81601755714e9fSE Android	free(mod_pols);
305255e72915d4cbddceb435e13d81601755714e9fSE Android	if (retval == -3) {
306255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
307255e72915d4cbddceb435e13d81601755714e9fSE Android	} else if (retval < 0) {
308255e72915d4cbddceb435e13d81601755714e9fSE Android		return -2;
309255e72915d4cbddceb435e13d81601755714e9fSE Android	}
310255e72915d4cbddceb435e13d81601755714e9fSE Android
311255e72915d4cbddceb435e13d81601755714e9fSE Android	if (link_file_contexts(base, modules, num_modules) == -1) {
312255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "Out of memory!");
313255e72915d4cbddceb435e13d81601755714e9fSE Android		return -2;
314255e72915d4cbddceb435e13d81601755714e9fSE Android	}
315255e72915d4cbddceb435e13d81601755714e9fSE Android
316255e72915d4cbddceb435e13d81601755714e9fSE Android	if (link_netfilter_contexts(base, modules, num_modules) == -1) {
317255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "Out of memory!");
318255e72915d4cbddceb435e13d81601755714e9fSE Android		return -2;
319255e72915d4cbddceb435e13d81601755714e9fSE Android	}
320255e72915d4cbddceb435e13d81601755714e9fSE Android
321255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
322255e72915d4cbddceb435e13d81601755714e9fSE Android}
323255e72915d4cbddceb435e13d81601755714e9fSE Android
324255e72915d4cbddceb435e13d81601755714e9fSE Android/* buf must be large enough - no checks are performed */
325255e72915d4cbddceb435e13d81601755714e9fSE Android#define _read_helper_bufsize BUFSIZ
326255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int read_helper(char *buf, struct policy_file *file, uint32_t bytes)
327255e72915d4cbddceb435e13d81601755714e9fSE Android{
328255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t offset, nel, read_len;
329255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc;
330255e72915d4cbddceb435e13d81601755714e9fSE Android
331255e72915d4cbddceb435e13d81601755714e9fSE Android	offset = 0;
332255e72915d4cbddceb435e13d81601755714e9fSE Android	nel = bytes;
333255e72915d4cbddceb435e13d81601755714e9fSE Android
334255e72915d4cbddceb435e13d81601755714e9fSE Android	while (nel) {
335255e72915d4cbddceb435e13d81601755714e9fSE Android		if (nel < _read_helper_bufsize)
336255e72915d4cbddceb435e13d81601755714e9fSE Android			read_len = nel;
337255e72915d4cbddceb435e13d81601755714e9fSE Android		else
338255e72915d4cbddceb435e13d81601755714e9fSE Android			read_len = _read_helper_bufsize;
339255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = next_entry(&buf[offset], file, read_len);
340255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc < 0)
341255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
342255e72915d4cbddceb435e13d81601755714e9fSE Android		offset += read_len;
343255e72915d4cbddceb435e13d81601755714e9fSE Android		nel -= read_len;
344255e72915d4cbddceb435e13d81601755714e9fSE Android	}
345255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
346255e72915d4cbddceb435e13d81601755714e9fSE Android}
347255e72915d4cbddceb435e13d81601755714e9fSE Android
348255e72915d4cbddceb435e13d81601755714e9fSE Android#define MAXSECTIONS 100
349255e72915d4cbddceb435e13d81601755714e9fSE Android
350255e72915d4cbddceb435e13d81601755714e9fSE Android/* Get the section offsets from a package file, offsets will be malloc'd to
351255e72915d4cbddceb435e13d81601755714e9fSE Android * the appropriate size and the caller must free() them */
352255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int module_package_read_offsets(sepol_module_package_t * mod,
353255e72915d4cbddceb435e13d81601755714e9fSE Android				       struct policy_file *file,
354255e72915d4cbddceb435e13d81601755714e9fSE Android				       size_t ** offsets, uint32_t * sections)
355255e72915d4cbddceb435e13d81601755714e9fSE Android{
356255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t *buf = NULL, nsec;
357255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned i;
358255e72915d4cbddceb435e13d81601755714e9fSE Android	size_t *off = NULL;
359255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc;
360255e72915d4cbddceb435e13d81601755714e9fSE Android
361255e72915d4cbddceb435e13d81601755714e9fSE Android	buf = malloc(sizeof(uint32_t)*3);
362255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!buf) {
363255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(file->handle, "out of memory");
364255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
365255e72915d4cbddceb435e13d81601755714e9fSE Android	}
366255e72915d4cbddceb435e13d81601755714e9fSE Android
367255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = next_entry(buf, file, sizeof(uint32_t) * 3);
368255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rc < 0) {
369255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(file->handle, "module package header truncated");
370255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
371255e72915d4cbddceb435e13d81601755714e9fSE Android	}
372255e72915d4cbddceb435e13d81601755714e9fSE Android	if (le32_to_cpu(buf[0]) != SEPOL_MODULE_PACKAGE_MAGIC) {
373255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(file->handle,
374255e72915d4cbddceb435e13d81601755714e9fSE Android		    "wrong magic number for module package:  expected %#08x, got %#08x",
375255e72915d4cbddceb435e13d81601755714e9fSE Android		    SEPOL_MODULE_PACKAGE_MAGIC, le32_to_cpu(buf[0]));
376255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
377255e72915d4cbddceb435e13d81601755714e9fSE Android	}
378255e72915d4cbddceb435e13d81601755714e9fSE Android
379255e72915d4cbddceb435e13d81601755714e9fSE Android	mod->version = le32_to_cpu(buf[1]);
380255e72915d4cbddceb435e13d81601755714e9fSE Android	nsec = *sections = le32_to_cpu(buf[2]);
381255e72915d4cbddceb435e13d81601755714e9fSE Android
382255e72915d4cbddceb435e13d81601755714e9fSE Android	if (nsec > MAXSECTIONS) {
383255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(file->handle, "too many sections (%u) in module package",
384255e72915d4cbddceb435e13d81601755714e9fSE Android		    nsec);
385255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
386255e72915d4cbddceb435e13d81601755714e9fSE Android	}
387255e72915d4cbddceb435e13d81601755714e9fSE Android
388255e72915d4cbddceb435e13d81601755714e9fSE Android	off = (size_t *) malloc((nsec + 1) * sizeof(size_t));
389255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!off) {
390255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(file->handle, "out of memory");
391255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
392255e72915d4cbddceb435e13d81601755714e9fSE Android	}
393255e72915d4cbddceb435e13d81601755714e9fSE Android
394255e72915d4cbddceb435e13d81601755714e9fSE Android	free(buf);
395255e72915d4cbddceb435e13d81601755714e9fSE Android	buf = malloc(sizeof(uint32_t) * nsec);
396255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!buf) {
397255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(file->handle, "out of memory");
398255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
399255e72915d4cbddceb435e13d81601755714e9fSE Android	}
400255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = next_entry(buf, file, sizeof(uint32_t) * nsec);
401255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rc < 0) {
402255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(file->handle, "module package offset array truncated");
403255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
404255e72915d4cbddceb435e13d81601755714e9fSE Android	}
405255e72915d4cbddceb435e13d81601755714e9fSE Android
406255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < nsec; i++) {
407255e72915d4cbddceb435e13d81601755714e9fSE Android		off[i] = le32_to_cpu(buf[i]);
408255e72915d4cbddceb435e13d81601755714e9fSE Android		if (i && off[i] < off[i - 1]) {
409255e72915d4cbddceb435e13d81601755714e9fSE Android			ERR(file->handle, "offsets are not increasing (at %u, "
410255e72915d4cbddceb435e13d81601755714e9fSE Android			    "offset %zu -> %zu", i, off[i - 1],
411255e72915d4cbddceb435e13d81601755714e9fSE Android			    off[i]);
412255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
413255e72915d4cbddceb435e13d81601755714e9fSE Android		}
414255e72915d4cbddceb435e13d81601755714e9fSE Android	}
415255e72915d4cbddceb435e13d81601755714e9fSE Android
416255e72915d4cbddceb435e13d81601755714e9fSE Android	off[nsec] = policy_file_length(file);
417255e72915d4cbddceb435e13d81601755714e9fSE Android	if (nsec && off[nsec] < off[nsec-1]) {
418255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(file->handle, "offset greater than file size (at %u, "
419255e72915d4cbddceb435e13d81601755714e9fSE Android		    "offset %zu -> %zu", nsec, off[nsec - 1],
420255e72915d4cbddceb435e13d81601755714e9fSE Android		    off[nsec]);
421255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
422255e72915d4cbddceb435e13d81601755714e9fSE Android	}
423255e72915d4cbddceb435e13d81601755714e9fSE Android	*offsets = off;
424255e72915d4cbddceb435e13d81601755714e9fSE Android	free(buf);
425255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
426255e72915d4cbddceb435e13d81601755714e9fSE Android
427255e72915d4cbddceb435e13d81601755714e9fSE Androiderr:
428255e72915d4cbddceb435e13d81601755714e9fSE Android	free(buf);
429255e72915d4cbddceb435e13d81601755714e9fSE Android	free(off);
430255e72915d4cbddceb435e13d81601755714e9fSE Android	return -1;
431255e72915d4cbddceb435e13d81601755714e9fSE Android}
432255e72915d4cbddceb435e13d81601755714e9fSE Android
433255e72915d4cbddceb435e13d81601755714e9fSE Android/* Flags for which sections have been seen during parsing of module package. */
434255e72915d4cbddceb435e13d81601755714e9fSE Android#define SEEN_MOD 1
435255e72915d4cbddceb435e13d81601755714e9fSE Android#define SEEN_FC  2
436255e72915d4cbddceb435e13d81601755714e9fSE Android#define SEEN_SEUSER 4
437255e72915d4cbddceb435e13d81601755714e9fSE Android#define SEEN_USER_EXTRA 8
438255e72915d4cbddceb435e13d81601755714e9fSE Android#define SEEN_NETFILTER 16
439255e72915d4cbddceb435e13d81601755714e9fSE Android
440255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_module_package_read(sepol_module_package_t * mod,
441255e72915d4cbddceb435e13d81601755714e9fSE Android			      struct sepol_policy_file *spf, int verbose)
442255e72915d4cbddceb435e13d81601755714e9fSE Android{
443255e72915d4cbddceb435e13d81601755714e9fSE Android	struct policy_file *file = &spf->pf;
444255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t buf[1], nsec;
445255e72915d4cbddceb435e13d81601755714e9fSE Android	size_t *offsets, len;
446255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc;
447255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned i, seen = 0;
448255e72915d4cbddceb435e13d81601755714e9fSE Android
449255e72915d4cbddceb435e13d81601755714e9fSE Android	if (module_package_read_offsets(mod, file, &offsets, &nsec))
450255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
451255e72915d4cbddceb435e13d81601755714e9fSE Android
452255e72915d4cbddceb435e13d81601755714e9fSE Android	/* we know the section offsets, seek to them and read in the data */
453255e72915d4cbddceb435e13d81601755714e9fSE Android
454255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < nsec; i++) {
455255e72915d4cbddceb435e13d81601755714e9fSE Android
456255e72915d4cbddceb435e13d81601755714e9fSE Android		if (policy_file_seek(file, offsets[i])) {
457255e72915d4cbddceb435e13d81601755714e9fSE Android			ERR(file->handle, "error seeking to offset %zu for "
458255e72915d4cbddceb435e13d81601755714e9fSE Android			    "module package section %u", offsets[i], i);
459255e72915d4cbddceb435e13d81601755714e9fSE Android			goto cleanup;
460255e72915d4cbddceb435e13d81601755714e9fSE Android		}
461255e72915d4cbddceb435e13d81601755714e9fSE Android
462255e72915d4cbddceb435e13d81601755714e9fSE Android		len = offsets[i + 1] - offsets[i];
463255e72915d4cbddceb435e13d81601755714e9fSE Android
464255e72915d4cbddceb435e13d81601755714e9fSE Android		if (len < sizeof(uint32_t)) {
465255e72915d4cbddceb435e13d81601755714e9fSE Android			ERR(file->handle, "module package section %u "
466255e72915d4cbddceb435e13d81601755714e9fSE Android			    "has too small length %zu", i, len);
467255e72915d4cbddceb435e13d81601755714e9fSE Android			goto cleanup;
468255e72915d4cbddceb435e13d81601755714e9fSE Android		}
469255e72915d4cbddceb435e13d81601755714e9fSE Android
470255e72915d4cbddceb435e13d81601755714e9fSE Android		/* read the magic number, so that we know which function to call */
471255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = next_entry(buf, file, sizeof(uint32_t));
472255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc < 0) {
473255e72915d4cbddceb435e13d81601755714e9fSE Android			ERR(file->handle,
474255e72915d4cbddceb435e13d81601755714e9fSE Android			    "module package section %u truncated, lacks magic number",
475255e72915d4cbddceb435e13d81601755714e9fSE Android			    i);
476255e72915d4cbddceb435e13d81601755714e9fSE Android			goto cleanup;
477255e72915d4cbddceb435e13d81601755714e9fSE Android		}
478255e72915d4cbddceb435e13d81601755714e9fSE Android
479255e72915d4cbddceb435e13d81601755714e9fSE Android		switch (le32_to_cpu(buf[0])) {
480255e72915d4cbddceb435e13d81601755714e9fSE Android		case SEPOL_PACKAGE_SECTION_FC:
481255e72915d4cbddceb435e13d81601755714e9fSE Android			if (seen & SEEN_FC) {
482255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
483255e72915d4cbddceb435e13d81601755714e9fSE Android				    "found multiple file contexts sections in module package (at section %u)",
484255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
485255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
486255e72915d4cbddceb435e13d81601755714e9fSE Android			}
487255e72915d4cbddceb435e13d81601755714e9fSE Android
488255e72915d4cbddceb435e13d81601755714e9fSE Android			mod->file_contexts_len = len - sizeof(uint32_t);
489255e72915d4cbddceb435e13d81601755714e9fSE Android			mod->file_contexts =
490255e72915d4cbddceb435e13d81601755714e9fSE Android			    (char *)malloc(mod->file_contexts_len);
491255e72915d4cbddceb435e13d81601755714e9fSE Android			if (!mod->file_contexts) {
492255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle, "out of memory");
493255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
494255e72915d4cbddceb435e13d81601755714e9fSE Android			}
495255e72915d4cbddceb435e13d81601755714e9fSE Android			if (read_helper
496255e72915d4cbddceb435e13d81601755714e9fSE Android			    (mod->file_contexts, file,
497255e72915d4cbddceb435e13d81601755714e9fSE Android			     mod->file_contexts_len)) {
498255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
499255e72915d4cbddceb435e13d81601755714e9fSE Android				    "invalid file contexts section at section %u",
500255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
501255e72915d4cbddceb435e13d81601755714e9fSE Android				free(mod->file_contexts);
502255e72915d4cbddceb435e13d81601755714e9fSE Android				mod->file_contexts = NULL;
503255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
504255e72915d4cbddceb435e13d81601755714e9fSE Android			}
505255e72915d4cbddceb435e13d81601755714e9fSE Android			seen |= SEEN_FC;
506255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
507255e72915d4cbddceb435e13d81601755714e9fSE Android		case SEPOL_PACKAGE_SECTION_SEUSER:
508255e72915d4cbddceb435e13d81601755714e9fSE Android			if (seen & SEEN_SEUSER) {
509255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
510255e72915d4cbddceb435e13d81601755714e9fSE Android				    "found multiple seuser sections in module package (at section %u)",
511255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
512255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
513255e72915d4cbddceb435e13d81601755714e9fSE Android			}
514255e72915d4cbddceb435e13d81601755714e9fSE Android
515255e72915d4cbddceb435e13d81601755714e9fSE Android			mod->seusers_len = len - sizeof(uint32_t);
516255e72915d4cbddceb435e13d81601755714e9fSE Android			mod->seusers = (char *)malloc(mod->seusers_len);
517255e72915d4cbddceb435e13d81601755714e9fSE Android			if (!mod->seusers) {
518255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle, "out of memory");
519255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
520255e72915d4cbddceb435e13d81601755714e9fSE Android			}
521255e72915d4cbddceb435e13d81601755714e9fSE Android			if (read_helper(mod->seusers, file, mod->seusers_len)) {
522255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
523255e72915d4cbddceb435e13d81601755714e9fSE Android				    "invalid seuser section at section %u", i);
524255e72915d4cbddceb435e13d81601755714e9fSE Android				free(mod->seusers);
525255e72915d4cbddceb435e13d81601755714e9fSE Android				mod->seusers = NULL;
526255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
527255e72915d4cbddceb435e13d81601755714e9fSE Android			}
528255e72915d4cbddceb435e13d81601755714e9fSE Android			seen |= SEEN_SEUSER;
529255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
530255e72915d4cbddceb435e13d81601755714e9fSE Android		case SEPOL_PACKAGE_SECTION_USER_EXTRA:
531255e72915d4cbddceb435e13d81601755714e9fSE Android			if (seen & SEEN_USER_EXTRA) {
532255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
533255e72915d4cbddceb435e13d81601755714e9fSE Android				    "found multiple user_extra sections in module package (at section %u)",
534255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
535255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
536255e72915d4cbddceb435e13d81601755714e9fSE Android			}
537255e72915d4cbddceb435e13d81601755714e9fSE Android
538255e72915d4cbddceb435e13d81601755714e9fSE Android			mod->user_extra_len = len - sizeof(uint32_t);
539255e72915d4cbddceb435e13d81601755714e9fSE Android			mod->user_extra = (char *)malloc(mod->user_extra_len);
540255e72915d4cbddceb435e13d81601755714e9fSE Android			if (!mod->user_extra) {
541255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle, "out of memory");
542255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
543255e72915d4cbddceb435e13d81601755714e9fSE Android			}
544255e72915d4cbddceb435e13d81601755714e9fSE Android			if (read_helper
545255e72915d4cbddceb435e13d81601755714e9fSE Android			    (mod->user_extra, file, mod->user_extra_len)) {
546255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
547255e72915d4cbddceb435e13d81601755714e9fSE Android				    "invalid user_extra section at section %u",
548255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
549255e72915d4cbddceb435e13d81601755714e9fSE Android				free(mod->user_extra);
550255e72915d4cbddceb435e13d81601755714e9fSE Android				mod->user_extra = NULL;
551255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
552255e72915d4cbddceb435e13d81601755714e9fSE Android			}
553255e72915d4cbddceb435e13d81601755714e9fSE Android			seen |= SEEN_USER_EXTRA;
554255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
555255e72915d4cbddceb435e13d81601755714e9fSE Android		case SEPOL_PACKAGE_SECTION_NETFILTER:
556255e72915d4cbddceb435e13d81601755714e9fSE Android			if (seen & SEEN_NETFILTER) {
557255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
558255e72915d4cbddceb435e13d81601755714e9fSE Android				    "found multiple netfilter contexts sections in module package (at section %u)",
559255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
560255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
561255e72915d4cbddceb435e13d81601755714e9fSE Android			}
562255e72915d4cbddceb435e13d81601755714e9fSE Android
563255e72915d4cbddceb435e13d81601755714e9fSE Android			mod->netfilter_contexts_len = len - sizeof(uint32_t);
564255e72915d4cbddceb435e13d81601755714e9fSE Android			mod->netfilter_contexts =
565255e72915d4cbddceb435e13d81601755714e9fSE Android			    (char *)malloc(mod->netfilter_contexts_len);
566255e72915d4cbddceb435e13d81601755714e9fSE Android			if (!mod->netfilter_contexts) {
567255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle, "out of memory");
568255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
569255e72915d4cbddceb435e13d81601755714e9fSE Android			}
570255e72915d4cbddceb435e13d81601755714e9fSE Android			if (read_helper
571255e72915d4cbddceb435e13d81601755714e9fSE Android			    (mod->netfilter_contexts, file,
572255e72915d4cbddceb435e13d81601755714e9fSE Android			     mod->netfilter_contexts_len)) {
573255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
574255e72915d4cbddceb435e13d81601755714e9fSE Android				    "invalid netfilter contexts section at section %u",
575255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
576255e72915d4cbddceb435e13d81601755714e9fSE Android				free(mod->netfilter_contexts);
577255e72915d4cbddceb435e13d81601755714e9fSE Android				mod->netfilter_contexts = NULL;
578255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
579255e72915d4cbddceb435e13d81601755714e9fSE Android			}
580255e72915d4cbddceb435e13d81601755714e9fSE Android			seen |= SEEN_NETFILTER;
581255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
582255e72915d4cbddceb435e13d81601755714e9fSE Android		case POLICYDB_MOD_MAGIC:
583255e72915d4cbddceb435e13d81601755714e9fSE Android			if (seen & SEEN_MOD) {
584255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
585255e72915d4cbddceb435e13d81601755714e9fSE Android				    "found multiple module sections in module package (at section %u)",
586255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
587255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
588255e72915d4cbddceb435e13d81601755714e9fSE Android			}
589255e72915d4cbddceb435e13d81601755714e9fSE Android
590255e72915d4cbddceb435e13d81601755714e9fSE Android			/* seek back to where the magic number was */
591255e72915d4cbddceb435e13d81601755714e9fSE Android			if (policy_file_seek(file, offsets[i]))
592255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
593255e72915d4cbddceb435e13d81601755714e9fSE Android
594255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = policydb_read(&mod->policy->p, file, verbose);
595255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc < 0) {
596255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
597255e72915d4cbddceb435e13d81601755714e9fSE Android				    "invalid module in module package (at section %u)",
598255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
599255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
600255e72915d4cbddceb435e13d81601755714e9fSE Android			}
601255e72915d4cbddceb435e13d81601755714e9fSE Android			seen |= SEEN_MOD;
602255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
603255e72915d4cbddceb435e13d81601755714e9fSE Android		default:
604255e72915d4cbddceb435e13d81601755714e9fSE Android			/* unknown section, ignore */
605255e72915d4cbddceb435e13d81601755714e9fSE Android			ERR(file->handle,
606255e72915d4cbddceb435e13d81601755714e9fSE Android			    "unknown magic number at section %u, offset: %zx, number: %ux ",
607255e72915d4cbddceb435e13d81601755714e9fSE Android			    i, offsets[i], le32_to_cpu(buf[0]));
608255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
609255e72915d4cbddceb435e13d81601755714e9fSE Android		}
610255e72915d4cbddceb435e13d81601755714e9fSE Android	}
611255e72915d4cbddceb435e13d81601755714e9fSE Android
612255e72915d4cbddceb435e13d81601755714e9fSE Android	if ((seen & SEEN_MOD) == 0) {
613255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(file->handle, "missing module in module package");
614255e72915d4cbddceb435e13d81601755714e9fSE Android		goto cleanup;
615255e72915d4cbddceb435e13d81601755714e9fSE Android	}
616255e72915d4cbddceb435e13d81601755714e9fSE Android
617255e72915d4cbddceb435e13d81601755714e9fSE Android	free(offsets);
618255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
619255e72915d4cbddceb435e13d81601755714e9fSE Android
620255e72915d4cbddceb435e13d81601755714e9fSE Android      cleanup:
621255e72915d4cbddceb435e13d81601755714e9fSE Android	free(offsets);
622255e72915d4cbddceb435e13d81601755714e9fSE Android	return -1;
623255e72915d4cbddceb435e13d81601755714e9fSE Android}
624255e72915d4cbddceb435e13d81601755714e9fSE Android
625255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_module_package_info(struct sepol_policy_file *spf, int *type,
626255e72915d4cbddceb435e13d81601755714e9fSE Android			      char **name, char **version)
627255e72915d4cbddceb435e13d81601755714e9fSE Android{
628255e72915d4cbddceb435e13d81601755714e9fSE Android	struct policy_file *file = &spf->pf;
629255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_module_package_t *mod = NULL;
630255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t buf[5], len, nsec;
631255e72915d4cbddceb435e13d81601755714e9fSE Android	size_t *offsets = NULL;
632255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned i, seen = 0;
633255e72915d4cbddceb435e13d81601755714e9fSE Android	char *id;
634255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc;
635255e72915d4cbddceb435e13d81601755714e9fSE Android
636255e72915d4cbddceb435e13d81601755714e9fSE Android	if (sepol_module_package_create(&mod))
637255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
638255e72915d4cbddceb435e13d81601755714e9fSE Android
639255e72915d4cbddceb435e13d81601755714e9fSE Android	if (module_package_read_offsets(mod, file, &offsets, &nsec)) {
640255e72915d4cbddceb435e13d81601755714e9fSE Android		goto cleanup;
641255e72915d4cbddceb435e13d81601755714e9fSE Android	}
642255e72915d4cbddceb435e13d81601755714e9fSE Android
643255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < nsec; i++) {
644255e72915d4cbddceb435e13d81601755714e9fSE Android
645255e72915d4cbddceb435e13d81601755714e9fSE Android		if (policy_file_seek(file, offsets[i])) {
646255e72915d4cbddceb435e13d81601755714e9fSE Android			ERR(file->handle, "error seeking to offset "
647255e72915d4cbddceb435e13d81601755714e9fSE Android			    "%zu for module package section %u", offsets[i], i);
648255e72915d4cbddceb435e13d81601755714e9fSE Android			goto cleanup;
649255e72915d4cbddceb435e13d81601755714e9fSE Android		}
650255e72915d4cbddceb435e13d81601755714e9fSE Android
651255e72915d4cbddceb435e13d81601755714e9fSE Android		len = offsets[i + 1] - offsets[i];
652255e72915d4cbddceb435e13d81601755714e9fSE Android
653255e72915d4cbddceb435e13d81601755714e9fSE Android		if (len < sizeof(uint32_t)) {
654255e72915d4cbddceb435e13d81601755714e9fSE Android			ERR(file->handle,
655255e72915d4cbddceb435e13d81601755714e9fSE Android			    "module package section %u has too small length %u",
656255e72915d4cbddceb435e13d81601755714e9fSE Android			    i, len);
657255e72915d4cbddceb435e13d81601755714e9fSE Android			goto cleanup;
658255e72915d4cbddceb435e13d81601755714e9fSE Android		}
659255e72915d4cbddceb435e13d81601755714e9fSE Android
660255e72915d4cbddceb435e13d81601755714e9fSE Android		/* read the magic number, so that we know which function to call */
661255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = next_entry(buf, file, sizeof(uint32_t) * 2);
662255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc < 0) {
663255e72915d4cbddceb435e13d81601755714e9fSE Android			ERR(file->handle,
664255e72915d4cbddceb435e13d81601755714e9fSE Android			    "module package section %u truncated, lacks magic number",
665255e72915d4cbddceb435e13d81601755714e9fSE Android			    i);
666255e72915d4cbddceb435e13d81601755714e9fSE Android			goto cleanup;
667255e72915d4cbddceb435e13d81601755714e9fSE Android		}
668255e72915d4cbddceb435e13d81601755714e9fSE Android
669255e72915d4cbddceb435e13d81601755714e9fSE Android		switch (le32_to_cpu(buf[0])) {
670255e72915d4cbddceb435e13d81601755714e9fSE Android		case SEPOL_PACKAGE_SECTION_FC:
671255e72915d4cbddceb435e13d81601755714e9fSE Android			/* skip file contexts */
672255e72915d4cbddceb435e13d81601755714e9fSE Android			if (seen & SEEN_FC) {
673255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
674255e72915d4cbddceb435e13d81601755714e9fSE Android				    "found multiple file contexts sections in module package (at section %u)",
675255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
676255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
677255e72915d4cbddceb435e13d81601755714e9fSE Android			}
678255e72915d4cbddceb435e13d81601755714e9fSE Android			seen |= SEEN_FC;
679255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
680255e72915d4cbddceb435e13d81601755714e9fSE Android		case SEPOL_PACKAGE_SECTION_SEUSER:
681255e72915d4cbddceb435e13d81601755714e9fSE Android			/* skip seuser */
682255e72915d4cbddceb435e13d81601755714e9fSE Android			if (seen & SEEN_SEUSER) {
683255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
684255e72915d4cbddceb435e13d81601755714e9fSE Android				    "found seuser sections in module package (at section %u)",
685255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
686255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
687255e72915d4cbddceb435e13d81601755714e9fSE Android			}
688255e72915d4cbddceb435e13d81601755714e9fSE Android			seen |= SEEN_SEUSER;
689255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
690255e72915d4cbddceb435e13d81601755714e9fSE Android		case SEPOL_PACKAGE_SECTION_USER_EXTRA:
691255e72915d4cbddceb435e13d81601755714e9fSE Android			/* skip user_extra */
692255e72915d4cbddceb435e13d81601755714e9fSE Android			if (seen & SEEN_USER_EXTRA) {
693255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
694255e72915d4cbddceb435e13d81601755714e9fSE Android				    "found user_extra sections in module package (at section %u)",
695255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
696255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
697255e72915d4cbddceb435e13d81601755714e9fSE Android			}
698255e72915d4cbddceb435e13d81601755714e9fSE Android			seen |= SEEN_USER_EXTRA;
699255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
700255e72915d4cbddceb435e13d81601755714e9fSE Android		case SEPOL_PACKAGE_SECTION_NETFILTER:
701255e72915d4cbddceb435e13d81601755714e9fSE Android			/* skip netfilter contexts */
702255e72915d4cbddceb435e13d81601755714e9fSE Android			if (seen & SEEN_NETFILTER) {
703255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
704255e72915d4cbddceb435e13d81601755714e9fSE Android				    "found multiple netfilter contexts sections in module package (at section %u)",
705255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
706255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
707255e72915d4cbddceb435e13d81601755714e9fSE Android			}
708255e72915d4cbddceb435e13d81601755714e9fSE Android			seen |= SEEN_NETFILTER;
709255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
710255e72915d4cbddceb435e13d81601755714e9fSE Android		case POLICYDB_MOD_MAGIC:
711255e72915d4cbddceb435e13d81601755714e9fSE Android			if (seen & SEEN_MOD) {
712255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
713255e72915d4cbddceb435e13d81601755714e9fSE Android				    "found multiple module sections in module package (at section %u)",
714255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
715255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
716255e72915d4cbddceb435e13d81601755714e9fSE Android			}
717255e72915d4cbddceb435e13d81601755714e9fSE Android			len = le32_to_cpu(buf[1]);
718255e72915d4cbddceb435e13d81601755714e9fSE Android			if (len != strlen(POLICYDB_MOD_STRING)) {
719255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
720255e72915d4cbddceb435e13d81601755714e9fSE Android				    "module string length is wrong (at section %u)",
721255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
722255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
723255e72915d4cbddceb435e13d81601755714e9fSE Android			}
724255e72915d4cbddceb435e13d81601755714e9fSE Android
725255e72915d4cbddceb435e13d81601755714e9fSE Android			/* skip id */
726255e72915d4cbddceb435e13d81601755714e9fSE Android			id = malloc(len + 1);
727255e72915d4cbddceb435e13d81601755714e9fSE Android			if (!id) {
728255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
729255e72915d4cbddceb435e13d81601755714e9fSE Android				    "out of memory (at section %u)",
730255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
731255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
732255e72915d4cbddceb435e13d81601755714e9fSE Android			}
733255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = next_entry(id, file, len);
734255e72915d4cbddceb435e13d81601755714e9fSE Android			free(id);
735255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc < 0) {
736255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
737255e72915d4cbddceb435e13d81601755714e9fSE Android				    "cannot get module string (at section %u)",
738255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
739255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
740255e72915d4cbddceb435e13d81601755714e9fSE Android			}
741255e72915d4cbddceb435e13d81601755714e9fSE Android
742255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = next_entry(buf, file, sizeof(uint32_t) * 5);
743255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc < 0) {
744255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
745255e72915d4cbddceb435e13d81601755714e9fSE Android				    "cannot get module header (at section %u)",
746255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
747255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
748255e72915d4cbddceb435e13d81601755714e9fSE Android			}
749255e72915d4cbddceb435e13d81601755714e9fSE Android
750255e72915d4cbddceb435e13d81601755714e9fSE Android			*type = le32_to_cpu(buf[0]);
751255e72915d4cbddceb435e13d81601755714e9fSE Android			/* if base - we're done */
752255e72915d4cbddceb435e13d81601755714e9fSE Android			if (*type == POLICY_BASE) {
753255e72915d4cbddceb435e13d81601755714e9fSE Android				*name = NULL;
754255e72915d4cbddceb435e13d81601755714e9fSE Android				*version = NULL;
755255e72915d4cbddceb435e13d81601755714e9fSE Android				seen |= SEEN_MOD;
756255e72915d4cbddceb435e13d81601755714e9fSE Android				break;
757255e72915d4cbddceb435e13d81601755714e9fSE Android			} else if (*type != POLICY_MOD) {
758255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
759255e72915d4cbddceb435e13d81601755714e9fSE Android				    "module has invalid type %d (at section %u)",
760255e72915d4cbddceb435e13d81601755714e9fSE Android				    *type, i);
761255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
762255e72915d4cbddceb435e13d81601755714e9fSE Android			}
763255e72915d4cbddceb435e13d81601755714e9fSE Android
764255e72915d4cbddceb435e13d81601755714e9fSE Android			/* read the name and version */
765255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = next_entry(buf, file, sizeof(uint32_t));
766255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc < 0) {
767255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
768255e72915d4cbddceb435e13d81601755714e9fSE Android				    "cannot get module name len (at section %u)",
769255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
770255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
771255e72915d4cbddceb435e13d81601755714e9fSE Android			}
772255e72915d4cbddceb435e13d81601755714e9fSE Android			len = le32_to_cpu(buf[0]);
773255e72915d4cbddceb435e13d81601755714e9fSE Android			*name = malloc(len + 1);
774255e72915d4cbddceb435e13d81601755714e9fSE Android			if (!*name) {
775255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle, "out of memory");
776255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
777255e72915d4cbddceb435e13d81601755714e9fSE Android			}
778255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = next_entry(*name, file, len);
779255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc < 0) {
780255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
781255e72915d4cbddceb435e13d81601755714e9fSE Android				    "cannot get module name string (at section %u)",
782255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
783255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
784255e72915d4cbddceb435e13d81601755714e9fSE Android			}
785255e72915d4cbddceb435e13d81601755714e9fSE Android			(*name)[len] = '\0';
786255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = next_entry(buf, file, sizeof(uint32_t));
787255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc < 0) {
788255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
789255e72915d4cbddceb435e13d81601755714e9fSE Android				    "cannot get module version len (at section %u)",
790255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
791255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
792255e72915d4cbddceb435e13d81601755714e9fSE Android			}
793255e72915d4cbddceb435e13d81601755714e9fSE Android			len = le32_to_cpu(buf[0]);
794255e72915d4cbddceb435e13d81601755714e9fSE Android			*version = malloc(len + 1);
795255e72915d4cbddceb435e13d81601755714e9fSE Android			if (!*version) {
796255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle, "out of memory");
797255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
798255e72915d4cbddceb435e13d81601755714e9fSE Android			}
799255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = next_entry(*version, file, len);
800255e72915d4cbddceb435e13d81601755714e9fSE Android			if (rc < 0) {
801255e72915d4cbddceb435e13d81601755714e9fSE Android				ERR(file->handle,
802255e72915d4cbddceb435e13d81601755714e9fSE Android				    "cannot get module version string (at section %u)",
803255e72915d4cbddceb435e13d81601755714e9fSE Android				    i);
804255e72915d4cbddceb435e13d81601755714e9fSE Android				goto cleanup;
805255e72915d4cbddceb435e13d81601755714e9fSE Android			}
806255e72915d4cbddceb435e13d81601755714e9fSE Android			(*version)[len] = '\0';
807255e72915d4cbddceb435e13d81601755714e9fSE Android			seen |= SEEN_MOD;
808255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
809255e72915d4cbddceb435e13d81601755714e9fSE Android		default:
810255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
811255e72915d4cbddceb435e13d81601755714e9fSE Android		}
812255e72915d4cbddceb435e13d81601755714e9fSE Android
813255e72915d4cbddceb435e13d81601755714e9fSE Android	}
814255e72915d4cbddceb435e13d81601755714e9fSE Android
815255e72915d4cbddceb435e13d81601755714e9fSE Android	if ((seen & SEEN_MOD) == 0) {
816255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(file->handle, "missing module in module package");
817255e72915d4cbddceb435e13d81601755714e9fSE Android		goto cleanup;
818255e72915d4cbddceb435e13d81601755714e9fSE Android	}
819255e72915d4cbddceb435e13d81601755714e9fSE Android
820255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_module_package_free(mod);
821255e72915d4cbddceb435e13d81601755714e9fSE Android	free(offsets);
822255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
823255e72915d4cbddceb435e13d81601755714e9fSE Android
824255e72915d4cbddceb435e13d81601755714e9fSE Android      cleanup:
825255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_module_package_free(mod);
826255e72915d4cbddceb435e13d81601755714e9fSE Android	free(offsets);
827255e72915d4cbddceb435e13d81601755714e9fSE Android	return -1;
828255e72915d4cbddceb435e13d81601755714e9fSE Android}
829255e72915d4cbddceb435e13d81601755714e9fSE Android
830255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int write_helper(char *data, size_t len, struct policy_file *file)
831255e72915d4cbddceb435e13d81601755714e9fSE Android{
832255e72915d4cbddceb435e13d81601755714e9fSE Android	int idx = 0;
833255e72915d4cbddceb435e13d81601755714e9fSE Android	size_t len2;
834255e72915d4cbddceb435e13d81601755714e9fSE Android
835255e72915d4cbddceb435e13d81601755714e9fSE Android	while (len) {
836255e72915d4cbddceb435e13d81601755714e9fSE Android		if (len > BUFSIZ)
837255e72915d4cbddceb435e13d81601755714e9fSE Android			len2 = BUFSIZ;
838255e72915d4cbddceb435e13d81601755714e9fSE Android		else
839255e72915d4cbddceb435e13d81601755714e9fSE Android			len2 = len;
840255e72915d4cbddceb435e13d81601755714e9fSE Android
841255e72915d4cbddceb435e13d81601755714e9fSE Android		if (put_entry(&data[idx], 1, len2, file) != len2) {
842255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
843255e72915d4cbddceb435e13d81601755714e9fSE Android		}
844255e72915d4cbddceb435e13d81601755714e9fSE Android		len -= len2;
845255e72915d4cbddceb435e13d81601755714e9fSE Android		idx += len2;
846255e72915d4cbddceb435e13d81601755714e9fSE Android	}
847255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
848255e72915d4cbddceb435e13d81601755714e9fSE Android}
849255e72915d4cbddceb435e13d81601755714e9fSE Android
850255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_module_package_write(sepol_module_package_t * p,
851255e72915d4cbddceb435e13d81601755714e9fSE Android			       struct sepol_policy_file *spf)
852255e72915d4cbddceb435e13d81601755714e9fSE Android{
853255e72915d4cbddceb435e13d81601755714e9fSE Android	struct policy_file *file = &spf->pf;
854255e72915d4cbddceb435e13d81601755714e9fSE Android	policy_file_t polfile;
855255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t buf[5], offsets[5], len, nsec = 0;
856255e72915d4cbddceb435e13d81601755714e9fSE Android	int i;
857255e72915d4cbddceb435e13d81601755714e9fSE Android
858255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->policy) {
859255e72915d4cbddceb435e13d81601755714e9fSE Android		/* compute policy length */
860255e72915d4cbddceb435e13d81601755714e9fSE Android		policy_file_init(&polfile);
861255e72915d4cbddceb435e13d81601755714e9fSE Android		polfile.type = PF_LEN;
862255e72915d4cbddceb435e13d81601755714e9fSE Android		polfile.handle = file->handle;
863255e72915d4cbddceb435e13d81601755714e9fSE Android		if (policydb_write(&p->policy->p, &polfile))
864255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
865255e72915d4cbddceb435e13d81601755714e9fSE Android		len = polfile.len;
866255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!polfile.len)
867255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
868255e72915d4cbddceb435e13d81601755714e9fSE Android		nsec++;
869255e72915d4cbddceb435e13d81601755714e9fSE Android
870255e72915d4cbddceb435e13d81601755714e9fSE Android	} else {
871255e72915d4cbddceb435e13d81601755714e9fSE Android		/* We don't support writing a package without a module at this point */
872255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
873255e72915d4cbddceb435e13d81601755714e9fSE Android	}
874255e72915d4cbddceb435e13d81601755714e9fSE Android
875255e72915d4cbddceb435e13d81601755714e9fSE Android	/* seusers and user_extra only supported in base at the moment */
876255e72915d4cbddceb435e13d81601755714e9fSE Android	if ((p->seusers || p->user_extra)
877255e72915d4cbddceb435e13d81601755714e9fSE Android	    && (p->policy->p.policy_type != SEPOL_POLICY_BASE)) {
878255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(file->handle,
879255e72915d4cbddceb435e13d81601755714e9fSE Android		    "seuser and user_extra sections only supported in base");
880255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
881255e72915d4cbddceb435e13d81601755714e9fSE Android	}
882255e72915d4cbddceb435e13d81601755714e9fSE Android
883255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->file_contexts)
884255e72915d4cbddceb435e13d81601755714e9fSE Android		nsec++;
885255e72915d4cbddceb435e13d81601755714e9fSE Android
886255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->seusers)
887255e72915d4cbddceb435e13d81601755714e9fSE Android		nsec++;
888255e72915d4cbddceb435e13d81601755714e9fSE Android
889255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->user_extra)
890255e72915d4cbddceb435e13d81601755714e9fSE Android		nsec++;
891255e72915d4cbddceb435e13d81601755714e9fSE Android
892255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->netfilter_contexts)
893255e72915d4cbddceb435e13d81601755714e9fSE Android		nsec++;
894255e72915d4cbddceb435e13d81601755714e9fSE Android
895255e72915d4cbddceb435e13d81601755714e9fSE Android	buf[0] = cpu_to_le32(SEPOL_MODULE_PACKAGE_MAGIC);
896255e72915d4cbddceb435e13d81601755714e9fSE Android	buf[1] = cpu_to_le32(p->version);
897255e72915d4cbddceb435e13d81601755714e9fSE Android	buf[2] = cpu_to_le32(nsec);
898255e72915d4cbddceb435e13d81601755714e9fSE Android	if (put_entry(buf, sizeof(uint32_t), 3, file) != 3)
899255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
900255e72915d4cbddceb435e13d81601755714e9fSE Android
901255e72915d4cbddceb435e13d81601755714e9fSE Android	/* calculate offsets */
902255e72915d4cbddceb435e13d81601755714e9fSE Android	offsets[0] = (nsec + 3) * sizeof(uint32_t);
903255e72915d4cbddceb435e13d81601755714e9fSE Android	buf[0] = cpu_to_le32(offsets[0]);
904255e72915d4cbddceb435e13d81601755714e9fSE Android
905255e72915d4cbddceb435e13d81601755714e9fSE Android	i = 1;
906255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->file_contexts) {
907255e72915d4cbddceb435e13d81601755714e9fSE Android		offsets[i] = offsets[i - 1] + len;
908255e72915d4cbddceb435e13d81601755714e9fSE Android		buf[i] = cpu_to_le32(offsets[i]);
909255e72915d4cbddceb435e13d81601755714e9fSE Android		/* add a uint32_t to compensate for the magic number */
910255e72915d4cbddceb435e13d81601755714e9fSE Android		len = p->file_contexts_len + sizeof(uint32_t);
911255e72915d4cbddceb435e13d81601755714e9fSE Android		i++;
912255e72915d4cbddceb435e13d81601755714e9fSE Android	}
913255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->seusers) {
914255e72915d4cbddceb435e13d81601755714e9fSE Android		offsets[i] = offsets[i - 1] + len;
915255e72915d4cbddceb435e13d81601755714e9fSE Android		buf[i] = cpu_to_le32(offsets[i]);
916255e72915d4cbddceb435e13d81601755714e9fSE Android		len = p->seusers_len + sizeof(uint32_t);
917255e72915d4cbddceb435e13d81601755714e9fSE Android		i++;
918255e72915d4cbddceb435e13d81601755714e9fSE Android	}
919255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->user_extra) {
920255e72915d4cbddceb435e13d81601755714e9fSE Android		offsets[i] = offsets[i - 1] + len;
921255e72915d4cbddceb435e13d81601755714e9fSE Android		buf[i] = cpu_to_le32(offsets[i]);
922255e72915d4cbddceb435e13d81601755714e9fSE Android		len = p->user_extra_len + sizeof(uint32_t);
923255e72915d4cbddceb435e13d81601755714e9fSE Android		i++;
924255e72915d4cbddceb435e13d81601755714e9fSE Android	}
925255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->netfilter_contexts) {
926255e72915d4cbddceb435e13d81601755714e9fSE Android		offsets[i] = offsets[i - 1] + len;
927255e72915d4cbddceb435e13d81601755714e9fSE Android		buf[i] = cpu_to_le32(offsets[i]);
928255e72915d4cbddceb435e13d81601755714e9fSE Android		len = p->netfilter_contexts_len + sizeof(uint32_t);
929255e72915d4cbddceb435e13d81601755714e9fSE Android		i++;
930255e72915d4cbddceb435e13d81601755714e9fSE Android	}
931255e72915d4cbddceb435e13d81601755714e9fSE Android	if (put_entry(buf, sizeof(uint32_t), nsec, file) != nsec)
932255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
933255e72915d4cbddceb435e13d81601755714e9fSE Android
934255e72915d4cbddceb435e13d81601755714e9fSE Android	/* write sections */
935255e72915d4cbddceb435e13d81601755714e9fSE Android
936255e72915d4cbddceb435e13d81601755714e9fSE Android	if (policydb_write(&p->policy->p, file))
937255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
938255e72915d4cbddceb435e13d81601755714e9fSE Android
939255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->file_contexts) {
940255e72915d4cbddceb435e13d81601755714e9fSE Android		buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_FC);
941255e72915d4cbddceb435e13d81601755714e9fSE Android		if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
942255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
943255e72915d4cbddceb435e13d81601755714e9fSE Android		if (write_helper(p->file_contexts, p->file_contexts_len, file))
944255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
945255e72915d4cbddceb435e13d81601755714e9fSE Android	}
946255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->seusers) {
947255e72915d4cbddceb435e13d81601755714e9fSE Android		buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_SEUSER);
948255e72915d4cbddceb435e13d81601755714e9fSE Android		if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
949255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
950255e72915d4cbddceb435e13d81601755714e9fSE Android		if (write_helper(p->seusers, p->seusers_len, file))
951255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
952255e72915d4cbddceb435e13d81601755714e9fSE Android
953255e72915d4cbddceb435e13d81601755714e9fSE Android	}
954255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->user_extra) {
955255e72915d4cbddceb435e13d81601755714e9fSE Android		buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_USER_EXTRA);
956255e72915d4cbddceb435e13d81601755714e9fSE Android		if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
957255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
958255e72915d4cbddceb435e13d81601755714e9fSE Android		if (write_helper(p->user_extra, p->user_extra_len, file))
959255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
960255e72915d4cbddceb435e13d81601755714e9fSE Android	}
961255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->netfilter_contexts) {
962255e72915d4cbddceb435e13d81601755714e9fSE Android		buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_NETFILTER);
963255e72915d4cbddceb435e13d81601755714e9fSE Android		if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
964255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
965255e72915d4cbddceb435e13d81601755714e9fSE Android		if (write_helper
966255e72915d4cbddceb435e13d81601755714e9fSE Android		    (p->netfilter_contexts, p->netfilter_contexts_len, file))
967255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
968255e72915d4cbddceb435e13d81601755714e9fSE Android	}
969255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
970255e72915d4cbddceb435e13d81601755714e9fSE Android}
971255e72915d4cbddceb435e13d81601755714e9fSE Android
972255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_link_modules(sepol_handle_t * handle,
973255e72915d4cbddceb435e13d81601755714e9fSE Android		       sepol_policydb_t * base,
974255e72915d4cbddceb435e13d81601755714e9fSE Android		       sepol_policydb_t ** modules, size_t len, int verbose)
975255e72915d4cbddceb435e13d81601755714e9fSE Android{
976255e72915d4cbddceb435e13d81601755714e9fSE Android	return link_modules(handle, &base->p, (policydb_t **) modules, len,
977255e72915d4cbddceb435e13d81601755714e9fSE Android			    verbose);
978255e72915d4cbddceb435e13d81601755714e9fSE Android}
979255e72915d4cbddceb435e13d81601755714e9fSE Android
980255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_expand_module(sepol_handle_t * handle,
981255e72915d4cbddceb435e13d81601755714e9fSE Android			sepol_policydb_t * base,
982255e72915d4cbddceb435e13d81601755714e9fSE Android			sepol_policydb_t * out, int verbose, int check)
983255e72915d4cbddceb435e13d81601755714e9fSE Android{
984255e72915d4cbddceb435e13d81601755714e9fSE Android	return expand_module(handle, &base->p, &out->p, verbose, check);
985255e72915d4cbddceb435e13d81601755714e9fSE Android}
986