/* * This was derived from public domain works with updates to * work with more modern SELinux libraries. * * It is released into the public domain. * */ #include #include #include #include #include #include #include #include #include #include void usage(char *arg0) { fprintf(stderr, "%s -s -t -c -p -P -o \n", arg0); exit(1); } void *cmalloc(size_t s) { void *t = malloc(s); if (t == NULL) { fprintf(stderr, "Out of memory\n"); exit(1); } return t; } int add_rule(char *s, char *t, char *c, char *p, policydb_t *policy) { type_datum_t *src, *tgt; class_datum_t *cls; perm_datum_t *perm; avtab_datum_t *av; avtab_key_t key; src = hashtab_search(policy->p_types.table, s); if (src == NULL) { fprintf(stderr, "source type %s does not exist\n", s); return 1; } tgt = hashtab_search(policy->p_types.table, t); if (tgt == NULL) { fprintf(stderr, "target type %s does not exist\n", t); return 1; } cls = hashtab_search(policy->p_classes.table, c); if (cls == NULL) { fprintf(stderr, "class %s does not exist\n", c); return 1; } perm = hashtab_search(cls->permissions.table, p); if (perm == NULL) { if (cls->comdatum == NULL) { fprintf(stderr, "perm %s does not exist in class %s\n", p, c); return 1; } perm = hashtab_search(cls->comdatum->permissions.table, p); if (perm == NULL) { fprintf(stderr, "perm %s does not exist in class %s\n", p, c); return 1; } } // See if there is already a rule key.source_type = src->s.value; key.target_type = tgt->s.value; key.target_class = cls->s.value; key.specified = AVTAB_ALLOWED; av = avtab_search(&policy->te_avtab, &key); if (av == NULL) { av = cmalloc(sizeof av); av->data |= 1U << (perm->s.value - 1); int ret = avtab_insert(&policy->te_avtab, &key, av); if (ret) { fprintf(stderr, "Error inserting into avtab\n"); return 1; } } av->data |= 1U << (perm->s.value - 1); return 0; } int load_policy(char *filename, policydb_t *policydb, struct policy_file *pf) { int fd; struct stat sb; void *map; int ret; fd = open(filename, O_RDONLY); if (fd < 0) { fprintf(stderr, "Can't open '%s': %s\n", filename, strerror(errno)); return 1; } if (fstat(fd, &sb) < 0) { fprintf(stderr, "Can't stat '%s': %s\n", filename, strerror(errno)); return 1; } map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { fprintf(stderr, "Can't mmap '%s': %s\n", filename, strerror(errno)); return 1; } policy_file_init(pf); pf->type = PF_USE_MEMORY; pf->data = map; pf->len = sb.st_size; if (policydb_init(policydb)) { fprintf(stderr, "policydb_init: Out of memory!\n"); return 1; } ret = policydb_read(policydb, pf, 1); if (ret) { fprintf(stderr, "error(s) encountered while parsing configuration\n"); return 1; } return 0; } int main(int argc, char **argv) { char *policy = NULL, *source = NULL, *target = NULL, *class = NULL, *perm = NULL, *outfile = NULL; policydb_t policydb; struct policy_file pf, outpf; sidtab_t sidtab; char ch; FILE *fp; struct option long_options[] = { {"source", required_argument, NULL, 's'}, {"target", required_argument, NULL, 't'}, {"class", required_argument, NULL, 'c'}, {"perm", required_argument, NULL, 'p'}, {"policy", required_argument, NULL, 'P'}, {"output", required_argument, NULL, 'o'}, {NULL, 0, NULL, 0} }; while ((ch = getopt_long(argc, argv, "s:t:c:p:P:o:", long_options, NULL)) != -1) { switch (ch) { case 's': source = optarg; break; case 't': target = optarg; break; case 'c': class = optarg; break; case 'p': perm = optarg; break; case 'P': policy = optarg; break; case 'o': outfile = optarg; break; default: usage(argv[0]); } } if (!source || !target || !class || !perm || !policy) usage(argv[0]); sepol_set_policydb(&policydb); sepol_set_sidtab(&sidtab); if (load_policy(policy, &policydb, &pf)) { fprintf(stderr, "Could not load policy\n"); return 1; } if (policydb_load_isids(&policydb, &sidtab)) return 1; if (add_rule(source, target, class, perm, &policydb)) { fprintf(stderr, "Could not add rule\n"); return 1; } fp = fopen(outfile, "w"); if (!fp) { fprintf(stderr, "Could not open outfile\n"); return 1; } policy_file_init(&outpf); outpf.type = PF_USE_STDIO; outpf.fp = fp; if (policydb_write(&policydb, &outpf)) { fprintf(stderr, "Could not write policy\n"); return 1; } policydb_destroy(&policydb); fclose(fp); return 0; }