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