1 #include <stdio.h>
2 #include <string>
3 #include <sstream>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <iostream>
7 #include <sys/mman.h>
8 #include <sys/stat.h>
9 #include <sepol/policydb/avtab.h>
10 #include <sepol/policydb/policydb.h>
11 #include <sepol/policydb/services.h>
12 #include <sepol/policydb/util.h>
13 #include <sys/types.h>
14 #include <fstream>
15 
16 #include <android-base/file.h>
17 #include <android-base/strings.h>
18 #include <sepol_wrap.h>
19 
20 struct genfs_iter {
21     genfs_t *genfs;
22     ocontext_t *ocon;
23 };
24 
init_genfs_iter(void * policydbp)25 void *init_genfs_iter(void *policydbp)
26 {
27     struct genfs_iter *out = (struct genfs_iter *)
28                             calloc(1, sizeof(struct genfs_iter));
29 
30     if (!out) {
31         std::cerr << "Failed to allocate genfs iterator" << std::endl;
32         return NULL;
33     }
34 
35     policydb_t *db = static_cast<policydb_t *>(policydbp);
36 
37     out->genfs = db->genfs;
38     out->ocon = db->genfs->head;
39 
40     return static_cast<void *>(out);
41 }
42 
43 /*
44  * print genfs path into *out buffer.
45  *
46  * Returns -1 on error.
47  * Returns 0 on successfully retrieving a genfs entry.
48  * Returns 1 on successfully retrieving the final genfs entry.
49  */
get_genfs(char * out,size_t max_size,void * policydbp,void * genfs_iterp)50 int get_genfs(char *out, size_t max_size, void *policydbp, void *genfs_iterp)
51 {
52     size_t len;
53     struct genfs_iter *i = static_cast<struct genfs_iter *>(genfs_iterp);
54     policydb_t *db = static_cast<policydb_t *>(policydbp);
55 
56     len = snprintf(out, max_size, "%s %s %s:%s:%s:s0",
57             i->genfs->fstype,
58             i->ocon->u.name,
59             db->p_user_val_to_name[i->ocon->context->user-1],
60             db->p_role_val_to_name[i->ocon->context->role-1],
61             db->p_type_val_to_name[i->ocon->context->type-1]);
62 
63     if (len >= max_size) {
64         std::cerr << "genfs path exceeds buffer size." << std::endl;
65         return -1;
66     }
67 
68     i->ocon = i->ocon->next;
69     if (i->ocon == NULL) {
70         if (i->genfs->next != NULL) {
71             i->genfs = i->genfs->next;
72             i->ocon = i->genfs->head;
73         } else {
74             return 1;
75         }
76     }
77 
78     return 0;
79 }
80 
destroy_genfs_iter(void * genfs_iterp)81 void destroy_genfs_iter(void *genfs_iterp)
82 {
83     struct genfs_iter *genfs_i = static_cast<struct genfs_iter *>(genfs_iterp);
84     free(genfs_i);
85 }
86 
87 #define TYPE_ITER_LOOKUP   0
88 #define TYPE_ITER_ALLTYPES 1
89 #define TYPE_ITER_ALLATTRS 2
90 struct type_iter {
91     unsigned int alltypes;
92     type_datum *d;
93     ebitmap_node *n;
94     unsigned int length;
95     unsigned int bit;
96 };
97 
init_type_iter(void * policydbp,const char * type,bool is_attr)98 void *init_type_iter(void *policydbp, const char *type, bool is_attr)
99 {
100     policydb_t *db = static_cast<policydb_t *>(policydbp);
101     struct type_iter *out = (struct type_iter *)
102                             calloc(1, sizeof(struct type_iter));
103 
104     if (!out) {
105         std::cerr << "Failed to allocate type type iterator" << std::endl;
106         return NULL;
107     }
108 
109     if (type == NULL) {
110         out->length = db->p_types.nprim;
111         out->bit = 0;
112         if (is_attr)
113             out->alltypes = TYPE_ITER_ALLATTRS;
114         else
115             out->alltypes = TYPE_ITER_ALLTYPES;
116     } else {
117         out->alltypes = TYPE_ITER_LOOKUP;
118         out->d = static_cast<type_datum *>(hashtab_search(db->p_types.table, type));
119         if (is_attr && out->d->flavor != TYPE_ATTRIB) {
120             std::cerr << "\"" << type << "\" MUST be an attribute in the policy" << std::endl;
121             free(out);
122             return NULL;
123         } else if (!is_attr && out->d->flavor !=TYPE_TYPE) {
124             std::cerr << "\"" << type << "\" MUST be a type in the policy" << std::endl;
125             free(out);
126             return NULL;
127         }
128 
129         if (is_attr) {
130             out->bit = ebitmap_start(&db->attr_type_map[out->d->s.value - 1], &out->n);
131             out->length = ebitmap_length(&db->attr_type_map[out->d->s.value - 1]);
132         } else {
133             out->bit = ebitmap_start(&db->type_attr_map[out->d->s.value - 1], &out->n);
134             out->length = ebitmap_length(&db->type_attr_map[out->d->s.value - 1]);
135         }
136     }
137 
138     return static_cast<void *>(out);
139 }
140 
destroy_type_iter(void * type_iterp)141 void destroy_type_iter(void *type_iterp)
142 {
143     struct type_iter *type_i = static_cast<struct type_iter *>(type_iterp);
144     free(type_i);
145 }
146 
147 /*
148  * print type into *out buffer.
149  *
150  * Returns -1 on error.
151  * Returns 0 on successfully reading an avtab entry.
152  * Returns 1 on complete
153  */
get_type(char * out,size_t max_size,void * policydbp,void * type_iterp)154 int get_type(char *out, size_t max_size, void *policydbp, void *type_iterp)
155 {
156     size_t len;
157     policydb_t *db = static_cast<policydb_t *>(policydbp);
158     struct type_iter *i = static_cast<struct type_iter *>(type_iterp);
159 
160     if (!i->alltypes) {
161         for (; i->bit < i->length; i->bit = ebitmap_next(&i->n, i->bit)) {
162             if (!ebitmap_node_get_bit(i->n, i->bit)) {
163                 continue;
164             }
165             break;
166         }
167     }
168     while (i->bit < i->length &&
169            ((i->alltypes == TYPE_ITER_ALLATTRS
170             && db->type_val_to_struct[i->bit]->flavor != TYPE_ATTRIB)
171             || (i->alltypes == TYPE_ITER_ALLTYPES
172             && db->type_val_to_struct[i->bit]->flavor != TYPE_TYPE))) {
173         i->bit++;
174     }
175     if (i->bit >= i->length)
176         return 1;
177     len = snprintf(out, max_size, "%s", db->p_type_val_to_name[i->bit]);
178     if (len >= max_size) {
179         std::cerr << "type name exceeds buffer size." << std::endl;
180         return -1;
181     }
182     i->alltypes ? i->bit++ : i->bit = ebitmap_next(&i->n, i->bit);
183     return 0;
184 }
185 
load_policy(const char * policy_path)186 void *load_policy(const char *policy_path)
187 {
188     FILE *fp;
189     policydb_t *db;
190 
191     fp = fopen(policy_path, "re");
192     if (!fp) {
193         std::cerr << "Invalid or non-existing policy file: " << policy_path << std::endl;
194         return NULL;
195     }
196 
197     db = (policydb_t *) calloc(1, sizeof(policydb_t));
198     if (!db) {
199         std::cerr << "Failed to allocate memory for policy db." << std::endl;
200         fclose(fp);
201         return NULL;
202     }
203 
204     sidtab_t sidtab;
205     sepol_set_sidtab(&sidtab);
206     sepol_set_policydb(db);
207 
208     struct stat sb;
209     if (fstat(fileno(fp), &sb)) {
210         std::cerr << "Failed to stat the policy file" << std::endl;
211         free(db);
212         fclose(fp);
213         return NULL;
214     }
215 
216     auto unmap = [=](void *ptr) { munmap(ptr, sb.st_size); };
217     std::unique_ptr<void, decltype(unmap)> map(
218         mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fileno(fp), 0), unmap);
219     if (!map) {
220         std::cerr << "Failed to map the policy file" << std::endl;
221         free(db);
222         fclose(fp);
223         return NULL;
224     }
225 
226     struct policy_file pf;
227     policy_file_init(&pf);
228     pf.type = PF_USE_MEMORY;
229     pf.data = static_cast<char *>(map.get());
230     pf.len = sb.st_size;
231     if (policydb_init(db)) {
232         std::cerr << "Failed to initialize policydb" << std::endl;
233         free(db);
234         fclose(fp);
235         return NULL;
236     }
237 
238     if (policydb_read(db, &pf, 0)) {
239         std::cerr << "Failed to read binary policy" << std::endl;
240         policydb_destroy(db);
241         free(db);
242         fclose(fp);
243         return NULL;
244     }
245 
246     return static_cast<void *>(db);
247 }
248 
249 /* items needed to iterate over the avtab */
250 struct avtab_iter {
251     avtab_t *avtab;
252     uint32_t i;
253     avtab_ptr_t cur;
254 };
255 
256 /*
257  * print allow rule into *out buffer.
258  *
259  * Returns -1 on error.
260  * Returns 0 on successfully reading an avtab entry.
261  * Returns 1 on complete
262  */
get_avtab_allow_rule(char * out,size_t max_size,policydb_t * db,struct avtab_iter * avtab_i)263 static int get_avtab_allow_rule(char *out, size_t max_size, policydb_t *db,
264                                  struct avtab_iter *avtab_i)
265 {
266     size_t len;
267 
268     for (; avtab_i->i < avtab_i->avtab->nslot; (avtab_i->i)++) {
269         if (avtab_i->cur == NULL) {
270             avtab_i->cur = avtab_i->avtab->htable[avtab_i->i];
271         }
272         for (; avtab_i->cur; avtab_i->cur = (avtab_i->cur)->next) {
273             if (!((avtab_i->cur)->key.specified & AVTAB_ALLOWED)) continue;
274 
275             len = snprintf(out, max_size, "allow,%s,%s,%s,%s",
276                     db->p_type_val_to_name[(avtab_i->cur)->key.source_type - 1],
277                     db->p_type_val_to_name[(avtab_i->cur)->key.target_type - 1],
278                     db->p_class_val_to_name[(avtab_i->cur)->key.target_class - 1],
279                     sepol_av_to_string(db, (avtab_i->cur)->key.target_class, (avtab_i->cur)->datum.data));
280             avtab_i->cur = (avtab_i->cur)->next;
281             if (!(avtab_i->cur))
282                 (avtab_i->i)++;
283             if (len >= max_size) {
284                 std::cerr << "Allow rule exceeds buffer size." << std::endl;
285                 return -1;
286             }
287             return 0;
288         }
289         avtab_i->cur = NULL;
290     }
291 
292     return 1;
293 }
294 
get_allow_rule(char * out,size_t len,void * policydbp,void * avtab_iterp)295 int get_allow_rule(char *out, size_t len, void *policydbp, void *avtab_iterp)
296 {
297     policydb_t *db = static_cast<policydb_t *>(policydbp);
298     struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
299 
300     return get_avtab_allow_rule(out, len, db, avtab_i);
301 }
302 
init_avtab_common(avtab_t * in)303 static avtab_iter *init_avtab_common(avtab_t *in)
304 {
305     struct avtab_iter *out = (struct avtab_iter *)
306                             calloc(1, sizeof(struct avtab_iter));
307     if (!out) {
308         std::cerr << "Failed to allocate avtab iterator" << std::endl;
309         return NULL;
310     }
311 
312     out->avtab = in;
313     return out;
314 }
315 
init_avtab(void * policydbp)316 void *init_avtab(void *policydbp)
317 {
318     policydb_t *p = static_cast<policydb_t *>(policydbp);
319     return static_cast<void *>(init_avtab_common(&p->te_avtab));
320 }
321 
init_cond_avtab(void * policydbp)322 void *init_cond_avtab(void *policydbp)
323 {
324     policydb_t *p = static_cast<policydb_t *>(policydbp);
325     return static_cast<void *>(init_avtab_common(&p->te_cond_avtab));
326 }
327 
destroy_avtab(void * avtab_iterp)328 void destroy_avtab(void *avtab_iterp)
329 {
330     struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
331     free(avtab_i);
332 }
333 
334 /*
335  * <sepol/policydb/expand.h->conditional.h> uses 'bool' as a variable name
336  * inside extern "C" { .. } construct, which clang doesn't like.
337  * So, declare the function we need from expand.h ourselves.
338  */
339 extern "C" int expand_avtab(policydb_t *p, avtab_t *a, avtab_t *expa);
340 
init_expanded_avtab_common(avtab_t * in,policydb_t * p)341 static avtab_iter *init_expanded_avtab_common(avtab_t *in, policydb_t *p)
342 {
343     struct avtab_iter *out = (struct avtab_iter *)
344                             calloc(1, sizeof(struct avtab_iter));
345     if (!out) {
346         std::cerr << "Failed to allocate avtab iterator" << std::endl;
347         return NULL;
348     }
349 
350     avtab_t *avtab = (avtab_t *) calloc(1, sizeof(avtab_t));
351 
352     if (!avtab) {
353         std::cerr << "Failed to allocate avtab" << std::endl;
354         free(out);
355         return NULL;
356     }
357 
358     out->avtab = avtab;
359     if (avtab_init(out->avtab)) {
360         std::cerr << "Failed to initialize avtab" << std::endl;
361         free(avtab);
362         free(out);
363         return NULL;
364     }
365 
366     if (expand_avtab(p, in, out->avtab)) {
367         std::cerr << "Failed to expand avtab" << std::endl;
368         free(avtab);
369         free(out);
370         return NULL;
371     }
372     return out;
373 }
374 
init_expanded_avtab(void * policydbp)375 void *init_expanded_avtab(void *policydbp)
376 {
377     policydb_t *p = static_cast<policydb_t *>(policydbp);
378     return static_cast<void *>(init_expanded_avtab_common(&p->te_avtab, p));
379 }
380 
init_expanded_cond_avtab(void * policydbp)381 void *init_expanded_cond_avtab(void *policydbp)
382 {
383     policydb_t *p = static_cast<policydb_t *>(policydbp);
384     return static_cast<void *>(init_expanded_avtab_common(&p->te_cond_avtab, p));
385 }
386 
destroy_expanded_avtab(void * avtab_iterp)387 void destroy_expanded_avtab(void *avtab_iterp)
388 {
389     struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
390     avtab_destroy(avtab_i->avtab);
391     free(avtab_i->avtab);
392     free(avtab_i);
393 }
394 
destroy_policy(void * policydbp)395 void destroy_policy(void *policydbp)
396 {
397     policydb_t *p = static_cast<policydb_t *>(policydbp);
398     policydb_destroy(p);
399 }
400