113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Author: Karl MacMillan <kmacmillan@tresys.com>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *         Jason Tang     <jtang@tresys.com>
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *         Chris PeBenito <cpebenito@tresys.com>
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Copyright (C) 2004-2005 Tresys Technology, LLC
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  This library is free software; you can redistribute it and/or
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  modify it under the terms of the GNU Lesser General Public
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  License as published by the Free Software Foundation; either
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  version 2.1 of the License, or (at your option) any later version.
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  This library is distributed in the hope that it will be useful,
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  Lesser General Public License for more details.
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  You should have received a copy of the GNU Lesser General Public
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  License along with this library; if not, write to the Free Software
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "policydb_internal.h"
2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "module_internal.h"
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/link.h>
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/expand.h>
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/module.h>
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "debug.h"
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "private.h"
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h>
3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <limits.h>
3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define SEPOL_PACKAGE_SECTION_FC 0xf97cff90
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define SEPOL_PACKAGE_SECTION_SEUSER 0x97cff91
3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define SEPOL_PACKAGE_SECTION_USER_EXTRA 0x97cff92
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define SEPOL_PACKAGE_SECTION_NETFILTER 0x97cff93
3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int policy_file_seek(struct policy_file *fp, size_t offset)
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (fp->type) {
4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case PF_USE_STDIO:
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (offset > LONG_MAX) {
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			errno = EFAULT;
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return fseek(fp->fp, (long)offset, SEEK_SET);
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case PF_USE_MEMORY:
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (offset > fp->size) {
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			errno = EFAULT;
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fp->data -= fp->size - fp->len;
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fp->data += offset;
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fp->len = fp->size - offset;
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
62afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Parisstatic int policy_file_length(struct policy_file *fp, size_t *out)
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	long prev_offset, end_offset;
65afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris	int rc;
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (fp->type) {
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case PF_USE_STDIO:
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		prev_offset = ftell(fp->fp);
69afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		if (prev_offset < 0)
70afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			return prev_offset;
71afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		rc = fseek(fp->fp, 0L, SEEK_END);
72afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		if (rc < 0)
73afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			return rc;
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		end_offset = ftell(fp->fp);
75afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		if (end_offset < 0)
76afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			return end_offset;
77afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		rc = fseek(fp->fp, prev_offset, SEEK_SET);
78afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		if (rc < 0)
79afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris			return rc;
80afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		*out = end_offset;
81afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		break;
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case PF_USE_MEMORY:
83afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		*out = fp->size;
84afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		break;;
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:
86afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		*out = 0;
87afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		break;
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
89afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris	return 0;
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int module_package_init(sepol_module_package_t * p)
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(p, 0, sizeof(sepol_module_package_t));
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_policydb_create(&p->policy))
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	p->version = 1;
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int set_char(char **field, char *data, size_t len)
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (*field) {
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(*field);
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*field = NULL;
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (len) {
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*field = malloc(len);
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!*field)
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memcpy(*field, data, len);
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_module_package_create(sepol_module_package_t ** p)
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
119afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris	int rc;
120afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*p = calloc(1, sizeof(sepol_module_package_t));
12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!(*p))
12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
124afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris
125afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris	rc = module_package_init(*p);
126afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris	if (rc < 0)
127afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		free(*p);
128afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris
129afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris	return rc;
13013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
13113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlehidden_def(sepol_module_package_create)
13313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Deallocates all memory associated with a module package, including
13513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * the pointer itself.  Does nothing if p is NULL.
13613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
13713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlevoid sepol_module_package_free(sepol_module_package_t * p)
13813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
13913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p == NULL)
14013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return;
14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_policydb_free(p->policy);
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(p->file_contexts);
14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(p->seusers);
14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(p->user_extra);
14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(p->netfilter_contexts);
14713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(p);
14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlehidden_def(sepol_module_package_free)
15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlechar *sepol_module_package_get_file_contexts(sepol_module_package_t * p)
15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return p->file_contexts;
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlesize_t sepol_module_package_get_file_contexts_len(sepol_module_package_t * p)
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return p->file_contexts_len;
16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlechar *sepol_module_package_get_seusers(sepol_module_package_t * p)
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return p->seusers;
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlesize_t sepol_module_package_get_seusers_len(sepol_module_package_t * p)
16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return p->seusers_len;
17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlechar *sepol_module_package_get_user_extra(sepol_module_package_t * p)
17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return p->user_extra;
17513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlesize_t sepol_module_package_get_user_extra_len(sepol_module_package_t * p)
17813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return p->user_extra_len;
18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
18113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlechar *sepol_module_package_get_netfilter_contexts(sepol_module_package_t * p)
18313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
18413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return p->netfilter_contexts;
18513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
18613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlesize_t sepol_module_package_get_netfilter_contexts_len(sepol_module_package_t *
18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						       p)
18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
19013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return p->netfilter_contexts_len;
19113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
19213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_module_package_set_file_contexts(sepol_module_package_t * p,
19413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					   char *data, size_t len)
19513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
19613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (set_char(&p->file_contexts, data, len))
19713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
19813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	p->file_contexts_len = len;
20013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
20113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
20213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_module_package_set_seusers(sepol_module_package_t * p,
20413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     char *data, size_t len)
20513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
20613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (set_char(&p->seusers, data, len))
20713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
20813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	p->seusers_len = len;
21013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
21113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
21213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_module_package_set_user_extra(sepol_module_package_t * p,
21413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					char *data, size_t len)
21513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
21613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (set_char(&p->user_extra, data, len))
21713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
21813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	p->user_extra_len = len;
22013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
22113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
22213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_module_package_set_netfilter_contexts(sepol_module_package_t * p,
22413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						char *data, size_t len)
22513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
22613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (set_char(&p->netfilter_contexts, data, len))
22713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
22813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	p->netfilter_contexts_len = len;
23013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
23113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
23213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlesepol_policydb_t *sepol_module_package_get_policy(sepol_module_package_t * p)
23413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
23513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return p->policy;
23613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
23713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Append each of the file contexts from each module to the base
23913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * policy's file context.  'base_context' will be reallocated to a
24013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * larger size (and thus it is an in/out reference
24113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * variable). 'base_fc_len' is the length of base's file context; it
24213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * too is a reference variable.  Return 0 on success, -1 if out of
24313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * memory. */
24413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int link_file_contexts(sepol_module_package_t * base,
24513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      sepol_module_package_t ** modules,
24613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      int num_modules)
24713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
24813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size_t fc_len;
24913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int i;
25013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *s;
25113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
25213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fc_len = base->file_contexts_len;
25313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < num_modules; i++) {
25413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fc_len += modules[i]->file_contexts_len;
25513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
25613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
25713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((s = (char *)realloc(base->file_contexts, fc_len)) == NULL) {
25813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
25913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
26013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	base->file_contexts = s;
26113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < num_modules; i++) {
26213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memcpy(base->file_contexts + base->file_contexts_len,
26313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		       modules[i]->file_contexts,
26413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		       modules[i]->file_contexts_len);
26513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base->file_contexts_len += modules[i]->file_contexts_len;
26613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
26713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
26813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
26913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
27013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Append each of the netfilter contexts from each module to the base
27113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * policy's netfilter context.  'base_context' will be reallocated to a
27213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * larger size (and thus it is an in/out reference
27313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * variable). 'base_nc_len' is the length of base's netfilter contexts; it
27413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * too is a reference variable.  Return 0 on success, -1 if out of
27513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * memory. */
27613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int link_netfilter_contexts(sepol_module_package_t * base,
27713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   sepol_module_package_t ** modules,
27813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   int num_modules)
27913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
28013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size_t base_nc_len;
28113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int i;
28213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *base_context;
28313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	base_nc_len = base->netfilter_contexts_len;
28513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < num_modules; i++) {
28613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base_nc_len += modules[i]->netfilter_contexts_len;
28713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
28813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((base_context =
29013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	     (char *)realloc(base->netfilter_contexts, base_nc_len)) == NULL) {
29113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
29213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
29313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	base->netfilter_contexts = base_context;
29413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < num_modules; i++) {
29513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memcpy(base->netfilter_contexts + base->netfilter_contexts_len,
29613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		       modules[i]->netfilter_contexts,
29713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		       modules[i]->netfilter_contexts_len);
29813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		base->netfilter_contexts_len +=
29913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    modules[i]->netfilter_contexts_len;
30013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
30113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
30213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
30313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
30413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Links the module packages into the base.  Returns 0 on success, -1
30513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * if a requirement was not met, or -2 for all other errors. */
30613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_link_packages(sepol_handle_t * handle,
30713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			sepol_module_package_t * base,
30813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			sepol_module_package_t ** modules, int num_modules,
30913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			int verbose)
31013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
31113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t **mod_pols = NULL;
31213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int i, retval;
31313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
31413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((mod_pols = calloc(num_modules, sizeof(*mod_pols))) == NULL) {
31513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
31613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -2;
31713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
31813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < num_modules; i++) {
31913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mod_pols[i] = &modules[i]->policy->p;
32013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
32113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
32213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = link_modules(handle, &base->policy->p, mod_pols, num_modules,
32313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      verbose);
32413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(mod_pols);
32513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval == -3) {
32613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
32713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else if (retval < 0) {
32813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -2;
32913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
33013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
33113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (link_file_contexts(base, modules, num_modules) == -1) {
33213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
33313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -2;
33413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
33513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
33613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (link_netfilter_contexts(base, modules, num_modules) == -1) {
33713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "Out of memory!");
33813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -2;
33913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
34013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
34113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
34213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
34313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
34413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* buf must be large enough - no checks are performed */
34513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define _read_helper_bufsize BUFSIZ
34613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int read_helper(char *buf, struct policy_file *file, uint32_t bytes)
34713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
34813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t offset, nel, read_len;
34913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc;
35013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
35113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	offset = 0;
35213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	nel = bytes;
35313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
35413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (nel) {
35513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (nel < _read_helper_bufsize)
35613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			read_len = nel;
35713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		else
35813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			read_len = _read_helper_bufsize;
35913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		rc = next_entry(&buf[offset], file, read_len);
36013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (rc < 0)
36113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
36213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		offset += read_len;
36313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nel -= read_len;
36413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
36513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
36613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
36713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
36813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define MAXSECTIONS 100
36913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
37013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Get the section offsets from a package file, offsets will be malloc'd to
37113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * the appropriate size and the caller must free() them */
37213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int module_package_read_offsets(sepol_module_package_t * mod,
37313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       struct policy_file *file,
37413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				       size_t ** offsets, uint32_t * sections)
37513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
37613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t *buf = NULL, nsec;
37713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned i;
37813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size_t *off = NULL;
37913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc;
38013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
38113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	buf = malloc(sizeof(uint32_t)*3);
38213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!buf) {
38313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(file->handle, "out of memory");
38413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
38513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
38613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
38713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rc = next_entry(buf, file, sizeof(uint32_t) * 3);
38813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (rc < 0) {
38913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(file->handle, "module package header truncated");
39013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
39113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
39213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (le32_to_cpu(buf[0]) != SEPOL_MODULE_PACKAGE_MAGIC) {
39313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(file->handle,
39413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    "wrong magic number for module package:  expected %#08x, got %#08x",
39513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    SEPOL_MODULE_PACKAGE_MAGIC, le32_to_cpu(buf[0]));
39613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
39713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
39813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
39913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mod->version = le32_to_cpu(buf[1]);
40013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	nsec = *sections = le32_to_cpu(buf[2]);
40113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
40213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (nsec > MAXSECTIONS) {
40313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(file->handle, "too many sections (%u) in module package",
40413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    nsec);
40513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
40613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
40713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
40813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	off = (size_t *) malloc((nsec + 1) * sizeof(size_t));
40913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!off) {
41013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(file->handle, "out of memory");
41113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
41213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
41313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
41413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(buf);
41513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	buf = malloc(sizeof(uint32_t) * nsec);
41613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!buf) {
41713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(file->handle, "out of memory");
41813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
41913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
42013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rc = next_entry(buf, file, sizeof(uint32_t) * nsec);
42113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (rc < 0) {
42213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(file->handle, "module package offset array truncated");
42313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
42413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
42513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < nsec; i++) {
42713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		off[i] = le32_to_cpu(buf[i]);
42813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (i && off[i] < off[i - 1]) {
42913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(file->handle, "offsets are not increasing (at %u, "
43013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "offset %zu -> %zu", i, off[i - 1],
43113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    off[i]);
432a0440a66c3418842f309fc4f78f2aad87ba6c96fStephen Smalley			goto err;
43313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
43413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
43513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
436afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris	rc = policy_file_length(file, &off[nsec]);
437afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris	if (rc < 0)
438afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris		goto err;
439afe88d8c69543b2ebd6e25efdaab76f40ea4d3c7Eric Paris
440a0440a66c3418842f309fc4f78f2aad87ba6c96fStephen Smalley	if (nsec && off[nsec] < off[nsec-1]) {
441a0440a66c3418842f309fc4f78f2aad87ba6c96fStephen Smalley		ERR(file->handle, "offset greater than file size (at %u, "
442a0440a66c3418842f309fc4f78f2aad87ba6c96fStephen Smalley		    "offset %zu -> %zu", nsec, off[nsec - 1],
443a0440a66c3418842f309fc4f78f2aad87ba6c96fStephen Smalley		    off[nsec]);
444a0440a66c3418842f309fc4f78f2aad87ba6c96fStephen Smalley		goto err;
445a0440a66c3418842f309fc4f78f2aad87ba6c96fStephen Smalley	}
44613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*offsets = off;
447a0440a66c3418842f309fc4f78f2aad87ba6c96fStephen Smalley	free(buf);
44813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
44913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
45013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleerr:
45113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(buf);
45213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(off);
45313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
45413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
45513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
45613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Flags for which sections have been seen during parsing of module package. */
45713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define SEEN_MOD 1
45813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define SEEN_FC  2
45913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define SEEN_SEUSER 4
46013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define SEEN_USER_EXTRA 8
46113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define SEEN_NETFILTER 16
46213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
46313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_module_package_read(sepol_module_package_t * mod,
46413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      struct sepol_policy_file *spf, int verbose)
46513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
46613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct policy_file *file = &spf->pf;
46713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t buf[1], nsec;
46813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size_t *offsets, len;
46913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc;
47013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned i, seen = 0;
47113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
47213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (module_package_read_offsets(mod, file, &offsets, &nsec))
47313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
47413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
47513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* we know the section offsets, seek to them and read in the data */
47613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
47713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < nsec; i++) {
47813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
47913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (policy_file_seek(file, offsets[i])) {
48013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(file->handle, "error seeking to offset %zu for "
48113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "module package section %u", offsets[i], i);
48213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
48313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
48413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
48513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		len = offsets[i + 1] - offsets[i];
48613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
48713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (len < sizeof(uint32_t)) {
48813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(file->handle, "module package section %u "
48913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "has too small length %zu", i, len);
49013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
49113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
49213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
49313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* read the magic number, so that we know which function to call */
49413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		rc = next_entry(buf, file, sizeof(uint32_t));
49513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (rc < 0) {
49613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(file->handle,
49713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "module package section %u truncated, lacks magic number",
49813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    i);
49913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
50013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
50113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
50213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		switch (le32_to_cpu(buf[0])) {
50313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case SEPOL_PACKAGE_SECTION_FC:
50413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (seen & SEEN_FC) {
50513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
50613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "found multiple file contexts sections in module package (at section %u)",
50713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
50813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
50913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
51013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
51113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mod->file_contexts_len = len - sizeof(uint32_t);
51213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mod->file_contexts =
51313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (char *)malloc(mod->file_contexts_len);
51413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!mod->file_contexts) {
51513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle, "out of memory");
51613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
51713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
51813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (read_helper
51913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (mod->file_contexts, file,
52013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     mod->file_contexts_len)) {
52113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
52213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "invalid file contexts section at section %u",
52313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
52413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(mod->file_contexts);
52513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				mod->file_contexts = NULL;
52613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
52713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
52813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			seen |= SEEN_FC;
52913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
53013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case SEPOL_PACKAGE_SECTION_SEUSER:
53113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (seen & SEEN_SEUSER) {
53213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
53313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "found multiple seuser sections in module package (at section %u)",
53413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
53513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
53613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
53713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
53813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mod->seusers_len = len - sizeof(uint32_t);
53913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mod->seusers = (char *)malloc(mod->seusers_len);
54013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!mod->seusers) {
54113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle, "out of memory");
54213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
54313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
54413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (read_helper(mod->seusers, file, mod->seusers_len)) {
54513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
54613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "invalid seuser section at section %u", i);
54713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(mod->seusers);
54813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				mod->seusers = NULL;
54913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
55013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
55113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			seen |= SEEN_SEUSER;
55213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
55313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case SEPOL_PACKAGE_SECTION_USER_EXTRA:
55413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (seen & SEEN_USER_EXTRA) {
55513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
55613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "found multiple user_extra sections in module package (at section %u)",
55713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
55813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
55913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
56013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
56113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mod->user_extra_len = len - sizeof(uint32_t);
56213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mod->user_extra = (char *)malloc(mod->user_extra_len);
56313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!mod->user_extra) {
56413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle, "out of memory");
56513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
56613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
56713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (read_helper
56813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (mod->user_extra, file, mod->user_extra_len)) {
56913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
57013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "invalid user_extra section at section %u",
57113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
57213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(mod->user_extra);
57313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				mod->user_extra = NULL;
57413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
57513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
57613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			seen |= SEEN_USER_EXTRA;
57713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
57813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case SEPOL_PACKAGE_SECTION_NETFILTER:
57913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (seen & SEEN_NETFILTER) {
58013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
58113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "found multiple netfilter contexts sections in module package (at section %u)",
58213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
58313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
58413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
58513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
58613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mod->netfilter_contexts_len = len - sizeof(uint32_t);
58713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mod->netfilter_contexts =
58813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (char *)malloc(mod->netfilter_contexts_len);
58913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!mod->netfilter_contexts) {
59013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle, "out of memory");
59113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
59213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
59313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (read_helper
59413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (mod->netfilter_contexts, file,
59513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     mod->netfilter_contexts_len)) {
59613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
59713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "invalid netfilter contexts section at section %u",
59813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
59913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(mod->netfilter_contexts);
60013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				mod->netfilter_contexts = NULL;
60113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
60213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
60313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			seen |= SEEN_NETFILTER;
60413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
60513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case POLICYDB_MOD_MAGIC:
60613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (seen & SEEN_MOD) {
60713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
60813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "found multiple module sections in module package (at section %u)",
60913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
61013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
61113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
61213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
61313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* seek back to where the magic number was */
61413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (policy_file_seek(file, offsets[i]))
61513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
61613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
61713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = policydb_read(&mod->policy->p, file, verbose);
61813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc < 0) {
61913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
62013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "invalid module in module package (at section %u)",
62113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
62213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
62313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
62413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			seen |= SEEN_MOD;
62513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
62613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		default:
62713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* unknown section, ignore */
62813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(file->handle,
62913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "unknown magic number at section %u, offset: %zx, number: %ux ",
63013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    i, offsets[i], le32_to_cpu(buf[0]));
63113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
63213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
63313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
63413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
63513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((seen & SEEN_MOD) == 0) {
63613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(file->handle, "missing module in module package");
63713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
63813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
63913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
64013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(offsets);
64113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
64213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
64313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
64413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(offsets);
64513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
64613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
64713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
64813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_module_package_info(struct sepol_policy_file *spf, int *type,
64913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      char **name, char **version)
65013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
65113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct policy_file *file = &spf->pf;
65213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_module_package_t *mod = NULL;
65313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t buf[5], len, nsec;
65413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size_t *offsets = NULL;
65513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned i, seen = 0;
65613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *id;
65713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc;
65813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
65913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_module_package_create(&mod))
66013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
66113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
66213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (module_package_read_offsets(mod, file, &offsets, &nsec)) {
66313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
66413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
66513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
66613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < nsec; i++) {
66713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
66813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (policy_file_seek(file, offsets[i])) {
66913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(file->handle, "error seeking to offset "
67013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "%zu for module package section %u", offsets[i], i);
67113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
67213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
67313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
67413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		len = offsets[i + 1] - offsets[i];
67513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
67613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (len < sizeof(uint32_t)) {
67713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(file->handle,
67813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "module package section %u has too small length %u",
67913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    i, len);
68013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
68113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
68213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
68313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* read the magic number, so that we know which function to call */
68413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		rc = next_entry(buf, file, sizeof(uint32_t) * 2);
68513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (rc < 0) {
68613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ERR(file->handle,
68713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    "module package section %u truncated, lacks magic number",
68813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    i);
68913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto cleanup;
69013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
69113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
69213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		switch (le32_to_cpu(buf[0])) {
69313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case SEPOL_PACKAGE_SECTION_FC:
69413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* skip file contexts */
69513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (seen & SEEN_FC) {
69613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
69713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "found multiple file contexts sections in module package (at section %u)",
69813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
69913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
70013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
70113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			seen |= SEEN_FC;
70213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
70313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case SEPOL_PACKAGE_SECTION_SEUSER:
70413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* skip seuser */
70513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (seen & SEEN_SEUSER) {
70613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
70713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "found seuser sections in module package (at section %u)",
70813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
70913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
71013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
71113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			seen |= SEEN_SEUSER;
71213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
71313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case SEPOL_PACKAGE_SECTION_USER_EXTRA:
71413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* skip user_extra */
71513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (seen & SEEN_USER_EXTRA) {
71613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
71713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "found user_extra sections in module package (at section %u)",
71813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
71913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
72013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
72113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			seen |= SEEN_USER_EXTRA;
72213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
72313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case SEPOL_PACKAGE_SECTION_NETFILTER:
72413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* skip netfilter contexts */
72513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (seen & SEEN_NETFILTER) {
72613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
72713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "found multiple netfilter contexts sections in module package (at section %u)",
72813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
72913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
73013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
73113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			seen |= SEEN_NETFILTER;
73213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
73313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case POLICYDB_MOD_MAGIC:
73413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (seen & SEEN_MOD) {
73513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
73613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "found multiple module sections in module package (at section %u)",
73713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
73813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
73913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
74013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			len = le32_to_cpu(buf[1]);
74113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (len != strlen(POLICYDB_MOD_STRING)) {
74213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
74313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "module string length is wrong (at section %u)",
74413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
74513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
74613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
74713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
74813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* skip id */
74913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			id = malloc(len + 1);
75013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!id) {
75113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
75213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "out of memory (at section %u)",
75313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
75413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
75513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
75613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = next_entry(id, file, len);
75713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(id);
75813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc < 0) {
75913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
76013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "cannot get module string (at section %u)",
76113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
76213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
76313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
76413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
76513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = next_entry(buf, file, sizeof(uint32_t) * 5);
76613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc < 0) {
76713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
76813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "cannot get module header (at section %u)",
76913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
77013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
77113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
77213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
77313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*type = le32_to_cpu(buf[0]);
77413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* if base - we're done */
77513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (*type == POLICY_BASE) {
77613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				*name = NULL;
77713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				*version = NULL;
77813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				seen |= SEEN_MOD;
77913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
78013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else if (*type != POLICY_MOD) {
78113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
78213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "module has invalid type %d (at section %u)",
78313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    *type, i);
78413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
78513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
78613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
78713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* read the name and version */
78813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = next_entry(buf, file, sizeof(uint32_t));
78913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc < 0) {
79013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
79113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "cannot get module name len (at section %u)",
79213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
79313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
79413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
79513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			len = le32_to_cpu(buf[0]);
79613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*name = malloc(len + 1);
79713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!*name) {
79813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle, "out of memory");
79913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
80013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
80113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = next_entry(*name, file, len);
80213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc < 0) {
80313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
80413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "cannot get module name string (at section %u)",
80513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
80613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
80713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
80813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			(*name)[len] = '\0';
80913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = next_entry(buf, file, sizeof(uint32_t));
81013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc < 0) {
81113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
81213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "cannot get module version len (at section %u)",
81313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
81413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
81513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
81613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			len = le32_to_cpu(buf[0]);
81713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*version = malloc(len + 1);
81813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!*version) {
81913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle, "out of memory");
82013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
82113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
82213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			rc = next_entry(*version, file, len);
82313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (rc < 0) {
82413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ERR(file->handle,
82513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    "cannot get module version string (at section %u)",
82613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    i);
82713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto cleanup;
82813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
82913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			(*version)[len] = '\0';
83013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			seen |= SEEN_MOD;
83113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
83213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		default:
83313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
83413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
83513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
83613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
83713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
83813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((seen & SEEN_MOD) == 0) {
83913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(file->handle, "missing module in module package");
84013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
84113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
84213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
84313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_module_package_free(mod);
84413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(offsets);
84513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
84613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
84713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
84813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_module_package_free(mod);
84913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(offsets);
85013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -1;
85113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
85213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
85313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int write_helper(char *data, size_t len, struct policy_file *file)
85413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
85513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int idx = 0;
85613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size_t len2;
85713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
85813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (len) {
85913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (len > BUFSIZ)
86013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			len2 = BUFSIZ;
86113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		else
86213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			len2 = len;
86313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
86413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (put_entry(&data[idx], 1, len2, file) != len2) {
86513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
86613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
86713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		len -= len2;
86813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		idx += len2;
86913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
87013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
87113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
87213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
87313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_module_package_write(sepol_module_package_t * p,
87413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			       struct sepol_policy_file *spf)
87513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
87613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct policy_file *file = &spf->pf;
87713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policy_file_t polfile;
87813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t buf[5], offsets[5], len, nsec = 0;
87913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int i;
88013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
88113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->policy) {
88213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* compute policy length */
88313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		policy_file_init(&polfile);
88413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		polfile.type = PF_LEN;
88513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		polfile.handle = file->handle;
88613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (policydb_write(&p->policy->p, &polfile))
88713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
88813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		len = polfile.len;
88913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!polfile.len)
89013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
89113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nsec++;
89213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
89313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
89413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* We don't support writing a package without a module at this point */
89513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
89613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
89713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
89813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* seusers and user_extra only supported in base at the moment */
89913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((p->seusers || p->user_extra)
90013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    && (p->policy->p.policy_type != SEPOL_POLICY_BASE)) {
90113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(file->handle,
90213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    "seuser and user_extra sections only supported in base");
90313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
90413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
90513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
90613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->file_contexts)
90713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nsec++;
90813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
90913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->seusers)
91013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nsec++;
91113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
91213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->user_extra)
91313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nsec++;
91413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
91513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->netfilter_contexts)
91613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nsec++;
91713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
91813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	buf[0] = cpu_to_le32(SEPOL_MODULE_PACKAGE_MAGIC);
91913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	buf[1] = cpu_to_le32(p->version);
92013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	buf[2] = cpu_to_le32(nsec);
92113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (put_entry(buf, sizeof(uint32_t), 3, file) != 3)
92213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
92313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
92413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* calculate offsets */
92513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	offsets[0] = (nsec + 3) * sizeof(uint32_t);
92613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	buf[0] = cpu_to_le32(offsets[0]);
92713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
92813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	i = 1;
92913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->file_contexts) {
93013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		offsets[i] = offsets[i - 1] + len;
93113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		buf[i] = cpu_to_le32(offsets[i]);
93213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* add a uint32_t to compensate for the magic number */
93313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		len = p->file_contexts_len + sizeof(uint32_t);
93413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		i++;
93513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
93613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->seusers) {
93713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		offsets[i] = offsets[i - 1] + len;
93813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		buf[i] = cpu_to_le32(offsets[i]);
93913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		len = p->seusers_len + sizeof(uint32_t);
94013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		i++;
94113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
94213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->user_extra) {
94313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		offsets[i] = offsets[i - 1] + len;
94413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		buf[i] = cpu_to_le32(offsets[i]);
94513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		len = p->user_extra_len + sizeof(uint32_t);
94613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		i++;
94713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
94813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->netfilter_contexts) {
94913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		offsets[i] = offsets[i - 1] + len;
95013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		buf[i] = cpu_to_le32(offsets[i]);
95113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		len = p->netfilter_contexts_len + sizeof(uint32_t);
95213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		i++;
95313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
95413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (put_entry(buf, sizeof(uint32_t), nsec, file) != nsec)
95513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
95613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
95713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* write sections */
95813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
95913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policydb_write(&p->policy->p, file))
96013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
96113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
96213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->file_contexts) {
96313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_FC);
96413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
96513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
96613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (write_helper(p->file_contexts, p->file_contexts_len, file))
96713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
96813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
96913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->seusers) {
97013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_SEUSER);
97113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
97213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
97313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (write_helper(p->seusers, p->seusers_len, file))
97413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
97513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
97613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
97713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->user_extra) {
97813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_USER_EXTRA);
97913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
98013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
98113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (write_helper(p->user_extra, p->user_extra_len, file))
98213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
98313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
98413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p->netfilter_contexts) {
98513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_NETFILTER);
98613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
98713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
98813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (write_helper
98913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (p->netfilter_contexts, p->netfilter_contexts_len, file))
99013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
99113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
99213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
99313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
99413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
99513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_link_modules(sepol_handle_t * handle,
99613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		       sepol_policydb_t * base,
99713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		       sepol_policydb_t ** modules, size_t len, int verbose)
99813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
99913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return link_modules(handle, &base->p, (policydb_t **) modules, len,
100013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    verbose);
100113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
100213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
100313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_expand_module(sepol_handle_t * handle,
100413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			sepol_policydb_t * base,
100513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			sepol_policydb_t * out, int verbose, int check)
100613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
100713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return expand_module(handle, &base->p, &out->p, verbose, check);
100813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
1009