Home | History | Annotate | Download | only in semodule_expand
      1 /* Authors: Karl MacMillan <kmacmillan (at) tresys.com>
      2  * 	    Joshua Brindle <jbrindle (at) tresys.com>
      3  *
      4  * Copyright (C) 2004 Tresys Technology, LLC
      5  *	This program is free software; you can redistribute it and/or modify
      6  *  	it under the terms of the GNU General Public License as published by
      7  *	the Free Software Foundation, version 2.
      8  */
      9 
     10 #include <sepol/policydb.h>
     11 #include <sepol/module.h>
     12 
     13 #include <getopt.h>
     14 #include <fcntl.h>
     15 #include <stdio.h>
     16 #include <errno.h>
     17 #include <sys/mman.h>
     18 #include <sys/types.h>
     19 #include <sys/stat.h>
     20 #include <stdlib.h>
     21 #include <unistd.h>
     22 #include <string.h>
     23 
     24 extern char *optarg;
     25 extern int optind;
     26 
     27 int policyvers = 0;
     28 
     29 #define EXPANDPOLICY_VERSION "1.0"
     30 
     31 static __attribute__((__noreturn__)) void usage(const char *program_name)
     32 {
     33 	printf("usage: %s [-V -a -c [version]] basemodpkg outputfile\n",
     34 	       program_name);
     35 	exit(1);
     36 }
     37 
     38 int main(int argc, char **argv)
     39 {
     40 	char *basename, *outname;
     41 	int ch, ret, show_version = 0, verbose = 0;
     42 	struct sepol_policy_file *pf;
     43 	sepol_module_package_t *base;
     44 	sepol_policydb_t *out, *p;
     45 	FILE *fp, *outfile;
     46 	int check_assertions = 1;
     47 	sepol_handle_t *handle;
     48 
     49 	while ((ch = getopt(argc, argv, "c:Vva")) != EOF) {
     50 		switch (ch) {
     51 		case 'V':
     52 			show_version = 1;
     53 			break;
     54 		case 'v':
     55 			verbose = 1;
     56 			break;
     57 		case 'c':{
     58 				long int n = strtol(optarg, NULL, 10);
     59 				if (errno) {
     60 					fprintf(stderr,
     61 						"%s:  Invalid policyvers specified: %s\n",
     62 						argv[0], optarg);
     63 					usage(argv[0]);
     64 					exit(1);
     65 				}
     66 				if (n < sepol_policy_kern_vers_min()
     67 				    || n > sepol_policy_kern_vers_max()) {
     68 					fprintf(stderr,
     69 						"%s:  policyvers value %ld not in range %d-%d\n",
     70 						argv[0], n,
     71 						sepol_policy_kern_vers_min(),
     72 						sepol_policy_kern_vers_max());
     73 					usage(argv[0]);
     74 					exit(1);
     75 				}
     76 				policyvers = n;
     77 				break;
     78 			}
     79 		case 'a':{
     80 				check_assertions = 0;
     81 				break;
     82 			}
     83 		default:
     84 			usage(argv[0]);
     85 		}
     86 	}
     87 
     88 	if (verbose) {
     89 		if (policyvers)
     90 			printf("Building version %d policy\n", policyvers);
     91 	}
     92 
     93 	if (show_version) {
     94 		printf("%s\n", EXPANDPOLICY_VERSION);
     95 		exit(0);
     96 	}
     97 
     98 	/* check args */
     99 	if (argc < 3 || !(optind != (argc - 1))) {
    100 		fprintf(stderr,
    101 			"%s:  You must provide the base module package and output filename\n",
    102 			argv[0]);
    103 		usage(argv[0]);
    104 	}
    105 
    106 	basename = argv[optind++];
    107 	outname = argv[optind];
    108 
    109 	handle = sepol_handle_create();
    110 	if (!handle)
    111 		exit(1);
    112 
    113 	if (sepol_policy_file_create(&pf)) {
    114 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
    115 		exit(1);
    116 	}
    117 
    118 	/* read the base module */
    119 	if (sepol_module_package_create(&base)) {
    120 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
    121 		exit(1);
    122 	}
    123 	fp = fopen(basename, "r");
    124 	if (!fp) {
    125 		fprintf(stderr, "%s:  Can't open '%s':  %s\n",
    126 			argv[0], basename, strerror(errno));
    127 		exit(1);
    128 	}
    129 	sepol_policy_file_set_fp(pf, fp);
    130 	ret = sepol_module_package_read(base, pf, 0);
    131 	if (ret) {
    132 		fprintf(stderr, "%s:  Error in reading package from %s\n",
    133 			argv[0], basename);
    134 		exit(1);
    135 	}
    136 	fclose(fp);
    137 
    138 	/* linking the base takes care of enabling optional avrules */
    139 	p = sepol_module_package_get_policy(base);
    140 	if (sepol_link_modules(handle, p, NULL, 0, 0)) {
    141 		fprintf(stderr, "%s:  Error while enabling avrules\n", argv[0]);
    142 		exit(1);
    143 	}
    144 
    145 	/* create the output policy */
    146 
    147 	if (sepol_policydb_create(&out)) {
    148 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
    149 		exit(1);
    150 	}
    151 
    152 	sepol_set_expand_consume_base(handle, 1);
    153 
    154 	if (sepol_expand_module(handle, p, out, verbose, check_assertions)) {
    155 		fprintf(stderr, "%s:  Error while expanding policy\n", argv[0]);
    156 		exit(1);
    157 	}
    158 
    159 	if (policyvers) {
    160 		if (sepol_policydb_set_vers(out, policyvers)) {
    161 			fprintf(stderr, "%s:  Invalid version %d\n", argv[0],
    162 				policyvers);
    163 			exit(1);
    164 		}
    165 	}
    166 
    167 	sepol_module_package_free(base);
    168 
    169 	outfile = fopen(outname, "w");
    170 	if (!outfile) {
    171 		perror(outname);
    172 		exit(1);
    173 	}
    174 
    175 	sepol_policy_file_set_fp(pf, outfile);
    176 	ret = sepol_policydb_write(out, pf);
    177 	if (ret) {
    178 		fprintf(stderr,
    179 			"%s:  Error while writing expanded policy to %s\n",
    180 			argv[0], outname);
    181 		exit(1);
    182 	}
    183 	fclose(outfile);
    184 	sepol_handle_destroy(handle);
    185 	sepol_policydb_free(out);
    186 	sepol_policy_file_free(pf);
    187 
    188 	return 0;
    189 }
    190