17b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <getopt.h>
27b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <unistd.h>
37b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <stddef.h>
47b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <stdlib.h>
57b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <sys/mman.h>
67b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <sys/types.h>
77b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <sys/stat.h>
87b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <fcntl.h>
97b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <stdio.h>
107b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <sepol/policydb/policydb.h>
117b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <sepol/policydb/services.h>
127b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <sepol/policydb/expand.h>
137b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley#include <sepol/policydb/util.h>
1443b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley#include <stdbool.h>
157b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
167b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalleyvoid usage(char *arg0)
177b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley{
18c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman    fprintf(stderr, "%s [-e|--equiv] [-d|--diff] [-D|--dups] [-p|--permissive] -P <policy file>\n", arg0);
197b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    exit(1);
207b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley}
217b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
227b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalleyint load_policy(char *filename, policydb_t * policydb, struct policy_file *pf)
237b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley{
247b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    int fd;
257b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    struct stat sb;
267b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    void *map;
277b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    int ret;
287b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
297b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    fd = open(filename, O_RDONLY);
307b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (fd < 0) {
317b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        fprintf(stderr, "Can't open '%s':  %s\n", filename, strerror(errno));
327b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return 1;
337b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
347b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (fstat(fd, &sb) < 0) {
357b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        fprintf(stderr, "Can't stat '%s':  %s\n", filename, strerror(errno));
367b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        close(fd);
377b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return 1;
387b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
397b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
407b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (map == MAP_FAILED) {
417b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        fprintf(stderr, "Can't mmap '%s':  %s\n", filename, strerror(errno));
427b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        close(fd);
437b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return 1;
447b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
457b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
467b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    policy_file_init(pf);
477b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    pf->type = PF_USE_MEMORY;
487b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    pf->data = map;
497b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    pf->len = sb.st_size;
507b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (policydb_init(policydb)) {
517b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        fprintf(stderr, "Could not initialize policydb!\n");
527b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        close(fd);
537b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        munmap(map, sb.st_size);
547b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return 1;
557b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
567b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    ret = policydb_read(policydb, pf, 0);
577b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (ret) {
587b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        fprintf(stderr, "error(s) encountered while parsing configuration\n");
597b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        close(fd);
607b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        munmap(map, sb.st_size);
617b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return 1;
627b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
637b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
647b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    return 0;
657b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley}
667b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
677b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalleystatic int insert_type_rule(avtab_key_t * k, avtab_datum_t * d,
687b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                            struct avtab_node *type_rules)
697b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley{
707b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    struct avtab_node *p, *c, *n;
717b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
727b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    for (p = type_rules, c = type_rules->next; c; p = c, c = c->next) {
737b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        /*
747b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley         * Find the insertion point, keeping the list
757b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley         * ordered by source type, then target type, then
767b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley         * target class.
777b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley         */
787b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        if (k->source_type < c->key.source_type)
797b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            break;
807b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        if (k->source_type == c->key.source_type &&
817b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            k->target_type < c->key.target_type)
827b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            break;
837b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        if (k->source_type == c->key.source_type &&
847b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            k->target_type == c->key.target_type &&
857b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            k->target_class <= c->key.target_class)
867b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            break;
877b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
887b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
897b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (c &&
907b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        k->source_type == c->key.source_type &&
917b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        k->target_type == c->key.target_type &&
927b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        k->target_class == c->key.target_class) {
937b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        c->datum.data |= d->data;
947b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return 0;
957b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
967b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
977b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    /* Insert the rule */
987b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    n = malloc(sizeof(struct avtab_node));
997b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (!n) {
1007b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        fprintf(stderr, "out of memory\n");
1017b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        exit(1);
1027b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
1037b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
1047b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    n->key = *k;
1057b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    n->datum = *d;
1067b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    n->next = p->next;
1077b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    p->next = n;
1087b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    return 0;
1097b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley}
1107b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
1117b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalleystatic int create_type_rules_helper(avtab_key_t * k, avtab_datum_t * d,
1127b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                                    void *args)
1137b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley{
1147b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    struct avtab_node *type_rules = args;
1157b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    avtab_key_t key;
1167b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
1177b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    /*
1187b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     * Insert the rule into the list for
1197b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     * the source type.  The source type value
1207b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     * is cleared as we want to compare against other type
1217b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     * rules with different source types.
1227b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     */
1237b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    key = *k;
1247b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    key.source_type = 0;
1257b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (k->source_type == k->target_type) {
1267b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        /* Clear target type as well; this is a self rule. */
1277b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        key.target_type = 0;
1287b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
1297b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (insert_type_rule(&key, d, &type_rules[k->source_type - 1]))
1307b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return -1;
1317b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
1327b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (k->source_type == k->target_type)
1337b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return 0;
1347b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
1357b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    /*
1367b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     * If the target type differs, then we also
1377b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     * insert the rule into the list for the target
1387b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     * type.  We clear the target type value so that
1397b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     * we can compare against other type rules with
1407b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     * different target types.
1417b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     */
1427b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    key = *k;
1437b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    key.target_type = 0;
1447b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (insert_type_rule(&key, d, &type_rules[k->target_type - 1]))
1457b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return -1;
1467b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
1477b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    return 0;
1487b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley}
1497b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
1507b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalleystatic int create_type_rules(avtab_key_t * k, avtab_datum_t * d, void *args)
1517b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley{
1527b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (k->specified & AVTAB_ALLOWED)
1537b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return create_type_rules_helper(k, d, args);
1547b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    return 0;
1557b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley}
1567b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
1577b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalleystatic int create_type_rules_cond(avtab_key_t * k, avtab_datum_t * d,
1587b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                                  void *args)
1597b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley{
1607b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if ((k->specified & (AVTAB_ALLOWED|AVTAB_ENABLED)) ==
1617b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        (AVTAB_ALLOWED|AVTAB_ENABLED))
1627b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return create_type_rules_helper(k, d, args);
1637b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    return 0;
1647b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley}
1657b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
1667b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalleystatic void free_type_rules(struct avtab_node *l)
1677b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley{
1687b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    struct avtab_node *tmp;
1697b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
1707b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    while (l) {
1717b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        tmp = l;
1727b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        l = l->next;
1737b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        free(tmp);
1747b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
1757b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley}
1767b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
177bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalleystatic void display_allow(policydb_t *policydb, avtab_key_t *key, int idx,
178bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                          uint32_t perms)
1797b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley{
1807b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    printf("    allow %s %s:%s { %s };\n",
181bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley           policydb->p_type_val_to_name[key->source_type
182bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                                        ? key->source_type - 1 : idx],
183bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley           key->target_type == key->source_type ? "self" :
184bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley           policydb->p_type_val_to_name[key->target_type
185bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                                        ? key->target_type - 1 : idx],
186bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley           policydb->p_class_val_to_name[key->target_class - 1],
1877b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley           sepol_av_to_string
188bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley           (policydb, key->target_class, perms));
1897b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley}
1907b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
1917b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalleystatic int find_match(policydb_t *policydb, struct avtab_node *l1,
1927b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                      int idx1, struct avtab_node *l2, int idx2)
1937b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley{
1947b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    struct avtab_node *c;
1957b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    uint32_t perms1, perms2;
1967b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
1977b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    for (c = l2; c; c = c->next) {
1987b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        if (l1->key.source_type < c->key.source_type)
1997b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            break;
2007b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        if (l1->key.source_type == c->key.source_type &&
2017b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            l1->key.target_type < c->key.target_type)
2027b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            break;
2037b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        if (l1->key.source_type == c->key.source_type &&
2047b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            l1->key.target_type == c->key.target_type &&
2057b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            l1->key.target_class <= c->key.target_class)
2067b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            break;
2077b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
2087b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
2097b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (c &&
2107b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        l1->key.source_type == c->key.source_type &&
2117b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        l1->key.target_type == c->key.target_type &&
2127b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        l1->key.target_class == c->key.target_class) {
2137b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        perms1 = l1->datum.data & ~c->datum.data;
2147b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        perms2 = c->datum.data & ~l1->datum.data;
2157b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        if (perms1 || perms2) {
2167b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            if (perms1)
217bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                display_allow(policydb, &l1->key, idx1, perms1);
2187b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            if (perms2)
219bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                display_allow(policydb, &c->key, idx2, perms2);
2207b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            printf("\n");
2217b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            return 1;
2227b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        }
2237b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
2247b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
2257b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    return 0;
2267b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley}
2277b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
2287b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalleystatic int analyze_types(policydb_t * policydb, char equiv, char diff)
2297b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley{
2307b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    avtab_t exp_avtab, exp_cond_avtab;
2317b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    struct avtab_node *type_rules, *l1, *l2;
2327b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    struct type_datum *type;
2337b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    size_t i, j;
2347b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
2357b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    /*
2367b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     * Create a list of access vector rules for each type
2377b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     * from the access vector table.
2387b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     */
2397b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    type_rules = malloc(sizeof(struct avtab_node) * policydb->p_types.nprim);
2407b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (!type_rules) {
2417b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        fprintf(stderr, "out of memory\n");
2427b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        exit(1);
2437b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
2447b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    memset(type_rules, 0, sizeof(struct avtab_node) * policydb->p_types.nprim);
2457b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
2467b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (avtab_init(&exp_avtab) || avtab_init(&exp_cond_avtab)) {
2477b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        fputs("out of memory\n", stderr);
2487b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return -1;
2497b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
2507b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
2517b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (expand_avtab(policydb, &policydb->te_avtab, &exp_avtab)) {
2527b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        fputs("out of memory\n", stderr);
2537b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        avtab_destroy(&exp_avtab);
2547b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return -1;
2557b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
2567b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
2577b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (expand_avtab(policydb, &policydb->te_cond_avtab, &exp_cond_avtab)) {
2587b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        fputs("out of memory\n", stderr);
2597b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        avtab_destroy(&exp_avtab);
2607b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        return -1;
2617b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
2627b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
2637b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (avtab_map(&exp_avtab, create_type_rules, type_rules))
2647b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        exit(1);
2657b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
2667b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (avtab_map(&exp_cond_avtab, create_type_rules_cond, type_rules))
2677b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        exit(1);
2687b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
2697b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    avtab_destroy(&exp_avtab);
2707b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    avtab_destroy(&exp_cond_avtab);
2717b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
2727b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    /*
2737b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     * Compare the type lists and identify similar types.
2747b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley     */
2757b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    for (i = 0; i < policydb->p_types.nprim - 1; i++) {
2767b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        if (!type_rules[i].next)
2777b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            continue;
2787b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        type = policydb->type_val_to_struct[i];
2797b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        if (type->flavor) {
2807b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            free_type_rules(type_rules[i].next);
2817b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            type_rules[i].next = NULL;
2827b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            continue;
2837b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        }
2847b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        for (j = i + 1; j < policydb->p_types.nprim; j++) {
2857b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            type = policydb->type_val_to_struct[j];
2867b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            if (type->flavor) {
2877b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                free_type_rules(type_rules[j].next);
2887b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                type_rules[j].next = NULL;
2897b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                continue;
2907b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            }
2917b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            for (l1 = type_rules[i].next, l2 = type_rules[j].next;
2927b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                 l1 && l2; l1 = l1->next, l2 = l2->next) {
2937b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                if (l1->key.source_type != l2->key.source_type)
2947b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                    break;
2957b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                if (l1->key.target_type != l2->key.target_type)
2967b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                    break;
2977b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                if (l1->key.target_class != l2->key.target_class
2987b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                    || l1->datum.data != l2->datum.data)
2997b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                    break;
3007b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            }
3017b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            if (l1 || l2) {
3027b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                if (diff) {
3037b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                    printf
3047b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                        ("Types %s and %s differ, starting with:\n",
3057b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                         policydb->p_type_val_to_name[i],
3067b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                         policydb->p_type_val_to_name[j]);
3077b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
3087b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                    if (l1 && l2) {
3097b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                        if (find_match(policydb, l1, i, l2, j))
3107b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                            continue;
3117b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                        if (find_match(policydb, l2, j, l1, i))
3127b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                            continue;
3137b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                    }
3147b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                    if (l1)
315bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                        display_allow(policydb, &l1->key, i, l1->datum.data);
3167b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                    if (l2)
317bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                        display_allow(policydb, &l2->key, j, l2->datum.data);
3187b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                    printf("\n");
3197b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                }
3207b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                continue;
3217b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            }
3227b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            free_type_rules(type_rules[j].next);
3237b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            type_rules[j].next = NULL;
3247b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            if (equiv) {
3257b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                printf("Types %s and %s are equivalent.\n",
3267b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                       policydb->p_type_val_to_name[i],
3277b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley                       policydb->p_type_val_to_name[j]);
3287b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            }
3297b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        }
3307b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        free_type_rules(type_rules[i].next);
3317b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        type_rules[i].next = NULL;
3327b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
3337b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
3347b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    free(type_rules);
3357b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    return 0;
3367b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley}
3377b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
338bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalleystatic int find_dups_helper(avtab_key_t * k, avtab_datum_t * d,
339bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                            void *args)
340bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley{
341bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    policydb_t *policydb = args;
342bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    ebitmap_t *sattr, *tattr;
343bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    ebitmap_node_t *snode, *tnode;
344bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    unsigned int i, j;
345bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    avtab_key_t avkey;
346bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    avtab_ptr_t node;
34743b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley    struct type_datum *stype, *ttype, *stype2, *ttype2;
34843b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley    bool attrib1, attrib2;
349bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley
350bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    if (!(k->specified & AVTAB_ALLOWED))
351bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley        return 0;
352bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley
35343b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley    if (k->source_type == k->target_type)
35443b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley        return 0; /* self rule */
35543b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley
356bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    avkey.target_class = k->target_class;
357bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    avkey.specified = k->specified;
358bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley
359bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    sattr = &policydb->type_attr_map[k->source_type - 1];
360bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    tattr = &policydb->type_attr_map[k->target_type - 1];
36143b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley    stype = policydb->type_val_to_struct[k->source_type - 1];
36243b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley    ttype = policydb->type_val_to_struct[k->target_type - 1];
36343b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley    attrib1 = stype->flavor || ttype->flavor;
364bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    ebitmap_for_each_bit(sattr, snode, i) {
365bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley        if (!ebitmap_node_get_bit(snode, i))
366bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley            continue;
367bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley        ebitmap_for_each_bit(tattr, tnode, j) {
368bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley            if (!ebitmap_node_get_bit(tnode, j))
369bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                continue;
370bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley            avkey.source_type = i + 1;
371bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley            avkey.target_type = j + 1;
372bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley            if (avkey.source_type == k->source_type &&
373bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                avkey.target_type == k->target_type)
374bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                continue;
37543b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley            if (avkey.source_type == avkey.target_type)
37643b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley                continue; /* self rule */
37743b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley            stype2 = policydb->type_val_to_struct[avkey.source_type - 1];
37843b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley            ttype2 = policydb->type_val_to_struct[avkey.target_type - 1];
37943b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley            attrib2 = stype2->flavor || ttype2->flavor;
38043b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley            if (attrib1 && attrib2)
38143b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley                continue; /* overlapping attribute-based rules */
382bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley            for (node = avtab_search_node(&policydb->te_avtab, &avkey);
383bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                 node != NULL;
384bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                 node = avtab_search_node_next(node, avkey.specified)) {
38543b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley                uint32_t perms = node->datum.data & d->data;
38643b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley                if ((attrib1 && perms == node->datum.data) ||
38743b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley                    (attrib2 && perms == d->data)) {
38843b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley                    /*
38943b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley                     * The attribute-based rule is a superset of the
39043b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley                     * non-attribute-based rule.  This is a dup.
39143b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley                     */
392bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                    printf("Duplicate allow rule found:\n");
39343b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley                    display_allow(policydb, k, i, d->data);
39443b9cfd3561e16225563610f1eb794eb73d0845fStephen Smalley                    display_allow(policydb, &node->key, i, node->datum.data);
395bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                    printf("\n");
396bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley                }
397bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley            }
398bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley        }
399bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    }
400bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley
401bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    return 0;
402bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley}
403bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley
404bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalleystatic int find_dups(policydb_t * policydb)
405bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley{
406bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    if (avtab_map(&policydb->te_avtab, find_dups_helper, policydb))
407bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley        return -1;
408bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    return 0;
409bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley}
410bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley
411c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashmanstatic int list_permissive(policydb_t * policydb)
412c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman{
413c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman    struct ebitmap_node *n;
414c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman    unsigned int bit;
415c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman
416c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman    /*
417c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman     * iterate over all domains and check if domain is in permissive
418c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman     */
419c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman    ebitmap_for_each_bit(&policydb->permissive_map, n, bit)
420c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman    {
421c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman        if (ebitmap_node_get_bit(n, bit)) {
422c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman            printf("%s\n", policydb->p_type_val_to_name[bit -1]);
423c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman        }
424c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman    }
425c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman    return 0;
426c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman}
427c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman
4287b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalleyint main(int argc, char **argv)
4297b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley{
4307b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    char *policy = NULL;
4317b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    struct policy_file pf;
4327b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    policydb_t policydb;
4337b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    char ch;
434c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman    char equiv = 0, diff = 0, dups = 0, permissive = 0;
4357b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
4367b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    struct option long_options[] = {
4377b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        {"equiv", no_argument, NULL, 'e'},
4387b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        {"diff", no_argument, NULL, 'd'},
439bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley        {"dups", no_argument, NULL, 'D'},
440c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman        {"permissive", no_argument, NULL, 'p'},
4417b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        {"policy", required_argument, NULL, 'P'},
4427b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        {NULL, 0, NULL, 0}
4437b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    };
4447b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
445c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman    while ((ch = getopt_long(argc, argv, "edDpP:", long_options, NULL)) != -1) {
4467b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        switch (ch) {
4477b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        case 'e':
4487b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            equiv = 1;
4497b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            break;
4507b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        case 'd':
4517b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            diff = 1;
4527b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            break;
453bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley        case 'D':
454bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley            dups = 1;
455bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley            break;
456c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman        case 'p':
457c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman            permissive = 1;
458c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman            break;
4597b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        case 'P':
4607b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            policy = optarg;
4617b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            break;
4627b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        default:
4637b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley            usage(argv[0]);
4647b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        }
4657b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    }
4667b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
467c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman    if (!policy || (!equiv && !diff && !dups && !permissive))
4687b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        usage(argv[0]);
4697b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
4707b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    if (load_policy(policy, &policydb, &pf))
4717b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley        exit(1);
4727b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
473bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    if (equiv || diff)
474bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley        analyze_types(&policydb, equiv, diff);
475bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley
476bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley    if (dups)
477bec54f42ede821a31c7a7acc570ec70d8591dad6Stephen Smalley        find_dups(&policydb);
4787b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
479c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman    if (permissive)
480c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman        list_permissive(&policydb);
481c30dd63f56ba5035eeb604b0b9b48f36ef5e8937dcashman
4827b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    policydb_destroy(&policydb);
4837b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley
4847b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley    return 0;
4857b2bee99c18b8cb3f52161b1191d16b8ab50b08fStephen Smalley}
486