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 nullptr;
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 == nullptr) {
70 if (i->genfs->next != nullptr) {
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 nullptr;
107 }
108
109 if (type == nullptr) {
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 (out->d == nullptr) {
120 std::cerr << "\"" << type << "\" does not exist" << std::endl;
121 free(out);
122 return nullptr;
123 }
124 if (is_attr && out->d->flavor != TYPE_ATTRIB) {
125 std::cerr << "\"" << type << "\" MUST be an attribute in the policy" << std::endl;
126 free(out);
127 return nullptr;
128 } else if (!is_attr && out->d->flavor != TYPE_TYPE) {
129 std::cerr << "\"" << type << "\" MUST be a type in the policy" << std::endl;
130 free(out);
131 return nullptr;
132 }
133
134 if (is_attr) {
135 out->bit = ebitmap_start(&db->attr_type_map[out->d->s.value - 1], &out->n);
136 out->length = ebitmap_length(&db->attr_type_map[out->d->s.value - 1]);
137 } else {
138 out->bit = ebitmap_start(&db->type_attr_map[out->d->s.value - 1], &out->n);
139 out->length = ebitmap_length(&db->type_attr_map[out->d->s.value - 1]);
140 }
141 }
142
143 return static_cast<void *>(out);
144 }
145
destroy_type_iter(void * type_iterp)146 void destroy_type_iter(void *type_iterp)
147 {
148 struct type_iter *type_i = static_cast<struct type_iter *>(type_iterp);
149 free(type_i);
150 }
151
152 /*
153 * print type into *out buffer.
154 *
155 * Returns -1 on error.
156 * Returns 0 on successfully reading an avtab entry.
157 * Returns 1 on complete
158 */
get_type(char * out,size_t max_size,void * policydbp,void * type_iterp)159 int get_type(char *out, size_t max_size, void *policydbp, void *type_iterp)
160 {
161 size_t len;
162 policydb_t *db = static_cast<policydb_t *>(policydbp);
163 struct type_iter *i = static_cast<struct type_iter *>(type_iterp);
164
165 if (!i->alltypes) {
166 for (; i->bit < i->length; i->bit = ebitmap_next(&i->n, i->bit)) {
167 if (!ebitmap_node_get_bit(i->n, i->bit)) {
168 continue;
169 }
170 break;
171 }
172 }
173 while (i->bit < i->length &&
174 ((i->alltypes == TYPE_ITER_ALLATTRS
175 && db->type_val_to_struct[i->bit]->flavor != TYPE_ATTRIB)
176 || (i->alltypes == TYPE_ITER_ALLTYPES
177 && db->type_val_to_struct[i->bit]->flavor != TYPE_TYPE))) {
178 i->bit++;
179 }
180 if (i->bit >= i->length)
181 return 1;
182 len = snprintf(out, max_size, "%s", db->p_type_val_to_name[i->bit]);
183 if (len >= max_size) {
184 std::cerr << "type name exceeds buffer size." << std::endl;
185 return -1;
186 }
187 i->alltypes ? i->bit++ : i->bit = ebitmap_next(&i->n, i->bit);
188 return 0;
189 }
190
load_policy(const char * policy_path)191 void *load_policy(const char *policy_path)
192 {
193 FILE *fp;
194 policydb_t *db;
195
196 fp = fopen(policy_path, "re");
197 if (!fp) {
198 std::cerr << "Invalid or non-existing policy file: " << policy_path << std::endl;
199 return nullptr;
200 }
201
202 db = (policydb_t *) calloc(1, sizeof(policydb_t));
203 if (!db) {
204 std::cerr << "Failed to allocate memory for policy db." << std::endl;
205 fclose(fp);
206 return nullptr;
207 }
208
209 sidtab_t sidtab;
210 sepol_set_sidtab(&sidtab);
211 sepol_set_policydb(db);
212
213 struct stat sb;
214 if (fstat(fileno(fp), &sb)) {
215 std::cerr << "Failed to stat the policy file" << std::endl;
216 free(db);
217 fclose(fp);
218 return nullptr;
219 }
220
221 auto unmap = [=](void *ptr) { munmap(ptr, sb.st_size); };
222 std::unique_ptr<void, decltype(unmap)> map(
223 mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fileno(fp), 0), unmap);
224 if (!map) {
225 std::cerr << "Failed to map the policy file" << std::endl;
226 free(db);
227 fclose(fp);
228 return nullptr;
229 }
230
231 struct policy_file pf;
232 policy_file_init(&pf);
233 pf.type = PF_USE_MEMORY;
234 pf.data = static_cast<char *>(map.get());
235 pf.len = sb.st_size;
236 if (policydb_init(db)) {
237 std::cerr << "Failed to initialize policydb" << std::endl;
238 free(db);
239 fclose(fp);
240 return nullptr;
241 }
242
243 if (policydb_read(db, &pf, 0)) {
244 std::cerr << "Failed to read binary policy" << std::endl;
245 policydb_destroy(db);
246 free(db);
247 fclose(fp);
248 return nullptr;
249 }
250
251 return static_cast<void *>(db);
252 }
253
254 /* items needed to iterate over the avtab */
255 struct avtab_iter {
256 avtab_t *avtab;
257 uint32_t i;
258 avtab_ptr_t cur;
259 };
260
261 /*
262 * print allow rule into *out buffer.
263 *
264 * Returns -1 on error.
265 * Returns 0 on successfully reading an avtab entry.
266 * Returns 1 on complete
267 */
get_avtab_allow_rule(char * out,size_t max_size,policydb_t * db,struct avtab_iter * avtab_i)268 static int get_avtab_allow_rule(char *out, size_t max_size, policydb_t *db,
269 struct avtab_iter *avtab_i)
270 {
271 size_t len;
272
273 for (; avtab_i->i < avtab_i->avtab->nslot; (avtab_i->i)++) {
274 if (avtab_i->cur == nullptr) {
275 avtab_i->cur = avtab_i->avtab->htable[avtab_i->i];
276 }
277 for (; avtab_i->cur; avtab_i->cur = (avtab_i->cur)->next) {
278 if (!((avtab_i->cur)->key.specified & AVTAB_ALLOWED)) continue;
279
280 len = snprintf(out, max_size, "allow,%s,%s,%s,%s",
281 db->p_type_val_to_name[(avtab_i->cur)->key.source_type - 1],
282 db->p_type_val_to_name[(avtab_i->cur)->key.target_type - 1],
283 db->p_class_val_to_name[(avtab_i->cur)->key.target_class - 1],
284 sepol_av_to_string(db, (avtab_i->cur)->key.target_class, (avtab_i->cur)->datum.data));
285 avtab_i->cur = (avtab_i->cur)->next;
286 if (!(avtab_i->cur))
287 (avtab_i->i)++;
288 if (len >= max_size) {
289 std::cerr << "Allow rule exceeds buffer size." << std::endl;
290 return -1;
291 }
292 return 0;
293 }
294 avtab_i->cur = nullptr;
295 }
296
297 return 1;
298 }
299
get_allow_rule(char * out,size_t len,void * policydbp,void * avtab_iterp)300 int get_allow_rule(char *out, size_t len, void *policydbp, void *avtab_iterp)
301 {
302 policydb_t *db = static_cast<policydb_t *>(policydbp);
303 struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
304
305 return get_avtab_allow_rule(out, len, db, avtab_i);
306 }
307
init_avtab_common(avtab_t * in)308 static avtab_iter *init_avtab_common(avtab_t *in)
309 {
310 struct avtab_iter *out = (struct avtab_iter *)
311 calloc(1, sizeof(struct avtab_iter));
312 if (!out) {
313 std::cerr << "Failed to allocate avtab iterator" << std::endl;
314 return nullptr;
315 }
316
317 out->avtab = in;
318 return out;
319 }
320
init_avtab(void * policydbp)321 void *init_avtab(void *policydbp)
322 {
323 policydb_t *p = static_cast<policydb_t *>(policydbp);
324 return static_cast<void *>(init_avtab_common(&p->te_avtab));
325 }
326
init_cond_avtab(void * policydbp)327 void *init_cond_avtab(void *policydbp)
328 {
329 policydb_t *p = static_cast<policydb_t *>(policydbp);
330 return static_cast<void *>(init_avtab_common(&p->te_cond_avtab));
331 }
332
destroy_avtab(void * avtab_iterp)333 void destroy_avtab(void *avtab_iterp)
334 {
335 struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
336 free(avtab_i);
337 }
338
339 /*
340 * <sepol/policydb/expand.h->conditional.h> uses 'bool' as a variable name
341 * inside extern "C" { .. } construct, which clang doesn't like.
342 * So, declare the function we need from expand.h ourselves.
343 */
344 extern "C" int expand_avtab(policydb_t *p, avtab_t *a, avtab_t *expa);
345
init_expanded_avtab_common(avtab_t * in,policydb_t * p)346 static avtab_iter *init_expanded_avtab_common(avtab_t *in, policydb_t *p)
347 {
348 struct avtab_iter *out = (struct avtab_iter *)
349 calloc(1, sizeof(struct avtab_iter));
350 if (!out) {
351 std::cerr << "Failed to allocate avtab iterator" << std::endl;
352 return nullptr;
353 }
354
355 avtab_t *avtab = (avtab_t *) calloc(1, sizeof(avtab_t));
356
357 if (!avtab) {
358 std::cerr << "Failed to allocate avtab" << std::endl;
359 free(out);
360 return nullptr;
361 }
362
363 out->avtab = avtab;
364 if (avtab_init(out->avtab)) {
365 std::cerr << "Failed to initialize avtab" << std::endl;
366 free(avtab);
367 free(out);
368 return nullptr;
369 }
370
371 if (expand_avtab(p, in, out->avtab)) {
372 std::cerr << "Failed to expand avtab" << std::endl;
373 free(avtab);
374 free(out);
375 return nullptr;
376 }
377 return out;
378 }
379
init_expanded_avtab(void * policydbp)380 void *init_expanded_avtab(void *policydbp)
381 {
382 policydb_t *p = static_cast<policydb_t *>(policydbp);
383 return static_cast<void *>(init_expanded_avtab_common(&p->te_avtab, p));
384 }
385
init_expanded_cond_avtab(void * policydbp)386 void *init_expanded_cond_avtab(void *policydbp)
387 {
388 policydb_t *p = static_cast<policydb_t *>(policydbp);
389 return static_cast<void *>(init_expanded_avtab_common(&p->te_cond_avtab, p));
390 }
391
destroy_expanded_avtab(void * avtab_iterp)392 void destroy_expanded_avtab(void *avtab_iterp)
393 {
394 struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
395 avtab_destroy(avtab_i->avtab);
396 free(avtab_i->avtab);
397 free(avtab_i);
398 }
399
destroy_policy(void * policydbp)400 void destroy_policy(void *policydbp)
401 {
402 policydb_t *p = static_cast<policydb_t *>(policydbp);
403 policydb_destroy(p);
404 }
405