Home | History | Annotate | Download | only in checkpolicy
      1 /*
      2  * Authors: Joshua Brindle <jbrindle (at) tresys.com>
      3  *	    Karl MacMillan <kmacmillan (at) tresys.com>
      4  *          Jason Tang     <jtang (at) tresys.com>
      5  *
      6  *
      7  * Copyright (C) 2004-5 Tresys Technology, LLC
      8  *	This program is free software; you can redistribute it and/or modify
      9  *  	it under the terms of the GNU General Public License as published by
     10  *	the Free Software Foundation, version 2.
     11  */
     12 
     13 #include <getopt.h>
     14 #include <unistd.h>
     15 #include <stdlib.h>
     16 #include <sys/types.h>
     17 #include <sys/stat.h>
     18 #include <fcntl.h>
     19 #include <stdio.h>
     20 #include <errno.h>
     21 #include <sys/mman.h>
     22 
     23 #include <sepol/module_to_cil.h>
     24 #include <sepol/policydb/policydb.h>
     25 #include <sepol/policydb/services.h>
     26 #include <sepol/policydb/conditional.h>
     27 #include <sepol/policydb/flask.h>
     28 #include <sepol/policydb/hierarchy.h>
     29 #include <sepol/policydb/expand.h>
     30 #include <sepol/policydb/link.h>
     31 #include <sepol/policydb/sidtab.h>
     32 
     33 #include "queue.h"
     34 #include "checkpolicy.h"
     35 #include "parse_util.h"
     36 
     37 extern char *optarg;
     38 extern int optind;
     39 
     40 static sidtab_t sidtab;
     41 
     42 extern int mlspol;
     43 
     44 static int handle_unknown = SEPOL_DENY_UNKNOWN;
     45 static const char *txtfile = "policy.conf";
     46 static const char *binfile = "policy";
     47 
     48 unsigned int policy_type = POLICY_BASE;
     49 unsigned int policyvers = MOD_POLICYDB_VERSION_MAX;
     50 
     51 static int read_binary_policy(policydb_t * p, const char *file, const char *progname)
     52 {
     53 	int fd;
     54 	struct stat sb;
     55 	void *map;
     56 	struct policy_file f, *fp;
     57 
     58 	fd = open(file, O_RDONLY);
     59 	if (fd < 0) {
     60 		fprintf(stderr, "Can't open '%s':  %s\n",
     61 			file, strerror(errno));
     62 		return -1;
     63 	}
     64 	if (fstat(fd, &sb) < 0) {
     65 		fprintf(stderr, "Can't stat '%s':  %s\n",
     66 			file, strerror(errno));
     67 		close(fd);
     68 		return -1;
     69 	}
     70 	map =
     71 	    mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
     72 	close(fd);
     73 	if (map == MAP_FAILED) {
     74 		fprintf(stderr, "Can't map '%s':  %s\n", file, strerror(errno));
     75 		return -1;
     76 	}
     77 	policy_file_init(&f);
     78 	f.type = PF_USE_MEMORY;
     79 	f.data = map;
     80 	f.len = sb.st_size;
     81 	fp = &f;
     82 
     83 	if (policydb_init(p)) {
     84 		fprintf(stderr, "%s:  policydb_init:  Out of memory!\n",
     85 			progname);
     86 		return -1;
     87 	}
     88 	if (policydb_read(p, fp, 1)) {
     89 		fprintf(stderr,
     90 			"%s:  error(s) encountered while parsing configuration\n",
     91 			progname);
     92 		return -1;
     93 	}
     94 
     95 	/* Check Policy Consistency */
     96 	if (p->mls) {
     97 		if (!mlspol) {
     98 			fprintf(stderr, "%s:  MLS policy, but non-MLS"
     99 				" is specified\n", progname);
    100 			return -1;
    101 		}
    102 	} else {
    103 		if (mlspol) {
    104 			fprintf(stderr, "%s:  non-MLS policy, but MLS"
    105 				" is specified\n", progname);
    106 			return -1;
    107 		}
    108 	}
    109 	return 0;
    110 }
    111 
    112 static int write_binary_policy(policydb_t * p, FILE *outfp)
    113 {
    114 	struct policy_file pf;
    115 
    116 	p->policy_type = policy_type;
    117 	p->policyvers = policyvers;
    118 	p->handle_unknown = handle_unknown;
    119 
    120 	policy_file_init(&pf);
    121 	pf.type = PF_USE_STDIO;
    122 	pf.fp = outfp;
    123 	return policydb_write(p, &pf);
    124 }
    125 
    126 static void usage(char *progname)
    127 {
    128 	printf("usage:  %s [-h] [-V] [-b] [-C] [-U handle_unknown] [-m] [-M] [-o FILE] [INPUT]\n", progname);
    129 	printf("Build base and policy modules.\n");
    130 	printf("Options:\n");
    131 	printf("  INPUT      build module from INPUT (else read from \"%s\")\n",
    132 	       txtfile);
    133 	printf("  -V         show policy versions created by this program\n");
    134 	printf("  -b         treat input as a binary policy file\n");
    135 	printf("  -C         output CIL policy instead of binary policy\n");
    136 	printf("  -h         print usage\n");
    137 	printf("  -U OPTION  How to handle unknown classes and permissions\n");
    138 	printf("               deny: Deny unknown kernel checks\n");
    139 	printf("               reject: Reject loading of policy with unknowns\n");
    140 	printf("               allow: Allow unknown kernel checks\n");
    141 	printf("  -m         build a policy module instead of a base module\n");
    142 	printf("  -M         enable MLS policy\n");
    143 	printf("  -o FILE    write module to FILE (else just check syntax)\n");
    144 	exit(1);
    145 }
    146 
    147 int main(int argc, char **argv)
    148 {
    149 	const char *file = txtfile, *outfile = NULL;
    150 	unsigned int binary = 0, cil = 0;
    151 	int ch;
    152 	int show_version = 0;
    153 	policydb_t modpolicydb;
    154 	struct option long_options[] = {
    155 		{"help", no_argument, NULL, 'h'},
    156 		{"output", required_argument, NULL, 'o'},
    157 		{"binary", no_argument, NULL, 'b'},
    158 		{"version", no_argument, NULL, 'V'},
    159 		{"handle-unknown", required_argument, NULL, 'U'},
    160 		{"mls", no_argument, NULL, 'M'},
    161 		{"cil", no_argument, NULL, 'C'},
    162 		{NULL, 0, NULL, 0}
    163 	};
    164 
    165 	while ((ch = getopt_long(argc, argv, "ho:bVU:mMC", long_options, NULL)) != -1) {
    166 		switch (ch) {
    167 		case 'h':
    168 			usage(argv[0]);
    169 			break;
    170 		case 'o':
    171 			outfile = optarg;
    172 			break;
    173 		case 'b':
    174 			binary = 1;
    175 			file = binfile;
    176 			break;
    177 		case 'V':
    178 			show_version = 1;
    179 			break;
    180 		case 'U':
    181 			if (!strcasecmp(optarg, "deny")) {
    182 				handle_unknown = DENY_UNKNOWN;
    183 				break;
    184 			}
    185 			if (!strcasecmp(optarg, "reject")) {
    186 				handle_unknown = REJECT_UNKNOWN;
    187 				break;
    188 			}
    189 			if (!strcasecmp(optarg, "allow")) {
    190 				handle_unknown = ALLOW_UNKNOWN;
    191 				break;
    192 			}
    193 			usage(argv[0]);
    194 		case 'm':
    195 			policy_type = POLICY_MOD;
    196 			policyvers = MOD_POLICYDB_VERSION_MAX;
    197 			break;
    198 		case 'M':
    199 			mlspol = 1;
    200 			break;
    201 		case 'C':
    202 			cil = 1;
    203 			break;
    204 		default:
    205 			usage(argv[0]);
    206 		}
    207 	}
    208 
    209 	if (show_version) {
    210 		printf("Module versions %d-%d\n",
    211 		       MOD_POLICYDB_VERSION_MIN, MOD_POLICYDB_VERSION_MAX);
    212 		exit(0);
    213 	}
    214 
    215 	if (handle_unknown && (policy_type != POLICY_BASE)) {
    216 		fprintf(stderr, "%s:  Handling of unknown classes and permissions is only valid in the base module.\n", argv[0]);
    217 		exit(1);
    218 	}
    219 
    220 	if (binary && (policy_type != POLICY_BASE)) {
    221 		fprintf(stderr, "%s:  -b and -m are incompatible with each other.\n", argv[0]);
    222 		exit(1);
    223 	}
    224 
    225 	if (optind != argc) {
    226 		file = argv[optind++];
    227 		if (optind != argc)
    228 			usage(argv[0]);
    229 	}
    230 	printf("%s:  loading policy configuration from %s\n", argv[0], file);
    231 
    232 	/* Set policydb and sidtab used by libsepol service functions
    233 	   to my structures, so that I can directly populate and
    234 	   manipulate them. */
    235 	sepol_set_policydb(&modpolicydb);
    236 	sepol_set_sidtab(&sidtab);
    237 
    238 	if (binary) {
    239 		if (read_binary_policy(&modpolicydb, file, argv[0]) == -1) {
    240 			exit(1);
    241 		}
    242 	} else {
    243 		if (policydb_init(&modpolicydb)) {
    244 			fprintf(stderr, "%s: out of memory!\n", argv[0]);
    245 			return -1;
    246 		}
    247 
    248 		modpolicydb.policy_type = policy_type;
    249 		modpolicydb.mls = mlspol;
    250 		modpolicydb.handle_unknown = handle_unknown;
    251 
    252 		if (read_source_policy(&modpolicydb, file, argv[0]) == -1) {
    253 			exit(1);
    254 		}
    255 
    256 		if (hierarchy_check_constraints(NULL, &modpolicydb)) {
    257 			return -1;
    258 		}
    259 	}
    260 
    261 	if (modpolicydb.policy_type == POLICY_BASE && !cil) {
    262 		/* Verify that we can successfully expand the base module. */
    263 		policydb_t kernpolicydb;
    264 
    265 		if (policydb_init(&kernpolicydb)) {
    266 			fprintf(stderr, "%s:  policydb_init failed\n", argv[0]);
    267 			exit(1);
    268 		}
    269 		if (link_modules(NULL, &modpolicydb, NULL, 0, 0)) {
    270 			fprintf(stderr, "%s:  link modules failed\n", argv[0]);
    271 			exit(1);
    272 		}
    273 		if (expand_module(NULL, &modpolicydb, &kernpolicydb, 0, 1)) {
    274 			fprintf(stderr, "%s:  expand module failed\n", argv[0]);
    275 			exit(1);
    276 		}
    277 		policydb_destroy(&kernpolicydb);
    278 	}
    279 
    280 	if (policydb_load_isids(&modpolicydb, &sidtab))
    281 		exit(1);
    282 
    283 	sepol_sidtab_destroy(&sidtab);
    284 
    285 	printf("%s:  policy configuration loaded\n", argv[0]);
    286 
    287 	if (outfile) {
    288 		FILE *outfp = fopen(outfile, "w");
    289 
    290 		if (!outfp) {
    291 			perror(outfile);
    292 			exit(1);
    293 		}
    294 
    295 		if (!cil) {
    296 			printf("%s:  writing binary representation (version %d) to %s\n",
    297 				   argv[0], policyvers, file);
    298 
    299 			if (write_binary_policy(&modpolicydb, outfp) != 0) {
    300 				fprintf(stderr, "%s:  error writing %s\n", argv[0], outfile);
    301 				exit(1);
    302 			}
    303 		} else {
    304 			printf("%s:  writing CIL to %s\n",argv[0], outfile);
    305 
    306 			if (sepol_module_policydb_to_cil(outfp, &modpolicydb, 0) != 0) {
    307 				fprintf(stderr, "%s:  error writing %s\n", argv[0], outfile);
    308 				exit(1);
    309 			}
    310 		}
    311 
    312 		fclose(outfp);
    313 	} else if (cil) {
    314 		fprintf(stderr, "%s:  No file to write CIL was specified\n", argv[0]);
    315 		exit(1);
    316 	}
    317 
    318 	policydb_destroy(&modpolicydb);
    319 
    320 	return 0;
    321 }
    322 
    323 /* FLASK */
    324