113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Copyright (C) 2006 Tresys Technology, LLC
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Copyright (C) 2006-2007 Red Hat, Inc.
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * This program is free software; you can redistribute it and/or modify
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * it under the terms of the GNU General Public License as published by
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * the Free Software Foundation, version 2.
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Because we _must_ muck around in the internal representation of
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * the policydb (and include the internal header below) this program
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * must be statically linked to libsepol like checkpolicy. It is
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * not clear if it is worthwhile to fix this, as exposing the details
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * of avrule_blocks - even in an ABI safe way - seems undesirable.
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/module.h>
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/errcodes.h>
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/policydb.h>
2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <getopt.h>
2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <fcntl.h>
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h>
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <errno.h>
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/mman.h>
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/types.h>
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/stat.h>
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <unistd.h>
3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <assert.h>
3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* for getopt */
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleextern char *optarg;
3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleextern int optind;
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* This is really a horrible hack, but the base module
3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * is referred to with the following name. The same
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * thing is done in the linker for displaying error
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * messages.
4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define BASE_NAME "BASE"
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void usage(char *program_name)
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	printf("usage: %s [-v -g -b] basemodpkg modpkg1 [modpkg2 ... ]\n",
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	       program_name);
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	exit(1);
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Basic string hash and compare for the hashtables used in
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * generate_requires. Copied from symtab.c.
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic unsigned int reqsymhash(hashtab_t h, hashtab_key_t key)
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *p, *keyp;
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size_t size;
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int val;
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	val = 0;
6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	keyp = (char *)key;
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size = strlen(keyp);
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (p = keyp; ((size_t) (p - keyp)) < size; p++)
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		val =
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return val & (h->size - 1);
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int reqsymcmp(hashtab_t h
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     __attribute__ ((unused)), hashtab_key_t key1,
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     hashtab_key_t key2)
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *keyp1, *keyp2;
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	keyp1 = (char *)key1;
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	keyp2 = (char *)key2;
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return strcmp(keyp1, keyp2);
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Load a policy package from the given filename. Progname is used for
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * error reporting.
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic sepol_module_package_t *load_module(char *filename, char *progname)
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	FILE *fp = NULL;
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct sepol_policy_file *pf = NULL;
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_module_package_t *p = NULL;
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_module_package_create(&p)) {
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Out of memory\n", progname);
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto bad;
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_policy_file_create(&pf)) {
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Out of memory\n", progname);
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto bad;
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fp = fopen(filename, "r");
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!fp) {
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Could not open package %s:  %s", progname,
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			filename, strerror(errno));
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto bad;
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_policy_file_set_fp(pf, fp);
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = sepol_module_package_read(p, pf, 0);
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Error while reading package from %s\n",
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			progname, filename);
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto bad;
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fclose(fp);
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_policy_file_free(pf);
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return p;
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      bad:
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_module_package_free(p);
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_policy_file_free(pf);
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (fp)
12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fclose(fp);
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return NULL;
12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* This function generates the requirements graph and stores it in
12513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * a set of nested hashtables. The top level hash table stores modules
12613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * keyed by name. The value of that module is a hashtable storing all
12713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * of the requirements keyed by name. There is no value for the requirements
12813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * hashtable.
12913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
13013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * This only tracks symbols that are _required_ - optional symbols
13113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * are completely ignored. A future version might look at this.
13213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
13313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * This requirement generation only looks at booleans and types because:
13413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  - object classes: (for now) only present in bases
13513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  - roles: since they are multiply declared it is not clear how
13613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *           to present these requirements as they will be satisfied
13713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *           by multiple modules.
13813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  - users: same problem as roles plus they are usually defined outside
13913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *           of the policy.
14013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  - levels / cats: can't be required or used in modules.
14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic hashtab_t generate_requires(policydb_t * p)
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_block_t *block;
14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	avrule_decl_t *decl;
14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *mod_name, *req_name, *id;
14713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_t *b;
14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ebitmap_node_t *node;
14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t i, j;
15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	scope_datum_t *scope;
15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_t mods;
15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_t reqs;
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mods = hashtab_create(reqsymhash, reqsymcmp, 64);
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mods == NULL)
15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return NULL;
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (block = p->global; block != NULL; block = block->next) {
16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (block->flags & AVRULE_OPTIONAL)
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (decl = block->branch_list; decl != NULL; decl = decl->next) {
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			mod_name =
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    decl->module_name ? decl->module_name : BASE_NAME;
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			for (i = 0; i < SYM_NUM; i++) {
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!(i == SYM_TYPES || i == SYM_BOOLS))
16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					continue;
16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				b = &decl->required.scope[i];
16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				ebitmap_for_each_bit(b, node, j) {
17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (!ebitmap_node_get_bit(node, j))
17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						continue;
17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					id = p->sym_val_to_name[i][j];
17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					scope =
17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    (scope_datum_t *) hashtab_search(p->
17513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle									     scope
17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle									     [i].
17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle									     table,
17813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle									     id);
17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					/* since this is only called after a successful link,
18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					 * this should never happen */
18113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					assert(scope->scope == SCOPE_DECL);
18213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					req_name =
18313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    p->decl_val_to_struct[scope->
18413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								  decl_ids[0]]->
18513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    module_name ? p->
18613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    decl_val_to_struct[scope->
18713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							       decl_ids[0]]->
18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    module_name : BASE_NAME;
18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					reqs =
19113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    (hashtab_t) hashtab_search(mods,
19213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								       mod_name);
19313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (!reqs) {
19413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						reqs =
19513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						    hashtab_create(reqsymhash,
19613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								   reqsymcmp,
19713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								   64);
19813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						if (reqs == NULL) {
19913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							return NULL;
20013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						}
20113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						ret =
20213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						    hashtab_insert(mods,
20313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								   mod_name,
20413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle								   reqs);
20513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						if (ret != SEPOL_OK)
20613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							return NULL;
20713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
20813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					ret =
20913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    hashtab_insert(reqs, req_name,
21013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							   NULL);
21113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (!
21213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    (ret == SEPOL_EEXIST
21313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     || ret == SEPOL_OK))
21413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						return NULL;
21513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
21613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
21713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
21913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
22013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return mods;
22213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
22313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void free_requires(hashtab_t req)
22513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
22613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
22713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_ptr_t cur;
22813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* We steal memory for everything stored in the hash tables
23013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 * from the policydb, so this only looks like it leaks.
23113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	 */
23213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < req->size; i++) {
23313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = req->htable[i];
23413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		while (cur != NULL) {
23513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			hashtab_destroy((hashtab_t) cur->datum);
23613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cur = cur->next;
23713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
23813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
23913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_destroy(req);
24013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
24113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
24213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void output_graphviz(hashtab_t mods, int exclude_base, FILE * f)
24313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
24413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
24513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_ptr_t cur, cur2;
24613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_t reqs;
24713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
24813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fprintf(f, "digraph mod_deps {\n");
24913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fprintf(f, "\toverlap=false\n");
25013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
25113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < mods->size; i++) {
25213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = mods->htable[i];
25313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		while (cur != NULL) {
25413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			reqs = (hashtab_t) cur->datum;
25513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(reqs);
25613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			for (j = 0; j < reqs->size; j++) {
25713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				cur2 = reqs->htable[j];
25813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				while (cur2 != NULL) {
25913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (exclude_base
26013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    && strcmp(cur2->key,
26113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						      BASE_NAME) == 0) {
26213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						cur2 = cur2->next;
26313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						continue;
26413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
26513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					fprintf(f, "\t%s -> %s\n", cur->key,
26613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						cur2->key);
26713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					cur2 = cur2->next;
26813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
26913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
27013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cur = cur->next;
27113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
27213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
27313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fprintf(f, "}\n");
27413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
27513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
27613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void output_requirements(hashtab_t mods, int exclude_base, FILE * f)
27713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
27813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i, j;
27913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_ptr_t cur, cur2;
28013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_t reqs;
28113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int found_req;
28213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < mods->size; i++) {
28413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		cur = mods->htable[i];
28513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		while (cur != NULL) {
28613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			reqs = (hashtab_t) cur->datum;
28713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			assert(reqs);
28813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			fprintf(f, "module: %s\n", cur->key);
28913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			found_req = 0;
29013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			for (j = 0; j < reqs->size; j++) {
29113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				cur2 = reqs->htable[j];
29213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				while (cur2 != NULL) {
29313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (exclude_base
29413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					    && strcmp(cur2->key,
29513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						      BASE_NAME) == 0) {
29613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						cur2 = cur2->next;
29713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						continue;
29813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					}
29913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					found_req = 1;
30013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					fprintf(f, "\t%s\n", cur2->key);
30113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					cur2 = cur2->next;
30213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
30313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
30413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!found_req)
30513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				fprintf(f, "\t[no dependencies]\n");
30613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			cur = cur->next;
30713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
30813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
30913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fprintf(f, "}\n");
31013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
31113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
31213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Possible commands - see the command variable in
31313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * main below and the man page for more info.
31413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
31513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define SHOW_DEPS    1
31613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define GEN_GRAPHVIZ 2
31713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
31813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint main(int argc, char **argv)
31913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
32013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ch, i, num_mods;
32113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int verbose = 0, exclude_base = 1, command = SHOW_DEPS;
32213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *basename;
32313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_module_package_t *base, **mods;
32413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *p;
32513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	hashtab_t req;
32613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
32713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while ((ch = getopt(argc, argv, "vgb")) != EOF) {
32813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		switch (ch) {
32913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case 'v':
33013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			verbose = 1;
33113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
33213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case 'g':
33313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			command = GEN_GRAPHVIZ;
33413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
33513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case 'b':
33613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			exclude_base = 0;
33713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
33813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		default:
33913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			usage(argv[0]);
34013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
34113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
34213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
34313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* check args */
34413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (argc < 3 || !(optind != (argc - 1))) {
34513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr,
34613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			"%s:  You must provide the base module package and at least one other module package\n",
34713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			argv[0]);
34813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		usage(argv[0]);
34913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
35013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
35113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	basename = argv[optind++];
35213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	base = load_module(basename, argv[0]);
35313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!base) {
35413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr,
35513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			"%s:  Could not load base module from file %s\n",
35613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			argv[0], basename);
35713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
35813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
35913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
36013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	num_mods = argc - optind;
36113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mods =
36213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    (sepol_module_package_t **) malloc(sizeof(sepol_module_package_t *)
36313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					       * num_mods);
36413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!mods) {
36513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
36613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
36713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
36813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(mods, 0, sizeof(sepol_module_package_t *) * num_mods);
36913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
37013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; optind < argc; optind++, i++) {
37113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mods[i] = load_module(argv[optind], argv[0]);
37213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!mods[i]) {
37313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			fprintf(stderr,
37413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				"%s:  Could not load module from file %s\n",
37513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				argv[0], argv[optind]);
37613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			exit(1);
37713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
37813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
37913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
38013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_link_packages(NULL, base, mods, num_mods, verbose)) {
38113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Error while linking packages\n", argv[0]);
38213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
38313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
38413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
38513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	p = (policydb_t *) sepol_module_package_get_policy(base);
38613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (p == NULL)
38713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
38813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
38913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	req = generate_requires(p);
39013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (req == NULL)
39113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
39213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
39313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (command == SHOW_DEPS)
39413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		output_requirements(req, exclude_base, stdout);
39513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else
39613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		output_graphviz(req, exclude_base, stdout);
39713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
39813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_module_package_free(base);
39913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < num_mods; i++)
40013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		sepol_module_package_free(mods[i]);
40113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
40213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free_requires(req);
40313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
40413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	exit(0);
40513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
406