sepolicy-check.c 6.6 KB

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