From 13eae1c2669e36651fa31004c9ad17d4264cebb6 Mon Sep 17 00:00:00 2001 From: Petr Lautrbach Date: Fri, 23 Oct 2020 23:07:40 +0200 Subject: [PATCH] Rebase on db0f2f382e31 at SELinuxProject - drop deprecated functions and duplicated symbols - change library version to libsepol.so.2 - temporary ship -compat with libsepol.so.1 - based on upstream db0f2f382e31 - re-enable lto flags --- ...licy-optimize-storage-of-filename-tr.patch | 592 ++++++++++++++++++ ...plement-POLICYDB_VERSION_COMP_FTRANS.patch | 394 ++++++++++++ ...idate-constraint-expressions-before-.patch | 172 +++++ ...idate-conditional-expressions-before.patch | 172 +++++ ...-neverallow-checking-involving-class.patch | 50 ++ ...-signed-overflow-caused-by-using-1-3.patch | 90 +++ ...libsepol-drop-confusing-BUG_ON-macro.patch | 77 +++ ...-potential-NULL-pointer-dereference-.patch | 66 ++ ...id-of-the-old-and-duplicated-symbols.patch | 193 ++++++ 0010-libsepol-Drop-deprecated-functions.patch | 134 ++++ 0011-libsepol-Bump-libsepol.so-version.patch | 45 ++ libsepol.spec | 27 +- 12 files changed, 2010 insertions(+), 2 deletions(-) create mode 100644 0001-libsepol-checkpolicy-optimize-storage-of-filename-tr.patch create mode 100644 0002-libsepol-implement-POLICYDB_VERSION_COMP_FTRANS.patch create mode 100644 0003-libsepol-cil-Validate-constraint-expressions-before-.patch create mode 100644 0004-libsepol-cil-Validate-conditional-expressions-before.patch create mode 100644 0005-libsepol-cil-Fix-neverallow-checking-involving-class.patch create mode 100644 0006-libsepol-cil-fix-signed-overflow-caused-by-using-1-3.patch create mode 100644 0007-libsepol-drop-confusing-BUG_ON-macro.patch create mode 100644 0008-libsepol-silence-potential-NULL-pointer-dereference-.patch create mode 100644 0009-libsepol-Get-rid-of-the-old-and-duplicated-symbols.patch create mode 100644 0010-libsepol-Drop-deprecated-functions.patch create mode 100644 0011-libsepol-Bump-libsepol.so-version.patch diff --git a/0001-libsepol-checkpolicy-optimize-storage-of-filename-tr.patch b/0001-libsepol-checkpolicy-optimize-storage-of-filename-tr.patch new file mode 100644 index 0000000..374be33 --- /dev/null +++ b/0001-libsepol-checkpolicy-optimize-storage-of-filename-tr.patch @@ -0,0 +1,592 @@ +From 42ae834a7428c57f7b2a9f448adf4cf991fa3487 Mon Sep 17 00:00:00 2001 +From: Ondrej Mosnacek +Date: Fri, 31 Jul 2020 13:10:34 +0200 +Subject: [PATCH] libsepol,checkpolicy: optimize storage of filename + transitions + +In preparation to support a new policy format with a more optimal +representation of filename transition rules, this patch applies an +equivalent change from kernel commit c3a276111ea2 ("selinux: optimize +storage of filename transitions"). + +See the kernel commit's description [1] for the rationale behind this +representation. This change doesn't bring any measurable difference of +policy build performance (semodule -B) on Fedora. + +[1] https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git/commit/?id=c3a276111ea2572399281988b3129683e2a6b60b + +Signed-off-by: Ondrej Mosnacek +--- + libsepol/cil/src/cil_binary.c | 26 ++--- + libsepol/include/sepol/policydb/policydb.h | 15 ++- + libsepol/src/expand.c | 56 ++------- + libsepol/src/kernel_to_cil.c | 24 +++- + libsepol/src/kernel_to_conf.c | 24 +++- + libsepol/src/policydb.c | 125 +++++++++++++++------ + libsepol/src/write.c | 46 ++++---- + 7 files changed, 183 insertions(+), 133 deletions(-) + +diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c +index 62178d998468..7726685809af 100644 +--- a/libsepol/cil/src/cil_binary.c ++++ b/libsepol/cil/src/cil_binary.c +@@ -1131,11 +1131,10 @@ int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, stru + class_datum_t *sepol_obj = NULL; + struct cil_list *class_list; + type_datum_t *sepol_result = NULL; +- filename_trans_t *newkey = NULL; +- filename_trans_datum_t *newdatum = NULL, *otype = NULL; + ebitmap_t src_bitmap, tgt_bitmap; + ebitmap_node_t *node1, *node2; + unsigned int i, j; ++ uint32_t otype; + struct cil_list_item *c; + char *name = DATUM(typetrans->name)->name; + +@@ -1176,22 +1175,14 @@ int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, stru + rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj); + if (rc != SEPOL_OK) goto exit; + +- newkey = cil_calloc(1, sizeof(*newkey)); +- newdatum = cil_calloc(1, sizeof(*newdatum)); +- newkey->stype = sepol_src->s.value; +- newkey->ttype = sepol_tgt->s.value; +- newkey->tclass = sepol_obj->s.value; +- newkey->name = cil_strdup(name); +- newdatum->otype = sepol_result->s.value; +- +- rc = hashtab_insert(pdb->filename_trans, +- (hashtab_key_t)newkey, +- newdatum); ++ rc = policydb_filetrans_insert( ++ pdb, sepol_src->s.value, sepol_tgt->s.value, ++ sepol_obj->s.value, name, NULL, ++ sepol_result->s.value, &otype ++ ); + if (rc != SEPOL_OK) { + if (rc == SEPOL_EEXIST) { +- otype = hashtab_search(pdb->filename_trans, +- (hashtab_key_t)newkey); +- if (newdatum->otype != otype->otype) { ++ if (sepol_result->s.value!= otype) { + cil_log(CIL_ERR, "Conflicting name type transition rules\n"); + } else { + rc = SEPOL_OK; +@@ -1199,9 +1190,6 @@ int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, stru + } else { + cil_log(CIL_ERR, "Out of memory\n"); + } +- free(newkey->name); +- free(newkey); +- free(newdatum); + if (rc != SEPOL_OK) { + goto exit; + } +diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h +index 81b63fefbb20..c3180c611c64 100644 +--- a/libsepol/include/sepol/policydb/policydb.h ++++ b/libsepol/include/sepol/policydb/policydb.h +@@ -162,15 +162,16 @@ typedef struct role_allow { + } role_allow_t; + + /* filename_trans rules */ +-typedef struct filename_trans { +- uint32_t stype; ++typedef struct filename_trans_key { + uint32_t ttype; + uint32_t tclass; + char *name; +-} filename_trans_t; ++} filename_trans_key_t; + + typedef struct filename_trans_datum { +- uint32_t otype; /* expected of new object */ ++ ebitmap_t stypes; ++ uint32_t otype; ++ struct filename_trans_datum *next; + } filename_trans_datum_t; + + /* Type attributes */ +@@ -591,6 +592,7 @@ typedef struct policydb { + + /* file transitions with the last path component */ + hashtab_t filename_trans; ++ uint32_t filename_trans_count; + + ebitmap_t *type_attr_map; + +@@ -650,6 +652,11 @@ extern int policydb_load_isids(policydb_t * p, sidtab_t * s); + + extern int policydb_sort_ocontexts(policydb_t *p); + ++extern int policydb_filetrans_insert(policydb_t *p, uint32_t stype, ++ uint32_t ttype, uint32_t tclass, ++ const char *name, char **name_alloc, ++ uint32_t otype, uint32_t *present_otype); ++ + /* Deprecated */ + extern int policydb_context_isvalid(const policydb_t * p, + const context_struct_t * c); +diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c +index 529e1d356a89..19e48c507236 100644 +--- a/libsepol/src/expand.c ++++ b/libsepol/src/expand.c +@@ -1371,8 +1371,6 @@ static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules) + static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules) + { + unsigned int i, j; +- filename_trans_t key, *new_trans; +- filename_trans_datum_t *otype; + filename_trans_rule_t *cur_rule; + ebitmap_t stypes, ttypes; + ebitmap_node_t *snode, *tnode; +@@ -1380,7 +1378,7 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r + + cur_rule = rules; + while (cur_rule) { +- uint32_t mapped_otype; ++ uint32_t mapped_otype, present_otype; + + ebitmap_init(&stypes); + ebitmap_init(&ttypes); +@@ -1401,15 +1399,14 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r + + ebitmap_for_each_positive_bit(&stypes, snode, i) { + ebitmap_for_each_positive_bit(&ttypes, tnode, j) { +- key.stype = i + 1; +- key.ttype = j + 1; +- key.tclass = cur_rule->tclass; +- key.name = cur_rule->name; +- otype = hashtab_search(state->out->filename_trans, +- (hashtab_key_t) &key); +- if (otype) { ++ rc = policydb_filetrans_insert( ++ state->out, i + 1, j + 1, ++ cur_rule->tclass, cur_rule->name, ++ NULL, mapped_otype, &present_otype ++ ); ++ if (rc == SEPOL_EEXIST) { + /* duplicate rule, ignore */ +- if (otype->otype == mapped_otype) ++ if (present_otype == mapped_otype) + continue; + + ERR(state->handle, "Conflicting name-based type_transition %s %s:%s \"%s\": %s vs %s", +@@ -1417,44 +1414,11 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r + state->out->p_type_val_to_name[j], + state->out->p_class_val_to_name[cur_rule->tclass - 1], + cur_rule->name, +- state->out->p_type_val_to_name[otype->otype - 1], ++ state->out->p_type_val_to_name[present_otype - 1], + state->out->p_type_val_to_name[mapped_otype - 1]); + return -1; +- } +- +- new_trans = calloc(1, sizeof(*new_trans)); +- if (!new_trans) { +- ERR(state->handle, "Out of memory!"); +- return -1; +- } +- +- new_trans->name = strdup(cur_rule->name); +- if (!new_trans->name) { +- ERR(state->handle, "Out of memory!"); +- free(new_trans); +- return -1; +- } +- new_trans->stype = i + 1; +- new_trans->ttype = j + 1; +- new_trans->tclass = cur_rule->tclass; +- +- otype = calloc(1, sizeof(*otype)); +- if (!otype) { +- ERR(state->handle, "Out of memory!"); +- free(new_trans->name); +- free(new_trans); +- return -1; +- } +- otype->otype = mapped_otype; +- +- rc = hashtab_insert(state->out->filename_trans, +- (hashtab_key_t)new_trans, +- otype); +- if (rc) { ++ } else if (rc < 0) { + ERR(state->handle, "Out of memory!"); +- free(otype); +- free(new_trans->name); +- free(new_trans); + return -1; + } + } +diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c +index 958adc4cfc0a..c247b32f9e75 100644 +--- a/libsepol/src/kernel_to_cil.c ++++ b/libsepol/src/kernel_to_cil.c +@@ -1841,21 +1841,35 @@ struct map_filename_trans_args { + + static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg) + { +- filename_trans_t *ft = (filename_trans_t *)key; ++ filename_trans_key_t *ft = (filename_trans_key_t *)key; + filename_trans_datum_t *datum = data; + struct map_filename_trans_args *map_args = arg; + struct policydb *pdb = map_args->pdb; + struct strs *strs = map_args->strs; + char *src, *tgt, *class, *filename, *new; ++ struct ebitmap_node *node; ++ uint32_t bit; ++ int rc; + +- src = pdb->p_type_val_to_name[ft->stype - 1]; + tgt = pdb->p_type_val_to_name[ft->ttype - 1]; + class = pdb->p_class_val_to_name[ft->tclass - 1]; + filename = ft->name; +- new = pdb->p_type_val_to_name[datum->otype - 1]; ++ do { ++ new = pdb->p_type_val_to_name[datum->otype - 1]; ++ ++ ebitmap_for_each_positive_bit(&datum->stypes, node, bit) { ++ src = pdb->p_type_val_to_name[bit]; ++ rc = strs_create_and_add(strs, ++ "(typetransition %s %s %s %s %s)", ++ 5, src, tgt, class, filename, new); ++ if (rc) ++ return rc; ++ } ++ ++ datum = datum->next; ++ } while (datum); + +- return strs_create_and_add(strs, "(typetransition %s %s %s %s %s)", 5, +- src, tgt, class, filename, new); ++ return 0; + } + + static int write_filename_trans_rules_to_cil(FILE *out, struct policydb *pdb) +diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c +index 7cc91eb3d129..62bf706c1aa0 100644 +--- a/libsepol/src/kernel_to_conf.c ++++ b/libsepol/src/kernel_to_conf.c +@@ -1822,21 +1822,35 @@ struct map_filename_trans_args { + + static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg) + { +- filename_trans_t *ft = (filename_trans_t *)key; ++ filename_trans_key_t *ft = (filename_trans_key_t *)key; + filename_trans_datum_t *datum = data; + struct map_filename_trans_args *map_args = arg; + struct policydb *pdb = map_args->pdb; + struct strs *strs = map_args->strs; + char *src, *tgt, *class, *filename, *new; ++ struct ebitmap_node *node; ++ uint32_t bit; ++ int rc; + +- src = pdb->p_type_val_to_name[ft->stype - 1]; + tgt = pdb->p_type_val_to_name[ft->ttype - 1]; + class = pdb->p_class_val_to_name[ft->tclass - 1]; + filename = ft->name; +- new = pdb->p_type_val_to_name[datum->otype - 1]; ++ do { ++ new = pdb->p_type_val_to_name[datum->otype - 1]; ++ ++ ebitmap_for_each_positive_bit(&datum->stypes, node, bit) { ++ src = pdb->p_type_val_to_name[bit]; ++ rc = strs_create_and_add(strs, ++ "type_transition %s %s:%s %s \"%s\";", ++ 5, src, tgt, class, new, filename); ++ if (rc) ++ return rc; ++ } ++ ++ datum = datum->next; ++ } while (datum); + +- return strs_create_and_add(strs, "type_transition %s %s:%s %s \"%s\";", 5, +- src, tgt, class, new, filename); ++ return 0; + } + + static int write_filename_trans_rules_to_conf(FILE *out, struct policydb *pdb) +diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c +index 3992ea56f092..0b98d50b8096 100644 +--- a/libsepol/src/policydb.c ++++ b/libsepol/src/policydb.c +@@ -789,12 +789,12 @@ partial_name_hash(unsigned long c, unsigned long prevhash) + + static unsigned int filenametr_hash(hashtab_t h, const_hashtab_key_t k) + { +- const struct filename_trans *ft = (const struct filename_trans *)k; ++ const filename_trans_key_t *ft = (const filename_trans_key_t *)k; + unsigned long hash; + unsigned int byte_num; + unsigned char focus; + +- hash = ft->stype ^ ft->ttype ^ ft->tclass; ++ hash = ft->ttype ^ ft->tclass; + + byte_num = 0; + while ((focus = ft->name[byte_num++])) +@@ -805,14 +805,10 @@ static unsigned int filenametr_hash(hashtab_t h, const_hashtab_key_t k) + static int filenametr_cmp(hashtab_t h __attribute__ ((unused)), + const_hashtab_key_t k1, const_hashtab_key_t k2) + { +- const struct filename_trans *ft1 = (const struct filename_trans *)k1; +- const struct filename_trans *ft2 = (const struct filename_trans *)k2; ++ const filename_trans_key_t *ft1 = (const filename_trans_key_t *)k1; ++ const filename_trans_key_t *ft2 = (const filename_trans_key_t *)k2; + int v; + +- v = ft1->stype - ft2->stype; +- if (v) +- return v; +- + v = ft1->ttype - ft2->ttype; + if (v) + return v; +@@ -1409,9 +1405,12 @@ common_destroy, class_destroy, role_destroy, type_destroy, user_destroy, + static int filenametr_destroy(hashtab_key_t key, hashtab_datum_t datum, + void *p __attribute__ ((unused))) + { +- struct filename_trans *ft = (struct filename_trans *)key; ++ filename_trans_key_t *ft = (filename_trans_key_t *)key; ++ filename_trans_datum_t *fd = datum; ++ + free(ft->name); + free(key); ++ ebitmap_destroy(&fd->stypes); + free(datum); + return 0; + } +@@ -2595,12 +2594,85 @@ int role_allow_read(role_allow_t ** r, struct policy_file *fp) + return 0; + } + ++int policydb_filetrans_insert(policydb_t *p, uint32_t stype, uint32_t ttype, ++ uint32_t tclass, const char *name, ++ char **name_alloc, uint32_t otype, ++ uint32_t *present_otype) ++{ ++ filename_trans_key_t *ft, key; ++ filename_trans_datum_t *datum, *last; ++ ++ key.ttype = ttype; ++ key.tclass = tclass; ++ key.name = (char *)name; ++ ++ last = NULL; ++ datum = hashtab_search(p->filename_trans, (hashtab_key_t)&key); ++ while (datum) { ++ if (ebitmap_get_bit(&datum->stypes, stype - 1)) { ++ if (present_otype) ++ *present_otype = datum->otype; ++ return SEPOL_EEXIST; ++ } ++ if (datum->otype == otype) ++ break; ++ last = datum; ++ datum = datum->next; ++ } ++ if (!datum) { ++ datum = malloc(sizeof(*datum)); ++ if (!datum) ++ return SEPOL_ENOMEM; ++ ++ ebitmap_init(&datum->stypes); ++ datum->otype = otype; ++ datum->next = NULL; ++ ++ if (last) { ++ last->next = datum; ++ } else { ++ char *name_dup; ++ ++ if (name_alloc) { ++ name_dup = *name_alloc; ++ *name_alloc = NULL; ++ } else { ++ name_dup = strdup(name); ++ if (!name_dup) { ++ free(datum); ++ return SEPOL_ENOMEM; ++ } ++ } ++ ++ ft = malloc(sizeof(*ft)); ++ if (!ft) { ++ free(name_dup); ++ free(datum); ++ return SEPOL_ENOMEM; ++ } ++ ++ ft->ttype = ttype; ++ ft->tclass = tclass; ++ ft->name = name_dup; ++ ++ if (hashtab_insert(p->filename_trans, (hashtab_key_t)ft, ++ (hashtab_datum_t)datum)) { ++ free(name_dup); ++ free(datum); ++ free(ft); ++ return SEPOL_ENOMEM; ++ } ++ } ++ } ++ ++ p->filename_trans_count++; ++ return ebitmap_set_bit(&datum->stypes, stype - 1, 1); ++} ++ + int filename_trans_read(policydb_t *p, struct policy_file *fp) + { + unsigned int i; +- uint32_t buf[4], nel, len; +- filename_trans_t *ft; +- filename_trans_datum_t *otype; ++ uint32_t buf[4], nel, len, stype, ttype, tclass, otype; + int rc; + char *name; + +@@ -2610,16 +2682,8 @@ int filename_trans_read(policydb_t *p, struct policy_file *fp) + nel = le32_to_cpu(buf[0]); + + for (i = 0; i < nel; i++) { +- ft = NULL; +- otype = NULL; + name = NULL; + +- ft = calloc(1, sizeof(*ft)); +- if (!ft) +- goto err; +- otype = calloc(1, sizeof(*otype)); +- if (!otype) +- goto err; + rc = next_entry(buf, fp, sizeof(uint32_t)); + if (rc < 0) + goto err; +@@ -2631,8 +2695,6 @@ int filename_trans_read(policydb_t *p, struct policy_file *fp) + if (!name) + goto err; + +- ft->name = name; +- + rc = next_entry(name, fp, len); + if (rc < 0) + goto err; +@@ -2641,13 +2703,13 @@ int filename_trans_read(policydb_t *p, struct policy_file *fp) + if (rc < 0) + goto err; + +- ft->stype = le32_to_cpu(buf[0]); +- ft->ttype = le32_to_cpu(buf[1]); +- ft->tclass = le32_to_cpu(buf[2]); +- otype->otype = le32_to_cpu(buf[3]); ++ stype = le32_to_cpu(buf[0]); ++ ttype = le32_to_cpu(buf[1]); ++ tclass = le32_to_cpu(buf[2]); ++ otype = le32_to_cpu(buf[3]); + +- rc = hashtab_insert(p->filename_trans, (hashtab_key_t) ft, +- otype); ++ rc = policydb_filetrans_insert(p, stype, ttype, tclass, name, ++ &name, otype, NULL); + if (rc) { + if (rc != SEPOL_EEXIST) + goto err; +@@ -2657,16 +2719,11 @@ int filename_trans_read(policydb_t *p, struct policy_file *fp) + * compatibility, do not reject such policies, just + * ignore the duplicate. + */ +- free(ft); +- free(name); +- free(otype); +- /* continue, ignoring this one */ + } ++ free(name); + } + return 0; + err: +- free(ft); +- free(otype); + free(name); + return -1; + } +diff --git a/libsepol/src/write.c b/libsepol/src/write.c +index 1fd6a16a248b..d3aee8d5bf22 100644 +--- a/libsepol/src/write.c ++++ b/libsepol/src/write.c +@@ -571,44 +571,50 @@ static int role_allow_write(role_allow_t * r, struct policy_file *fp) + + static int filename_write_helper(hashtab_key_t key, void *data, void *ptr) + { +- uint32_t buf[4]; ++ uint32_t bit, buf[4]; + size_t items, len; +- struct filename_trans *ft = (struct filename_trans *)key; +- struct filename_trans_datum *otype = data; ++ filename_trans_key_t *ft = (filename_trans_key_t *)key; ++ filename_trans_datum_t *datum = data; ++ ebitmap_node_t *node; + void *fp = ptr; + + len = strlen(ft->name); +- buf[0] = cpu_to_le32(len); +- items = put_entry(buf, sizeof(uint32_t), 1, fp); +- if (items != 1) +- return POLICYDB_ERROR; ++ do { ++ ebitmap_for_each_positive_bit(&datum->stypes, node, bit) { ++ buf[0] = cpu_to_le32(len); ++ items = put_entry(buf, sizeof(uint32_t), 1, fp); ++ if (items != 1) ++ return POLICYDB_ERROR; + +- items = put_entry(ft->name, sizeof(char), len, fp); +- if (items != len) +- return POLICYDB_ERROR; ++ items = put_entry(ft->name, sizeof(char), len, fp); ++ if (items != len) ++ return POLICYDB_ERROR; + +- buf[0] = cpu_to_le32(ft->stype); +- buf[1] = cpu_to_le32(ft->ttype); +- buf[2] = cpu_to_le32(ft->tclass); +- buf[3] = cpu_to_le32(otype->otype); +- items = put_entry(buf, sizeof(uint32_t), 4, fp); +- if (items != 4) +- return POLICYDB_ERROR; ++ buf[0] = cpu_to_le32(bit + 1); ++ buf[1] = cpu_to_le32(ft->ttype); ++ buf[2] = cpu_to_le32(ft->tclass); ++ buf[3] = cpu_to_le32(datum->otype); ++ items = put_entry(buf, sizeof(uint32_t), 4, fp); ++ if (items != 4) ++ return POLICYDB_ERROR; ++ } ++ ++ datum = datum->next; ++ } while (datum); + + return 0; + } + + static int filename_trans_write(struct policydb *p, void *fp) + { +- size_t nel, items; ++ size_t items; + uint32_t buf[1]; + int rc; + + if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS) + return 0; + +- nel = p->filename_trans->nel; +- buf[0] = cpu_to_le32(nel); ++ buf[0] = cpu_to_le32(p->filename_trans_count); + items = put_entry(buf, sizeof(uint32_t), 1, fp); + if (items != 1) + return POLICYDB_ERROR; +-- +2.29.0.rc2 + diff --git a/0002-libsepol-implement-POLICYDB_VERSION_COMP_FTRANS.patch b/0002-libsepol-implement-POLICYDB_VERSION_COMP_FTRANS.patch new file mode 100644 index 0000000..8ef7272 --- /dev/null +++ b/0002-libsepol-implement-POLICYDB_VERSION_COMP_FTRANS.patch @@ -0,0 +1,394 @@ +From 8206b8cb00392aab358f4eeae38f98850438085c Mon Sep 17 00:00:00 2001 +From: Ondrej Mosnacek +Date: Fri, 31 Jul 2020 13:10:35 +0200 +Subject: [PATCH] libsepol: implement POLICYDB_VERSION_COMP_FTRANS + +Implement a new, more space-efficient form of storing filename +transitions in the binary policy. The internal structures have already +been converted to this new representation; this patch just implements +reading/writing an equivalent representation from/to the binary policy. + +This new format reduces the size of Fedora policy from 7.6 MB to only +3.3 MB (with policy optimization enabled in both cases). With the +unconfined module disabled, the size is reduced from 3.3 MB to 2.4 MB. + +Signed-off-by: Ondrej Mosnacek +--- + libsepol/include/sepol/policydb/policydb.h | 3 +- + libsepol/src/policydb.c | 209 +++++++++++++++++---- + libsepol/src/write.c | 73 ++++++- + 3 files changed, 242 insertions(+), 43 deletions(-) + +diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h +index c3180c611c64..9ef43abc2f12 100644 +--- a/libsepol/include/sepol/policydb/policydb.h ++++ b/libsepol/include/sepol/policydb/policydb.h +@@ -755,10 +755,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform); + #define POLICYDB_VERSION_XPERMS_IOCTL 30 /* Linux-specific */ + #define POLICYDB_VERSION_INFINIBAND 31 /* Linux-specific */ + #define POLICYDB_VERSION_GLBLUB 32 ++#define POLICYDB_VERSION_COMP_FTRANS 33 /* compressed filename transitions */ + + /* Range of policy versions we understand*/ + #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE +-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_GLBLUB ++#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COMP_FTRANS + + /* Module versions and specific changes*/ + #define MOD_POLICYDB_VERSION_BASE 4 +diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c +index 0b98d50b8096..ce8f3ad77005 100644 +--- a/libsepol/src/policydb.c ++++ b/libsepol/src/policydb.c +@@ -200,6 +200,13 @@ static struct policydb_compat_info policydb_compat[] = { + .ocon_num = OCON_IBENDPORT + 1, + .target_platform = SEPOL_TARGET_SELINUX, + }, ++ { ++ .type = POLICY_KERN, ++ .version = POLICYDB_VERSION_COMP_FTRANS, ++ .sym_num = SYM_NUM, ++ .ocon_num = OCON_IBENDPORT + 1, ++ .target_platform = SEPOL_TARGET_SELINUX, ++ }, + { + .type = POLICY_BASE, + .version = MOD_POLICYDB_VERSION_BASE, +@@ -2669,65 +2676,201 @@ int policydb_filetrans_insert(policydb_t *p, uint32_t stype, uint32_t ttype, + return ebitmap_set_bit(&datum->stypes, stype - 1, 1); + } + +-int filename_trans_read(policydb_t *p, struct policy_file *fp) ++static int filename_trans_read_one_compat(policydb_t *p, struct policy_file *fp) + { +- unsigned int i; +- uint32_t buf[4], nel, len, stype, ttype, tclass, otype; ++ uint32_t buf[4], len, stype, ttype, tclass, otype; ++ char *name = NULL; + int rc; +- char *name; + + rc = next_entry(buf, fp, sizeof(uint32_t)); + if (rc < 0) + return -1; +- nel = le32_to_cpu(buf[0]); ++ len = le32_to_cpu(buf[0]); ++ if (zero_or_saturated(len)) ++ return -1; + +- for (i = 0; i < nel; i++) { +- name = NULL; ++ name = calloc(len + 1, sizeof(*name)); ++ if (!name) ++ return -1; + +- rc = next_entry(buf, fp, sizeof(uint32_t)); +- if (rc < 0) +- goto err; +- len = le32_to_cpu(buf[0]); +- if (zero_or_saturated(len)) ++ rc = next_entry(name, fp, len); ++ if (rc < 0) ++ goto err; ++ ++ rc = next_entry(buf, fp, sizeof(uint32_t) * 4); ++ if (rc < 0) ++ goto err; ++ ++ stype = le32_to_cpu(buf[0]); ++ ttype = le32_to_cpu(buf[1]); ++ tclass = le32_to_cpu(buf[2]); ++ otype = le32_to_cpu(buf[3]); ++ ++ rc = policydb_filetrans_insert(p, stype, ttype, tclass, name, &name, ++ otype, NULL); ++ if (rc) { ++ if (rc != SEPOL_EEXIST) + goto err; ++ /* ++ * Some old policies were wrongly generated with ++ * duplicate filename transition rules. For backward ++ * compatibility, do not reject such policies, just ++ * ignore the duplicate. ++ */ ++ } ++ free(name); ++ return 0; ++err: ++ free(name); ++ return -1; ++} ++ ++static int filename_trans_check_datum(filename_trans_datum_t *datum) ++{ ++ ebitmap_t stypes, otypes; ++ int rc = -1; ++ ++ ebitmap_init(&stypes); ++ ebitmap_init(&otypes); ++ ++ while (datum) { ++ if (ebitmap_get_bit(&otypes, datum->otype)) ++ goto out; ++ ++ if (ebitmap_set_bit(&otypes, datum->otype, 1)) ++ goto out; ++ ++ if (ebitmap_match_any(&stypes, &datum->stypes)) ++ goto out; + +- name = calloc(len + 1, sizeof(*name)); +- if (!name) ++ if (ebitmap_union(&stypes, &datum->stypes)) ++ goto out; ++ ++ datum = datum->next; ++ } ++ rc = 0; ++out: ++ ebitmap_destroy(&stypes); ++ ebitmap_destroy(&otypes); ++ return rc; ++} ++ ++static int filename_trans_read_one(policydb_t *p, struct policy_file *fp) ++{ ++ filename_trans_key_t *ft = NULL; ++ filename_trans_datum_t **dst, *datum, *first = NULL; ++ unsigned int i; ++ uint32_t buf[3], len, ttype, tclass, ndatum; ++ char *name = NULL; ++ int rc; ++ ++ rc = next_entry(buf, fp, sizeof(uint32_t)); ++ if (rc < 0) ++ return -1; ++ len = le32_to_cpu(buf[0]); ++ if (zero_or_saturated(len)) ++ return -1; ++ ++ name = calloc(len + 1, sizeof(*name)); ++ if (!name) ++ return -1; ++ ++ rc = next_entry(name, fp, len); ++ if (rc < 0) ++ goto err; ++ ++ rc = next_entry(buf, fp, sizeof(uint32_t) * 3); ++ if (rc < 0) ++ goto err; ++ ++ ttype = le32_to_cpu(buf[0]); ++ tclass = le32_to_cpu(buf[1]); ++ ndatum = le32_to_cpu(buf[2]); ++ if (ndatum == 0) ++ goto err; ++ ++ dst = &first; ++ for (i = 0; i < ndatum; i++) { ++ datum = malloc(sizeof(*datum)); ++ if (!datum) + goto err; + +- rc = next_entry(name, fp, len); ++ *dst = datum; ++ ++ /* ebitmap_read() will at least init the bitmap */ ++ rc = ebitmap_read(&datum->stypes, fp); + if (rc < 0) + goto err; + +- rc = next_entry(buf, fp, sizeof(uint32_t) * 4); ++ rc = next_entry(buf, fp, sizeof(uint32_t)); + if (rc < 0) + goto err; + +- stype = le32_to_cpu(buf[0]); +- ttype = le32_to_cpu(buf[1]); +- tclass = le32_to_cpu(buf[2]); +- otype = le32_to_cpu(buf[3]); ++ datum->otype = le32_to_cpu(buf[0]); + +- rc = policydb_filetrans_insert(p, stype, ttype, tclass, name, +- &name, otype, NULL); +- if (rc) { +- if (rc != SEPOL_EEXIST) +- goto err; +- /* +- * Some old policies were wrongly generated with +- * duplicate filename transition rules. For backward +- * compatibility, do not reject such policies, just +- * ignore the duplicate. +- */ +- } +- free(name); ++ p->filename_trans_count += ebitmap_cardinality(&datum->stypes); ++ ++ dst = &datum->next; + } ++ *dst = NULL; ++ ++ if (ndatum > 1 && filename_trans_check_datum(first)) ++ goto err; ++ ++ ft = malloc(sizeof(*ft)); ++ if (!ft) ++ goto err; ++ ++ ft->ttype = ttype; ++ ft->tclass = tclass; ++ ft->name = name; ++ ++ rc = hashtab_insert(p->filename_trans, (hashtab_key_t)ft, ++ (hashtab_datum_t)first); ++ if (rc) ++ goto err; ++ + return 0; + err: ++ free(ft); + free(name); ++ while (first) { ++ datum = first; ++ first = first->next; ++ ++ ebitmap_destroy(&datum->stypes); ++ free(datum); ++ } + return -1; + } + ++int filename_trans_read(policydb_t *p, struct policy_file *fp) ++{ ++ unsigned int i; ++ uint32_t buf[1], nel; ++ int rc; ++ ++ rc = next_entry(buf, fp, sizeof(uint32_t)); ++ if (rc < 0) ++ return -1; ++ nel = le32_to_cpu(buf[0]); ++ ++ if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) { ++ for (i = 0; i < nel; i++) { ++ rc = filename_trans_read_one_compat(p, fp); ++ if (rc < 0) ++ return -1; ++ } ++ } else { ++ for (i = 0; i < nel; i++) { ++ rc = filename_trans_read_one(p, fp); ++ if (rc < 0) ++ return -1; ++ } ++ } ++ return 0; ++} ++ + static int ocontext_read_xen(struct policydb_compat_info *info, + policydb_t *p, struct policy_file *fp) + { +diff --git a/libsepol/src/write.c b/libsepol/src/write.c +index d3aee8d5bf22..84bcaf3f57ca 100644 +--- a/libsepol/src/write.c ++++ b/libsepol/src/write.c +@@ -569,7 +569,7 @@ static int role_allow_write(role_allow_t * r, struct policy_file *fp) + return POLICYDB_SUCCESS; + } + +-static int filename_write_helper(hashtab_key_t key, void *data, void *ptr) ++static int filename_write_one_compat(hashtab_key_t key, void *data, void *ptr) + { + uint32_t bit, buf[4]; + size_t items, len; +@@ -605,6 +605,54 @@ static int filename_write_helper(hashtab_key_t key, void *data, void *ptr) + return 0; + } + ++static int filename_write_one(hashtab_key_t key, void *data, void *ptr) ++{ ++ uint32_t buf[3]; ++ size_t items, len, ndatum; ++ filename_trans_key_t *ft = (filename_trans_key_t *)key; ++ filename_trans_datum_t *datum; ++ void *fp = ptr; ++ ++ len = strlen(ft->name); ++ buf[0] = cpu_to_le32(len); ++ items = put_entry(buf, sizeof(uint32_t), 1, fp); ++ if (items != 1) ++ return POLICYDB_ERROR; ++ ++ items = put_entry(ft->name, sizeof(char), len, fp); ++ if (items != len) ++ return POLICYDB_ERROR; ++ ++ ndatum = 0; ++ datum = data; ++ do { ++ ndatum++; ++ datum = datum->next; ++ } while (datum); ++ ++ buf[0] = cpu_to_le32(ft->ttype); ++ buf[1] = cpu_to_le32(ft->tclass); ++ buf[2] = cpu_to_le32(ndatum); ++ items = put_entry(buf, sizeof(uint32_t), 3, fp); ++ if (items != 3) ++ return POLICYDB_ERROR; ++ ++ datum = data; ++ do { ++ if (ebitmap_write(&datum->stypes, fp)) ++ return POLICYDB_ERROR; ++ ++ buf[0] = cpu_to_le32(datum->otype); ++ items = put_entry(buf, sizeof(uint32_t), 1, fp); ++ if (items != 1) ++ return POLICYDB_ERROR; ++ ++ datum = datum->next; ++ } while (datum); ++ ++ return 0; ++} ++ + static int filename_trans_write(struct policydb *p, void *fp) + { + size_t items; +@@ -614,16 +662,23 @@ static int filename_trans_write(struct policydb *p, void *fp) + if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS) + return 0; + +- buf[0] = cpu_to_le32(p->filename_trans_count); +- items = put_entry(buf, sizeof(uint32_t), 1, fp); +- if (items != 1) +- return POLICYDB_ERROR; ++ if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) { ++ buf[0] = cpu_to_le32(p->filename_trans_count); ++ items = put_entry(buf, sizeof(uint32_t), 1, fp); ++ if (items != 1) ++ return POLICYDB_ERROR; + +- rc = hashtab_map(p->filename_trans, filename_write_helper, fp); +- if (rc) +- return rc; ++ rc = hashtab_map(p->filename_trans, filename_write_one_compat, ++ fp); ++ } else { ++ buf[0] = cpu_to_le32(p->filename_trans->nel); ++ items = put_entry(buf, sizeof(uint32_t), 1, fp); ++ if (items != 1) ++ return POLICYDB_ERROR; + +- return 0; ++ rc = hashtab_map(p->filename_trans, filename_write_one, fp); ++ } ++ return rc; + } + + static int role_set_write(role_set_t * x, struct policy_file *fp) +-- +2.29.0.rc2 + diff --git a/0003-libsepol-cil-Validate-constraint-expressions-before-.patch b/0003-libsepol-cil-Validate-constraint-expressions-before-.patch new file mode 100644 index 0000000..7a0aa08 --- /dev/null +++ b/0003-libsepol-cil-Validate-constraint-expressions-before-.patch @@ -0,0 +1,172 @@ +From 685f577aa01ed378374cde9c0105b19c18ca7c07 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Wed, 9 Sep 2020 16:57:12 -0400 +Subject: [PATCH] libsepol/cil: Validate constraint expressions before adding + to binary policy + +CIL was not correctly determining the depth of constraint expressions +which prevented it from giving an error when the max depth was exceeded. +This allowed invalid policy binaries with constraint expressions exceeding +the max depth to be created. + +Validate the constraint expression using the same logic that is used +when reading the binary policy. This includes checking the depth of the +the expression. + +Reported-by: Jonathan Hettwer +Signed-off-by: James Carter +Acked-by: Stephen Smalley +--- + libsepol/cil/src/cil_binary.c | 48 ++++++++++++++++++++++++++++++++ + libsepol/cil/src/cil_build_ast.c | 20 ++++--------- + 2 files changed, 53 insertions(+), 15 deletions(-) + +diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c +index 7726685809af..c8e41f09e53f 100644 +--- a/libsepol/cil/src/cil_binary.c ++++ b/libsepol/cil/src/cil_binary.c +@@ -2713,6 +2713,49 @@ int __cil_constrain_expr_to_sepol_expr(policydb_t *pdb, const struct cil_db *db, + return SEPOL_OK; + } + ++int __cil_validate_constrain_expr(constraint_expr_t *sepol_expr) ++{ ++ constraint_expr_t *e; ++ int depth = -1; ++ ++ for (e = sepol_expr; e != NULL; e = e->next) { ++ switch (e->expr_type) { ++ case CEXPR_NOT: ++ if (depth < 0) { ++ cil_log(CIL_ERR,"Invalid constraint expression\n"); ++ return SEPOL_ERR; ++ } ++ break; ++ case CEXPR_AND: ++ case CEXPR_OR: ++ if (depth < 1) { ++ cil_log(CIL_ERR,"Invalid constraint expression\n"); ++ return SEPOL_ERR; ++ } ++ depth--; ++ break; ++ case CEXPR_ATTR: ++ case CEXPR_NAMES: ++ if (depth == (CEXPR_MAXDEPTH - 1)) { ++ cil_log(CIL_ERR,"Constraint expression exceeded max allowable depth\n"); ++ return SEPOL_ERR; ++ } ++ depth++; ++ break; ++ default: ++ cil_log(CIL_ERR,"Invalid constraint expression\n"); ++ return SEPOL_ERR; ++ } ++ } ++ ++ if (depth != 0) { ++ cil_log(CIL_ERR,"Invalid constraint expression\n"); ++ return SEPOL_ERR; ++ } ++ ++ return SEPOL_OK; ++} ++ + int cil_constrain_to_policydb_helper(policydb_t *pdb, const struct cil_db *db, struct cil_symtab_datum *class, struct cil_list *perms, struct cil_list *expr) + { + int rc = SEPOL_ERR; +@@ -2736,6 +2779,11 @@ int cil_constrain_to_policydb_helper(policydb_t *pdb, const struct cil_db *db, s + goto exit; + } + ++ rc = __cil_validate_constrain_expr(sepol_expr); ++ if (rc != SEPOL_OK) { ++ goto exit; ++ } ++ + sepol_constrain->expr = sepol_expr; + sepol_constrain->next = sepol_class->constraints; + sepol_class->constraints = sepol_constrain; +diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c +index 60ecaaff3060..870c6923b4de 100644 +--- a/libsepol/cil/src/cil_build_ast.c ++++ b/libsepol/cil/src/cil_build_ast.c +@@ -2738,7 +2738,7 @@ exit: + return SEPOL_ERR; + } + +-static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr, int *depth) ++static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) + { + int rc = SEPOL_ERR; + enum cil_flavor op; +@@ -2750,12 +2750,6 @@ static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_fl + goto exit; + } + +- if (*depth > CEXPR_MAXDEPTH) { +- cil_log(CIL_ERR, "Max depth of %d exceeded for constraint expression\n", CEXPR_MAXDEPTH); +- rc = SEPOL_ERR; +- goto exit; +- } +- + op = __cil_get_constraint_operator_flavor(current->data); + + rc = cil_verify_constraint_expr_syntax(current, op); +@@ -2769,14 +2763,13 @@ static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_fl + case CIL_CONS_DOM: + case CIL_CONS_DOMBY: + case CIL_CONS_INCOMP: +- (*depth)++; + rc = __cil_fill_constraint_leaf_expr(current, flavor, op, expr); + if (rc != SEPOL_OK) { + goto exit; + } + break; + case CIL_NOT: +- rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr, depth); ++ rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr); + if (rc != SEPOL_OK) { + goto exit; + } +@@ -2785,11 +2778,11 @@ static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_fl + cil_list_append(*expr, CIL_LIST, lexpr); + break; + default: +- rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr, depth); ++ rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr); + if (rc != SEPOL_OK) { + goto exit; + } +- rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr, depth); ++ rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr); + if (rc != SEPOL_OK) { + cil_list_destroy(&lexpr, CIL_TRUE); + goto exit; +@@ -2801,8 +2794,6 @@ static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_fl + break; + } + +- (*depth)--; +- + return SEPOL_OK; + exit: + +@@ -2812,13 +2803,12 @@ exit: + int cil_gen_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) + { + int rc = SEPOL_ERR; +- int depth = 0; + + if (current->cl_head == NULL) { + goto exit; + } + +- rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr, &depth); ++ rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr); + if (rc != SEPOL_OK) { + goto exit; + } +-- +2.29.0.rc2 + diff --git a/0004-libsepol-cil-Validate-conditional-expressions-before.patch b/0004-libsepol-cil-Validate-conditional-expressions-before.patch new file mode 100644 index 0000000..9b1d3df --- /dev/null +++ b/0004-libsepol-cil-Validate-conditional-expressions-before.patch @@ -0,0 +1,172 @@ +From 734e4beb55cb53d3370201838caa4850b2a6d276 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Wed, 9 Sep 2020 16:57:02 -0400 +Subject: [PATCH] libsepol/cil: Validate conditional expressions before adding + to binary policy + +CIL was not correctly determining the depth of conditional expressions +which prevented it from giving an error when the max depth was exceeded. +This allowed invalid policy binaries to be created. + +Validate the conditional expression using the same logic that is used +when evaluating a conditional expression. This includes checking the +depth of the expression. + +Signed-off-by: James Carter +Acked-by: Stephen Smalley +--- + libsepol/cil/src/cil_binary.c | 50 ++++++++++++++++++++++++++++++++ + libsepol/cil/src/cil_build_ast.c | 26 +++++------------ + 2 files changed, 57 insertions(+), 19 deletions(-) + +diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c +index c8e41f09e53f..50cc7f757c62 100644 +--- a/libsepol/cil/src/cil_binary.c ++++ b/libsepol/cil/src/cil_binary.c +@@ -2176,6 +2176,51 @@ static int __cil_cond_expr_to_sepol_expr(policydb_t *pdb, struct cil_list *cil_e + return SEPOL_OK; + } + ++int __cil_validate_cond_expr(cond_expr_t *cond_expr) ++{ ++ cond_expr_t *e; ++ int depth = -1; ++ ++ for (e = cond_expr; e != NULL; e = e->next) { ++ switch (e->expr_type) { ++ case COND_BOOL: ++ if (depth == (COND_EXPR_MAXDEPTH - 1)) { ++ cil_log(CIL_ERR,"Conditional expression exceeded max allowable depth\n"); ++ return SEPOL_ERR; ++ } ++ depth++; ++ break; ++ case COND_NOT: ++ if (depth < 0) { ++ cil_log(CIL_ERR,"Invalid conditional expression\n"); ++ return SEPOL_ERR; ++ } ++ break; ++ case COND_OR: ++ case COND_AND: ++ case COND_XOR: ++ case COND_EQ: ++ case COND_NEQ: ++ if (depth < 1) { ++ cil_log(CIL_ERR,"Invalid conditional expression\n"); ++ return SEPOL_ERR; ++ } ++ depth--; ++ break; ++ default: ++ cil_log(CIL_ERR,"Invalid conditional expression\n"); ++ return SEPOL_ERR; ++ } ++ } ++ ++ if (depth != 0) { ++ cil_log(CIL_ERR,"Invalid conditional expression\n"); ++ return SEPOL_ERR; ++ } ++ ++ return SEPOL_OK; ++} ++ + int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_tree_node *node) + { + int rc = SEPOL_ERR; +@@ -2204,6 +2249,11 @@ int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c + goto exit; + } + ++ rc = __cil_validate_cond_expr(tmp_cond->expr); ++ if (rc != SEPOL_OK) { ++ goto exit; ++ } ++ + tmp_cond->true_list = &tmp_cl; + + rc = cond_normalize_expr(pdb, tmp_cond); +diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c +index 870c6923b4de..3aabb05ec534 100644 +--- a/libsepol/cil/src/cil_build_ast.c ++++ b/libsepol/cil/src/cil_build_ast.c +@@ -2548,18 +2548,13 @@ static enum cil_flavor __cil_get_expr_operator_flavor(const char *op) + else return CIL_NONE; + } + +-static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth); ++static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr); + +-static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth) ++static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr) + { + int rc = SEPOL_ERR; + enum cil_flavor op; + +- if (flavor == CIL_BOOL && *depth > COND_EXPR_MAXDEPTH) { +- cil_log(CIL_ERR, "Max depth of %d exceeded for boolean expression\n", COND_EXPR_MAXDEPTH); +- goto exit; +- } +- + op = __cil_get_expr_operator_flavor(current->data); + + rc = cil_verify_expr_syntax(current, op, flavor); +@@ -2572,26 +2567,20 @@ static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor + current = current->next; + } + +- if (op == CIL_NONE || op == CIL_ALL) { +- (*depth)++; +- } +- + for (;current != NULL; current = current->next) { +- rc = __cil_fill_expr(current, flavor, expr, depth); ++ rc = __cil_fill_expr(current, flavor, expr); + if (rc != SEPOL_OK) { + goto exit; + } + } + +- (*depth)--; +- + return SEPOL_OK; + + exit: + return rc; + } + +-static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth) ++static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr) + { + int rc = SEPOL_ERR; + +@@ -2605,7 +2594,7 @@ static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor + } else { + struct cil_list *sub_expr; + cil_list_init(&sub_expr, flavor); +- rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr, depth); ++ rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr); + if (rc != SEPOL_OK) { + cil_list_destroy(&sub_expr, CIL_TRUE); + goto exit; +@@ -2623,14 +2612,13 @@ exit: + int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) + { + int rc = SEPOL_ERR; +- int depth = 0; + + cil_list_init(expr, flavor); + + if (current->cl_head == NULL) { +- rc = __cil_fill_expr(current, flavor, *expr, &depth); ++ rc = __cil_fill_expr(current, flavor, *expr); + } else { +- rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr, &depth); ++ rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr); + } + + if (rc != SEPOL_OK) { +-- +2.29.0.rc2 + diff --git a/0005-libsepol-cil-Fix-neverallow-checking-involving-class.patch b/0005-libsepol-cil-Fix-neverallow-checking-involving-class.patch new file mode 100644 index 0000000..cb44ce9 --- /dev/null +++ b/0005-libsepol-cil-Fix-neverallow-checking-involving-class.patch @@ -0,0 +1,50 @@ +From a152653b9a43fe2c776d239efc2d46d336555bc8 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Tue, 15 Sep 2020 14:48:06 -0400 +Subject: [PATCH] libsepol/cil: Fix neverallow checking involving classmaps + +When classmaps used in a neverallow were being expanded during CIL +neverallow checking, an empty classmapping in the list of +classmappings for a classmap would cause the classmap expansion to +stop and the rest of the classmapping of the classmap to be ignored. +This would mean that not all of the classes and permissions associated +with the classmap would be used to check for a neverallow violation. + +Do not end the expansion of a classmap when one classmapping is empty. + +Reported-by: Jonathan Hettwer +Signed-off-by: James Carter +Acked-by: Stephen Smalley +--- + libsepol/cil/src/cil_binary.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c +index 50cc7f757c62..36720eda4549 100644 +--- a/libsepol/cil/src/cil_binary.c ++++ b/libsepol/cil/src/cil_binary.c +@@ -4363,15 +4363,13 @@ static int __cil_rule_to_sepol_class_perms(policydb_t *pdb, struct cil_list *cla + + rc = __cil_perms_to_datum(cp->perms, sepol_class, &data); + if (rc != SEPOL_OK) goto exit; +- if (data == 0) { +- /* No permissions */ +- return SEPOL_OK; ++ if (data != 0) { /* Only add if there are permissions */ ++ cpn = cil_malloc(sizeof(class_perm_node_t)); ++ cpn->tclass = sepol_class->s.value; ++ cpn->data = data; ++ cpn->next = *sepol_class_perms; ++ *sepol_class_perms = cpn; + } +- cpn = cil_malloc(sizeof(class_perm_node_t)); +- cpn->tclass = sepol_class->s.value; +- cpn->data = data; +- cpn->next = *sepol_class_perms; +- *sepol_class_perms = cpn; + } else { /* MAP */ + struct cil_list_item *j = NULL; + cil_list_for_each(j, cp->perms) { +-- +2.29.0.rc2 + diff --git a/0006-libsepol-cil-fix-signed-overflow-caused-by-using-1-3.patch b/0006-libsepol-cil-fix-signed-overflow-caused-by-using-1-3.patch new file mode 100644 index 0000000..b6ee7c1 --- /dev/null +++ b/0006-libsepol-cil-fix-signed-overflow-caused-by-using-1-3.patch @@ -0,0 +1,90 @@ +From 521e6a2f478a4c7a7c198c017d4d12e8667d89e7 Mon Sep 17 00:00:00 2001 +From: Nicolas Iooss +Date: Sat, 3 Oct 2020 15:19:08 +0200 +Subject: [PATCH] libsepol/cil: fix signed overflow caused by using (1 << 31) - + 1 + +When compiling SELinux userspace tools with -ftrapv (this option +generates traps for signed overflow on addition, subtraction, +multiplication operations, instead of silently wrapping around), +semodule crashes when running the tests from +scripts/ci/fedora-test-runner.sh in a Fedora 32 virtual machine: + + [root@localhost selinux-testsuite]# make test + make -C policy load + make[1]: Entering directory '/root/selinux-testsuite/policy' + # Test for "expand-check = 0" in /etc/selinux/semanage.conf + # General policy build + make[2]: Entering directory '/root/selinux-testsuite/policy/test_policy' + Compiling targeted test_policy module + Creating targeted test_policy.pp policy package + rm tmp/test_policy.mod.fc + make[2]: Leaving directory '/root/selinux-testsuite/policy/test_policy' + # General policy load + domain_fd_use --> off + /usr/sbin/semodule -i test_policy/test_policy.pp test_mlsconstrain.cil test_overlay_defaultrange.cil test_add_levels.cil test_glblub.cil + make[1]: *** [Makefile:174: load] Aborted (core dumped) + +Using "coredumpctl gdb" leads to the following strack trace: + + (gdb) bt + #0 0x00007f608fe4fa25 in raise () from /lib64/libc.so.6 + #1 0x00007f608fe38895 in abort () from /lib64/libc.so.6 + #2 0x00007f6090028aca in __addvsi3.cold () from /lib64/libsepol.so.1 + #3 0x00007f6090096f59 in __avrule_xperm_setrangebits (low=30, high=30, xperms=0x8b9eea0) + at ../cil/src/cil_binary.c:1551 + #4 0x00007f60900970dd in __cil_permx_bitmap_to_sepol_xperms_list (xperms=0xb650a30, xperms_list=0x7ffce2653b18) + at ../cil/src/cil_binary.c:1596 + #5 0x00007f6090097286 in __cil_avrulex_ioctl_to_policydb (k=0xb8ec200 "@\023\214\022\006", datum=0xb650a30, + args=0x239a640) at ../cil/src/cil_binary.c:1649 + #6 0x00007f609003f1e5 in hashtab_map (h=0x41f8710, apply=0x7f60900971da <__cil_avrulex_ioctl_to_policydb>, + args=0x239a640) at hashtab.c:234 + #7 0x00007f609009ea19 in cil_binary_create_allocated_pdb (db=0x2394f10, policydb=0x239a640) + at ../cil/src/cil_binary.c:4969 + #8 0x00007f609009d19d in cil_binary_create (db=0x2394f10, policydb=0x7ffce2653d30) at ../cil/src/cil_binary.c:4329 + #9 0x00007f609008ec23 in cil_build_policydb_create_pdb (db=0x2394f10, sepol_db=0x7ffce2653d30) + at ../cil/src/cil.c:631 + #10 0x00007f608fff4bf3 in semanage_direct_commit () from /lib64/libsemanage.so.1 + #11 0x00007f608fff9fae in semanage_commit () from /lib64/libsemanage.so.1 + #12 0x0000000000403e2b in main (argc=7, argv=0x7ffce2655058) at semodule.c:753 + + (gdb) f 3 + #3 0x00007f6090096f59 in __avrule_xperm_setrangebits (low=30, high=30, xperms=0x8b9eea0) + at ../cil/src/cil_binary.c:1551 + 1551 xperms->perms[i] |= XPERM_SETBITS(h) - XPERM_SETBITS(low); + +A signed integer overflow therefore occurs in XPERM_SETBITS(h): + + #define XPERM_SETBITS(x) ((1 << (x & 0x1f)) - 1) + +This macro is expanded with h=31, so "(1 << 31) - 1" is computed: + +* (1 << 31) = -0x80000000 is the lowest signed 32-bit integer value +* (1 << 31) - 1 overflows the capacity of a signed 32-bit integer and + results in 0x7fffffff (which is unsigned) + +Using unsigned integers (with "1U") fixes the crash, as +(1U << 31) = 0x80000000U has no overflowing issues. + +Signed-off-by: Nicolas Iooss +Acked-by: Petr Lautrbach +--- + libsepol/cil/src/cil_binary.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c +index 36720eda4549..e417c5c28b8b 100644 +--- a/libsepol/cil/src/cil_binary.c ++++ b/libsepol/cil/src/cil_binary.c +@@ -1526,7 +1526,7 @@ int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_ + /* index of the u32 containing the permission */ + #define XPERM_IDX(x) (x >> 5) + /* set bits 0 through x-1 within the u32 */ +-#define XPERM_SETBITS(x) ((1 << (x & 0x1f)) - 1) ++#define XPERM_SETBITS(x) ((1U << (x & 0x1f)) - 1) + /* low value for this u32 */ + #define XPERM_LOW(x) (x << 5) + /* high value for this u32 */ +-- +2.29.0.rc2 + diff --git a/0007-libsepol-drop-confusing-BUG_ON-macro.patch b/0007-libsepol-drop-confusing-BUG_ON-macro.patch new file mode 100644 index 0000000..9c8e943 --- /dev/null +++ b/0007-libsepol-drop-confusing-BUG_ON-macro.patch @@ -0,0 +1,77 @@ +From 64387cb37379fc8f135eeecd2bd9fdf3c591c763 Mon Sep 17 00:00:00 2001 +From: Nicolas Iooss +Date: Sat, 3 Oct 2020 15:34:19 +0200 +Subject: [PATCH] libsepol: drop confusing BUG_ON macro + +Contrary to Linux kernel, BUG_ON() does not halt the execution, in +libsepol/src/services.c. Instead it displays an error message and +continues the execution. + +This means that this code does not prevent an out-of-bound write from +happening: + + case CEXPR_AND: + BUG_ON(sp < 1); + sp--; + s[sp] &= s[sp + 1]; + +Use if(...){BUG();rc=-EINVAL;goto out;} constructions instead, to make +sure that the array access is always in-bound. + +This issue has been found using clang's static analyzer: +https://558-118970575-gh.circle-artifacts.com/0/output-scan-build/2020-10-02-065849-6375-1/report-50a861.html#EndPath + +Signed-off-by: Nicolas Iooss +--- + libsepol/src/services.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/libsepol/src/services.c b/libsepol/src/services.c +index 90da1f4efef3..beb0711f6680 100644 +--- a/libsepol/src/services.c ++++ b/libsepol/src/services.c +@@ -67,7 +67,6 @@ + #include "flask.h" + + #define BUG() do { ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0) +-#define BUG_ON(x) do { if (x) ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0) + + static int selinux_enforcing = 1; + +@@ -469,18 +468,30 @@ static int constraint_expr_eval_reason(context_struct_t *scontext, + /* Now process each expression of the constraint */ + switch (e->expr_type) { + case CEXPR_NOT: +- BUG_ON(sp < 0); ++ if (sp < 0) { ++ BUG(); ++ rc = -EINVAL; ++ goto out; ++ } + s[sp] = !s[sp]; + cat_expr_buf(expr_list[expr_counter], "not"); + break; + case CEXPR_AND: +- BUG_ON(sp < 1); ++ if (sp < 1) { ++ BUG(); ++ rc = -EINVAL; ++ goto out; ++ } + sp--; + s[sp] &= s[sp + 1]; + cat_expr_buf(expr_list[expr_counter], "and"); + break; + case CEXPR_OR: +- BUG_ON(sp < 1); ++ if (sp < 1) { ++ BUG(); ++ rc = -EINVAL; ++ goto out; ++ } + sp--; + s[sp] |= s[sp + 1]; + cat_expr_buf(expr_list[expr_counter], "or"); +-- +2.29.0.rc2 + diff --git a/0008-libsepol-silence-potential-NULL-pointer-dereference-.patch b/0008-libsepol-silence-potential-NULL-pointer-dereference-.patch new file mode 100644 index 0000000..0230daa --- /dev/null +++ b/0008-libsepol-silence-potential-NULL-pointer-dereference-.patch @@ -0,0 +1,66 @@ +From c97d63c6b40c71c693d3b5bb25628869a95dff24 Mon Sep 17 00:00:00 2001 +From: Nicolas Iooss +Date: Sat, 3 Oct 2020 15:56:58 +0200 +Subject: [PATCH] libsepol: silence potential NULL pointer dereference warning + +When find_avtab_node() is called with key->specified & AVTAB_XPERMS and +xperms=NULL, xperms is being dereferenced. This is detected as a +"NULL pointer dereference issue" by static analyzers. + +Even though it does not make much sense to call find_avtab_node() in a +way which triggers the NULL pointer dereference issue, static analyzers +have a hard time with calls such as: + + node = find_avtab_node(handle, avtab, &avkey, cond, NULL); + +... where xperms=NULL. + +So, make the function report an error instead of crashing. + +Here is an example of report from clang's static analyzer: +https://558-118970575-gh.circle-artifacts.com/0/output-scan-build/2020-10-02-065849-6375-1/report-d86a57.html#EndPath + +Signed-off-by: Nicolas Iooss +--- + libsepol/src/expand.c | 23 ++++++++++++++--------- + 1 file changed, 14 insertions(+), 9 deletions(-) + +diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c +index 19e48c507236..eac7e4507d02 100644 +--- a/libsepol/src/expand.c ++++ b/libsepol/src/expand.c +@@ -1570,17 +1570,22 @@ static avtab_ptr_t find_avtab_node(sepol_handle_t * handle, + + /* AVTAB_XPERMS entries are not necessarily unique */ + if (key->specified & AVTAB_XPERMS) { +- node = avtab_search_node(avtab, key); +- while (node) { +- if ((node->datum.xperms->specified == xperms->specified) && +- (node->datum.xperms->driver == xperms->driver)) { +- match = 1; +- break; ++ if (xperms == NULL) { ++ ERR(handle, "searching xperms NULL"); ++ node = NULL; ++ } else { ++ node = avtab_search_node(avtab, key); ++ while (node) { ++ if ((node->datum.xperms->specified == xperms->specified) && ++ (node->datum.xperms->driver == xperms->driver)) { ++ match = 1; ++ break; ++ } ++ node = avtab_search_node_next(node, key->specified); + } +- node = avtab_search_node_next(node, key->specified); ++ if (!match) ++ node = NULL; + } +- if (!match) +- node = NULL; + } else { + node = avtab_search_node(avtab, key); + } +-- +2.29.0.rc2 + diff --git a/0009-libsepol-Get-rid-of-the-old-and-duplicated-symbols.patch b/0009-libsepol-Get-rid-of-the-old-and-duplicated-symbols.patch new file mode 100644 index 0000000..e0694d7 --- /dev/null +++ b/0009-libsepol-Get-rid-of-the-old-and-duplicated-symbols.patch @@ -0,0 +1,193 @@ +From ae58e84b4fd825b6cd2c67f3856ac35557c45e9c Mon Sep 17 00:00:00 2001 +From: Petr Lautrbach +Date: Fri, 9 Oct 2020 15:00:47 +0200 +Subject: [PATCH] libsepol: Get rid of the old and duplicated symbols + +Versioned duplicate symbols cause problems for LTO. These symbols were +introduced during the CIL integration several releases ago and were only +consumed by other SELinux userspace components. + +Fixes: https://github.com/SELinuxProject/selinux/issues/245 + +Signed-off-by: Petr Lautrbach +--- + libsepol/cil/src/cil.c | 84 ------------------------------------ + libsepol/src/libsepol.map.in | 5 --- + 2 files changed, 89 deletions(-) + +diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c +index a3c6a2934c72..95bdb5e5854c 100644 +--- a/libsepol/cil/src/cil.c ++++ b/libsepol/cil/src/cil.c +@@ -51,27 +51,6 @@ + #include "cil_policy.h" + #include "cil_strpool.h" + +-#if !defined(SHARED) || defined(ANDROID) || defined(__APPLE__) +- #define DISABLE_SYMVER 1 +-#endif +- +-#ifndef DISABLE_SYMVER +-asm(".symver cil_build_policydb_pdb, cil_build_policydb@LIBSEPOL_1.0"); +-asm(".symver cil_build_policydb_create_pdb, cil_build_policydb@@LIBSEPOL_1.1"); +- +-asm(".symver cil_compile_pdb, cil_compile@LIBSEPOL_1.0"); +-asm(".symver cil_compile_nopdb, cil_compile@@LIBSEPOL_1.1"); +- +-asm(".symver cil_userprefixes_to_string_pdb, cil_userprefixes_to_string@LIBSEPOL_1.0"); +-asm(".symver cil_userprefixes_to_string_nopdb, cil_userprefixes_to_string@@LIBSEPOL_1.1"); +- +-asm(".symver cil_selinuxusers_to_string_pdb, cil_selinuxusers_to_string@LIBSEPOL_1.0"); +-asm(".symver cil_selinuxusers_to_string_nopdb, cil_selinuxusers_to_string@@LIBSEPOL_1.1"); +- +-asm(".symver cil_filecons_to_string_pdb, cil_filecons_to_string@LIBSEPOL_1.0"); +-asm(".symver cil_filecons_to_string_nopdb, cil_filecons_to_string@@LIBSEPOL_1.1"); +-#endif +- + int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = { + {64, 64, 64, 1 << 13, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, +@@ -549,11 +528,7 @@ exit: + return rc; + } + +-#ifdef DISABLE_SYMVER + int cil_compile(struct cil_db *db) +-#else +-int cil_compile_nopdb(struct cil_db *db) +-#endif + { + int rc = SEPOL_ERR; + +@@ -597,33 +572,7 @@ exit: + return rc; + } + +-#ifndef DISABLE_SYMVER +-int cil_compile_pdb(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db) +-{ +- return cil_compile_nopdb(db); +-} +- +-int cil_build_policydb_pdb(cil_db_t *db, sepol_policydb_t *sepol_db) +-{ +- int rc; +- +- cil_log(CIL_INFO, "Building policy binary\n"); +- rc = cil_binary_create_allocated_pdb(db, sepol_db); +- if (rc != SEPOL_OK) { +- cil_log(CIL_ERR, "Failed to generate binary\n"); +- goto exit; +- } +- +-exit: +- return rc; +-} +-#endif +- +-#ifdef DISABLE_SYMVER + int cil_build_policydb(cil_db_t *db, sepol_policydb_t **sepol_db) +-#else +-int cil_build_policydb_create_pdb(cil_db_t *db, sepol_policydb_t **sepol_db) +-#endif + { + int rc; + +@@ -1371,11 +1320,7 @@ const char * cil_node_to_string(struct cil_tree_node *node) + return ""; + } + +-#ifdef DISABLE_SYMVER + int cil_userprefixes_to_string(struct cil_db *db, char **out, size_t *size) +-#else +-int cil_userprefixes_to_string_nopdb(struct cil_db *db, char **out, size_t *size) +-#endif + { + int rc = SEPOL_ERR; + size_t str_len = 0; +@@ -1420,13 +1365,6 @@ exit: + + } + +-#ifndef DISABLE_SYMVER +-int cil_userprefixes_to_string_pdb(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db, char **out, size_t *size) +-{ +- return cil_userprefixes_to_string_nopdb(db, out, size); +-} +-#endif +- + static int cil_cats_to_ebitmap(struct cil_cats *cats, struct ebitmap* cats_ebitmap) + { + int rc = SEPOL_ERR; +@@ -1614,11 +1552,7 @@ static int __cil_level_to_string(struct cil_level *lvl, char *out) + return str_tmp - out; + } + +-#ifdef DISABLE_SYMVER + int cil_selinuxusers_to_string(struct cil_db *db, char **out, size_t *size) +-#else +-int cil_selinuxusers_to_string_nopdb(struct cil_db *db, char **out, size_t *size) +-#endif + { + size_t str_len = 0; + int buf_pos = 0; +@@ -1675,18 +1609,7 @@ int cil_selinuxusers_to_string_nopdb(struct cil_db *db, char **out, size_t *size + return SEPOL_OK; + } + +-#ifndef DISABLE_SYMVER +-int cil_selinuxusers_to_string_pdb(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db, char **out, size_t *size) +-{ +- return cil_selinuxusers_to_string_nopdb(db, out, size); +-} +-#endif +- +-#ifdef DISABLE_SYMVER + int cil_filecons_to_string(struct cil_db *db, char **out, size_t *size) +-#else +-int cil_filecons_to_string_nopdb(struct cil_db *db, char **out, size_t *size) +-#endif + { + uint32_t i = 0; + int buf_pos = 0; +@@ -1804,13 +1727,6 @@ int cil_filecons_to_string_nopdb(struct cil_db *db, char **out, size_t *size) + return SEPOL_OK; + } + +-#ifndef DISABLE_SYMVER +-int cil_filecons_to_string_pdb(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db, char **out, size_t *size) +-{ +- return cil_filecons_to_string_nopdb(db, out, size); +-} +-#endif +- + void cil_set_disable_dontaudit(struct cil_db *db, int disable_dontaudit) + { + db->disable_dontaudit = disable_dontaudit; +diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in +index f08c2a861693..98da9789b71b 100644 +--- a/libsepol/src/libsepol.map.in ++++ b/libsepol/src/libsepol.map.in +@@ -1,19 +1,14 @@ + LIBSEPOL_1.0 { + global: + cil_add_file; +- cil_build_policydb; +- cil_compile; + cil_db_destroy; + cil_db_init; +- cil_filecons_to_string; +- cil_selinuxusers_to_string; + cil_set_disable_dontaudit; + cil_set_disable_neverallow; + cil_set_handle_unknown; + cil_set_log_handler; + cil_set_log_level; + cil_set_preserve_tunables; +- cil_userprefixes_to_string; + expand_module_avrules; + sepol_bool_clone; + sepol_bool_compare; +-- +2.29.0.rc2 + diff --git a/0010-libsepol-Drop-deprecated-functions.patch b/0010-libsepol-Drop-deprecated-functions.patch new file mode 100644 index 0000000..7f728d6 --- /dev/null +++ b/0010-libsepol-Drop-deprecated-functions.patch @@ -0,0 +1,134 @@ +From 506c7b95b802ab157fe9ae1dae22fab12c515306 Mon Sep 17 00:00:00 2001 +From: Petr Lautrbach +Date: Fri, 9 Oct 2020 15:00:48 +0200 +Subject: [PATCH] libsepol: Drop deprecated functions + +These functions were converted to no-op by commit +c3f9492d7ff0 ("selinux: Remove legacy local boolean and user code") and +left in libsepol/src/deprecated_functions.c to preserve API/ABI. As we +change libsepol ABI dropping duplicate symbols it's time to drop these +functions too. + +Signed-off-by: Petr Lautrbach +--- + libsepol/include/sepol/booleans.h | 5 ---- + libsepol/include/sepol/users.h | 6 ---- + libsepol/src/deprecated_funcs.c | 50 ------------------------------- + libsepol/src/libsepol.map.in | 4 --- + 4 files changed, 65 deletions(-) + delete mode 100644 libsepol/src/deprecated_funcs.c + +diff --git a/libsepol/include/sepol/booleans.h b/libsepol/include/sepol/booleans.h +index 06d2230c395d..25229057dbd7 100644 +--- a/libsepol/include/sepol/booleans.h ++++ b/libsepol/include/sepol/booleans.h +@@ -10,11 +10,6 @@ + extern "C" { + #endif + +-/* These two functions are deprecated. See src/deprecated_funcs.c */ +-extern int sepol_genbools(void *data, size_t len, const char *boolpath); +-extern int sepol_genbools_array(void *data, size_t len, +- char **names, int *values, int nel); +- + /* Set the specified boolean */ + extern int sepol_bool_set(sepol_handle_t * handle, + sepol_policydb_t * policydb, +diff --git a/libsepol/include/sepol/users.h b/libsepol/include/sepol/users.h +index 70158ac41e40..156d1adb2d60 100644 +--- a/libsepol/include/sepol/users.h ++++ b/libsepol/include/sepol/users.h +@@ -10,12 +10,6 @@ + extern "C" { + #endif + +-/* These two functions are deprecated. See src/deprecated_funcs.c */ +-extern int sepol_genusers(void *data, size_t len, +- const char *usersdir, +- void **newdata, size_t * newlen); +-extern void sepol_set_delusers(int on); +- + /* Modify the user, or add it, if the key is not found */ + extern int sepol_user_modify(sepol_handle_t * handle, + sepol_policydb_t * policydb, +diff --git a/libsepol/src/deprecated_funcs.c b/libsepol/src/deprecated_funcs.c +deleted file mode 100644 +index d0dab7dfcb4a..000000000000 +--- a/libsepol/src/deprecated_funcs.c ++++ /dev/null +@@ -1,50 +0,0 @@ +-#include +-#include "debug.h" +- +-/* +- * Need to keep these stubs for the libsepol interfaces exported in +- * libsepol.map.in, as they are part of the shared library ABI. +- */ +- +-static const char *msg = "Deprecated interface"; +- +-/* +- * These two functions are deprecated and referenced in: +- * include/libsepol/users.h +- */ +-int sepol_genusers(void *data __attribute((unused)), +- size_t len __attribute((unused)), +- const char *usersdir __attribute((unused)), +- void **newdata __attribute((unused)), +- size_t *newlen __attribute((unused))) +-{ +- WARN(NULL, "%s", msg); +- return -1; +-} +- +-void sepol_set_delusers(int on __attribute((unused))) +-{ +- WARN(NULL, "%s", msg); +-} +- +-/* +- * These two functions are deprecated and referenced in: +- * include/libsepol/booleans.h +- */ +-int sepol_genbools(void *data __attribute((unused)), +- size_t len __attribute((unused)), +- const char *booleans __attribute((unused))) +-{ +- WARN(NULL, "%s", msg); +- return -1; +-} +- +-int sepol_genbools_array(void *data __attribute((unused)), +- size_t len __attribute((unused)), +- char **names __attribute((unused)), +- int *values __attribute((unused)), +- int nel __attribute((unused))) +-{ +- WARN(NULL, "%s", msg); +- return -1; +-} +diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in +index 98da9789b71b..eb5721257638 100644 +--- a/libsepol/src/libsepol.map.in ++++ b/libsepol/src/libsepol.map.in +@@ -45,9 +45,6 @@ LIBSEPOL_1.0 { + sepol_context_to_string; + sepol_debug; + sepol_expand_module; +- sepol_genbools; +- sepol_genbools_array; +- sepol_genusers; + sepol_get_disable_dontaudit; + sepol_get_preserve_tunables; + sepol_handle_create; +@@ -213,7 +210,6 @@ LIBSEPOL_1.0 { + sepol_port_set_port; + sepol_port_set_proto; + sepol_port_set_range; +- sepol_set_delusers; + sepol_set_disable_dontaudit; + sepol_set_expand_consume_base; + sepol_set_policydb_from_file; +-- +2.29.0.rc2 + diff --git a/0011-libsepol-Bump-libsepol.so-version.patch b/0011-libsepol-Bump-libsepol.so-version.patch new file mode 100644 index 0000000..9324e54 --- /dev/null +++ b/0011-libsepol-Bump-libsepol.so-version.patch @@ -0,0 +1,45 @@ +From 4a142ac46a116feb9f978eaec68a30efef979c73 Mon Sep 17 00:00:00 2001 +From: Petr Lautrbach +Date: Fri, 9 Oct 2020 15:00:49 +0200 +Subject: [PATCH] libsepol: Bump libsepol.so version + +Previous commits removed some symbols and broke ABI, therefore we need to change +SONAME. + +See the following quotes from distribution guidelines: + +https://www.debian.org/doc/debian-policy/ch-sharedlibs.html#run-time-shared-libraries + +Every time the shared library ABI changes in a way that may break +binaries linked against older versions of the shared library, the SONAME +of the library and the corresponding name for the binary package +containing the runtime shared library should change. + +https://docs.fedoraproject.org/en-US/packaging-guidelines/#_downstream_so_name_versioning + +When new versions of the library are released, you should use an ABI +comparison tool to check for ABI differences in the built shared +libraries. If it detects any incompatibilities, bump the n number by +one. + +Signed-off-by: Petr Lautrbach +--- + libsepol/src/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsepol/src/Makefile b/libsepol/src/Makefile +index 8d466f56ed0e..dc8b1773d974 100644 +--- a/libsepol/src/Makefile ++++ b/libsepol/src/Makefile +@@ -7,7 +7,7 @@ RANLIB ?= ranlib + CILDIR ?= ../cil + + VERSION = $(shell cat ../VERSION) +-LIBVERSION = 1 ++LIBVERSION = 2 + + LEX = flex + CIL_GENERATED = $(CILDIR)/src/cil_lexer.c +-- +2.29.0.rc2 + diff --git a/libsepol.spec b/libsepol.spec index a976a75..97a07cb 100644 --- a/libsepol.spec +++ b/libsepol.spec @@ -10,6 +10,17 @@ URL: https://github.com/SELinuxProject/selinux/wiki # $ git format-patch -N libsepol-3.1 -- libsepol # $ i=1; for j in 00*patch; do printf "Patch%04d: %s\n" $i $j; i=$((i+1));done # Patch list start +Patch0001: 0001-libsepol-checkpolicy-optimize-storage-of-filename-tr.patch +Patch0002: 0002-libsepol-implement-POLICYDB_VERSION_COMP_FTRANS.patch +Patch0003: 0003-libsepol-cil-Validate-constraint-expressions-before-.patch +Patch0004: 0004-libsepol-cil-Validate-conditional-expressions-before.patch +Patch0005: 0005-libsepol-cil-Fix-neverallow-checking-involving-class.patch +Patch0006: 0006-libsepol-cil-fix-signed-overflow-caused-by-using-1-3.patch +Patch0007: 0007-libsepol-drop-confusing-BUG_ON-macro.patch +Patch0008: 0008-libsepol-silence-potential-NULL-pointer-dereference-.patch +Patch0009: 0009-libsepol-Get-rid-of-the-old-and-duplicated-symbols.patch +Patch0010: 0010-libsepol-Drop-deprecated-functions.patch +Patch0011: 0011-libsepol-Bump-libsepol.so-version.patch # Patch list end BuildRequires: gcc BuildRequires: flex @@ -46,6 +57,12 @@ Requires: %{name}-devel%{?_isa} = %{version}-%{release} The libsepol-static package contains the static libraries and header files needed for developing applications that manipulate binary policies. +%package compat +Summary: Temporary compat libsepol.so.1 used for transition to libsepol.so.2 + +%description compat +Temporary compat libsepol.so.1 used for transition to libsepol.so.2 + %prep %autosetup -p 2 -n libsepol-%{version} @@ -55,8 +72,6 @@ sed -i 's/fpic/fPIC/g' src/Makefile %endif %build -# Disable LTO -%define _lto_cflags %{nil} %set_build_flags CFLAGS="$CFLAGS -fno-semantic-interposition" %make_build @@ -75,6 +90,11 @@ rm -f ${RPM_BUILD_ROOT}%{_bindir}/chkcon rm -rf ${RPM_BUILD_ROOT}%{_mandir}/man8 rm -rf ${RPM_BUILD_ROOT}%{_mandir}/ru/man8 +%set_build_flags +CFLAGS="$CFLAGS -fno-semantic-interposition" +sed -i 's/LIBVERSION = 2/LIBVERSION = 1/' src/Makefile +%make_build +cp src/libsepol.so.1 ${RPM_BUILD_ROOT}/%{_libdir}/libsepol.so.1 %files static %{_libdir}/libsepol.a @@ -93,6 +113,9 @@ rm -rf ${RPM_BUILD_ROOT}%{_mandir}/ru/man8 %files %{!?_licensedir:%global license %%doc} %license COPYING +%{_libdir}/libsepol.so.2 + +%files compat %{_libdir}/libsepol.so.1 %changelog