1ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <stdbool.h>
2ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <stdio.h>
3ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <sys/stat.h>
4ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <sys/types.h>
5ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
6ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include "dups.h"
7ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
8ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanvoid dups_usage() {
9ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    fprintf(stderr, "\tdups\n");
10ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman}
11ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
12ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanstatic int find_dups_helper(avtab_key_t * k, avtab_datum_t * d,
13ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                            void *args)
14ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman{
15ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    policydb_t *policydb = args;
16ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    ebitmap_t *sattr, *tattr;
17ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    ebitmap_node_t *snode, *tnode;
18ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    unsigned int i, j;
19ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    avtab_key_t avkey;
20ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    avtab_ptr_t node;
21ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    struct type_datum *stype, *ttype, *stype2, *ttype2;
22ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    bool attrib1, attrib2;
23ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
24ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (!(k->specified & AVTAB_ALLOWED))
25ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        return 0;
26ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
27ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (k->source_type == k->target_type)
28ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        return 0; /* self rule */
29ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
30ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    avkey.target_class = k->target_class;
31ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    avkey.specified = k->specified;
32ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
33ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    sattr = &policydb->type_attr_map[k->source_type - 1];
34ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    tattr = &policydb->type_attr_map[k->target_type - 1];
35ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    stype = policydb->type_val_to_struct[k->source_type - 1];
36ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    ttype = policydb->type_val_to_struct[k->target_type - 1];
37ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    attrib1 = stype->flavor || ttype->flavor;
38ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    ebitmap_for_each_bit(sattr, snode, i) {
39ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (!ebitmap_node_get_bit(snode, i))
40ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
41ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        ebitmap_for_each_bit(tattr, tnode, j) {
42ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (!ebitmap_node_get_bit(tnode, j))
43ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                continue;
44ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            avkey.source_type = i + 1;
45ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            avkey.target_type = j + 1;
46ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (avkey.source_type == k->source_type &&
47ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                avkey.target_type == k->target_type)
48ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                continue;
49ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (avkey.source_type == avkey.target_type)
50ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                continue; /* self rule */
51ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            stype2 = policydb->type_val_to_struct[avkey.source_type - 1];
52ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            ttype2 = policydb->type_val_to_struct[avkey.target_type - 1];
53ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            attrib2 = stype2->flavor || ttype2->flavor;
54ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (attrib1 && attrib2)
55ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                continue; /* overlapping attribute-based rules */
56ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            for (node = avtab_search_node(&policydb->te_avtab, &avkey);
57ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                 node != NULL;
58ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                 node = avtab_search_node_next(node, avkey.specified)) {
59ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                uint32_t perms = node->datum.data & d->data;
60ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                if ((attrib1 && perms == node->datum.data) ||
61ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                    (attrib2 && perms == d->data)) {
62ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                    /*
63ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                     * The attribute-based rule is a superset of the
64ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                     * non-attribute-based rule.  This is a dup.
65ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                     */
66ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                    printf("Duplicate allow rule found:\n");
67ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                    display_allow(policydb, k, i, d->data);
68ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                    display_allow(policydb, &node->key, i, node->datum.data);
69ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                    printf("\n");
70ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                }
71ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            }
72ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
73ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
74ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
75ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    return 0;
76ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman}
77ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
78ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanstatic int find_dups(policydb_t * policydb)
79ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman{
80ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (avtab_map(&policydb->te_avtab, find_dups_helper, policydb))
81ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        return -1;
82ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    return 0;
83ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman}
84ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
85ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanint dups_func (int argc, __attribute__ ((unused)) char **argv, policydb_t *policydb) {
86ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (argc != 1) {
87ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        USAGE_ERROR = true;
88ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        return -1;
89ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
90ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    return find_dups(policydb);
91ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman}
92