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 #define TYPE_ITER_LOOKUP 0 21 #define TYPE_ITER_ALLTYPES 1 22 #define TYPE_ITER_ALLATTRS 2 23 struct type_iter { 24 unsigned int alltypes; 25 type_datum *d; 26 ebitmap_node *n; 27 unsigned int length; 28 unsigned int bit; 29 }; 30 31 void *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 42 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; 49 } else { 50 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 } 69 } 70 71 return static_cast<void *>(out); 72 } 73 74 void 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 /* 81 * print type into *out buffer. 82 * 83 * Returns -1 on error. 84 * Returns 0 on successfully reading an avtab entry. 85 * Returns 1 on complete 86 */ 87 int 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 93 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; 99 } 100 } 101 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; 117 } 118 119 void *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 */ 183 struct avtab_iter { 184 avtab_t avtab; 185 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 */ 196 static 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 201 for (; avtab_i->i < avtab_i->avtab.nslot; (avtab_i->i)++) { 202 if (avtab_i->cur == NULL) { 203 avtab_i->cur = avtab_i->avtab.htable[avtab_i->i]; 204 } 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 228 int 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 236 /* 237 * <sepol/policydb/expand.h->conditional.h> uses 'bool' as a variable name 238 * inside extern "C" { .. } construct, which clang doesn't like. 239 * So, declare the function we need from expand.h ourselves. 240 */ 241 extern "C" int expand_avtab(policydb_t *p, avtab_t *a, avtab_t *expa); 242 243 static avtab_iter *init_avtab_common(avtab_t *in, policydb_t *p) 244 { 245 struct avtab_iter *out = (struct avtab_iter *) 246 calloc(1, sizeof(struct avtab_iter)); 247 if (!out) { 248 std::cerr << "Failed to allocate avtab" << std::endl; 249 return NULL; 250 } 251 252 if (avtab_init(&out->avtab)) { 253 std::cerr << "Failed to initialize avtab" << std::endl; 254 free(out); 255 return NULL; 256 } 257 258 if (expand_avtab(p, in, &out->avtab)) { 259 std::cerr << "Failed to expand avtab" << std::endl; 260 free(out); 261 return NULL; 262 } 263 return out; 264 } 265 266 void *init_avtab(void *policydbp) 267 { 268 policydb_t *p = static_cast<policydb_t *>(policydbp); 269 return static_cast<void *>(init_avtab_common(&p->te_avtab, p)); 270 } 271 272 void *init_cond_avtab(void *policydbp) 273 { 274 policydb_t *p = static_cast<policydb_t *>(policydbp); 275 return static_cast<void *>(init_avtab_common(&p->te_cond_avtab, p)); 276 } 277 278 void destroy_avtab(void *avtab_iterp) 279 { 280 struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp); 281 avtab_destroy(&avtab_i->avtab); 282 free(avtab_i); 283 } 284 285 void destroy_policy(void *policydbp) 286 { 287 policydb_t *p = static_cast<policydb_t *>(policydbp); 288 policydb_destroy(p); 289 } 290