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