1ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <ctype.h>
2ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <fcntl.h>
3ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <getopt.h>
4ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <stdbool.h>
5ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <stdio.h>
6ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <sys/mman.h>
7ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <sys/stat.h>
8ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <sys/types.h>
9ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include <unistd.h>
10ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
11ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman#include "neverallow.h"
12ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
13ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanstatic int debug;
14ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanstatic int warn;
15ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
16ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanvoid neverallow_usage() {
17ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    fprintf(stderr, "\tneverallow [-w|--warn] [-d|--debug] [-n|--neverallows <neverallow-rules>] | [-f|--file <neverallow-file>]\n");
18ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman}
19ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
20ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanstatic int read_typeset(policydb_t *policydb, char **ptr, char *end,
21ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                        type_set_t *typeset, uint32_t *flags)
22ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman{
23ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    const char *keyword = "self";
24ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    size_t keyword_size = strlen(keyword), len;
25ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    char *p = *ptr;
26ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    unsigned openparens = 0;
27ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    char *start, *id;
28ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    type_datum_t *type;
29ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    struct ebitmap_node *n;
30ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    unsigned int bit;
31ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    bool negate = false;
32ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    int rc;
33ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
34ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    do {
35ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        while (p < end && isspace(*p))
36ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
37ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
38ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (p == end)
39ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
40ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
41ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '~') {
42ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (debug)
43ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                printf(" ~");
44ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            typeset->flags = TYPE_COMP;
45ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
46ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            while (p < end && isspace(*p))
47ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                p++;
48ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (p == end)
49ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                goto err;
50ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
51ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
52ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '{') {
53ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (debug && !openparens)
54ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                printf(" {");
55ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            openparens++;
56ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
57ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
58ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
59ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
60ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '}') {
61ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (debug && openparens == 1)
62ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                printf(" }");
63ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (openparens == 0)
64ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                goto err;
65ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            openparens--;
66ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
67ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
68ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
69ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
70ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '*') {
71ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (debug)
72ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                printf(" *");
73ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            typeset->flags = TYPE_STAR;
74ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
75ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
76ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
77ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
78ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '-') {
79ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (debug)
80ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                printf(" -");
81ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            negate = true;
82ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
83ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
84ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
85ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
86ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '#') {
87ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            while (p < end && *p != '\n')
88ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                p++;
89ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
90ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
91ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
92ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        start = p;
93ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        while (p < end && !isspace(*p) && *p != ':' && *p != ';' && *p != '{' && *p != '}' && *p != '#')
94ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
95ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
96ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (p == start)
97ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
98ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
99ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        len = p - start;
100ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (len == keyword_size && !strncmp(start, keyword, keyword_size)) {
101ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (debug)
102ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                printf(" self");
103ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            *flags |= RULE_SELF;
104ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
105ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
106ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
107ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        id = calloc(1, len + 1);
108ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (!id)
109ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
110ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        memcpy(id, start, len);
111ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (debug)
112ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            printf(" %s", id);
113ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        type = hashtab_search(policydb->p_types.table, id);
114ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (!type) {
115ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (warn)
116ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                fprintf(stderr, "Warning!  Type or attribute %s used in neverallow undefined in policy being checked.\n", id);
117ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            negate = false;
118ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
119ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
120ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        free(id);
121ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
122ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (type->flavor == TYPE_ATTRIB) {
123ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (negate)
124ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                rc = ebitmap_union(&typeset->negset, &policydb->attr_type_map[type->s.value - 1]);
125ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            else
126ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                rc = ebitmap_union(&typeset->types, &policydb->attr_type_map[type->s.value - 1]);
127ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        } else if (negate) {
128ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            rc = ebitmap_set_bit(&typeset->negset, type->s.value - 1, 1);
129ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        } else {
130ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            rc = ebitmap_set_bit(&typeset->types, type->s.value - 1, 1);
131ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
132ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
133ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        negate = false;
134ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
135ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (rc)
136ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
137ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
138ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    } while (p < end && openparens);
139ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
140ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (p == end)
141ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        goto err;
142ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
143ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (typeset->flags & TYPE_STAR) {
144ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        for (bit = 0; bit < policydb->p_types.nprim; bit++) {
145ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (ebitmap_get_bit(&typeset->negset, bit))
146ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                continue;
147ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (policydb->type_val_to_struct[bit] &&
148ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                policydb->type_val_to_struct[bit]->flavor == TYPE_ATTRIB)
149ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                continue;
150ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (ebitmap_set_bit(&typeset->types, bit, 1))
151ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                goto err;
152ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
153ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
154ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
155ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    ebitmap_for_each_bit(&typeset->negset, n, bit) {
156ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (!ebitmap_node_get_bit(n, bit))
157ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
158ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (ebitmap_set_bit(&typeset->types, bit, 0))
159ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
160ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
161ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
162ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (typeset->flags & TYPE_COMP) {
163ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        for (bit = 0; bit < policydb->p_types.nprim; bit++) {
164ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (policydb->type_val_to_struct[bit] &&
165ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                policydb->type_val_to_struct[bit]->flavor == TYPE_ATTRIB)
166ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                continue;
167ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (ebitmap_get_bit(&typeset->types, bit))
168ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                ebitmap_set_bit(&typeset->types, bit, 0);
169ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            else {
170ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                if (ebitmap_set_bit(&typeset->types, bit, 1))
171ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                    goto err;
172ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            }
173ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
174ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
175ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
176ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    *ptr = p;
177ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    return 0;
178ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanerr:
179ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    return -1;
180ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman}
181ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
182ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanstatic int read_classperms(policydb_t *policydb, char **ptr, char *end,
183ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                           class_perm_node_t **perms)
184ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman{
185ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    char *p = *ptr;
186ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    unsigned openparens = 0;
187ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    char *id, *start;
188ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    class_datum_t *cls = NULL;
189ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    perm_datum_t *perm = NULL;
190ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    class_perm_node_t *classperms = NULL, *node = NULL;
191ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    bool complement = false;
192ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
193ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    while (p < end && isspace(*p))
194ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        p++;
195ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
196ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (p == end || *p != ':')
197ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        goto err;
198ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    p++;
199ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
200ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (debug)
201ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        printf(" :");
202ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
203ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    do {
204ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        while (p < end && isspace(*p))
205ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
206ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
207ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (p == end)
208ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
209ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
210ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '{') {
211ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (debug && !openparens)
212ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                printf(" {");
213ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            openparens++;
214ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
215ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
216ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
217ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
218ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '}') {
219ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (debug && openparens == 1)
220ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                printf(" }");
221ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (openparens == 0)
222ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                goto err;
223ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            openparens--;
224ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
225ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
226ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
227ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
228ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '#') {
229ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            while (p < end && *p != '\n')
230ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                p++;
231ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
232ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
233ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
234ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        start = p;
235ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        while (p < end && !isspace(*p) && *p != '{' && *p != '}' && *p != ';' && *p != '#')
236ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
237ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
238ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (p == start)
239ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
240ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
241ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        id = calloc(1, p - start + 1);
242ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (!id)
243ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
244ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        memcpy(id, start, p - start);
245ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (debug)
246ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            printf(" %s", id);
247ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        cls = hashtab_search(policydb->p_classes.table, id);
248ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (!cls) {
249ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (warn)
250ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                fprintf(stderr, "Warning!  Class %s used in neverallow undefined in policy being checked.\n", id);
251ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
252ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
253ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
254ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        node = calloc(1, sizeof *node);
255ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (!node)
256ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
2570de2b45f63709a691ad29274d28d64fb8501b7b2dcashman        node->tclass = cls->s.value;
258ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        node->next = classperms;
259ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        classperms = node;
260ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        free(id);
261ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    } while (p < end && openparens);
262ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
263ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (p == end)
264ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        goto err;
265ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
266ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (warn && !classperms)
267ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        fprintf(stderr, "Warning!  Empty class set\n");
268ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
269ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    do {
270ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        while (p < end && isspace(*p))
271ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
272ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
273ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (p == end)
274ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
275ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
276ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '~') {
277ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (debug)
278ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                printf(" ~");
279ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            complement = true;
280ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
281ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            while (p < end && isspace(*p))
282ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                p++;
283ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (p == end)
284ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                goto err;
285ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
286ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
287ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '{') {
288ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (debug && !openparens)
289ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                printf(" {");
290ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            openparens++;
291ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
292ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
293ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
294ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
295ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '}') {
296ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (debug && openparens == 1)
297ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                printf(" }");
298ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (openparens == 0)
299ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                goto err;
300ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            openparens--;
301ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
302ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
303ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
304ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
305ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '#') {
306ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            while (p < end && *p != '\n')
307ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                p++;
308ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
309ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
310ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
311ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        start = p;
312ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        while (p < end && !isspace(*p) && *p != '{' && *p != '}' && *p != ';' && *p != '#')
313ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
314ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
315ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (p == start)
316ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
317ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
318ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        id = calloc(1, p - start + 1);
319ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (!id)
320ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
321ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        memcpy(id, start, p - start);
322ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (debug)
323ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            printf(" %s", id);
324ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
325ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (!strcmp(id, "*")) {
326ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            for (node = classperms; node; node = node->next)
327ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                node->data = ~0;
328ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
329ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
330ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
331ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        for (node = classperms; node; node = node->next) {
3320de2b45f63709a691ad29274d28d64fb8501b7b2dcashman            cls = policydb->class_val_to_struct[node->tclass-1];
333ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            perm = hashtab_search(cls->permissions.table, id);
334ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (cls->comdatum && !perm)
335ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                perm = hashtab_search(cls->comdatum->permissions.table, id);
336ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (!perm) {
337ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                if (warn)
3380de2b45f63709a691ad29274d28d64fb8501b7b2dcashman                    fprintf(stderr, "Warning!  Permission %s used in neverallow undefined in class %s in policy being checked.\n", id, policydb->p_class_val_to_name[node->tclass-1]);
339ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                continue;
340ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            }
341ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            node->data |= 1U << (perm->s.value - 1);
342ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
343ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        free(id);
344ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    } while (p < end && openparens);
345ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
346ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (p == end)
347ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        goto err;
348ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
349ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (complement) {
350ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        for (node = classperms; node; node = node->next)
351ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            node->data = ~node->data;
352ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
353ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
354ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (warn) {
355ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        for (node = classperms; node; node = node->next)
356ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            if (!node->data)
357ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                fprintf(stderr, "Warning!  Empty permission set\n");
358ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
359ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
360ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    *perms = classperms;
361ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    *ptr = p;
362ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    return 0;
363ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanerr:
364ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    return -1;
365ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman}
366ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
367ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanstatic int check_neverallows(policydb_t *policydb, char *text, char *end)
368ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman{
369ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    const char *keyword = "neverallow";
370ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    size_t keyword_size = strlen(keyword), len;
371ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    struct avrule *neverallows = NULL, *avrule;
372ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    char *p, *start;
373ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
374ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    p = text;
375ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    while (p < end) {
376ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        while (p < end && isspace(*p))
377ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
378ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
379ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (*p == '#') {
380ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            while (p < end && *p != '\n')
381ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman                p++;
382ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
383ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
384ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
385ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        start = p;
386ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        while (p < end && !isspace(*p))
387ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
388ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
389ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        len = p - start;
390ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (len != keyword_size || strncmp(start, keyword, keyword_size))
391ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            continue;
392ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
393ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (debug)
394ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            printf("neverallow");
395ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
396ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        avrule = calloc(1, sizeof *avrule);
397ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (!avrule)
398ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
399ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
400ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        avrule->specified = AVRULE_NEVERALLOW;
401ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
402ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (read_typeset(policydb, &p, end, &avrule->stypes, &avrule->flags))
403ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
404ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
405ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (read_typeset(policydb, &p, end, &avrule->ttypes, &avrule->flags))
406ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
407ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
408ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (read_classperms(policydb, &p, end, &avrule->perms))
409ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
410ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
411ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        while (p < end && *p != ';')
412ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            p++;
413ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
414ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (p == end || *p != ';')
415ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            goto err;
416ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
417ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        if (debug)
418ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            printf(";\n");
419ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
420ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        avrule->next = neverallows;
421ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        neverallows = avrule;
422ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
423ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
424ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (!neverallows)
425ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        goto err;
426ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
427ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    return check_assertions(NULL, policydb, neverallows);
428ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanerr:
429ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (errno == ENOMEM) {
430ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        fprintf(stderr, "Out of memory while parsing neverallow rules\n");
431ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    } else
432ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        fprintf(stderr, "Error while parsing neverallow rules\n");
433ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    return -1;
434ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman}
435ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
436ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanstatic int check_neverallows_file(policydb_t *policydb, const char *filename)
437ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman{
438ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    int fd;
439ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    struct stat sb;
440ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    char *text, *end;
441ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
442ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    fd = open(filename, O_RDONLY);
443ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (fd < 0) {
444ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        fprintf(stderr, "Could not open %s:  %s\n", filename, strerror(errno));
445ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        return -1;
446ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
447ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (fstat(fd, &sb) < 0) {
448ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        fprintf(stderr, "Can't stat '%s':  %s\n", filename, strerror(errno));
449ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        close(fd);
450ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        return -1;
451ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
452ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    text = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
453ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    end = text + sb.st_size;
454ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (text == MAP_FAILED) {
455ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        fprintf(stderr, "Can't mmap '%s':  %s\n", filename, strerror(errno));
456ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        close(fd);
457ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        return -1;
458ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
459ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    close(fd);
460ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    return check_neverallows(policydb, text, end);
461ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman}
462ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
463ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanstatic int check_neverallows_string(policydb_t *policydb, char *string, size_t len)
464ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman{
465ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    char *text, *end;
466ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    text = string;
467ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    end = text + len;
468ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    return check_neverallows(policydb, text, end);
469ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman}
470ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
471ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashmanint neverallow_func (int argc, char **argv, policydb_t *policydb) {
472ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    char *rules = 0, *file = 0;
473ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    char ch;
474ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
475ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    struct option neverallow_options[] = {
476ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        {"debug", no_argument, NULL, 'd'},
477ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        {"file_input", required_argument, NULL, 'f'},
478ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        {"neverallow", required_argument, NULL, 'n'},
479ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        {"warn", no_argument, NULL, 'w'},
480ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        {NULL, 0, NULL, 0}
481ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    };
482ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
483ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    while ((ch = getopt_long(argc, argv, "df:n:w", neverallow_options, NULL)) != -1) {
484ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        switch (ch) {
485ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        case 'd':
486ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            debug = 1;
487ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            break;
488ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        case 'f':
489ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            file = optarg;
490ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            break;
491ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        case 'n':
492ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            rules = optarg;
493ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            break;
494ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        case 'w':
495ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            warn = 1;
496ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            break;
497ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        default:
498ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            USAGE_ERROR = true;
499ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman            return -1;
500ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        }
501ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
502ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman
503ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (!(rules || file) || (rules && file)){
504ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        USAGE_ERROR = true;
505ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        return -1;
506ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
507ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    if (file) {
508ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        return check_neverallows_file(policydb, file);
509ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    } else {
510ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman        return check_neverallows_string(policydb, rules, strlen(rules));
511ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman    }
512ef4fd30672ebfeac1a0ad04f65deb7b38050b818dcashman}
513