blob: d537b7e00f242506e7fb9fbb927f0d454b309a78 [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
Dan Cashman91d398d2017-09-26 12:58:29 -070020#define TYPE_ITER_LOOKUP 0
21#define TYPE_ITER_ALLTYPES 1
22#define TYPE_ITER_ALLATTRS 2
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -070023struct type_iter {
Dan Cashman91d398d2017-09-26 12:58:29 -070024 unsigned int alltypes;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -070025 type_datum *d;
26 ebitmap_node *n;
27 unsigned int length;
28 unsigned int bit;
29};
30
31void *init_type_iter(void *policydbp, const char *type, bool is_attr)
32{
33 policydb_t *db = static_cast<policydb_t *>(policydbp);
34 struct type_iter *out = (struct type_iter *)
35 calloc(1, sizeof(struct type_iter));
36
37 if (!out) {
38 std::cerr << "Failed to allocate type type iterator" << std::endl;
39 return NULL;
40 }
41
Dan Cashman91d398d2017-09-26 12:58:29 -070042 if (type == NULL) {
43 out->length = db->p_types.nprim;
44 out->bit = 0;
45 if (is_attr)
46 out->alltypes = TYPE_ITER_ALLATTRS;
47 else
48 out->alltypes = TYPE_ITER_ALLTYPES;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -070049 } else {
Dan Cashman91d398d2017-09-26 12:58:29 -070050 out->alltypes = TYPE_ITER_LOOKUP;
51 out->d = static_cast<type_datum *>(hashtab_search(db->p_types.table, type));
52 if (is_attr && out->d->flavor != TYPE_ATTRIB) {
53 std::cerr << "\"" << type << "\" MUST be an attribute in the policy" << std::endl;
54 free(out);
55 return NULL;
56 } else if (!is_attr && out->d->flavor !=TYPE_TYPE) {
57 std::cerr << "\"" << type << "\" MUST be a type in the policy" << std::endl;
58 free(out);
59 return NULL;
60 }
61
62 if (is_attr) {
63 out->bit = ebitmap_start(&db->attr_type_map[out->d->s.value - 1], &out->n);
64 out->length = ebitmap_length(&db->attr_type_map[out->d->s.value - 1]);
65 } else {
66 out->bit = ebitmap_start(&db->type_attr_map[out->d->s.value - 1], &out->n);
67 out->length = ebitmap_length(&db->type_attr_map[out->d->s.value - 1]);
68 }
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -070069 }
70
71 return static_cast<void *>(out);
72}
73
74void destroy_type_iter(void *type_iterp)
75{
76 struct type_iter *type_i = static_cast<struct type_iter *>(type_iterp);
77 free(type_i);
78}
79
80/*
Dan Cashman91d398d2017-09-26 12:58:29 -070081 * print type into *out buffer.
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -070082 *
83 * Returns -1 on error.
84 * Returns 0 on successfully reading an avtab entry.
85 * Returns 1 on complete
86 */
87int get_type(char *out, size_t max_size, void *policydbp, void *type_iterp)
88{
89 size_t len;
90 policydb_t *db = static_cast<policydb_t *>(policydbp);
91 struct type_iter *i = static_cast<struct type_iter *>(type_iterp);
92
Dan Cashman91d398d2017-09-26 12:58:29 -070093 if (!i->alltypes) {
94 for (; i->bit < i->length; i->bit = ebitmap_next(&i->n, i->bit)) {
95 if (!ebitmap_node_get_bit(i->n, i->bit)) {
96 continue;
97 }
98 break;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -070099 }
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700100 }
Dan Cashman91d398d2017-09-26 12:58:29 -0700101 while (i->bit < i->length &&
102 ((i->alltypes == TYPE_ITER_ALLATTRS
103 && db->type_val_to_struct[i->bit]->flavor != TYPE_ATTRIB)
104 || (i->alltypes == TYPE_ITER_ALLTYPES
105 && db->type_val_to_struct[i->bit]->flavor != TYPE_TYPE))) {
106 i->bit++;
107 }
108 if (i->bit >= i->length)
109 return 1;
110 len = snprintf(out, max_size, "%s", db->p_type_val_to_name[i->bit]);
111 if (len >= max_size) {
112 std::cerr << "type name exceeds buffer size." << std::endl;
113 return -1;
114 }
115 i->alltypes ? i->bit++ : i->bit = ebitmap_next(&i->n, i->bit);
116 return 0;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700117}
118
119void *load_policy(const char *policy_path)
120{
121 FILE *fp;
122 policydb_t *db;
123
124 fp = fopen(policy_path, "re");
125 if (!fp) {
126 std::cerr << "Invalid or non-existing policy file: " << policy_path << std::endl;
127 return NULL;
128 }
129
130 db = (policydb_t *) calloc(1, sizeof(policydb_t));
131 if (!db) {
132 std::cerr << "Failed to allocate memory for policy db." << std::endl;
133 fclose(fp);
134 return NULL;
135 }
136
137 sidtab_t sidtab;
138 sepol_set_sidtab(&sidtab);
139 sepol_set_policydb(db);
140
141 struct stat sb;
142 if (fstat(fileno(fp), &sb)) {
143 std::cerr << "Failed to stat the policy file" << std::endl;
144 free(db);
145 fclose(fp);
146 return NULL;
147 }
148
149 auto unmap = [=](void *ptr) { munmap(ptr, sb.st_size); };
150 std::unique_ptr<void, decltype(unmap)> map(
151 mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fileno(fp), 0), unmap);
152 if (!map) {
153 std::cerr << "Failed to map the policy file" << std::endl;
154 free(db);
155 fclose(fp);
156 return NULL;
157 }
158
159 struct policy_file pf;
160 policy_file_init(&pf);
161 pf.type = PF_USE_MEMORY;
162 pf.data = static_cast<char *>(map.get());
163 pf.len = sb.st_size;
164 if (policydb_init(db)) {
165 std::cerr << "Failed to initialize policydb" << std::endl;
166 free(db);
167 fclose(fp);
168 return NULL;
169 }
170
171 if (policydb_read(db, &pf, 0)) {
172 std::cerr << "Failed to read binary policy" << std::endl;
173 policydb_destroy(db);
174 free(db);
175 fclose(fp);
176 return NULL;
177 }
178
179 return static_cast<void *>(db);
180}
181
182/* items needed to iterate over the avtab */
183struct avtab_iter {
Dan Cashman91d398d2017-09-26 12:58:29 -0700184 avtab_t *avtab;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700185 uint32_t i;
186 avtab_ptr_t cur;
187};
188
189/*
190 * print allow rule into *out buffer.
191 *
192 * Returns -1 on error.
193 * Returns 0 on successfully reading an avtab entry.
194 * Returns 1 on complete
195 */
196static int get_avtab_allow_rule(char *out, size_t max_size, policydb_t *db,
197 struct avtab_iter *avtab_i)
198{
199 size_t len;
200
Dan Cashman91d398d2017-09-26 12:58:29 -0700201 for (; avtab_i->i < avtab_i->avtab->nslot; (avtab_i->i)++) {
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700202 if (avtab_i->cur == NULL) {
Dan Cashman91d398d2017-09-26 12:58:29 -0700203 avtab_i->cur = avtab_i->avtab->htable[avtab_i->i];
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700204 }
205 for (; avtab_i->cur; avtab_i->cur = (avtab_i->cur)->next) {
206 if (!((avtab_i->cur)->key.specified & AVTAB_ALLOWED)) continue;
207
208 len = snprintf(out, max_size, "allow,%s,%s,%s,%s",
209 db->p_type_val_to_name[(avtab_i->cur)->key.source_type - 1],
210 db->p_type_val_to_name[(avtab_i->cur)->key.target_type - 1],
211 db->p_class_val_to_name[(avtab_i->cur)->key.target_class - 1],
212 sepol_av_to_string(db, (avtab_i->cur)->key.target_class, (avtab_i->cur)->datum.data));
213 avtab_i->cur = (avtab_i->cur)->next;
214 if (!(avtab_i->cur))
215 (avtab_i->i)++;
216 if (len >= max_size) {
217 std::cerr << "Allow rule exceeds buffer size." << std::endl;
218 return -1;
219 }
220 return 0;
221 }
222 avtab_i->cur = NULL;
223 }
224
225 return 1;
226}
227
228int get_allow_rule(char *out, size_t len, void *policydbp, void *avtab_iterp)
229{
230 policydb_t *db = static_cast<policydb_t *>(policydbp);
231 struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
232
233 return get_avtab_allow_rule(out, len, db, avtab_i);
234}
235
Dan Cashman91d398d2017-09-26 12:58:29 -0700236static avtab_iter *init_avtab_common(avtab_t *in)
237{
238 struct avtab_iter *out = (struct avtab_iter *)
239 calloc(1, sizeof(struct avtab_iter));
240 if (!out) {
241 std::cerr << "Failed to allocate avtab iterator" << std::endl;
242 return NULL;
243 }
244
245 out->avtab = in;
246 return out;
247}
248
249void *init_avtab(void *policydbp)
250{
251 policydb_t *p = static_cast<policydb_t *>(policydbp);
252 return static_cast<void *>(init_avtab_common(&p->te_avtab));
253}
254
255void *init_cond_avtab(void *policydbp)
256{
257 policydb_t *p = static_cast<policydb_t *>(policydbp);
258 return static_cast<void *>(init_avtab_common(&p->te_cond_avtab));
259}
260
261void destroy_avtab(void *avtab_iterp)
262{
263 struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
264 free(avtab_i);
265}
266
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700267/*
268 * <sepol/policydb/expand.h->conditional.h> uses 'bool' as a variable name
269 * inside extern "C" { .. } construct, which clang doesn't like.
270 * So, declare the function we need from expand.h ourselves.
271 */
272extern "C" int expand_avtab(policydb_t *p, avtab_t *a, avtab_t *expa);
273
Dan Cashman91d398d2017-09-26 12:58:29 -0700274static avtab_iter *init_expanded_avtab_common(avtab_t *in, policydb_t *p)
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700275{
276 struct avtab_iter *out = (struct avtab_iter *)
277 calloc(1, sizeof(struct avtab_iter));
278 if (!out) {
Dan Cashman91d398d2017-09-26 12:58:29 -0700279 std::cerr << "Failed to allocate avtab iterator" << std::endl;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700280 return NULL;
281 }
282
Dan Cashman91d398d2017-09-26 12:58:29 -0700283 avtab_t *avtab = (avtab_t *) calloc(1, sizeof(avtab_t));
284
285 if (!avtab) {
286 std::cerr << "Failed to allocate avtab" << std::endl;
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700287 free(out);
288 return NULL;
289 }
290
Dan Cashman91d398d2017-09-26 12:58:29 -0700291 out->avtab = avtab;
292 if (avtab_init(out->avtab)) {
293 std::cerr << "Failed to initialize avtab" << std::endl;
294 free(avtab);
295 free(out);
296 return NULL;
297 }
298
299 if (expand_avtab(p, in, out->avtab)) {
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700300 std::cerr << "Failed to expand avtab" << std::endl;
Dan Cashman91d398d2017-09-26 12:58:29 -0700301 free(avtab);
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700302 free(out);
303 return NULL;
304 }
305 return out;
306}
307
Dan Cashman91d398d2017-09-26 12:58:29 -0700308void *init_expanded_avtab(void *policydbp)
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700309{
310 policydb_t *p = static_cast<policydb_t *>(policydbp);
Dan Cashman91d398d2017-09-26 12:58:29 -0700311 return static_cast<void *>(init_expanded_avtab_common(&p->te_avtab, p));
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700312}
313
Dan Cashman91d398d2017-09-26 12:58:29 -0700314void *init_expanded_cond_avtab(void *policydbp)
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700315{
316 policydb_t *p = static_cast<policydb_t *>(policydbp);
Dan Cashman91d398d2017-09-26 12:58:29 -0700317 return static_cast<void *>(init_expanded_avtab_common(&p->te_cond_avtab, p));
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700318}
319
Dan Cashman91d398d2017-09-26 12:58:29 -0700320void destroy_expanded_avtab(void *avtab_iterp)
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700321{
322 struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
Dan Cashman91d398d2017-09-26 12:58:29 -0700323 avtab_destroy(avtab_i->avtab);
324 free(avtab_i->avtab);
Jeff Vander Stoepbdfc0302017-05-25 09:53:47 -0700325 free(avtab_i);
326}
327
328void destroy_policy(void *policydbp)
329{
330 policydb_t *p = static_cast<policydb_t *>(policydbp);
331 policydb_destroy(p);
332}