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 21struct type_iter { 22 type_datum *d; 23 ebitmap_node *n; 24 unsigned int length; 25 unsigned int bit; 26}; 27 28void *init_type_iter(void *policydbp, const char *type, bool is_attr) 29{ 30 policydb_t *db = static_cast<policydb_t *>(policydbp); 31 struct type_iter *out = (struct type_iter *) 32 calloc(1, sizeof(struct type_iter)); 33 34 if (!out) { 35 std::cerr << "Failed to allocate type type iterator" << std::endl; 36 return NULL; 37 } 38 39 out->d = static_cast<type_datum *>(hashtab_search(db->p_types.table, type)); 40 if (is_attr && out->d->flavor != TYPE_ATTRIB) { 41 std::cerr << "\"" << type << "\" MUST be an attribute in the policy" << std::endl; 42 free(out); 43 return NULL; 44 } else if (!is_attr && out->d->flavor !=TYPE_TYPE) { 45 std::cerr << "\"" << type << "\" MUST be a type in the policy" << std::endl; 46 free(out); 47 return NULL; 48 } 49 50 if (is_attr) { 51 out->bit = ebitmap_start(&db->attr_type_map[out->d->s.value - 1], &out->n); 52 out->length = ebitmap_length(&db->attr_type_map[out->d->s.value - 1]); 53 } else { 54 out->bit = ebitmap_start(&db->type_attr_map[out->d->s.value - 1], &out->n); 55 out->length = ebitmap_length(&db->type_attr_map[out->d->s.value - 1]); 56 } 57 58 return static_cast<void *>(out); 59} 60 61void destroy_type_iter(void *type_iterp) 62{ 63 struct type_iter *type_i = static_cast<struct type_iter *>(type_iterp); 64 free(type_i); 65} 66 67/* 68 * print allow rule into *out buffer. 69 * 70 * Returns -1 on error. 71 * Returns 0 on successfully reading an avtab entry. 72 * Returns 1 on complete 73 */ 74int get_type(char *out, size_t max_size, void *policydbp, void *type_iterp) 75{ 76 size_t len; 77 policydb_t *db = static_cast<policydb_t *>(policydbp); 78 struct type_iter *i = static_cast<struct type_iter *>(type_iterp); 79 80 for (; i->bit < i->length; i->bit = ebitmap_next(&i->n, i->bit)) { 81 if (!ebitmap_node_get_bit(i->n, i->bit)) { 82 continue; 83 } 84 len = snprintf(out, max_size, "%s", db->p_type_val_to_name[i->bit]); 85 if (len >= max_size) { 86 std::cerr << "type name exceeds buffer size." << std::endl; 87 return -1; 88 } 89 i->bit = ebitmap_next(&i->n, i->bit); 90 return 0; 91 } 92 93 return 1; 94} 95 96void *load_policy(const char *policy_path) 97{ 98 FILE *fp; 99 policydb_t *db; 100 101 fp = fopen(policy_path, "re"); 102 if (!fp) { 103 std::cerr << "Invalid or non-existing policy file: " << policy_path << std::endl; 104 return NULL; 105 } 106 107 db = (policydb_t *) calloc(1, sizeof(policydb_t)); 108 if (!db) { 109 std::cerr << "Failed to allocate memory for policy db." << std::endl; 110 fclose(fp); 111 return NULL; 112 } 113 114 sidtab_t sidtab; 115 sepol_set_sidtab(&sidtab); 116 sepol_set_policydb(db); 117 118 struct stat sb; 119 if (fstat(fileno(fp), &sb)) { 120 std::cerr << "Failed to stat the policy file" << std::endl; 121 free(db); 122 fclose(fp); 123 return NULL; 124 } 125 126 auto unmap = [=](void *ptr) { munmap(ptr, sb.st_size); }; 127 std::unique_ptr<void, decltype(unmap)> map( 128 mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fileno(fp), 0), unmap); 129 if (!map) { 130 std::cerr << "Failed to map the policy file" << std::endl; 131 free(db); 132 fclose(fp); 133 return NULL; 134 } 135 136 struct policy_file pf; 137 policy_file_init(&pf); 138 pf.type = PF_USE_MEMORY; 139 pf.data = static_cast<char *>(map.get()); 140 pf.len = sb.st_size; 141 if (policydb_init(db)) { 142 std::cerr << "Failed to initialize policydb" << std::endl; 143 free(db); 144 fclose(fp); 145 return NULL; 146 } 147 148 if (policydb_read(db, &pf, 0)) { 149 std::cerr << "Failed to read binary policy" << std::endl; 150 policydb_destroy(db); 151 free(db); 152 fclose(fp); 153 return NULL; 154 } 155 156 return static_cast<void *>(db); 157} 158 159/* items needed to iterate over the avtab */ 160struct avtab_iter { 161 avtab_t avtab; 162 uint32_t i; 163 avtab_ptr_t cur; 164}; 165 166/* 167 * print allow rule into *out buffer. 168 * 169 * Returns -1 on error. 170 * Returns 0 on successfully reading an avtab entry. 171 * Returns 1 on complete 172 */ 173static int get_avtab_allow_rule(char *out, size_t max_size, policydb_t *db, 174 struct avtab_iter *avtab_i) 175{ 176 size_t len; 177 178 for (; avtab_i->i < avtab_i->avtab.nslot; (avtab_i->i)++) { 179 if (avtab_i->cur == NULL) { 180 avtab_i->cur = avtab_i->avtab.htable[avtab_i->i]; 181 } 182 for (; avtab_i->cur; avtab_i->cur = (avtab_i->cur)->next) { 183 if (!((avtab_i->cur)->key.specified & AVTAB_ALLOWED)) continue; 184 185 len = snprintf(out, max_size, "allow,%s,%s,%s,%s", 186 db->p_type_val_to_name[(avtab_i->cur)->key.source_type - 1], 187 db->p_type_val_to_name[(avtab_i->cur)->key.target_type - 1], 188 db->p_class_val_to_name[(avtab_i->cur)->key.target_class - 1], 189 sepol_av_to_string(db, (avtab_i->cur)->key.target_class, (avtab_i->cur)->datum.data)); 190 avtab_i->cur = (avtab_i->cur)->next; 191 if (!(avtab_i->cur)) 192 (avtab_i->i)++; 193 if (len >= max_size) { 194 std::cerr << "Allow rule exceeds buffer size." << std::endl; 195 return -1; 196 } 197 return 0; 198 } 199 avtab_i->cur = NULL; 200 } 201 202 return 1; 203} 204 205int get_allow_rule(char *out, size_t len, void *policydbp, void *avtab_iterp) 206{ 207 policydb_t *db = static_cast<policydb_t *>(policydbp); 208 struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp); 209 210 return get_avtab_allow_rule(out, len, db, avtab_i); 211} 212 213/* 214 * <sepol/policydb/expand.h->conditional.h> uses 'bool' as a variable name 215 * inside extern "C" { .. } construct, which clang doesn't like. 216 * So, declare the function we need from expand.h ourselves. 217 */ 218extern "C" int expand_avtab(policydb_t *p, avtab_t *a, avtab_t *expa); 219 220static avtab_iter *init_avtab_common(avtab_t *in, policydb_t *p) 221{ 222 struct avtab_iter *out = (struct avtab_iter *) 223 calloc(1, sizeof(struct avtab_iter)); 224 if (!out) { 225 std::cerr << "Failed to allocate avtab" << std::endl; 226 return NULL; 227 } 228 229 if (avtab_init(&out->avtab)) { 230 std::cerr << "Failed to initialize avtab" << std::endl; 231 free(out); 232 return NULL; 233 } 234 235 if (expand_avtab(p, in, &out->avtab)) { 236 std::cerr << "Failed to expand avtab" << std::endl; 237 free(out); 238 return NULL; 239 } 240 return out; 241} 242 243void *init_avtab(void *policydbp) 244{ 245 policydb_t *p = static_cast<policydb_t *>(policydbp); 246 return static_cast<void *>(init_avtab_common(&p->te_avtab, p)); 247} 248 249void *init_cond_avtab(void *policydbp) 250{ 251 policydb_t *p = static_cast<policydb_t *>(policydbp); 252 return static_cast<void *>(init_avtab_common(&p->te_cond_avtab, p)); 253} 254 255void destroy_avtab(void *avtab_iterp) 256{ 257 struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp); 258 avtab_destroy(&avtab_i->avtab); 259 free(avtab_i); 260} 261 262void destroy_policy(void *policydbp) 263{ 264 policydb_t *p = static_cast<policydb_t *>(policydbp); 265 policydb_destroy(p); 266} 267