1f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#include <stdio.h>
2f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#include <stdarg.h>
3f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#include <ctype.h>
4f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#include <stdio.h>
5f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#include <stdlib.h>
6f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#include <unistd.h>
7f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#include <string.h>
8f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#include <errno.h>
9f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#include <stdint.h>
10f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#include <search.h>
1161846291746a3a3559f615ef3665312ccd2228c2William Roberts#include <stdbool.h>
12f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#include <sepol/sepol.h>
13f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#include <sepol/policydb/policydb.h>
1481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts#include <pcre.h>
15f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
16f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#define TABLE_SIZE 1024
17f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#define KVP_NUM_OF_RULES (sizeof(rules) / sizeof(key_map))
18f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#define log_set_verbose() do { logging_verbose = 1; log_info("Enabling verbose\n"); } while(0)
19f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#define log_error(fmt, ...) log_msg(stderr, "Error: ", fmt, ##__VA_ARGS__)
20f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#define log_warn(fmt, ...) log_msg(stderr, "Warning: ", fmt, ##__VA_ARGS__)
21f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#define log_info(fmt, ...) if (logging_verbose ) { log_msg(stdout, "Info: ", fmt, ##__VA_ARGS__); }
22f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
2381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts/**
2481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * Initializes an empty, static list.
2581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts */
2681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts#define list_init(free_fn) { .head = NULL, .tail = NULL, .freefn = free_fn }
2781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
2881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts/**
2981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * given an item in the list, finds the offset for the container
3081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * it was stored in.
3181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts *
3281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * @element The element from the list
3381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * @type The container type ie what you allocated that has the list_element structure in it.
3481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * @name The name of the field that is the list_element
3581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts *
3681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts */
3781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts#define list_entry(element, type, name) \
3881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		(type *)(((uint8_t *)element) - (uint8_t *)&(((type *)NULL)->name))
3981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
4081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts/**
4181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * Iterates over the list, do not free elements from the list when using this.
4281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * @list The list head to walk
4381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * @var The variable name for the cursor
4481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts */
4581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts#define list_for_each(list, var) \
4681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	for(var = (list)->head; var != NULL; var = var->next)
4781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
4881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
49f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertstypedef struct hash_entry hash_entry;
50f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertstypedef enum key_dir key_dir;
51f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertstypedef enum data_type data_type;
52f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertstypedef enum rule_map_switch rule_map_switch;
530ae3a8a2d50799d0b91d992434cdd4d3151b0348William Robertstypedef enum map_match map_match;
54f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertstypedef struct key_map key_map;
55f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertstypedef struct kvp kvp;
56f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertstypedef struct rule_map rule_map;
57f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertstypedef struct policy_info policy_info;
5881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertstypedef struct list_element list_element;
5981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertstypedef struct list list;
6081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertstypedef struct key_map_regex key_map_regex;
6181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertstypedef struct file_info file_info;
62f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
630ae3a8a2d50799d0b91d992434cdd4d3151b0348William Robertsenum map_match {
640ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	map_no_matches,
650ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	map_input_matched,
660ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	map_matched
670ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts};
680ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts
690b820042e4bb9bb93790e0cf0812fd97d15ce7a5Stephen Smalleyconst char *map_match_str[] = {
700b820042e4bb9bb93790e0cf0812fd97d15ce7a5Stephen Smalley	"do not match",
710b820042e4bb9bb93790e0cf0812fd97d15ce7a5Stephen Smalley	"match on all inputs",
720b820042e4bb9bb93790e0cf0812fd97d15ce7a5Stephen Smalley	"match on everything"
730b820042e4bb9bb93790e0cf0812fd97d15ce7a5Stephen Smalley};
740b820042e4bb9bb93790e0cf0812fd97d15ce7a5Stephen Smalley
75f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
76f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Whether or not the "key" from a key vaue pair is considered an
77f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * input or an output.
78f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
79f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsenum key_dir {
80f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	dir_in, dir_out
81f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts};
82f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
8381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstruct list_element {
8481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element *next;
8581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts};
8681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
8781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstruct list {
8881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element *head;
8981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element *tail;
9081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	void (*freefn)(list_element *e);
9181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts};
9281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
9381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstruct key_map_regex {
9481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	pcre *compiled;
9581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	pcre_extra *extra;
96f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts};
97f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
98f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
99f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * The workhorse of the logic. This struct maps key value pairs to
100f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * an associated set of meta data maintained in rule_map_new()
101f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
102f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstruct key_map {
103f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	char *name;
104f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	key_dir dir;
105f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	char *data;
10681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	key_map_regex regex;
1077bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	bool (*fn_validate)(char *value, char **errmsg);
108f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts};
109f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
110f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
111f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Key value pair struct, this represents the raw kvp values coming
112f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * from the rules files.
113f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
114f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstruct kvp {
115f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	char *key;
116f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	char *value;
117f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts};
118f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
119f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
120f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Rules are made up of meta data and an associated set of kvp stored in a
121f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * key_map array.
122f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
123f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstruct rule_map {
12481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	bool is_never_allow;
12581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list violations;
12681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element listify;
127f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	char *key; /** key value before hashing */
128610a4b1c32490ac9f6f7ca0fafba8c182a542934William Roberts	size_t length; /** length of the key map */
129f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	int lineno; /** Line number rule was encounter on */
13081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	char *filename; /** File it was found in */
131f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	key_map m[]; /** key value mapping */
132f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts};
133f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
134f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstruct hash_entry {
13581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element listify;
136f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	rule_map *r; /** The rule map to store at that location */
137f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts};
138f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
139f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
140f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Data associated for a policy file
141f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
142f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstruct policy_info {
143f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
144f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	char *policy_file_name; /** policy file path name */
145f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	FILE *policy_file;      /** file handle to the policy file */
146f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	sepol_policydb_t *db;
147f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	sepol_policy_file_t *pf;
148f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	sepol_handle_t *handle;
149f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	sepol_context_t *con;
150f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts};
151f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
15281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstruct file_info {
15381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	FILE *file; /** file itself */
15481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	const char *name; /** name of file. do not free, these are not alloc'd */
15581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element listify;
15681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts};
15781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
15881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic void input_file_list_freefn(list_element *e);
15981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic void line_order_list_freefn(list_element *e);
16081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic void rule_map_free(rule_map *rm, bool is_in_htable);
16181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
162f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/** Set to !0 to enable verbose logging */
163f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstatic int logging_verbose = 0;
164f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
165f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/** file handle to the output file */
16681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic file_info out_file;
167f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
16881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic list input_file_list = list_init(input_file_list_freefn);
169f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
170f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstatic policy_info pol = {
171f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	.policy_file_name = NULL,
172f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	.policy_file = NULL,
173f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	.db = NULL,
174f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	.pf = NULL,
175f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	.handle = NULL,
176f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	.con = NULL
177f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts};
178f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
179f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
18081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * Head pointer to a linked list of
18181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * rule map table entries (hash_entry), used for
18281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * preserving the order of entries
18381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * based on "first encounter"
18481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts */
18581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic list line_order_list = list_init(line_order_list_freefn);
18681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
18781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts/*
18881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * List of hash_entrys for never allow rules.
18981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts */
19081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic list nallow_list = list_init(line_order_list_freefn);
19181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
1927bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts/* validation call backs */
1937bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Robertsstatic bool validate_bool(char *value, char **errmsg);
1947bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Robertsstatic bool validate_levelFrom(char *value, char **errmsg);
1957bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Robertsstatic bool validate_selinux_type(char *value, char **errmsg);
1967bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Robertsstatic bool validate_selinux_level(char *value, char **errmsg);
1977bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
19881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts/**
199f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * The heart of the mapping process, this must be updated if a new key value pair is added
200f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * to a rule.
201f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
202f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertskey_map rules[] = {
203f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts                /*Inputs*/
204d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "isSystemServer", .dir = dir_in, .fn_validate = validate_bool },
205d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "isAutoPlayApp",  .dir = dir_in, .fn_validate = validate_bool },
206d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "isOwner",        .dir = dir_in, .fn_validate = validate_bool },
207d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "user",           .dir = dir_in,                              },
208d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "seinfo",         .dir = dir_in,                              },
209d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "name",           .dir = dir_in,                              },
210d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "path",           .dir = dir_in,                              },
211d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "isPrivApp",      .dir = dir_in, .fn_validate = validate_bool },
212f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts                /*Outputs*/
213d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "domain",         .dir = dir_out, .fn_validate = validate_selinux_type  },
214d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "type",           .dir = dir_out, .fn_validate = validate_selinux_type  },
215d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "levelFromUid",   .dir = dir_out, .fn_validate = validate_bool          },
216d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "levelFrom",      .dir = dir_out, .fn_validate = validate_levelFrom     },
217d7eedeb89c9d59562e9e2d82102fd4b3adba7f30William Roberts                { .name = "level",          .dir = dir_out, .fn_validate = validate_selinux_level },
218fff2980a1ac2aca5966f6b54fa030309a0d98e0cWilliam Roberts};
219f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
220f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
22181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * Appends to the end of the list.
22281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * @list The list to append to
22381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * @e the element to append
224f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
22581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsvoid list_append(list *list, list_element *e) {
22681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
22781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	memset(e, 0, sizeof(*e));
22881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
22981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if (list->head == NULL ) {
23081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		list->head = list->tail = e;
23181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		return;
23281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
23381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
23481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list->tail->next = e;
23581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list->tail = e;
23681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	return;
23781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts}
238f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
239f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
24081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * Free's all the elements in the specified list.
24181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * @list The list to free
242f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
24381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic void list_free(list *list) {
24481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
24581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element *tmp;
24681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element *cursor = list->head;
24781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
24881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	while (cursor) {
24981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		tmp = cursor;
25081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		cursor = cursor->next;
25181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		if (list->freefn) {
25281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			list->freefn(tmp);
25381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		}
25481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
25581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts}
25681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
25781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts/*
25881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * called when the lists are freed
25981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts */
26081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic void line_order_list_freefn(list_element *e) {
26181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	hash_entry *h = list_entry(e, typeof(*h), listify);
26281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	rule_map_free(h->r, true);
26381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	free(h);
26481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts}
26581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
26681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic void input_file_list_freefn(list_element *e) {
26781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	file_info *f = list_entry(e, typeof(*f), listify);
26881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
26981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if (f->file) {
27081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		fclose(f->file);
27181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
27281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	free(f);
27381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts}
274f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
275f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
276f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Send a logging message to a file
277f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param out
278f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	Output file to send message too
279f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param prefix
280f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	A special prefix to write to the file, such as "Error:"
281f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param fmt
282f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	The printf style formatter to use, such as "%d"
283f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
2841e8c061b053cdfd808c7a7649c78df4c33ded63dWilliam Robertsstatic void __attribute__ ((format(printf, 3, 4)))
2851e8c061b053cdfd808c7a7649c78df4c33ded63dWilliam Robertslog_msg(FILE *out, const char *prefix, const char *fmt, ...) {
2861e8c061b053cdfd808c7a7649c78df4c33ded63dWilliam Roberts
287f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	fprintf(out, "%s", prefix);
288f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	va_list args;
289f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	va_start(args, fmt);
290f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	vfprintf(out, fmt, args);
291f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	va_end(args);
292f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
293f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
294f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
295f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Checks for a type in the policy.
296f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param db
297f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	The policy db to search
298f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param type
299f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	The type to search for
300f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @return
301f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	1 if the type is found, 0 otherwise.
302f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @warning
303f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	This function always returns 1 if libsepol is not linked
304f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	statically to this executable and LINK_SEPOL_STATIC is not
305f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	defined.
306f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
307ffd053ba93f2ddc0f97c8461a722035972f61f03William Robertsstatic int check_type(sepol_policydb_t *db, char *type) {
308f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
309f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	int rc = 1;
310f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#if defined(LINK_SEPOL_STATIC)
311f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	policydb_t *d = (policydb_t *)db;
312f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	hashtab_datum_t dat;
313f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	dat = hashtab_search(d->p_types.table, type);
314f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	rc = (dat == NULL) ? 0 : 1;
315f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts#endif
316f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	return rc;
317f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
318f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
31981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic bool match_regex(key_map *assert, const key_map *check) {
32081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
32181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	char *tomatch = check->data;
32281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
32381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	int ret = pcre_exec(assert->regex.compiled, assert->regex.extra, tomatch,
32481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			strlen(tomatch), 0, 0, NULL, 0);
32581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
32681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	/* 0 from pcre_exec means matched */
32781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	return !ret;
32881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts}
32981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
33081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic bool compile_regex(key_map *km, const char **errbuf, int *erroff) {
33181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
33281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	size_t size;
33381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	char *anchored;
33481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
33581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	/*
33681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	 * Explicitly anchor all regex's
33781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	 * The size is the length of the string to anchor (km->data), the anchor
33881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	 * characters ^ and $ and the null byte. Hence strlen(km->data) + 3
33981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	 */
34081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	size = strlen(km->data) + 3;
34181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	anchored = alloca(size);
34281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	sprintf(anchored, "^%s$", km->data);
34381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
34481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	km->regex.compiled = pcre_compile(anchored, PCRE_DOTALL, errbuf, erroff,
34581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			NULL );
34681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if (!km->regex.compiled) {
34781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		return false;
34881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
34981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
35081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	km->regex.extra = pcre_study(km->regex.compiled, 0, errbuf);
35181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	return true;
35281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts}
35381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
3547bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Robertsstatic bool validate_bool(char *value, char **errmsg) {
3557bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
3567bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	if (!strcmp("true", value) || !strcmp("false", value)) {
3577bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts		return true;
3587bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	}
3597bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
3607bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	*errmsg = "Expecting \"true\" or \"false\"";
3617bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	return false;
3627bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts}
3637bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
3647bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Robertsstatic bool validate_levelFrom(char *value, char **errmsg) {
3657bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
3667bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	if(strcasecmp(value, "none") && strcasecmp(value, "all") &&
3677bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts		strcasecmp(value, "app") && strcasecmp(value, "user")) {
3687bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts		*errmsg = "Expecting one of: \"none\", \"all\", \"app\" or \"user\"";
3697bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts		return false;
3707bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	}
3717bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	return true;
3727bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts}
3737bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
3747bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Robertsstatic bool validate_selinux_type(char *value, char **errmsg) {
3757bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
3767bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	/*
3777bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	 * No policy file present means we cannot check
3787bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	 * SE Linux types
3797bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	 */
3807bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	if (!pol.policy_file) {
3817bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts		return true;
3827bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	}
3837bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
3847bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	if(!check_type(pol.db, value)) {
3857bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts		*errmsg = "Expecting a valid SELinux type";
3867bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts		return false;
3877bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	}
3887bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
3897bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	return true;
3907bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts}
3917bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
3927bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Robertsstatic bool validate_selinux_level(char *value, char **errmsg) {
3937bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
3947bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	/*
3957bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	 * No policy file present means we cannot check
3967bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	 * SE Linux MLS
3977bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	 */
3987bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	if (!pol.policy_file) {
3997bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts		return true;
4007bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	}
4017bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
4027bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	int ret = sepol_mls_check(pol.handle, pol.db, value);
4037bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	if (ret < 0) {
4047bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts		*errmsg = "Expecting a valid SELinux MLS value";
4057bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts		return false;
4067bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	}
4077bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
4087bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	return true;
4097bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts}
4107bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts
411f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
412f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Validates a key_map against a set of enforcement rules, this
413f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * function exits the application on a type that cannot be properly
414f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * checked
415f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts *
416f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param m
417f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	The key map to check
418f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param lineno
419f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	The line number in the source file for the corresponding key map
420fff2980a1ac2aca5966f6b54fa030309a0d98e0cWilliam Roberts * @return
42181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * 	true if valid, false if invalid
422f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
42381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic bool key_map_validate(key_map *m, const char *filename, int lineno,
42481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		bool is_neverallow) {
425f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
42681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	int erroff;
42781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	const char *errbuf;
42881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	bool rc = true;
429f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	char *key = m->name;
430f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	char *value = m->data;
4317bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	char *errmsg = NULL;
432f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
4330ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	log_info("Validating %s=%s\n", key, value);
4340ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts
43581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	/*
43681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	 * Neverallows are completely skipped from sanity checking so you can match
43781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	 * un-unspecified inputs.
43881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	 */
43981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if (is_neverallow) {
44081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		if (!m->regex.compiled) {
44181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			rc = compile_regex(m, &errbuf, &erroff);
44281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			if (!rc) {
44381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts				log_error("Invalid regex on line %d : %s PCRE error: %s at offset %d",
44481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts					lineno, value, errbuf, erroff);
44581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			}
44681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		}
44781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		goto out;
44881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
44981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
4507bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	/* If the key has a validation routine, call it */
4517bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts	if (m->fn_validate) {
4527bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts		rc = m->fn_validate(value, &errmsg);
45338084146e0fd665b68c8c4ff131cae9d07ef5993Stephen Smalley
4547bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts		if (!rc) {
4557bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts			log_error("Could not validate key \"%s\" for value \"%s\" on line: %d in file: \"%s\": %s\n", key, value,
4567bbdaefc7fe3364e39cdc8e7d1ab52e0de92327cWilliam Roberts			lineno, filename, errmsg);
457f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
458f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
459f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
4600ae3a8a2d50799d0b91d992434cdd4d3151b0348William Robertsout:
4610ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	log_info("Key map validate returning: %d\n", rc);
4620ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	return rc;
463f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
464f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
465f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
466f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Prints a rule map back to a file
467f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param fp
468f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	The file handle to print too
469f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param r
470f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	The rule map to print
471f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
472f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstatic void rule_map_print(FILE *fp, rule_map *r) {
473f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
474610a4b1c32490ac9f6f7ca0fafba8c182a542934William Roberts	size_t i;
475f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	key_map *m;
476f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
477f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	for (i = 0; i < r->length; i++) {
478f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		m = &(r->m[i]);
479f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if (i < r->length - 1)
480f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			fprintf(fp, "%s=%s ", m->name, m->data);
481f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		else
482f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			fprintf(fp, "%s=%s", m->name, m->data);
483f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
484f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
485f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
486f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
487f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Compare two rule maps for equality
488f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param rmA
489f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	a rule map to check
490f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param rmB
491f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	a rule map to check
492f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @return
493ae23a1f36a9372bb23ebe21c8267d4192cb45a30William Roberts *  a map_match enum indicating the result
494f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
4950ae3a8a2d50799d0b91d992434cdd4d3151b0348William Robertsstatic map_match rule_map_cmp(rule_map *rmA, rule_map *rmB) {
496f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
497610a4b1c32490ac9f6f7ca0fafba8c182a542934William Roberts	size_t i;
498610a4b1c32490ac9f6f7ca0fafba8c182a542934William Roberts	size_t j;
499f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	int inputs_found = 0;
500f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	int num_of_matched_inputs = 0;
501f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	int input_mode = 0;
502610a4b1c32490ac9f6f7ca0fafba8c182a542934William Roberts	size_t matches = 0;
503f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	key_map *mA;
504f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	key_map *mB;
505f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
506f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	for (i = 0; i < rmA->length; i++) {
507f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		mA = &(rmA->m[i]);
508f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
509f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		for (j = 0; j < rmB->length; j++) {
510f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			mB = &(rmB->m[j]);
511f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			input_mode = 0;
512f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
513f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			if (strcmp(mA->name, mB->name))
514f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				continue;
515f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
516f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			if (strcmp(mA->data, mB->data))
517f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				continue;
518f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
519f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			if (mB->dir != mA->dir)
520f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				continue;
521f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			else if (mB->dir == dir_in) {
522f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				input_mode = 1;
523f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				inputs_found++;
524f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			}
525f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
5260ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts			if (input_mode) {
5271e8c061b053cdfd808c7a7649c78df4c33ded63dWilliam Roberts				log_info("Matched input lines: name=%s data=%s\n", mA->name, mA->data);
528f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				num_of_matched_inputs++;
5290ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts			}
530f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
531f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			/* Match found, move on */
5321e8c061b053cdfd808c7a7649c78df4c33ded63dWilliam Roberts			log_info("Matched lines: name=%s data=%s", mA->name, mA->data);
533f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			matches++;
534f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			break;
535f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
536f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
537f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
538f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	/* If they all matched*/
5390ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	if (matches == rmA->length) {
5400ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts		log_info("Rule map cmp MATCH\n");
5410ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts		return map_matched;
5420ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	}
543f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
544f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	/* They didn't all match but the input's did */
5450ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	else if (num_of_matched_inputs == inputs_found) {
5460ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts		log_info("Rule map cmp INPUT MATCH\n");
5470ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts		return map_input_matched;
5480ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	}
549f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
550f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	/* They didn't all match, and the inputs didn't match, ie it didn't
551f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	 * match */
5520ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	else {
5530ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts		log_info("Rule map cmp NO MATCH\n");
5540ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts		return map_no_matches;
5550ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	}
556f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
557f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
558f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
559f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Frees a rule map
560f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param rm
561f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	rule map to be freed.
5627d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts * @is_in_htable
5637d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts * 	True if the rule map has been added to the hash table, false
5647d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts * 	otherwise.
5657d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts */
5667d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Robertsstatic void rule_map_free(rule_map *rm, bool is_in_htable) {
567f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
568610a4b1c32490ac9f6f7ca0fafba8c182a542934William Roberts	size_t i;
569610a4b1c32490ac9f6f7ca0fafba8c182a542934William Roberts	size_t len = rm->length;
570f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	for (i = 0; i < len; i++) {
571f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		key_map *m = &(rm->m[i]);
572f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		free(m->data);
57381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
57481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		if (m->regex.compiled) {
57581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			pcre_free(m->regex.compiled);
57681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		}
57781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
57881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		if (m->regex.extra) {
57981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			pcre_free_study(m->regex.extra);
58081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		}
581f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
582f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
5837d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts	/*
5847d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts	 * hdestroy() frees comparsion keys for non glibc
5857d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts	 * on GLIBC we always free on NON-GLIBC we free if
5867d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts	 * it is not in the htable.
5877d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts	 */
5887d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts	if (rm->key) {
5895dbfdc0b0fec04d670912c4eed179983f98abe8arpcraig#ifdef __GLIBC__
5907d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts		/* silence unused warning */
5917d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts		(void)is_in_htable;
592f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		free(rm->key);
5937d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts#else
5947d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts		if (!is_in_htable) {
5957d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts			free(rm->key);
5967d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts		}
5975dbfdc0b0fec04d670912c4eed179983f98abe8arpcraig#endif
5987d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts	}
599f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
60081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	free(rm->filename);
601f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	free(rm);
602f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
603f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
604f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstatic void free_kvp(kvp *k) {
605f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	free(k->key);
606f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	free(k->value);
607f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
608f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
609f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
61061846291746a3a3559f615ef3665312ccd2228c2William Roberts * Checks a rule_map for any variation of KVP's that shouldn't be allowed.
61181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * It builds an assertion failure list for each rule map.
61261846291746a3a3559f615ef3665312ccd2228c2William Roberts * Note that this function logs all errors.
61361846291746a3a3559f615ef3665312ccd2228c2William Roberts *
61461846291746a3a3559f615ef3665312ccd2228c2William Roberts * Current Checks:
61561846291746a3a3559f615ef3665312ccd2228c2William Roberts * 1. That a specified name entry should have a specified seinfo entry as well.
61681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * 2. That no rule violates a neverallow
61761846291746a3a3559f615ef3665312ccd2228c2William Roberts * @param rm
61861846291746a3a3559f615ef3665312ccd2228c2William Roberts *  The rule map to check for validity.
61961846291746a3a3559f615ef3665312ccd2228c2William Roberts */
62081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic void rule_map_validate(rule_map *rm) {
62161846291746a3a3559f615ef3665312ccd2228c2William Roberts
62281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	size_t i, j;
62381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	const key_map *rule;
62481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	key_map *nrule;
62581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	hash_entry *e;
62681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	rule_map *assert;
62781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element *cursor;
62881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
62981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_for_each(&nallow_list, cursor) {
63081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		e = list_entry(cursor, typeof(*e), listify);
63181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		assert = e->r;
63281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
63381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		size_t cnt = 0;
63481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
63581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		for (j = 0; j < assert->length; j++) {
63681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			nrule = &(assert->m[j]);
63781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
63881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			// mark that nrule->name is for a null check
63981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			bool is_null_check = !strcmp(nrule->data, "\"\"");
64061846291746a3a3559f615ef3665312ccd2228c2William Roberts
64181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			for (i = 0; i < rm->length; i++) {
64281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts				rule = &(rm->m[i]);
64361846291746a3a3559f615ef3665312ccd2228c2William Roberts
64481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts				if (!strcmp(rule->name, nrule->name)) {
64581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
64681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts					/* the name was found, (data cannot be false) then it was specified */
64781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts					is_null_check = false;
64881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
64981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts					if (match_regex(nrule, rule)) {
65081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts						cnt++;
65181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts					}
65281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts				}
65381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			}
65481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
65581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			/*
65681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			 * the nrule was marked in a null check and we never found a match on nrule, thus
65781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			 * it matched and we update the cnt
65881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			 */
65981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			if (is_null_check) {
66081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts				cnt++;
66181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			}
66261846291746a3a3559f615ef3665312ccd2228c2William Roberts		}
66381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		if (cnt == assert->length) {
66481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			list_append(&rm->violations, &assert->listify);
66561846291746a3a3559f615ef3665312ccd2228c2William Roberts		}
66661846291746a3a3559f615ef3665312ccd2228c2William Roberts	}
66761846291746a3a3559f615ef3665312ccd2228c2William Roberts}
66861846291746a3a3559f615ef3665312ccd2228c2William Roberts
66961846291746a3a3559f615ef3665312ccd2228c2William Roberts/**
670f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Given a set of key value pairs, this will construct a new rule map.
671f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * On error this function calls exit.
672f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param keys
673f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	Keys from a rule line to map
674f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param num_of_keys
675f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	The length of the keys array
676f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param lineno
677f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	The line number the keys were extracted from
678f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @return
679f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	A rule map pointer.
680f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
68181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic rule_map *rule_map_new(kvp keys[], size_t num_of_keys, int lineno,
68281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		const char *filename, bool is_never_allow) {
683f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
684610a4b1c32490ac9f6f7ca0fafba8c182a542934William Roberts	size_t i = 0, j = 0;
685f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	rule_map *new_map = NULL;
686f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	kvp *k = NULL;
687f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	key_map *r = NULL, *x = NULL;
688534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley	bool seen[KVP_NUM_OF_RULES];
689534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley
690534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley	for (i = 0; i < KVP_NUM_OF_RULES; i++)
691534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley		seen[i] = false;
692f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
693f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	new_map = calloc(1, (num_of_keys * sizeof(key_map)) + sizeof(rule_map));
694f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	if (!new_map)
695f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		goto oom;
696f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
69781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	new_map->is_never_allow = is_never_allow;
698f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	new_map->length = num_of_keys;
699f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	new_map->lineno = lineno;
70081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	new_map->filename = strdup(filename);
70181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if (!new_map->filename) {
70281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		goto oom;
70381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
704f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
705f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	/* For all the keys in a rule line*/
706f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	for (i = 0; i < num_of_keys; i++) {
707f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		k = &(keys[i]);
708f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		r = &(new_map->m[i]);
709f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
710f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		for (j = 0; j < KVP_NUM_OF_RULES; j++) {
711f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			x = &(rules[j]);
712f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
713f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			/* Only assign key name to map name */
714f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			if (strcasecmp(k->key, x->name)) {
715f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				if (i == KVP_NUM_OF_RULES) {
716f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts					log_error("No match for key: %s\n", k->key);
717f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts					goto err;
718f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				}
719f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				continue;
720f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			}
721f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
722534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley			if (seen[j]) {
723534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley					log_error("Duplicated key: %s\n", k->key);
724534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley					goto err;
725534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley			}
726534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley			seen[j] = true;
727534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley
728f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			memcpy(r, x, sizeof(key_map));
729f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
730f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			/* Assign rule map value to one from file */
731f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			r->data = strdup(k->value);
732f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			if (!r->data)
733f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				goto oom;
734f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
735f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			/* Enforce type check*/
7360ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts			log_info("Validating keys!\n");
73781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			if (!key_map_validate(r, filename, lineno, new_map->is_never_allow)) {
738f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				log_error("Could not validate\n");
739f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				goto err;
740f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			}
741f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
74281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			/*
74381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			 * Only build key off of inputs with the exception of neverallows.
74481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			 * Neverallows are keyed off of all key value pairs,
74581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			 */
74681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			if (r->dir == dir_in || new_map->is_never_allow) {
747f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				char *tmp;
748b3ab56c2bf35214b6ef81027b0a08c09e3dc916fWilliam Roberts				int key_len = strlen(k->key);
749b3ab56c2bf35214b6ef81027b0a08c09e3dc916fWilliam Roberts				int val_len = strlen(k->value);
750b3ab56c2bf35214b6ef81027b0a08c09e3dc916fWilliam Roberts				int l = (new_map->key) ? strlen(new_map->key) : 0;
751b3ab56c2bf35214b6ef81027b0a08c09e3dc916fWilliam Roberts				l = l + key_len + val_len;
752f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				l += 1;
753f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
754f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				tmp = realloc(new_map->key, l);
755f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				if (!tmp)
756f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts					goto oom;
757f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
758b3ab56c2bf35214b6ef81027b0a08c09e3dc916fWilliam Roberts				if (!new_map->key)
759b3ab56c2bf35214b6ef81027b0a08c09e3dc916fWilliam Roberts					memset(tmp, 0, l);
760b3ab56c2bf35214b6ef81027b0a08c09e3dc916fWilliam Roberts
761f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				new_map->key = tmp;
762f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
763b3ab56c2bf35214b6ef81027b0a08c09e3dc916fWilliam Roberts				strncat(new_map->key, k->key, key_len);
764b3ab56c2bf35214b6ef81027b0a08c09e3dc916fWilliam Roberts				strncat(new_map->key, k->value, val_len);
765f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			}
766f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			break;
767f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
768f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		free_kvp(k);
769f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
770f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
771f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	if (new_map->key == NULL) {
772f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		log_error("Strange, no keys found, input file corrupt perhaps?\n");
773f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		goto err;
774f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
775f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
776f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	return new_map;
777f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
778f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsoom:
779f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	log_error("Out of memory!\n");
780f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertserr:
781f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	if(new_map) {
7827d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts		rule_map_free(new_map, false);
783f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		for (; i < num_of_keys; i++) {
784f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			k = &(keys[i]);
785f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			free_kvp(k);
786f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
787f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
788534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley	return NULL;
789f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
790f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
791f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
792f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Print the usage of the program
793f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
794f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstatic void usage() {
795f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	printf(
796f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	        "checkseapp [options] <input file>\n"
797f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		        "Processes an seapp_contexts file specified by argument <input file> (default stdin) "
798ae23a1f36a9372bb23ebe21c8267d4192cb45a30William Roberts		        "and allows later declarations to override previous ones on a match.\n"
799f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		        "Options:\n"
800f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		        "-h - print this help message\n"
801f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		        "-v - enable verbose debugging informations\n"
802632972117a754dc64102cf81154ae6aed86febf3William Roberts		        "-p policy file - specify policy file for strict checking of output selectors against the policy\n"
80381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		        "-o output file - specify output file or - for stdout. No argument runs in silent mode and outputs nothing\n");
804f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
805f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
806f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstatic void init() {
807f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
80881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	bool has_out_file;
80981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element *cursor;
81081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	file_info *tmp;
81181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
81281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	/* input files if the list is empty, use stdin */
81381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if (!input_file_list.head) {
81481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		log_info("Using stdin for input\n");
81581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		tmp = malloc(sizeof(*tmp));
81681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		if (!tmp) {
81781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			log_error("oom");
818f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			exit(EXIT_FAILURE);
819f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
82081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		tmp->name = "stdin";
82181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		tmp->file = stdin;
82281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		list_append(&input_file_list, &(tmp->listify));
823f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
82481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	else {
82581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		list_for_each(&input_file_list, cursor) {
82681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			tmp = list_entry(cursor, typeof(*tmp), listify);
82781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
82881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			log_info("Opening input file: \"%s\"\n", tmp->name);
82981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			tmp->file = fopen(tmp->name, "r");
83081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			if (!tmp->file) {
83181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts				log_error("Could not open file: %s error: %s\n", tmp->name,
83281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts						strerror(errno));
83381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts				exit(EXIT_FAILURE);
83481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			}
835f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
836f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
837f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
83881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	has_out_file = out_file.name != NULL;
83981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
84081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	/* If output file is -, then use stdout, else open the path */
84181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if (has_out_file && !strcmp(out_file.name, "-")) {
84281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		out_file.file = stdout;
84381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		out_file.name = "stdout";
84481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
84581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	else if (has_out_file) {
84681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		out_file.file = fopen(out_file.name, "w+");
84781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
848f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
84981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if (has_out_file && !out_file.file) {
85081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		log_error("Could not open file: \"%s\" error: \"%s\"\n", out_file.name,
85181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts				strerror(errno));
85281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		exit(EXIT_FAILURE);
85381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
85481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
85581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if (pol.policy_file_name) {
856f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		log_info("Opening policy file: %s\n", pol.policy_file_name);
857f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		pol.policy_file = fopen(pol.policy_file_name, "rb");
858f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if (!pol.policy_file) {
859f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			log_error("Could not open file: %s error: %s\n",
860f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts					pol.policy_file_name, strerror(errno));
861f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			exit(EXIT_FAILURE);
862f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
863f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
864f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		pol.handle = sepol_handle_create();
865f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if (!pol.handle) {
866f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			log_error("Could not create sepolicy handle: %s\n",
867f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts					strerror(errno));
868f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			exit(EXIT_FAILURE);
869f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
870f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
871f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if (sepol_policy_file_create(&pol.pf) < 0) {
872f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			log_error("Could not create sepolicy file: %s!\n",
873f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts					strerror(errno));
874f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			exit(EXIT_FAILURE);
875f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
876f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
877f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		sepol_policy_file_set_fp(pol.pf, pol.policy_file);
878f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		sepol_policy_file_set_handle(pol.pf, pol.handle);
879f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
880f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if (sepol_policydb_create(&pol.db) < 0) {
881f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			log_error("Could not create sepolicy db: %s!\n",
882f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts					strerror(errno));
883f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			exit(EXIT_FAILURE);
884f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
885f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
886f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if (sepol_policydb_read(pol.db, pol.pf) < 0) {
887f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			log_error("Could not lod policy file to db: %s!\n",
888f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts					strerror(errno));
889f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			exit(EXIT_FAILURE);
890f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
891f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
892f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
89381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_for_each(&input_file_list, cursor) {
89481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		tmp = list_entry(cursor, typeof(*tmp), listify);
89581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		log_info("Input file set to: \"%s\"\n", tmp->name);
89681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
89781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
89881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	log_info("Policy file set to: \"%s\"\n",
89981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			(pol.policy_file_name == NULL) ? "None" : pol.policy_file_name);
90081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	log_info("Output file set to: \"%s\"\n", out_file.name);
901f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
9020ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts#if !defined(LINK_SEPOL_STATIC)
903a53ccf39c2793cb5a5894948de41242feea1ea31William Roberts	log_warn("LINK_SEPOL_STATIC is not defined\n""Not checking types!");
9040ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts#endif
9050ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts
906f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
907f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
908f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
909f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Handle parsing and setting the global flags for the command line
910f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * options. This function calls exit on failure.
911f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param argc
912f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	argument count
913f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param argv
914f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	argument list
915f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
916f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstatic void handle_options(int argc, char *argv[]) {
917f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
918f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	int c;
91981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	file_info *input_file;
920f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
921f26b6d427cce74bf22e3a45e2fcbe3f3bab6441cWilliam Roberts	while ((c = getopt(argc, argv, "ho:p:v")) != -1) {
922f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		switch (c) {
923f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		case 'h':
924f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			usage();
925f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			exit(EXIT_SUCCESS);
926f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		case 'o':
92781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			out_file.name = optarg;
928f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			break;
929f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		case 'p':
930f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			pol.policy_file_name = optarg;
931f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			break;
932f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		case 'v':
933f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			log_set_verbose();
934f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			break;
935f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		case '?':
936f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			if (optopt == 'o' || optopt == 'p')
937f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				log_error("Option -%c requires an argument.\n", optopt);
938f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			else if (isprint (optopt))
939f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				log_error("Unknown option `-%c'.\n", optopt);
940f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			else {
941f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				log_error(
942f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts						"Unknown option character `\\x%x'.\n",
943f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts						optopt);
944f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			}
945f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		default:
946f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			exit(EXIT_FAILURE);
947f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
948f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
949f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
95081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	for (c = optind; c < argc; c++) {
951f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
95281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		input_file = calloc(1, sizeof(*input_file));
95381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		if (!input_file) {
95481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			log_error("oom");
95581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			exit(EXIT_FAILURE);
95681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		}
95781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		input_file->name = argv[c];
95881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		list_append(&input_file_list, &input_file->listify);
959f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
960f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
961f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
962f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
963f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Adds a rule to the hash table and to the ordered list if needed.
964f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * @param rm
965f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * 	The rule map to add.
966f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
967f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstatic void rule_add(rule_map *rm) {
968f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
9690ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	map_match cmp;
970f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	ENTRY e;
971f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	ENTRY *f;
972f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	hash_entry *entry;
973f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	hash_entry *tmp;
97481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list *list_to_addto;
975f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
976f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	e.key = rm->key;
977f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
9780ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts	log_info("Searching for key: %s\n", e.key);
979f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	/* Check to see if it has already been added*/
980f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	f = hsearch(e, FIND);
981f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
982f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	/*
983f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	 * Since your only hashing on a partial key, the inputs we need to handle
984f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	 * when you want to override the outputs for a given input set, as well as
985f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	 * checking for duplicate entries.
986f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	 */
987f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	if(f) {
9880ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts		log_info("Existing entry found!\n");
989f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		tmp = (hash_entry *)f->data;
990f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		cmp = rule_map_cmp(rm, tmp->r);
9910b820042e4bb9bb93790e0cf0812fd97d15ce7a5Stephen Smalley		log_error("Duplicate line detected in file: %s\n"
9920b820042e4bb9bb93790e0cf0812fd97d15ce7a5Stephen Smalley			  "Lines %d and %d %s!\n",
99381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			  rm->filename, tmp->r->lineno, rm->lineno,
9940b820042e4bb9bb93790e0cf0812fd97d15ce7a5Stephen Smalley			  map_match_str[cmp]);
9957d65b547d3959b9f98334cf0da6afe9ab418b17aWilliam Roberts		rule_map_free(rm, false);
9960b820042e4bb9bb93790e0cf0812fd97d15ce7a5Stephen Smalley		goto err;
997f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
998f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	/* It wasn't found, just add the rule map to the table */
999f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	else {
1000f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1001f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		entry = malloc(sizeof(hash_entry));
1002f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if (!entry)
1003f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			goto oom;
1004f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1005f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		entry->r = rm;
1006f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		e.data = entry;
1007f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1008f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		f = hsearch(e, ENTER);
1009f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if(f == NULL) {
1010f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			goto oom;
1011f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		}
1012f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1013f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		/* new entries must be added to the ordered list */
1014f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		entry->r = rm;
101581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		list_to_addto = rm->is_never_allow ? &nallow_list : &line_order_list;
101681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		list_append(list_to_addto, &entry->listify);
1017f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
1018f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1019f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	return;
1020f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsoom:
1021f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	if (e.key)
1022f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		free(e.key);
1023f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	if (entry)
1024f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		free(entry);
1025f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	if (rm)
1026f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		free(rm);
1027f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	log_error("Out of memory in function: %s\n", __FUNCTION__);
1028f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertserr:
1029f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	exit(EXIT_FAILURE);
1030f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
1031f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
103281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic void parse_file(file_info *in_file) {
1033f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
103481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	char *p;
1035f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	size_t len;
103681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	char *token;
103781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	char *saveptr;
103881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	bool is_never_allow;
103981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	bool found_whitespace;
104081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
104181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	size_t lineno = 0;
104281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	char *name = NULL;
104381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	char *value = NULL;
1044610a4b1c32490ac9f6f7ca0fafba8c182a542934William Roberts	size_t token_cnt = 0;
1045f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
104681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	char line_buf[BUFSIZ];
104781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	kvp keys[KVP_NUM_OF_RULES];
1048f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
104981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	while (fgets(line_buf, sizeof(line_buf) - 1, in_file->file)) {
1050f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		lineno++;
105181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		is_never_allow = false;
105281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		found_whitespace = false;
105381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		log_info("Got line %zu\n", lineno);
1054f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		len = strlen(line_buf);
1055f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if (line_buf[len - 1] == '\n')
1056f6647eb9f40a6a3d6dc3c1374d583e176a735498Alice Chu			line_buf[len - 1] = '\0';
1057f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		p = line_buf;
105881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
105981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		/* neverallow lines must start with neverallow (ie ^neverallow) */
106081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		if (!strncasecmp(p, "neverallow", strlen("neverallow"))) {
106181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			p += strlen("neverallow");
106281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			is_never_allow = true;
106381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		}
106481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
106581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		/* strip trailing whitespace skip comments */
106681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		while (isspace(*p)) {
1067f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			p++;
106881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			found_whitespace = true;
106981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		}
1070f6647eb9f40a6a3d6dc3c1374d583e176a735498Alice Chu		if (*p == '#' || *p == '\0')
1071f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			continue;
1072f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1073f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		token = strtok_r(p, " \t", &saveptr);
1074f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if (!token)
1075f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			goto err;
1076f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1077f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		token_cnt = 0;
1078f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		memset(keys, 0, sizeof(kvp) * KVP_NUM_OF_RULES);
1079f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		while (1) {
10800ae3a8a2d50799d0b91d992434cdd4d3151b0348William Roberts
1081f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			name = token;
1082f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			value = strchr(name, '=');
1083f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			if (!value)
1084f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				goto err;
1085f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			*value++ = 0;
1086f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1087f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			keys[token_cnt].key = strdup(name);
1088f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			if (!keys[token_cnt].key)
1089f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				goto oom;
1090f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1091f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			keys[token_cnt].value = strdup(value);
1092f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			if (!keys[token_cnt].value)
1093f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				goto oom;
1094f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1095f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			token_cnt++;
1096f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1097f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			token = strtok_r(NULL, " \t", &saveptr);
1098f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			if (!token)
1099f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts				break;
1100f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1101f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		} /*End token parsing */
1102f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
110381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		rule_map *r = rule_map_new(keys, token_cnt, lineno, in_file->name, is_never_allow);
1104534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley		if (!r)
1105534fb0711d95615a77af23ffe643e8b720a527e6Stephen Smalley			goto err;
1106f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		rule_add(r);
1107f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1108f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	} /* End file parsing */
1109f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	return;
1110f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1111f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertserr:
1112d5c3e5000937d0456101b18de0309223654304bcWilliam Roberts	log_error("Reading file: \"%s\" line: %zu name: \"%s\" value: \"%s\"\n",
111381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		in_file->name, lineno, name, value);
111481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if(found_whitespace && name && !strcasecmp(name, "neverallow")) {
111581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		log_error("perhaps whitespace before neverallow\n");
111681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
1117f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	exit(EXIT_FAILURE);
1118f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsoom:
1119f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	log_error("In function %s:  Out of memory\n", __FUNCTION__);
1120f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	exit(EXIT_FAILURE);
1121f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
1122f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1123f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
112481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * Parses the seapp_contexts file and neverallow file
112581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * and adds them to the hash table and ordered list entries
112681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * when it encounters them.
112781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts * Calls exit on failure.
112881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts */
112981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic void parse() {
113081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
113181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	file_info *current;
113281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element *cursor;
113381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_for_each(&input_file_list, cursor) {
113481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		current = list_entry(cursor, typeof(*current), listify);
113581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		parse_file(current);
113681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
113781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts}
113881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
113981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Robertsstatic void validate() {
114081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
114181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element *cursor, *v;
114281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	bool found_issues = false;
114381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	hash_entry *e;
114481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	rule_map *r;
114581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_for_each(&line_order_list, cursor) {
114681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		e = list_entry(cursor, typeof(*e), listify);
114781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		rule_map_validate(e->r);
114881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
114981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
115081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_for_each(&line_order_list, cursor) {
115181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		e = list_entry(cursor, typeof(*e), listify);
115281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		r = e->r;
115381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		list_for_each(&r->violations, v) {
115481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			found_issues = true;
115581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			log_error("Rule in File \"%s\" on line %d: \"", e->r->filename, e->r->lineno);
115681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			rule_map_print(stderr, e->r);
115781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			r = list_entry(v, rule_map, listify);
115881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			fprintf(stderr, "\" violates neverallow in File \"%s\" on line %d: \"", r->filename, r->lineno);
115981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			rule_map_print(stderr, r);
116081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts			fprintf(stderr, "\"\n");
116181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		}
116281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
116381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
116481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if (found_issues) {
116581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		exit(EXIT_FAILURE);
116681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
116781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts}
116881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
116981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts/**
1170f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * Should be called after parsing to cause the printing of the rule_maps
1171f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * stored in the ordered list, head first, which preserves the "first encountered"
1172f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * ordering.
1173f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
1174f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstatic void output() {
1175f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
117681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	hash_entry *e;
117781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_element *cursor;
1178f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
117981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if (!out_file.file) {
118081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		log_info("No output file, not outputting.\n");
118181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		return;
118281e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	}
118381e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts
118481e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_for_each(&line_order_list, cursor) {
118581e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		e = list_entry(cursor, hash_entry, listify);
118681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		rule_map_print(out_file.file, e->r);
118781e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		fprintf(out_file.file, "\n");
1188f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
1189f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
1190f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1191f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts/**
1192f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * This function is registered to the at exit handler and should clean up
1193f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts * the programs dynamic resources, such as memory and fd's.
1194f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts */
1195f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsstatic void cleanup() {
1196f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1197f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	/* Only close this when it was opened by me and not the crt */
119881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	if (out_file.name && strcmp(out_file.name, "stdout") && out_file.file) {
119981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		log_info("Closing file: %s\n", out_file.name);
120081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts		fclose(out_file.file);
1201f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
1202f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1203f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	if (pol.policy_file) {
1204f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1205f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		log_info("Closing file: %s\n", pol.policy_file_name);
1206f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		fclose(pol.policy_file);
1207f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1208f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if (pol.db)
1209f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			sepol_policydb_free(pol.db);
1210f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1211f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if (pol.pf)
1212f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			sepol_policy_file_free(pol.pf);
1213f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1214f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		if (pol.handle)
1215f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts			sepol_handle_destroy(pol.handle);
1216f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
1217f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
121881e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	log_info("Freeing lists\n");
121981e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_free(&input_file_list);
122081e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_free(&line_order_list);
122181e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	list_free(&nallow_list);
1222f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	hdestroy();
1223f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
1224f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts
1225f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Robertsint main(int argc, char *argv[]) {
1226f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	if (!hcreate(TABLE_SIZE)) {
1227f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		log_error("Could not create hash table: %s\n", strerror(errno));
1228f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts		exit(EXIT_FAILURE);
1229f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	}
1230f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	atexit(cleanup);
1231f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	handle_options(argc, argv);
1232f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	init();
1233f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	log_info("Starting to parse\n");
1234f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	parse();
1235f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	log_info("Parsing completed, generating output\n");
123681e1f90cd13b262f9e3021f64ae3574b8f5cd5d0William Roberts	validate();
1237f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	output();
1238f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	log_info("Success, generated output\n");
1239f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts	exit(EXIT_SUCCESS);
1240f0e0a94e032e55c13bc54f1cffe243f04872278eWilliam Roberts}
1241