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