blob: 15f3e7079f06ab00d4fec3ce317e44b4c4bcad4e [file] [log] [blame]
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -07001#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
Jeff Vander Stoep1b828442018-03-21 17:27:20 -070020struct genfs_iter {
21 genfs_t *genfs;
22 ocontext_t *ocon;
23};
24
25void *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;
Yi Kong16544eb2018-07-24 14:54:56 -070032 return nullptr;
Jeff Vander Stoep1b828442018-03-21 17:27:20 -070033 }
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 */
50int 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;
Yi Kong16544eb2018-07-24 14:54:56 -070069 if (i->ocon == nullptr) {
70 if (i->genfs->next != nullptr) {
Jeff Vander Stoep1b828442018-03-21 17:27:20 -070071 i->genfs = i->genfs->next;
72 i->ocon = i->genfs->head;
73 } else {
74 return 1;
75 }
76 }
77
78 return 0;
79}
80
81void 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
Dan Cashman91d398d2017-09-26 12:58:29 -070087#define TYPE_ITER_LOOKUP 0
88#define TYPE_ITER_ALLTYPES 1
89#define TYPE_ITER_ALLATTRS 2
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -070090struct type_iter {
Dan Cashman91d398d2017-09-26 12:58:29 -070091 unsigned int alltypes;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -070092 type_datum *d;
93 ebitmap_node *n;
94 unsigned int length;
95 unsigned int bit;
96};
97
98void *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;
Yi Kong16544eb2018-07-24 14:54:56 -0700106 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700107 }
108
Yi Kong16544eb2018-07-24 14:54:56 -0700109 if (type == nullptr) {
Dan Cashman91d398d2017-09-26 12:58:29 -0700110 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;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700116 } else {
Dan Cashman91d398d2017-09-26 12:58:29 -0700117 out->alltypes = TYPE_ITER_LOOKUP;
118 out->d = static_cast<type_datum *>(hashtab_search(db->p_types.table, type));
Nick Kralevichbb880a22018-09-26 14:28:44 -0700119 if (out->d == nullptr) {
120 std::cerr << "\"" << type << "\" does not exist" << std::endl;
121 free(out);
122 return nullptr;
123 }
Dan Cashman91d398d2017-09-26 12:58:29 -0700124 if (is_attr && out->d->flavor != TYPE_ATTRIB) {
125 std::cerr << "\"" << type << "\" MUST be an attribute in the policy" << std::endl;
126 free(out);
Yi Kong16544eb2018-07-24 14:54:56 -0700127 return nullptr;
Nick Kralevichbb880a22018-09-26 14:28:44 -0700128 } else if (!is_attr && out->d->flavor != TYPE_TYPE) {
Dan Cashman91d398d2017-09-26 12:58:29 -0700129 std::cerr << "\"" << type << "\" MUST be a type in the policy" << std::endl;
130 free(out);
Yi Kong16544eb2018-07-24 14:54:56 -0700131 return nullptr;
Dan Cashman91d398d2017-09-26 12:58:29 -0700132 }
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 }
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700141 }
142
143 return static_cast<void *>(out);
144}
145
146void 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/*
Dan Cashman91d398d2017-09-26 12:58:29 -0700153 * print type into *out buffer.
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700154 *
155 * Returns -1 on error.
156 * Returns 0 on successfully reading an avtab entry.
157 * Returns 1 on complete
158 */
159int 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
Dan Cashman91d398d2017-09-26 12:58:29 -0700165 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;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700171 }
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700172 }
Dan Cashman91d398d2017-09-26 12:58:29 -0700173 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;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700189}
190
191void *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;
Yi Kong16544eb2018-07-24 14:54:56 -0700199 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700200 }
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);
Yi Kong16544eb2018-07-24 14:54:56 -0700206 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700207 }
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);
Yi Kong16544eb2018-07-24 14:54:56 -0700218 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700219 }
220
221 auto unmap = [=](void *ptr) { munmap(ptr, sb.st_size); };
222 std::unique_ptr<void, decltype(unmap)> map(
Yi Kong16544eb2018-07-24 14:54:56 -0700223 mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fileno(fp), 0), unmap);
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700224 if (!map) {
225 std::cerr << "Failed to map the policy file" << std::endl;
226 free(db);
227 fclose(fp);
Yi Kong16544eb2018-07-24 14:54:56 -0700228 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700229 }
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);
Yi Kong16544eb2018-07-24 14:54:56 -0700240 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700241 }
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);
Yi Kong16544eb2018-07-24 14:54:56 -0700248 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700249 }
250
251 return static_cast<void *>(db);
252}
253
254/* items needed to iterate over the avtab */
255struct avtab_iter {
Dan Cashman91d398d2017-09-26 12:58:29 -0700256 avtab_t *avtab;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700257 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 */
268static 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
Dan Cashman91d398d2017-09-26 12:58:29 -0700273 for (; avtab_i->i < avtab_i->avtab->nslot; (avtab_i->i)++) {
Yi Kong16544eb2018-07-24 14:54:56 -0700274 if (avtab_i->cur == nullptr) {
Dan Cashman91d398d2017-09-26 12:58:29 -0700275 avtab_i->cur = avtab_i->avtab->htable[avtab_i->i];
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700276 }
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 }
Yi Kong16544eb2018-07-24 14:54:56 -0700294 avtab_i->cur = nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700295 }
296
297 return 1;
298}
299
300int 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
Dan Cashman91d398d2017-09-26 12:58:29 -0700308static 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;
Yi Kong16544eb2018-07-24 14:54:56 -0700314 return nullptr;
Dan Cashman91d398d2017-09-26 12:58:29 -0700315 }
316
317 out->avtab = in;
318 return out;
319}
320
321void *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
327void *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
333void 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
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700339/*
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 */
344extern "C" int expand_avtab(policydb_t *p, avtab_t *a, avtab_t *expa);
345
Dan Cashman91d398d2017-09-26 12:58:29 -0700346static avtab_iter *init_expanded_avtab_common(avtab_t *in, policydb_t *p)
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700347{
348 struct avtab_iter *out = (struct avtab_iter *)
349 calloc(1, sizeof(struct avtab_iter));
350 if (!out) {
Dan Cashman91d398d2017-09-26 12:58:29 -0700351 std::cerr << "Failed to allocate avtab iterator" << std::endl;
Yi Kong16544eb2018-07-24 14:54:56 -0700352 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700353 }
354
Dan Cashman91d398d2017-09-26 12:58:29 -0700355 avtab_t *avtab = (avtab_t *) calloc(1, sizeof(avtab_t));
356
357 if (!avtab) {
358 std::cerr << "Failed to allocate avtab" << std::endl;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700359 free(out);
Yi Kong16544eb2018-07-24 14:54:56 -0700360 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700361 }
362
Dan Cashman91d398d2017-09-26 12:58:29 -0700363 out->avtab = avtab;
364 if (avtab_init(out->avtab)) {
365 std::cerr << "Failed to initialize avtab" << std::endl;
366 free(avtab);
367 free(out);
Yi Kong16544eb2018-07-24 14:54:56 -0700368 return nullptr;
Dan Cashman91d398d2017-09-26 12:58:29 -0700369 }
370
371 if (expand_avtab(p, in, out->avtab)) {
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700372 std::cerr << "Failed to expand avtab" << std::endl;
Dan Cashman91d398d2017-09-26 12:58:29 -0700373 free(avtab);
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700374 free(out);
Yi Kong16544eb2018-07-24 14:54:56 -0700375 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700376 }
377 return out;
378}
379
Dan Cashman91d398d2017-09-26 12:58:29 -0700380void *init_expanded_avtab(void *policydbp)
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700381{
382 policydb_t *p = static_cast<policydb_t *>(policydbp);
Dan Cashman91d398d2017-09-26 12:58:29 -0700383 return static_cast<void *>(init_expanded_avtab_common(&p->te_avtab, p));
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700384}
385
Dan Cashman91d398d2017-09-26 12:58:29 -0700386void *init_expanded_cond_avtab(void *policydbp)
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700387{
388 policydb_t *p = static_cast<policydb_t *>(policydbp);
Dan Cashman91d398d2017-09-26 12:58:29 -0700389 return static_cast<void *>(init_expanded_avtab_common(&p->te_cond_avtab, p));
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700390}
391
Dan Cashman91d398d2017-09-26 12:58:29 -0700392void destroy_expanded_avtab(void *avtab_iterp)
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700393{
394 struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
Dan Cashman91d398d2017-09-26 12:58:29 -0700395 avtab_destroy(avtab_i->avtab);
396 free(avtab_i->avtab);
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700397 free(avtab_i);
398}
399
400void destroy_policy(void *policydbp)
401{
402 policydb_t *p = static_cast<policydb_t *>(policydbp);
403 policydb_destroy(p);
404}