Home | History | Annotate | Download | only in tools
      1 #include <getopt.h>
      2 #include <unistd.h>
      3 #include <stdlib.h>
      4 #include <sys/mman.h>
      5 #include <sys/types.h>
      6 #include <sys/stat.h>
      7 #include <fcntl.h>
      8 #include <stdio.h>
      9 #include <sepol/policydb/policydb.h>
     10 #include <sepol/policydb/services.h>
     11 #include <sepol/policydb/expand.h>
     12 
     13 #define EQUALS 0
     14 #define NOT 1
     15 #define ANY 2
     16 
     17 void usage(char *arg0) {
     18 	fprintf(stderr, "%s -s <source> -t <target> -c <class> -p <perm> -P <policy file>\n", arg0);
     19 	exit(1);
     20 }
     21 
     22 void *cmalloc(size_t s) {
     23 	void *t = malloc(s);
     24 	if (t == NULL) {
     25 		fprintf(stderr, "Out of memory\n");
     26 		exit(1);
     27 	}
     28 	return t;
     29 }
     30 
     31 int parse_ops(char **arg) {
     32 	switch (*arg[0]) {
     33 		case '-':
     34 			*arg = *arg + 1;
     35 			return NOT;
     36 		case '*':
     37 			return ANY;
     38 		default:
     39 			return EQUALS;
     40 	}
     41 }
     42 
     43 int check(int op, uint16_t arg1, uint16_t arg2) {
     44 	switch (op) {
     45 		case EQUALS:
     46 			return arg1 == arg2;
     47 		case NOT:
     48 			return arg1 != arg2;
     49 		case ANY:
     50 			return 1;
     51 		default:
     52 			fprintf(stderr, "Bad op while checking!");
     53 			return 2;
     54 	}
     55 }
     56 
     57 int check_perm(avtab_ptr_t current, perm_datum_t *perm) {
     58 	uint16_t perm_bitmask = 1U << (perm->s.value - 1);
     59 	return (current->datum.data & perm_bitmask) != 0;
     60 }
     61 
     62 
     63 int expand_and_check(int s_op, uint32_t source_type,
     64 		     int t_op, uint32_t target_type,
     65 		     int c_op, uint32_t target_class,
     66 		     perm_datum_t *perm, policydb_t *policy, avtab_t *avtab) {
     67 	avtab_t exp_avtab;
     68 	avtab_ptr_t cur;
     69 	unsigned int i;
     70 	int match;
     71 
     72 	if (avtab_init(&exp_avtab)) {
     73 		fputs("out of memory\n", stderr);
     74 		return -1;
     75 	}
     76 
     77 	if (expand_avtab(policy, avtab, &exp_avtab)) {
     78 		fputs("out of memory\n", stderr);
     79 		avtab_destroy(&exp_avtab);
     80 		return -1;
     81 	}
     82 
     83 	for (i = 0; i < exp_avtab.nslot; i++) {
     84 		for (cur = exp_avtab.htable[i]; cur; cur = cur->next) {
     85 			match = 1;
     86 			match &= check(s_op, source_type, cur->key.source_type);
     87 			match &= check(t_op, target_type, cur->key.target_type);
     88 			match &= check(c_op, target_class, cur->key.target_class);
     89 			match &= check_perm(cur, perm);
     90 			if (match) {
     91 				avtab_destroy(&exp_avtab);
     92 				return 1;
     93 			}
     94 		}
     95 	}
     96 
     97 	avtab_destroy(&exp_avtab);
     98 	return 0;
     99 }
    100 
    101 /*
    102  * Checks to see if a rule matching the given arguments already exists.
    103  *
    104  * The format for the arguments is as follows:
    105  *
    106  * - A bare string is treated as a literal and will be matched by equality.
    107  * - A string starting with "-" will be matched by inequality.
    108  * - A string starting with "*" will be treated as a wildcard.
    109  *
    110  * The return codes for this function are as follows:
    111  *
    112  * - 0 indicates a successful return without a match
    113  * - 1 indicates a successful return with a match
    114  * - -1 indicates an error
    115  */
    116 int check_rule(char *s, char *t, char *c, char *p, policydb_t *policy) {
    117 	type_datum_t *src = NULL;
    118 	type_datum_t *tgt = NULL;
    119 	class_datum_t *cls = NULL;
    120 	perm_datum_t *perm = NULL;
    121 	int s_op = parse_ops(&s);
    122 	int t_op = parse_ops(&t);
    123 	int c_op = parse_ops(&c);
    124 	int p_op = parse_ops(&p);
    125 	avtab_key_t key;
    126 	int match;
    127 
    128 	key.source_type = key.target_type = key.target_class = 0;
    129 
    130 	if (s_op != ANY) {
    131 		src = hashtab_search(policy->p_types.table, s);
    132 		if (src == NULL) {
    133 			fprintf(stderr, "source type %s does not exist\n", s);
    134 			return -1;
    135 		}
    136 	}
    137 	if (t_op != ANY) {
    138 		tgt = hashtab_search(policy->p_types.table, t);
    139 		if (tgt == NULL) {
    140 			fprintf(stderr, "target type %s does not exist\n", t);
    141 			return -1;
    142 		}
    143 	}
    144 	if (c_op != ANY) {
    145 		cls = hashtab_search(policy->p_classes.table, c);
    146 		if (cls == NULL) {
    147 			fprintf(stderr, "class %s does not exist\n", c);
    148 			return -1;
    149 		}
    150 	}
    151 	if (p_op != ANY) {
    152 		perm = hashtab_search(cls->permissions.table, p);
    153 		if (perm == NULL) {
    154 			if (cls->comdatum == NULL) {
    155 				fprintf(stderr, "perm %s does not exist in class %s\n", p, c);
    156 				return -1;
    157 			}
    158 			perm = hashtab_search(cls->comdatum->permissions.table, p);
    159 			if (perm == NULL) {
    160 				fprintf(stderr, "perm %s does not exist in class %s\n", p, c);
    161 				return -1;
    162 			}
    163 		}
    164 	}
    165 
    166 	if (s_op != ANY)
    167 		key.source_type = src->s.value;
    168 	if (t_op != ANY)
    169 		key.target_type = tgt->s.value;
    170 	if (c_op != ANY)
    171 		key.target_class = cls->s.value;
    172 
    173 	/* Check unconditional rules after attribute expansion. */
    174 	match = expand_and_check(s_op, key.source_type,
    175 				 t_op, key.target_type,
    176 				 c_op, key.target_class,
    177 				 perm, policy, &policy->te_avtab);
    178 	if (match)
    179 		return match;
    180 
    181 	/* Check conditional rules after attribute expansion. */
    182 	return expand_and_check(s_op, key.source_type,
    183 				t_op, key.target_type,
    184 				c_op, key.target_class,
    185 				perm, policy, &policy->te_cond_avtab);
    186 }
    187 
    188 int load_policy(char *filename, policydb_t *policydb, struct policy_file *pf) {
    189 	int fd;
    190 	struct stat sb;
    191 	void *map;
    192 	int ret;
    193 
    194 	fd = open(filename, O_RDONLY);
    195 	if (fd < 0) {
    196 		fprintf(stderr, "Can't open '%s':  %s\n", filename, strerror(errno));
    197 		return 1;
    198 	}
    199 	if (fstat(fd, &sb) < 0) {
    200 		fprintf(stderr, "Can't stat '%s':  %s\n", filename, strerror(errno));
    201 		close(fd);
    202 		return 1;
    203 	}
    204 	map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
    205 	if (map == MAP_FAILED) {
    206 		fprintf(stderr, "Can't mmap '%s':  %s\n", filename, strerror(errno));
    207 		close(fd);
    208 		return 1;
    209 	}
    210 
    211 	policy_file_init(pf);
    212 	pf->type = PF_USE_MEMORY;
    213 	pf->data = map;
    214 	pf->len = sb.st_size;
    215 	if (policydb_init(policydb)) {
    216 		fprintf(stderr, "Could not initialize policydb!\n");
    217 		close(fd);
    218 		munmap(map, sb.st_size);
    219 		return 1;
    220 	}
    221 	ret = policydb_read(policydb, pf, 0);
    222 	if (ret) {
    223 		fprintf(stderr, "error(s) encountered while parsing configuration\n");
    224 		close(fd);
    225 		munmap(map, sb.st_size);
    226 		return 1;
    227 	}
    228 
    229 	return 0;
    230 }
    231 
    232 
    233 int main(int argc, char **argv)
    234 {
    235 	char *policy = NULL, *source = NULL, *target = NULL, *class = NULL, *perm = NULL;
    236 	policydb_t policydb;
    237 	struct policy_file pf;
    238 	sidtab_t sidtab;
    239 	char ch;
    240 	int match = 1;
    241 
    242 	struct option long_options[] = {
    243 			{"source", required_argument, NULL, 's'},
    244 			{"target", required_argument, NULL, 't'},
    245 			{"class", required_argument, NULL, 'c'},
    246 			{"perm", required_argument, NULL, 'p'},
    247 			{"policy", required_argument, NULL, 'P'},
    248 			{NULL, 0, NULL, 0}
    249 	};
    250 
    251 	while ((ch = getopt_long(argc, argv, "s:t:c:p:P:", long_options, NULL)) != -1) {
    252 		switch (ch) {
    253 			case 's':
    254 				source = optarg;
    255 				break;
    256 			case 't':
    257 				target = optarg;
    258 				break;
    259 			case 'c':
    260 				class = optarg;
    261 				break;
    262 			case 'p':
    263 				perm = optarg;
    264 				break;
    265 			case 'P':
    266 				policy = optarg;
    267 				break;
    268 			default:
    269 				usage(argv[0]);
    270 		}
    271 	}
    272 
    273 	if (!source || !target || !class || !perm || !policy)
    274 		usage(argv[0]);
    275 
    276 	sepol_set_policydb(&policydb);
    277 	sepol_set_sidtab(&sidtab);
    278 
    279 	if (load_policy(policy, &policydb, &pf))
    280 		goto out;
    281 
    282 	match = check_rule(source, target, class, perm, &policydb);
    283 	if (match < 0) {
    284 		fprintf(stderr, "Error checking rules!\n");
    285 		goto out;
    286 	} else if (match > 0) {
    287 		printf("Match found!\n");
    288 		goto out;
    289 	}
    290 
    291 	match = 0;
    292 
    293 out:
    294 	policydb_destroy(&policydb);
    295 	return match;
    296 }
    297