16cd6a6acSopenharmony_ci/*
26cd6a6acSopenharmony_ci * Authors: Joshua Brindle <jbrindle@tresys.com>
36cd6a6acSopenharmony_ci *	    Karl MacMillan <kmacmillan@tresys.com>
46cd6a6acSopenharmony_ci *          Jason Tang     <jtang@tresys.com>
56cd6a6acSopenharmony_ci *
66cd6a6acSopenharmony_ci *
76cd6a6acSopenharmony_ci * Copyright (C) 2004-5 Tresys Technology, LLC
86cd6a6acSopenharmony_ci *	This program is free software; you can redistribute it and/or modify
96cd6a6acSopenharmony_ci *  	it under the terms of the GNU General Public License as published by
106cd6a6acSopenharmony_ci *	the Free Software Foundation, version 2.
116cd6a6acSopenharmony_ci */
126cd6a6acSopenharmony_ci
136cd6a6acSopenharmony_ci#include <getopt.h>
146cd6a6acSopenharmony_ci#include <unistd.h>
156cd6a6acSopenharmony_ci#include <stdlib.h>
166cd6a6acSopenharmony_ci#include <sys/types.h>
176cd6a6acSopenharmony_ci#include <sys/stat.h>
186cd6a6acSopenharmony_ci#include <fcntl.h>
196cd6a6acSopenharmony_ci#include <stdio.h>
206cd6a6acSopenharmony_ci#include <errno.h>
216cd6a6acSopenharmony_ci#include <sys/mman.h>
226cd6a6acSopenharmony_ci#include <libgen.h>
236cd6a6acSopenharmony_ci
246cd6a6acSopenharmony_ci#include <sepol/module_to_cil.h>
256cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h>
266cd6a6acSopenharmony_ci#include <sepol/policydb/services.h>
276cd6a6acSopenharmony_ci#include <sepol/policydb/conditional.h>
286cd6a6acSopenharmony_ci#include <sepol/policydb/hierarchy.h>
296cd6a6acSopenharmony_ci#include <sepol/policydb/expand.h>
306cd6a6acSopenharmony_ci#include <sepol/policydb/link.h>
316cd6a6acSopenharmony_ci#include <sepol/policydb/sidtab.h>
326cd6a6acSopenharmony_ci
336cd6a6acSopenharmony_ci#include "queue.h"
346cd6a6acSopenharmony_ci#include "checkpolicy.h"
356cd6a6acSopenharmony_ci#include "parse_util.h"
366cd6a6acSopenharmony_ci
376cd6a6acSopenharmony_cistatic sidtab_t sidtab;
386cd6a6acSopenharmony_ci
396cd6a6acSopenharmony_ciextern int mlspol;
406cd6a6acSopenharmony_ciextern int werror;
416cd6a6acSopenharmony_ci
426cd6a6acSopenharmony_cistatic int handle_unknown = SEPOL_DENY_UNKNOWN;
436cd6a6acSopenharmony_cistatic const char *txtfile = "policy.conf";
446cd6a6acSopenharmony_cistatic const char *binfile = "policy";
456cd6a6acSopenharmony_ci
466cd6a6acSopenharmony_ciunsigned int policy_type = POLICY_BASE;
476cd6a6acSopenharmony_ciunsigned int policyvers = MOD_POLICYDB_VERSION_MAX;
486cd6a6acSopenharmony_ci
496cd6a6acSopenharmony_cistatic int read_binary_policy(policydb_t * p, const char *file, const char *progname)
506cd6a6acSopenharmony_ci{
516cd6a6acSopenharmony_ci	int fd;
526cd6a6acSopenharmony_ci	struct stat sb;
536cd6a6acSopenharmony_ci	void *map;
546cd6a6acSopenharmony_ci	struct policy_file f, *fp;
556cd6a6acSopenharmony_ci
566cd6a6acSopenharmony_ci	fd = open(file, O_RDONLY);
576cd6a6acSopenharmony_ci	if (fd < 0) {
586cd6a6acSopenharmony_ci		fprintf(stderr, "Can't open '%s':  %s\n",
596cd6a6acSopenharmony_ci			file, strerror(errno));
606cd6a6acSopenharmony_ci		return -1;
616cd6a6acSopenharmony_ci	}
626cd6a6acSopenharmony_ci	if (fstat(fd, &sb) < 0) {
636cd6a6acSopenharmony_ci		fprintf(stderr, "Can't stat '%s':  %s\n",
646cd6a6acSopenharmony_ci			file, strerror(errno));
656cd6a6acSopenharmony_ci		close(fd);
666cd6a6acSopenharmony_ci		return -1;
676cd6a6acSopenharmony_ci	}
686cd6a6acSopenharmony_ci	map =
696cd6a6acSopenharmony_ci	    mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
706cd6a6acSopenharmony_ci	close(fd);
716cd6a6acSopenharmony_ci	if (map == MAP_FAILED) {
726cd6a6acSopenharmony_ci		fprintf(stderr, "Can't map '%s':  %s\n", file, strerror(errno));
736cd6a6acSopenharmony_ci		return -1;
746cd6a6acSopenharmony_ci	}
756cd6a6acSopenharmony_ci	policy_file_init(&f);
766cd6a6acSopenharmony_ci	f.type = PF_USE_MEMORY;
776cd6a6acSopenharmony_ci	f.data = map;
786cd6a6acSopenharmony_ci	f.len = sb.st_size;
796cd6a6acSopenharmony_ci	fp = &f;
806cd6a6acSopenharmony_ci
816cd6a6acSopenharmony_ci	if (policydb_init(p)) {
826cd6a6acSopenharmony_ci		fprintf(stderr, "%s:  policydb_init:  Out of memory!\n",
836cd6a6acSopenharmony_ci			progname);
846cd6a6acSopenharmony_ci		return -1;
856cd6a6acSopenharmony_ci	}
866cd6a6acSopenharmony_ci	if (policydb_read(p, fp, 1)) {
876cd6a6acSopenharmony_ci		fprintf(stderr,
886cd6a6acSopenharmony_ci			"%s:  error(s) encountered while parsing configuration\n",
896cd6a6acSopenharmony_ci			progname);
906cd6a6acSopenharmony_ci		return -1;
916cd6a6acSopenharmony_ci	}
926cd6a6acSopenharmony_ci
936cd6a6acSopenharmony_ci	/* Check Policy Consistency */
946cd6a6acSopenharmony_ci	if (p->mls) {
956cd6a6acSopenharmony_ci		if (!mlspol) {
966cd6a6acSopenharmony_ci			fprintf(stderr, "%s:  MLS policy, but non-MLS"
976cd6a6acSopenharmony_ci				" is specified\n", progname);
986cd6a6acSopenharmony_ci			return -1;
996cd6a6acSopenharmony_ci		}
1006cd6a6acSopenharmony_ci	} else {
1016cd6a6acSopenharmony_ci		if (mlspol) {
1026cd6a6acSopenharmony_ci			fprintf(stderr, "%s:  non-MLS policy, but MLS"
1036cd6a6acSopenharmony_ci				" is specified\n", progname);
1046cd6a6acSopenharmony_ci			return -1;
1056cd6a6acSopenharmony_ci		}
1066cd6a6acSopenharmony_ci	}
1076cd6a6acSopenharmony_ci	return 0;
1086cd6a6acSopenharmony_ci}
1096cd6a6acSopenharmony_ci
1106cd6a6acSopenharmony_cistatic int write_binary_policy(policydb_t * p, FILE *outfp)
1116cd6a6acSopenharmony_ci{
1126cd6a6acSopenharmony_ci	struct policy_file pf;
1136cd6a6acSopenharmony_ci
1146cd6a6acSopenharmony_ci	p->policy_type = policy_type;
1156cd6a6acSopenharmony_ci	p->policyvers = policyvers;
1166cd6a6acSopenharmony_ci	p->handle_unknown = handle_unknown;
1176cd6a6acSopenharmony_ci
1186cd6a6acSopenharmony_ci	policy_file_init(&pf);
1196cd6a6acSopenharmony_ci	pf.type = PF_USE_STDIO;
1206cd6a6acSopenharmony_ci	pf.fp = outfp;
1216cd6a6acSopenharmony_ci	return policydb_write(p, &pf);
1226cd6a6acSopenharmony_ci}
1236cd6a6acSopenharmony_ci
1246cd6a6acSopenharmony_cistatic __attribute__((__noreturn__)) void usage(const char *progname)
1256cd6a6acSopenharmony_ci{
1266cd6a6acSopenharmony_ci	printf("usage:  %s [-h] [-V] [-b] [-C] [-E] [-U handle_unknown] [-m] [-M] [-o FILE] [-c VERSION] [INPUT]\n", progname);
1276cd6a6acSopenharmony_ci	printf("Build base and policy modules.\n");
1286cd6a6acSopenharmony_ci	printf("Options:\n");
1296cd6a6acSopenharmony_ci	printf("  INPUT      build module from INPUT (else read from \"%s\")\n",
1306cd6a6acSopenharmony_ci	       txtfile);
1316cd6a6acSopenharmony_ci	printf("  -V         show policy versions created by this program\n");
1326cd6a6acSopenharmony_ci	printf("  -b         treat input as a binary policy file\n");
1336cd6a6acSopenharmony_ci	printf("  -C         output CIL policy instead of binary policy\n");
1346cd6a6acSopenharmony_ci	printf("  -E         treat warnings as errors\n");
1356cd6a6acSopenharmony_ci	printf("  -h         print usage\n");
1366cd6a6acSopenharmony_ci	printf("  -U OPTION  How to handle unknown classes and permissions\n");
1376cd6a6acSopenharmony_ci	printf("               deny: Deny unknown kernel checks\n");
1386cd6a6acSopenharmony_ci	printf("               reject: Reject loading of policy with unknowns\n");
1396cd6a6acSopenharmony_ci	printf("               allow: Allow unknown kernel checks\n");
1406cd6a6acSopenharmony_ci	printf("  -m         build a policy module instead of a base module\n");
1416cd6a6acSopenharmony_ci	printf("  -M         enable MLS policy\n");
1426cd6a6acSopenharmony_ci	printf("  -o FILE    write module to FILE (else just check syntax)\n");
1436cd6a6acSopenharmony_ci	printf("  -c VERSION build a policy module targeting a modular policy version (%d-%d)\n",
1446cd6a6acSopenharmony_ci	       MOD_POLICYDB_VERSION_MIN, MOD_POLICYDB_VERSION_MAX);
1456cd6a6acSopenharmony_ci	exit(1);
1466cd6a6acSopenharmony_ci}
1476cd6a6acSopenharmony_ci
1486cd6a6acSopenharmony_ciint main(int argc, char **argv)
1496cd6a6acSopenharmony_ci{
1506cd6a6acSopenharmony_ci	const char *file = txtfile, *outfile = NULL;
1516cd6a6acSopenharmony_ci	unsigned int binary = 0, cil = 0;
1526cd6a6acSopenharmony_ci	int ch;
1536cd6a6acSopenharmony_ci	int show_version = 0;
1546cd6a6acSopenharmony_ci	policydb_t modpolicydb;
1556cd6a6acSopenharmony_ci	const struct option long_options[] = {
1566cd6a6acSopenharmony_ci		{"help", no_argument, NULL, 'h'},
1576cd6a6acSopenharmony_ci		{"output", required_argument, NULL, 'o'},
1586cd6a6acSopenharmony_ci		{"binary", no_argument, NULL, 'b'},
1596cd6a6acSopenharmony_ci		{"version", no_argument, NULL, 'V'},
1606cd6a6acSopenharmony_ci		{"handle-unknown", required_argument, NULL, 'U'},
1616cd6a6acSopenharmony_ci		{"mls", no_argument, NULL, 'M'},
1626cd6a6acSopenharmony_ci		{"cil", no_argument, NULL, 'C'},
1636cd6a6acSopenharmony_ci		{"werror", no_argument, NULL, 'E'},
1646cd6a6acSopenharmony_ci		{NULL, 0, NULL, 0}
1656cd6a6acSopenharmony_ci	};
1666cd6a6acSopenharmony_ci
1676cd6a6acSopenharmony_ci	while ((ch = getopt_long(argc, argv, "ho:bVEU:mMCc:", long_options, NULL)) != -1) {
1686cd6a6acSopenharmony_ci		switch (ch) {
1696cd6a6acSopenharmony_ci		case 'h':
1706cd6a6acSopenharmony_ci			usage(argv[0]);
1716cd6a6acSopenharmony_ci			break;
1726cd6a6acSopenharmony_ci		case 'o':
1736cd6a6acSopenharmony_ci			outfile = optarg;
1746cd6a6acSopenharmony_ci			break;
1756cd6a6acSopenharmony_ci		case 'b':
1766cd6a6acSopenharmony_ci			binary = 1;
1776cd6a6acSopenharmony_ci			file = binfile;
1786cd6a6acSopenharmony_ci			break;
1796cd6a6acSopenharmony_ci		case 'V':
1806cd6a6acSopenharmony_ci			show_version = 1;
1816cd6a6acSopenharmony_ci			break;
1826cd6a6acSopenharmony_ci		case 'E':
1836cd6a6acSopenharmony_ci			werror = 1;
1846cd6a6acSopenharmony_ci			break;
1856cd6a6acSopenharmony_ci		case 'U':
1866cd6a6acSopenharmony_ci			if (!strcasecmp(optarg, "deny")) {
1876cd6a6acSopenharmony_ci				handle_unknown = DENY_UNKNOWN;
1886cd6a6acSopenharmony_ci				break;
1896cd6a6acSopenharmony_ci			}
1906cd6a6acSopenharmony_ci			if (!strcasecmp(optarg, "reject")) {
1916cd6a6acSopenharmony_ci				handle_unknown = REJECT_UNKNOWN;
1926cd6a6acSopenharmony_ci				break;
1936cd6a6acSopenharmony_ci			}
1946cd6a6acSopenharmony_ci			if (!strcasecmp(optarg, "allow")) {
1956cd6a6acSopenharmony_ci				handle_unknown = ALLOW_UNKNOWN;
1966cd6a6acSopenharmony_ci				break;
1976cd6a6acSopenharmony_ci			}
1986cd6a6acSopenharmony_ci			usage(argv[0]);
1996cd6a6acSopenharmony_ci		case 'm':
2006cd6a6acSopenharmony_ci			policy_type = POLICY_MOD;
2016cd6a6acSopenharmony_ci			break;
2026cd6a6acSopenharmony_ci		case 'M':
2036cd6a6acSopenharmony_ci			mlspol = 1;
2046cd6a6acSopenharmony_ci			break;
2056cd6a6acSopenharmony_ci		case 'C':
2066cd6a6acSopenharmony_ci			cil = 1;
2076cd6a6acSopenharmony_ci			break;
2086cd6a6acSopenharmony_ci		case 'c': {
2096cd6a6acSopenharmony_ci			long int n;
2106cd6a6acSopenharmony_ci			errno = 0;
2116cd6a6acSopenharmony_ci			n = strtol(optarg, NULL, 10);
2126cd6a6acSopenharmony_ci			if (errno) {
2136cd6a6acSopenharmony_ci				fprintf(stderr,
2146cd6a6acSopenharmony_ci					"Invalid policyvers specified: %s\n",
2156cd6a6acSopenharmony_ci					optarg);
2166cd6a6acSopenharmony_ci				usage(argv[0]);
2176cd6a6acSopenharmony_ci			}
2186cd6a6acSopenharmony_ci
2196cd6a6acSopenharmony_ci			if (n < MOD_POLICYDB_VERSION_MIN
2206cd6a6acSopenharmony_ci			    || n > MOD_POLICYDB_VERSION_MAX) {
2216cd6a6acSopenharmony_ci				fprintf(stderr,
2226cd6a6acSopenharmony_ci					"policyvers value %ld not in range %d-%d\n",
2236cd6a6acSopenharmony_ci					n, MOD_POLICYDB_VERSION_MIN,
2246cd6a6acSopenharmony_ci					MOD_POLICYDB_VERSION_MAX);
2256cd6a6acSopenharmony_ci				usage(argv[0]);
2266cd6a6acSopenharmony_ci			}
2276cd6a6acSopenharmony_ci
2286cd6a6acSopenharmony_ci			policyvers = n;
2296cd6a6acSopenharmony_ci			break;
2306cd6a6acSopenharmony_ci		}
2316cd6a6acSopenharmony_ci		default:
2326cd6a6acSopenharmony_ci			usage(argv[0]);
2336cd6a6acSopenharmony_ci		}
2346cd6a6acSopenharmony_ci	}
2356cd6a6acSopenharmony_ci
2366cd6a6acSopenharmony_ci	if (show_version) {
2376cd6a6acSopenharmony_ci		printf("Module versions %d-%d\n",
2386cd6a6acSopenharmony_ci		       MOD_POLICYDB_VERSION_MIN, MOD_POLICYDB_VERSION_MAX);
2396cd6a6acSopenharmony_ci		exit(0);
2406cd6a6acSopenharmony_ci	}
2416cd6a6acSopenharmony_ci
2426cd6a6acSopenharmony_ci	if (handle_unknown && (policy_type != POLICY_BASE)) {
2436cd6a6acSopenharmony_ci		fprintf(stderr, "%s:  Handling of unknown classes and permissions is only valid in the base module.\n", argv[0]);
2446cd6a6acSopenharmony_ci		exit(1);
2456cd6a6acSopenharmony_ci	}
2466cd6a6acSopenharmony_ci
2476cd6a6acSopenharmony_ci	if (binary && (policy_type != POLICY_BASE)) {
2486cd6a6acSopenharmony_ci		fprintf(stderr, "%s:  -b and -m are incompatible with each other.\n", argv[0]);
2496cd6a6acSopenharmony_ci		exit(1);
2506cd6a6acSopenharmony_ci	}
2516cd6a6acSopenharmony_ci
2526cd6a6acSopenharmony_ci	if (optind != argc) {
2536cd6a6acSopenharmony_ci		file = argv[optind++];
2546cd6a6acSopenharmony_ci		if (optind != argc)
2556cd6a6acSopenharmony_ci			usage(argv[0]);
2566cd6a6acSopenharmony_ci	}
2576cd6a6acSopenharmony_ci
2586cd6a6acSopenharmony_ci	/* Set policydb and sidtab used by libsepol service functions
2596cd6a6acSopenharmony_ci	   to my structures, so that I can directly populate and
2606cd6a6acSopenharmony_ci	   manipulate them. */
2616cd6a6acSopenharmony_ci	sepol_set_policydb(&modpolicydb);
2626cd6a6acSopenharmony_ci	sepol_set_sidtab(&sidtab);
2636cd6a6acSopenharmony_ci
2646cd6a6acSopenharmony_ci	if (binary) {
2656cd6a6acSopenharmony_ci		if (read_binary_policy(&modpolicydb, file, argv[0]) == -1) {
2666cd6a6acSopenharmony_ci			exit(1);
2676cd6a6acSopenharmony_ci		}
2686cd6a6acSopenharmony_ci	} else {
2696cd6a6acSopenharmony_ci		if (policydb_init(&modpolicydb)) {
2706cd6a6acSopenharmony_ci			fprintf(stderr, "%s: out of memory!\n", argv[0]);
2716cd6a6acSopenharmony_ci			exit(1);
2726cd6a6acSopenharmony_ci		}
2736cd6a6acSopenharmony_ci
2746cd6a6acSopenharmony_ci		modpolicydb.policy_type = policy_type;
2756cd6a6acSopenharmony_ci		modpolicydb.mls = mlspol;
2766cd6a6acSopenharmony_ci		modpolicydb.handle_unknown = handle_unknown;
2776cd6a6acSopenharmony_ci
2786cd6a6acSopenharmony_ci		if (read_source_policy(&modpolicydb, file, argv[0]) == -1) {
2796cd6a6acSopenharmony_ci			exit(1);
2806cd6a6acSopenharmony_ci		}
2816cd6a6acSopenharmony_ci
2826cd6a6acSopenharmony_ci		if (hierarchy_check_constraints(NULL, &modpolicydb)) {
2836cd6a6acSopenharmony_ci			exit(1);
2846cd6a6acSopenharmony_ci		}
2856cd6a6acSopenharmony_ci	}
2866cd6a6acSopenharmony_ci
2876cd6a6acSopenharmony_ci	if (policy_type != POLICY_BASE && outfile) {
2886cd6a6acSopenharmony_ci		char *out_name;
2896cd6a6acSopenharmony_ci		char *separator;
2906cd6a6acSopenharmony_ci		char *mod_name = modpolicydb.name;
2916cd6a6acSopenharmony_ci		char *out_path = strdup(outfile);
2926cd6a6acSopenharmony_ci		if (out_path == NULL) {
2936cd6a6acSopenharmony_ci			fprintf(stderr, "%s:  out of memory\n", argv[0]);
2946cd6a6acSopenharmony_ci			exit(1);
2956cd6a6acSopenharmony_ci		}
2966cd6a6acSopenharmony_ci		out_name = basename(out_path);
2976cd6a6acSopenharmony_ci		separator = strrchr(out_name, '.');
2986cd6a6acSopenharmony_ci		if (separator) {
2996cd6a6acSopenharmony_ci			*separator = '\0';
3006cd6a6acSopenharmony_ci		}
3016cd6a6acSopenharmony_ci		if (strcmp(mod_name, out_name) != 0) {
3026cd6a6acSopenharmony_ci			fprintf(stderr,	"%s:  Module name %s is different than the output base filename %s\n", argv[0], mod_name, out_name);
3036cd6a6acSopenharmony_ci			exit(1);
3046cd6a6acSopenharmony_ci		}
3056cd6a6acSopenharmony_ci		free(out_path);
3066cd6a6acSopenharmony_ci	}
3076cd6a6acSopenharmony_ci
3086cd6a6acSopenharmony_ci	if (modpolicydb.policy_type == POLICY_BASE && !cil) {
3096cd6a6acSopenharmony_ci		/* Verify that we can successfully expand the base module. */
3106cd6a6acSopenharmony_ci		policydb_t kernpolicydb;
3116cd6a6acSopenharmony_ci
3126cd6a6acSopenharmony_ci		if (policydb_init(&kernpolicydb)) {
3136cd6a6acSopenharmony_ci			fprintf(stderr, "%s:  policydb_init failed\n", argv[0]);
3146cd6a6acSopenharmony_ci			exit(1);
3156cd6a6acSopenharmony_ci		}
3166cd6a6acSopenharmony_ci		if (link_modules(NULL, &modpolicydb, NULL, 0, 0)) {
3176cd6a6acSopenharmony_ci			fprintf(stderr, "%s:  link modules failed\n", argv[0]);
3186cd6a6acSopenharmony_ci			exit(1);
3196cd6a6acSopenharmony_ci		}
3206cd6a6acSopenharmony_ci		if (expand_module(NULL, &modpolicydb, &kernpolicydb, 0, 1)) {
3216cd6a6acSopenharmony_ci			fprintf(stderr, "%s:  expand module failed\n", argv[0]);
3226cd6a6acSopenharmony_ci			exit(1);
3236cd6a6acSopenharmony_ci		}
3246cd6a6acSopenharmony_ci		policydb_destroy(&kernpolicydb);
3256cd6a6acSopenharmony_ci	}
3266cd6a6acSopenharmony_ci
3276cd6a6acSopenharmony_ci	if (policydb_load_isids(&modpolicydb, &sidtab))
3286cd6a6acSopenharmony_ci		exit(1);
3296cd6a6acSopenharmony_ci
3306cd6a6acSopenharmony_ci	sepol_sidtab_destroy(&sidtab);
3316cd6a6acSopenharmony_ci
3326cd6a6acSopenharmony_ci	if (outfile) {
3336cd6a6acSopenharmony_ci		FILE *outfp = fopen(outfile, "w");
3346cd6a6acSopenharmony_ci
3356cd6a6acSopenharmony_ci		if (!outfp) {
3366cd6a6acSopenharmony_ci			fprintf(stderr, "%s:  error opening %s:  %s\n", argv[0], outfile, strerror(errno));
3376cd6a6acSopenharmony_ci			exit(1);
3386cd6a6acSopenharmony_ci		}
3396cd6a6acSopenharmony_ci
3406cd6a6acSopenharmony_ci		if (!cil) {
3416cd6a6acSopenharmony_ci			if (write_binary_policy(&modpolicydb, outfp) != 0) {
3426cd6a6acSopenharmony_ci				fprintf(stderr, "%s:  error writing %s\n", argv[0], outfile);
3436cd6a6acSopenharmony_ci				exit(1);
3446cd6a6acSopenharmony_ci			}
3456cd6a6acSopenharmony_ci		} else {
3466cd6a6acSopenharmony_ci			if (sepol_module_policydb_to_cil(outfp, &modpolicydb, 0) != 0) {
3476cd6a6acSopenharmony_ci				fprintf(stderr, "%s:  error writing %s\n", argv[0], outfile);
3486cd6a6acSopenharmony_ci				exit(1);
3496cd6a6acSopenharmony_ci			}
3506cd6a6acSopenharmony_ci		}
3516cd6a6acSopenharmony_ci
3526cd6a6acSopenharmony_ci		if (fclose(outfp)) {
3536cd6a6acSopenharmony_ci			fprintf(stderr, "%s:  error closing %s:  %s\n", argv[0], outfile, strerror(errno));
3546cd6a6acSopenharmony_ci			exit(1);
3556cd6a6acSopenharmony_ci		}
3566cd6a6acSopenharmony_ci	} else if (cil) {
3576cd6a6acSopenharmony_ci		fprintf(stderr, "%s:  No file to write CIL was specified\n", argv[0]);
3586cd6a6acSopenharmony_ci		exit(1);
3596cd6a6acSopenharmony_ci	}
3606cd6a6acSopenharmony_ci
3616cd6a6acSopenharmony_ci	policydb_destroy(&modpolicydb);
3626cd6a6acSopenharmony_ci
3636cd6a6acSopenharmony_ci	return 0;
3646cd6a6acSopenharmony_ci}
3656cd6a6acSopenharmony_ci
3666cd6a6acSopenharmony_ci/* FLASK */
367