blob: 41f13bf7fe2127f0c366a4502c920944dfecfc9c [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));
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);
Yi Kong16544eb2018-07-24 14:54:56 -0700122 return nullptr;
Dan Cashman91d398d2017-09-26 12:58:29 -0700123 } 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);
Yi Kong16544eb2018-07-24 14:54:56 -0700126 return nullptr;
Dan Cashman91d398d2017-09-26 12:58:29 -0700127 }
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 }
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700136 }
137
138 return static_cast<void *>(out);
139}
140
141void 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/*
Dan Cashman91d398d2017-09-26 12:58:29 -0700148 * print type into *out buffer.
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700149 *
150 * Returns -1 on error.
151 * Returns 0 on successfully reading an avtab entry.
152 * Returns 1 on complete
153 */
154int 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
Dan Cashman91d398d2017-09-26 12:58:29 -0700160 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;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700166 }
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700167 }
Dan Cashman91d398d2017-09-26 12:58:29 -0700168 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;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700184}
185
186void *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;
Yi Kong16544eb2018-07-24 14:54:56 -0700194 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700195 }
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);
Yi Kong16544eb2018-07-24 14:54:56 -0700201 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700202 }
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);
Yi Kong16544eb2018-07-24 14:54:56 -0700213 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700214 }
215
216 auto unmap = [=](void *ptr) { munmap(ptr, sb.st_size); };
217 std::unique_ptr<void, decltype(unmap)> map(
Yi Kong16544eb2018-07-24 14:54:56 -0700218 mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fileno(fp), 0), unmap);
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700219 if (!map) {
220 std::cerr << "Failed to map the policy file" << std::endl;
221 free(db);
222 fclose(fp);
Yi Kong16544eb2018-07-24 14:54:56 -0700223 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700224 }
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);
Yi Kong16544eb2018-07-24 14:54:56 -0700235 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700236 }
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);
Yi Kong16544eb2018-07-24 14:54:56 -0700243 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700244 }
245
246 return static_cast<void *>(db);
247}
248
249/* items needed to iterate over the avtab */
250struct avtab_iter {
Dan Cashman91d398d2017-09-26 12:58:29 -0700251 avtab_t *avtab;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700252 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 */
263static 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
Dan Cashman91d398d2017-09-26 12:58:29 -0700268 for (; avtab_i->i < avtab_i->avtab->nslot; (avtab_i->i)++) {
Yi Kong16544eb2018-07-24 14:54:56 -0700269 if (avtab_i->cur == nullptr) {
Dan Cashman91d398d2017-09-26 12:58:29 -0700270 avtab_i->cur = avtab_i->avtab->htable[avtab_i->i];
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700271 }
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 }
Yi Kong16544eb2018-07-24 14:54:56 -0700289 avtab_i->cur = nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700290 }
291
292 return 1;
293}
294
295int 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
Dan Cashman91d398d2017-09-26 12:58:29 -0700303static 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;
Yi Kong16544eb2018-07-24 14:54:56 -0700309 return nullptr;
Dan Cashman91d398d2017-09-26 12:58:29 -0700310 }
311
312 out->avtab = in;
313 return out;
314}
315
316void *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
322void *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
328void 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
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700334/*
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 */
339extern "C" int expand_avtab(policydb_t *p, avtab_t *a, avtab_t *expa);
340
Dan Cashman91d398d2017-09-26 12:58:29 -0700341static avtab_iter *init_expanded_avtab_common(avtab_t *in, policydb_t *p)
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700342{
343 struct avtab_iter *out = (struct avtab_iter *)
344 calloc(1, sizeof(struct avtab_iter));
345 if (!out) {
Dan Cashman91d398d2017-09-26 12:58:29 -0700346 std::cerr << "Failed to allocate avtab iterator" << std::endl;
Yi Kong16544eb2018-07-24 14:54:56 -0700347 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700348 }
349
Dan Cashman91d398d2017-09-26 12:58:29 -0700350 avtab_t *avtab = (avtab_t *) calloc(1, sizeof(avtab_t));
351
352 if (!avtab) {
353 std::cerr << "Failed to allocate avtab" << std::endl;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700354 free(out);
Yi Kong16544eb2018-07-24 14:54:56 -0700355 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700356 }
357
Dan Cashman91d398d2017-09-26 12:58:29 -0700358 out->avtab = avtab;
359 if (avtab_init(out->avtab)) {
360 std::cerr << "Failed to initialize avtab" << std::endl;
361 free(avtab);
362 free(out);
Yi Kong16544eb2018-07-24 14:54:56 -0700363 return nullptr;
Dan Cashman91d398d2017-09-26 12:58:29 -0700364 }
365
366 if (expand_avtab(p, in, out->avtab)) {
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700367 std::cerr << "Failed to expand avtab" << std::endl;
Dan Cashman91d398d2017-09-26 12:58:29 -0700368 free(avtab);
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700369 free(out);
Yi Kong16544eb2018-07-24 14:54:56 -0700370 return nullptr;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700371 }
372 return out;
373}
374
Dan Cashman91d398d2017-09-26 12:58:29 -0700375void *init_expanded_avtab(void *policydbp)
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700376{
377 policydb_t *p = static_cast<policydb_t *>(policydbp);
Dan Cashman91d398d2017-09-26 12:58:29 -0700378 return static_cast<void *>(init_expanded_avtab_common(&p->te_avtab, p));
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700379}
380
Dan Cashman91d398d2017-09-26 12:58:29 -0700381void *init_expanded_cond_avtab(void *policydbp)
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700382{
383 policydb_t *p = static_cast<policydb_t *>(policydbp);
Dan Cashman91d398d2017-09-26 12:58:29 -0700384 return static_cast<void *>(init_expanded_avtab_common(&p->te_cond_avtab, p));
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700385}
386
Dan Cashman91d398d2017-09-26 12:58:29 -0700387void destroy_expanded_avtab(void *avtab_iterp)
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700388{
389 struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
Dan Cashman91d398d2017-09-26 12:58:29 -0700390 avtab_destroy(avtab_i->avtab);
391 free(avtab_i->avtab);
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700392 free(avtab_i);
393}
394
395void destroy_policy(void *policydbp)
396{
397 policydb_t *p = static_cast<policydb_t *>(policydbp);
398 policydb_destroy(p);
399}