Home | History | Annotate | Download | only in tests
      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