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