• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include <sys/types.h>
6 #include <unistd.h>
7 
8 #include <arpa/inet.h>
9 #include <netinet/in.h>
10 #ifndef IPPROTO_DCCP
11 #define IPPROTO_DCCP 33
12 #endif
13 #ifndef IPPROTO_SCTP
14 #define IPPROTO_SCTP 132
15 #endif
16 
17 #include <sepol/policydb/ebitmap.h>
18 #include <sepol/policydb/hashtab.h>
19 #include <sepol/policydb/symtab.h>
20 
21 #include "kernel_to_common.h"
22 
23 
sepol_log_err(const char * fmt,...)24 void sepol_log_err(const char *fmt, ...)
25 {
26 	va_list argptr;
27 	va_start(argptr, fmt);
28 	if (vfprintf(stderr, fmt, argptr) < 0) {
29 		_exit(EXIT_FAILURE);
30 	}
31 	va_end(argptr);
32 	if (fprintf(stderr, "\n") < 0) {
33 		_exit(EXIT_FAILURE);
34 	}
35 }
36 
sepol_indent(FILE * out,int indent)37 void sepol_indent(FILE *out, int indent)
38 {
39 	if (fprintf(out, "%*s", indent * 4, "") < 0) {
40 		sepol_log_err("Failed to write to output");
41 	}
42 }
43 
sepol_printf(FILE * out,const char * fmt,...)44 void sepol_printf(FILE *out, const char *fmt, ...)
45 {
46 	va_list argptr;
47 	va_start(argptr, fmt);
48 	if (vfprintf(out, fmt, argptr) < 0) {
49 		sepol_log_err("Failed to write to output");
50 	}
51 	va_end(argptr);
52 }
53 
54 __attribute__ ((format(printf, 1, 0)))
create_str_helper(const char * fmt,int num,va_list vargs)55 static char *create_str_helper(const char *fmt, int num, va_list vargs)
56 {
57 	va_list vargs2;
58 	char *str = NULL;
59 	char *s;
60 	size_t len;
61 	int i, rc;
62 
63 	va_copy(vargs2, vargs);
64 
65 	len = strlen(fmt) + 1; /* +1 for '\0' */
66 
67 	for (i=0; i<num; i++) {
68 		s = va_arg(vargs, char *);
69 		len += strlen(s) - 2; /* -2 for each %s in fmt */
70 	}
71 
72 	str = malloc(len);
73 	if (!str) {
74 		sepol_log_err("Out of memory");
75 		goto exit;
76 	}
77 
78 	rc = vsnprintf(str, len, fmt, vargs2);
79 	if (rc < 0 || rc >= (int)len) {
80 		goto exit;
81 	}
82 
83 	va_end(vargs2);
84 
85 	return str;
86 
87 exit:
88 	free(str);
89 	va_end(vargs2);
90 	return NULL;
91 }
92 
create_str(const char * fmt,int num,...)93 char *create_str(const char *fmt, int num, ...)
94 {
95 	char *str = NULL;
96 	va_list vargs;
97 
98 	va_start(vargs, num);
99 	str = create_str_helper(fmt, num, vargs);
100 	va_end(vargs);
101 
102 	return str;
103 }
104 
strs_init(struct strs ** strs,size_t size)105 int strs_init(struct strs **strs, size_t size)
106 {
107 	struct strs *new;
108 
109 	*strs = NULL;
110 
111 	new = malloc(sizeof(struct strs));
112 	if (!new) {
113 		sepol_log_err("Out of memory");
114 		return -1;
115 	}
116 
117 	new->list = calloc(sizeof(char *), size);
118 	if (!new->list) {
119 		sepol_log_err("Out of memory");
120 		free(new);
121 		return -1;
122 	}
123 
124 	new->num = 0;
125 	new->size = size;
126 
127 	*strs = new;
128 
129 	return 0;
130 }
131 
strs_destroy(struct strs ** strs)132 void strs_destroy(struct strs **strs)
133 {
134 	if (!strs || !*strs) {
135 		return;
136 	}
137 
138 	free((*strs)->list);
139 	(*strs)->list = NULL;
140 	(*strs)->num = 0;
141 	(*strs)->size = 0;
142 	free(*strs);
143 	*strs = NULL;
144 }
145 
strs_free_all(struct strs * strs)146 void strs_free_all(struct strs *strs)
147 {
148 	if (!strs) {
149 		return;
150 	}
151 
152 	while (strs->num > 0) {
153 		strs->num--;
154 		free(strs->list[strs->num]);
155 	}
156 }
157 
strs_add(struct strs * strs,char * s)158 int strs_add(struct strs *strs, char *s)
159 {
160 	if (strs->num + 1 > strs->size) {
161 		char **new;
162 		unsigned i = strs->size;
163 		strs->size *= 2;
164 		new = realloc(strs->list, sizeof(char *)*strs->size);
165 		if (!new) {
166 			sepol_log_err("Out of memory");
167 			return -1;
168 		}
169 		strs->list = new;
170 		memset(&strs->list[i], 0, sizeof(char *)*(strs->size-i));
171 	}
172 
173 	strs->list[strs->num] = s;
174 	strs->num++;
175 
176 	return 0;
177 }
178 
strs_create_and_add(struct strs * strs,const char * fmt,int num,...)179 int strs_create_and_add(struct strs *strs, const char *fmt, int num, ...)
180 {
181 	char *str;
182 	va_list vargs;
183 	int rc;
184 
185 	va_start(vargs, num);
186 	str = create_str_helper(fmt, num, vargs);
187 	va_end(vargs);
188 
189 	if (!str) {
190 		rc = -1;
191 		goto exit;
192 	}
193 
194 	rc = strs_add(strs, str);
195 	if (rc != 0) {
196 		free(str);
197 		goto exit;
198 	}
199 
200 	return 0;
201 
202 exit:
203 	return rc;
204 }
205 
strs_remove_last(struct strs * strs)206 char *strs_remove_last(struct strs *strs)
207 {
208 	if (strs->num == 0) {
209 		return NULL;
210 	}
211 	strs->num--;
212 	return strs->list[strs->num];
213 }
214 
strs_add_at_index(struct strs * strs,char * s,unsigned index)215 int strs_add_at_index(struct strs *strs, char *s, unsigned index)
216 {
217 	if (index >= strs->size) {
218 		char **new;
219 		unsigned i = strs->size;
220 		while (index >= strs->size) {
221 			strs->size *= 2;
222 		}
223 		new = realloc(strs->list, sizeof(char *)*strs->size);
224 		if (!new) {
225 			sepol_log_err("Out of memory");
226 			return -1;
227 		}
228 		strs->list = new;
229 		memset(&strs->list[i], 0, sizeof(char *)*(strs->size - i));
230 	}
231 
232 	strs->list[index] = s;
233 	if (index >= strs->num) {
234 		strs->num = index+1;
235 	}
236 
237 	return 0;
238 }
239 
strs_read_at_index(struct strs * strs,unsigned index)240 char *strs_read_at_index(struct strs *strs, unsigned index)
241 {
242 	if (index >= strs->num) {
243 		return NULL;
244 	}
245 
246 	return strs->list[index];
247 }
248 
strs_cmp(const void * a,const void * b)249 static int strs_cmp(const void *a, const void *b)
250 {
251 	char *const *aa = a;
252 	char *const *bb = b;
253 	return strcmp(*aa,*bb);
254 }
255 
strs_sort(struct strs * strs)256 void strs_sort(struct strs *strs)
257 {
258 	if (strs->num == 0) {
259 		return;
260 	}
261 	qsort(strs->list, strs->num, sizeof(char *), strs_cmp);
262 }
263 
strs_num_items(struct strs * strs)264 unsigned strs_num_items(struct strs *strs)
265 {
266 	return strs->num;
267 }
268 
strs_len_items(struct strs * strs)269 size_t strs_len_items(struct strs *strs)
270 {
271 	unsigned i;
272 	size_t len = 0;
273 
274 	for (i=0; i<strs->num; i++) {
275 		if (!strs->list[i]) continue;
276 		len += strlen(strs->list[i]);
277 	}
278 
279 	return len;
280 }
281 
strs_to_str(struct strs * strs)282 char *strs_to_str(struct strs *strs)
283 {
284 	char *str = NULL;
285 	size_t len = 0;
286 	char *p;
287 	unsigned i;
288 	int rc;
289 
290 	if (strs->num == 0) {
291 		goto exit;
292 	}
293 
294 	/* strs->num added because either ' ' or '\0' follows each item */
295 	len = strs_len_items(strs) + strs->num;
296 	str = malloc(len);
297 	if (!str) {
298 		sepol_log_err("Out of memory");
299 		goto exit;
300 	}
301 
302 	p = str;
303 	for (i=0; i<strs->num; i++) {
304 		if (!strs->list[i]) continue;
305 		len = strlen(strs->list[i]);
306 		rc = snprintf(p, len+1, "%s", strs->list[i]);
307 		if (rc < 0 || rc > (int)len) {
308 			free(str);
309 			str = NULL;
310 			goto exit;
311 		}
312 		p += len;
313 		if (i < strs->num - 1) {
314 			*p++ = ' ';
315 		}
316 	}
317 
318 	*p = '\0';
319 
320 exit:
321 	return str;
322 }
323 
strs_write_each(struct strs * strs,FILE * out)324 void strs_write_each(struct strs *strs, FILE *out)
325 {
326 	unsigned i;
327 
328 	for (i=0; i<strs->num; i++) {
329 		if (!strs->list[i]) {
330 			continue;
331 		}
332 		sepol_printf(out, "%s\n",strs->list[i]);
333 	}
334 }
335 
strs_write_each_indented(struct strs * strs,FILE * out,int indent)336 void strs_write_each_indented(struct strs *strs, FILE *out, int indent)
337 {
338 	unsigned i;
339 
340 	for (i=0; i<strs->num; i++) {
341 		if (!strs->list[i]) {
342 			continue;
343 		}
344 		sepol_indent(out, indent);
345 		sepol_printf(out, "%s\n",strs->list[i]);
346 	}
347 }
348 
hashtab_ordered_to_strs(char * key,void * data,void * args)349 int hashtab_ordered_to_strs(char *key, void *data, void *args)
350 {
351 	struct strs *strs = (struct strs *)args;
352 	symtab_datum_t *datum = data;
353 
354 	return strs_add_at_index(strs, key, datum->value-1);
355 }
356 
ebitmap_to_strs(struct ebitmap * map,struct strs * strs,char ** val_to_name)357 int ebitmap_to_strs(struct ebitmap *map, struct strs *strs, char **val_to_name)
358 {
359 	struct ebitmap_node *node;
360 	uint32_t i;
361 	int rc;
362 
363 	ebitmap_for_each_positive_bit(map, node, i) {
364 		rc = strs_add(strs, val_to_name[i]);
365 		if (rc != 0) {
366 			return -1;
367 		}
368 	}
369 
370 	return 0;
371 }
372 
ebitmap_to_str(struct ebitmap * map,char ** val_to_name,int sort)373 char *ebitmap_to_str(struct ebitmap *map, char **val_to_name, int sort)
374 {
375 	struct strs *strs;
376 	char *str = NULL;
377 	int rc;
378 
379 	rc = strs_init(&strs, 32);
380 	if (rc != 0) {
381 		goto exit;
382 	}
383 
384 	rc = ebitmap_to_strs(map, strs, val_to_name);
385 	if (rc != 0) {
386 		goto exit;
387 	}
388 
389 	if (sort) {
390 		strs_sort(strs);
391 	}
392 
393 	str = strs_to_str(strs);
394 
395 exit:
396 	strs_destroy(&strs);
397 
398 	return str;
399 }
400 
strs_stack_init(struct strs ** stack)401 int strs_stack_init(struct strs **stack)
402 {
403 	return strs_init(stack, STACK_SIZE);
404 }
405 
strs_stack_destroy(struct strs ** stack)406 void strs_stack_destroy(struct strs **stack)
407 {
408 	return strs_destroy(stack);
409 }
410 
strs_stack_push(struct strs * stack,char * s)411 int strs_stack_push(struct strs *stack, char *s)
412 {
413 	return strs_add(stack, s);
414 }
415 
strs_stack_pop(struct strs * stack)416 char *strs_stack_pop(struct strs *stack)
417 {
418 	return strs_remove_last(stack);
419 }
420 
strs_stack_empty(struct strs * stack)421 int strs_stack_empty(struct strs *stack)
422 {
423 	return strs_num_items(stack) == 0;
424 }
425 
compare_ranges(uint64_t l1,uint64_t h1,uint64_t l2,uint64_t h2)426 static int compare_ranges(uint64_t l1, uint64_t h1, uint64_t l2, uint64_t h2)
427 {
428 	uint64_t d1, d2;
429 
430 	d1 = h1-l1;
431 	d2 = h2-l2;
432 
433 	if (d1 < d2) {
434 		return -1;
435 	} else if (d1 > d2) {
436 		return 1;
437 	} else {
438 		if (l1 < l2) {
439 			return -1;
440 		} else if (l1 > l2) {
441 			return 1;
442 		}
443 	}
444 
445 	return 0;
446 }
447 
fsuse_data_cmp(const void * a,const void * b)448 static int fsuse_data_cmp(const void *a, const void *b)
449 {
450 	struct ocontext *const *aa = a;
451 	struct ocontext *const *bb = b;
452 
453 	if ((*aa)->v.behavior != (*bb)->v.behavior) {
454 		if ((*aa)->v.behavior < (*bb)->v.behavior) {
455 			return -1;
456 		} else {
457 			return 1;
458 		}
459 	}
460 
461 	return strcmp((*aa)->u.name, (*bb)->u.name);
462 }
463 
portcon_data_cmp(const void * a,const void * b)464 static int portcon_data_cmp(const void *a, const void *b)
465 {
466 	struct ocontext *const *aa = a;
467 	struct ocontext *const *bb = b;
468 	int rc;
469 
470 	rc = compare_ranges((*aa)->u.port.low_port, (*aa)->u.port.high_port,
471 			    (*bb)->u.port.low_port, (*bb)->u.port.high_port);
472 	if (rc == 0) {
473 		if ((*aa)->u.port.protocol < (*bb)->u.port.protocol) {
474 			rc = -1;
475 		} else if ((*aa)->u.port.protocol > (*bb)->u.port.protocol) {
476 			rc = 1;
477 		}
478 	}
479 
480 	return rc;
481 }
482 
netif_data_cmp(const void * a,const void * b)483 static int netif_data_cmp(const void *a, const void *b)
484 {
485 	struct ocontext *const *aa = a;
486 	struct ocontext *const *bb = b;
487 
488 	return strcmp((*aa)->u.name, (*bb)->u.name);
489 }
490 
node_data_cmp(const void * a,const void * b)491 static int node_data_cmp(const void *a, const void *b)
492 {
493 	struct ocontext *const *aa = a;
494 	struct ocontext *const *bb = b;
495 	int rc;
496 
497 	rc = memcmp(&(*aa)->u.node.mask, &(*bb)->u.node.mask, sizeof((*aa)->u.node.mask));
498 	if (rc > 0) {
499 		return -1;
500 	} else if (rc < 0) {
501 		return 1;
502 	}
503 
504 	return memcmp(&(*aa)->u.node.addr, &(*bb)->u.node.addr, sizeof((*aa)->u.node.addr));
505 }
506 
node6_data_cmp(const void * a,const void * b)507 static int node6_data_cmp(const void *a, const void *b)
508 {
509 	struct ocontext *const *aa = a;
510 	struct ocontext *const *bb = b;
511 	int rc;
512 
513 	rc = memcmp(&(*aa)->u.node6.mask, &(*bb)->u.node6.mask, sizeof((*aa)->u.node6.mask));
514 	if (rc > 0) {
515 		return -1;
516 	} else if (rc < 0) {
517 		return 1;
518 	}
519 
520 	return memcmp(&(*aa)->u.node6.addr, &(*bb)->u.node6.addr, sizeof((*aa)->u.node6.addr));
521 }
522 
ibpkey_data_cmp(const void * a,const void * b)523 static int ibpkey_data_cmp(const void *a, const void *b)
524 {
525 	int rc;
526 	struct ocontext *const *aa = a;
527 	struct ocontext *const *bb = b;
528 
529 	rc = (*aa)->u.ibpkey.subnet_prefix - (*bb)->u.ibpkey.subnet_prefix;
530 	if (rc)
531 		return rc;
532 
533 	return compare_ranges((*aa)->u.ibpkey.low_pkey, (*aa)->u.ibpkey.high_pkey,
534 			      (*bb)->u.ibpkey.low_pkey, (*bb)->u.ibpkey.high_pkey);
535 }
536 
ibendport_data_cmp(const void * a,const void * b)537 static int ibendport_data_cmp(const void *a, const void *b)
538 {
539 	int rc;
540 	struct ocontext *const *aa = a;
541 	struct ocontext *const *bb = b;
542 
543 	rc = strcmp((*aa)->u.ibendport.dev_name, (*bb)->u.ibendport.dev_name);
544 	if (rc)
545 		return rc;
546 
547 	return (*aa)->u.ibendport.port - (*bb)->u.ibendport.port;
548 }
549 
pirq_data_cmp(const void * a,const void * b)550 static int pirq_data_cmp(const void *a, const void *b)
551 {
552 	struct ocontext *const *aa = a;
553 	struct ocontext *const *bb = b;
554 
555 	if ((*aa)->u.pirq < (*bb)->u.pirq) {
556 		return -1;
557 	} else if ((*aa)->u.pirq > (*bb)->u.pirq) {
558 		return 1;
559 	}
560 
561 	return 0;
562 }
563 
ioport_data_cmp(const void * a,const void * b)564 static int ioport_data_cmp(const void *a, const void *b)
565 {
566 	struct ocontext *const *aa = a;
567 	struct ocontext *const *bb = b;
568 
569 	return compare_ranges((*aa)->u.ioport.low_ioport, (*aa)->u.ioport.high_ioport,
570 			      (*bb)->u.ioport.low_ioport, (*bb)->u.ioport.high_ioport);
571 }
572 
iomem_data_cmp(const void * a,const void * b)573 static int iomem_data_cmp(const void *a, const void *b)
574 {
575 	struct ocontext *const *aa = a;
576 	struct ocontext *const *bb = b;
577 
578 	return compare_ranges((*aa)->u.iomem.low_iomem, (*aa)->u.iomem.high_iomem,
579 			      (*bb)->u.iomem.low_iomem, (*bb)->u.iomem.high_iomem);
580 }
581 
pcid_data_cmp(const void * a,const void * b)582 static int pcid_data_cmp(const void *a, const void *b)
583 {
584 	struct ocontext *const *aa = a;
585 	struct ocontext *const *bb = b;
586 
587 	if ((*aa)->u.device < (*bb)->u.device) {
588 		return -1;
589 	} else if ((*aa)->u.device > (*bb)->u.device) {
590 		return 1;
591 	}
592 
593 	return 0;
594 }
595 
dtree_data_cmp(const void * a,const void * b)596 static int dtree_data_cmp(const void *a, const void *b)
597 {
598 	struct ocontext *const *aa = a;
599 	struct ocontext *const *bb = b;
600 
601 	return strcmp((*aa)->u.name, (*bb)->u.name);
602 }
603 
sort_ocontext_data(struct ocontext ** ocons,int (* cmp)(const void *,const void *))604 static int sort_ocontext_data(struct ocontext **ocons, int (*cmp)(const void *, const void *))
605 {
606 	struct ocontext *ocon;
607 	struct ocontext **data;
608 	unsigned i, num;
609 
610 	num = 0;
611 	for (ocon = *ocons; ocon != NULL; ocon = ocon->next) {
612 		num++;
613 	}
614 
615 	if (num == 0) {
616 		return 0;
617 	}
618 
619 	data = calloc(sizeof(*data), num);
620 	if (!data) {
621 		sepol_log_err("Out of memory\n");
622 		return -1;
623 	}
624 
625 	i = 0;
626 	for (ocon = *ocons; ocon != NULL; ocon = ocon->next) {
627 		data[i] = ocon;
628 		i++;
629 	}
630 
631 	qsort(data, num, sizeof(*data), cmp);
632 
633 	*ocons = data[0];
634 	for (i=1; i < num; i++) {
635 		data[i-1]->next = data[i];
636 	}
637 	data[num-1]->next = NULL;
638 
639 	free(data);
640 
641 	return 0;
642 }
643 
sort_ocontexts(struct policydb * pdb)644 int sort_ocontexts(struct policydb *pdb)
645 {
646 	int rc = 0;
647 
648 	if (pdb->target_platform == SEPOL_TARGET_SELINUX) {
649 		rc = sort_ocontext_data(&pdb->ocontexts[5], fsuse_data_cmp);
650 		if (rc != 0) {
651 			goto exit;
652 		}
653 
654 		rc = sort_ocontext_data(&pdb->ocontexts[2], portcon_data_cmp);
655 		if (rc != 0) {
656 			goto exit;
657 		}
658 
659 		rc = sort_ocontext_data(&pdb->ocontexts[3], netif_data_cmp);
660 		if (rc != 0) {
661 			goto exit;
662 		}
663 
664 		rc = sort_ocontext_data(&pdb->ocontexts[4], node_data_cmp);
665 		if (rc != 0) {
666 			goto exit;
667 		}
668 
669 		rc = sort_ocontext_data(&pdb->ocontexts[6], node6_data_cmp);
670 		if (rc != 0) {
671 			goto exit;
672 		}
673 
674 		rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBPKEY], ibpkey_data_cmp);
675 		if (rc != 0) {
676 			goto exit;
677 		}
678 
679 		rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBENDPORT], ibendport_data_cmp);
680 		if (rc != 0) {
681 			goto exit;
682 		}
683 	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
684 		rc = sort_ocontext_data(&pdb->ocontexts[1], pirq_data_cmp);
685 		if (rc != 0) {
686 			goto exit;
687 		}
688 
689 		rc = sort_ocontext_data(&pdb->ocontexts[2], ioport_data_cmp);
690 		if (rc != 0) {
691 			goto exit;
692 		}
693 
694 		rc = sort_ocontext_data(&pdb->ocontexts[3], iomem_data_cmp);
695 		if (rc != 0) {
696 			goto exit;
697 		}
698 
699 		rc = sort_ocontext_data(&pdb->ocontexts[4], pcid_data_cmp);
700 		if (rc != 0) {
701 			goto exit;
702 		}
703 
704 		rc = sort_ocontext_data(&pdb->ocontexts[5], dtree_data_cmp);
705 		if (rc != 0) {
706 			goto exit;
707 		}
708 	}
709 
710 exit:
711 	if (rc != 0) {
712 		sepol_log_err("Error sorting ocontexts\n");
713 	}
714 
715 	return rc;
716 }
717