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