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 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 */ 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 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 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 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 */ 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 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 */ 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 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 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 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 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 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 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 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 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 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 400 void destroy_policy(void *policydbp) 401 { 402 policydb_t *p = static_cast<policydb_t *>(policydbp); 403 policydb_destroy(p); 404 } 405