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