Patches as of 2018-03-06 release
diff --git a/patches/platform_external_selinux/0001-libsepol-cil-Add-ability-to-redeclare-types-attribut.patch b/patches/platform_external_selinux/0001-libsepol-cil-Add-ability-to-redeclare-types-attribut.patch
new file mode 100644
index 0000000..d38aec2
--- /dev/null
+++ b/patches/platform_external_selinux/0001-libsepol-cil-Add-ability-to-redeclare-types-attribut.patch
@@ -0,0 +1,208 @@
+From be352c253dffb5c0d952fbeef905c3269853b7e0 Mon Sep 17 00:00:00 2001
+From: Dan Cashman <dcashman@android.com>
+Date: Tue, 29 Aug 2017 09:32:05 -0700
+Subject: [PATCH 1/5] libsepol: cil: Add ability to redeclare types[attributes]
+
+Modify cil_gen_node() to check to see if the cil_db supports multiple
+declarations, and if so, to check whether or not the
+repeated symbol is eligible to share the existing, already-stored datum. The
+only types considered so far are CIL_TYPE and CIL_TYPEATTRIBUTE, both of
+which intall empty datums during AST building, so they automatically return
+true.
+
+Test: Build policy with multilpe type and attribute declarations, and
+without. Policies are binary-identical.
+
+Signed-off-by: Dan Cashman <dcashman@android.com>
+Signed-off-by: James Carter <jwcart2@tycho.nsa.gov>
+---
+ libsepol/cil/include/cil/cil.h | 1 +
+ libsepol/cil/src/cil.c | 5 +++++
+ libsepol/cil/src/cil_build_ast.c | 48 ++++++++++++++++++++++++++++++++++------
+ libsepol/cil/src/cil_internal.h | 1 +
+ libsepol/src/libsepol.map.in | 1 +
+ secilc/secilc.c | 9 +++++++-
+ 6 files changed, 57 insertions(+), 8 deletions(-)
+
+diff --git a/libsepol/cil/include/cil/cil.h b/libsepol/cil/include/cil/cil.h
+index 4507892c..4df646a0 100644
+--- a/libsepol/cil/include/cil/cil.h
++++ b/libsepol/cil/include/cil/cil.h
+@@ -46,6 +46,7 @@ extern int cil_userprefixes_to_string(cil_db_t *db, char **out, size_t *size);
+ extern int cil_selinuxusers_to_string(cil_db_t *db, char **out, size_t *size);
+ extern int cil_filecons_to_string(cil_db_t *db, char **out, size_t *size);
+ extern void cil_set_disable_dontaudit(cil_db_t *db, int disable_dontaudit);
++extern void cil_set_multiple_decls(cil_db_t *db, int multiple_decls);
+ extern void cil_set_disable_neverallow(cil_db_t *db, int disable_neverallow);
+ extern void cil_set_preserve_tunables(cil_db_t *db, int preserve_tunables);
+ extern int cil_set_handle_unknown(cil_db_t *db, int handle_unknown);
+diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
+index 9b9ccc36..e8bbbfdf 100644
+--- a/libsepol/cil/src/cil.c
++++ b/libsepol/cil/src/cil.c
+@@ -1675,6 +1675,11 @@ void cil_set_mls(struct cil_db *db, int mls)
+ db->mls = mls;
+ }
+
++void cil_set_multiple_decls(struct cil_db *db, int multiple_decls)
++{
++ db->multiple_decls = multiple_decls;
++}
++
+ void cil_set_target_platform(struct cil_db *db, int target_platform)
+ {
+ db->target_platform = target_platform;
+diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
+index 36cc6735..9a10e7ab 100644
+--- a/libsepol/cil/src/cil_build_ast.c
++++ b/libsepol/cil/src/cil_build_ast.c
+@@ -82,10 +82,33 @@ exit:
+ return rc;
+ }
+
++/*
++ * Determine whether or not multiple declarations of the same key can share a
++ * datum, given the new datum and the one already present in a given symtab.
++ */
++int cil_is_datum_multiple_decl(__attribute__((unused)) struct cil_symtab_datum *cur,
++ __attribute__((unused)) struct cil_symtab_datum *old,
++ enum cil_flavor f)
++{
++ int rc = CIL_FALSE;
++
++ switch (f) {
++ case CIL_TYPE:
++ case CIL_TYPEATTRIBUTE:
++ /* type and typeattribute statements insert empty datums, ret true */
++ rc = CIL_TRUE;
++ break;
++ default:
++ break;
++ }
++ return rc;
++}
++
+ int cil_gen_node(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor)
+ {
+ int rc = SEPOL_ERR;
+ symtab_t *symtab = NULL;
++ struct cil_symtab_datum *prev;
+
+ rc = __cil_verify_name((const char*)key);
+ if (rc != SEPOL_OK) {
+@@ -103,15 +126,26 @@ int cil_gen_node(__attribute__((unused)) struct cil_db *db, struct cil_tree_node
+ if (symtab != NULL) {
+ rc = cil_symtab_insert(symtab, (hashtab_key_t)key, datum, ast_node);
+ if (rc == SEPOL_EEXIST) {
+- cil_log(CIL_ERR, "Re-declaration of %s %s\n",
+- cil_node_to_string(ast_node), key);
+- if (cil_symtab_get_datum(symtab, key, &datum) == SEPOL_OK) {
+- if (sflavor == CIL_SYM_BLOCKS) {
+- struct cil_tree_node *node = datum->nodes->head->data;
+- cil_tree_log(node, CIL_ERR, "Previous declaration");
++ if (!db->multiple_decls ||
++ cil_symtab_get_datum(symtab, (hashtab_key_t)key, &prev) != SEPOL_OK ||
++ !cil_is_datum_multiple_decl(datum, prev, nflavor)) {
++
++ /* multiple_decls not ok, ret error */
++ cil_log(CIL_ERR, "Re-declaration of %s %s\n",
++ cil_node_to_string(ast_node), key);
++ if (cil_symtab_get_datum(symtab, key, &datum) == SEPOL_OK) {
++ if (sflavor == CIL_SYM_BLOCKS) {
++ struct cil_tree_node *node = datum->nodes->head->data;
++ cil_tree_log(node, CIL_ERR, "Previous declaration");
++ }
+ }
++ goto exit;
+ }
+- goto exit;
++ /* multiple_decls is enabled and works for this datum type, add node */
++ cil_list_append(prev->nodes, CIL_NODE, ast_node);
++ ast_node->data = prev;
++ cil_symtab_datum_destroy(datum);
++ free(datum);
+ }
+ }
+
+diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
+index aee3f00c..abfacd8d 100644
+--- a/libsepol/cil/src/cil_internal.h
++++ b/libsepol/cil/src/cil_internal.h
+@@ -312,6 +312,7 @@ struct cil_db {
+ int preserve_tunables;
+ int handle_unknown;
+ int mls;
++ int multiple_decls;
+ int target_platform;
+ int policy_version;
+ };
+diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
+index 40426408..edd98d5a 100644
+--- a/libsepol/src/libsepol.map.in
++++ b/libsepol/src/libsepol.map.in
+@@ -47,6 +47,7 @@ LIBSEPOL_1.1 {
+ cil_set_mls;
+ cil_set_attrs_expand_generated;
+ cil_set_attrs_expand_size;
++ cil_set_multiple_decls;
+ cil_write_policy_conf;
+ sepol_ppfile_to_module_package;
+ sepol_module_package_to_cil;
+diff --git a/secilc/secilc.c b/secilc/secilc.c
+index f2232e72..0be6975b 100644
+--- a/secilc/secilc.c
++++ b/secilc/secilc.c
+@@ -63,6 +63,7 @@ static __attribute__((__noreturn__)) void usage(const char *prog)
+ printf(" statement if present in the policy\n");
+ printf(" -D, --disable-dontaudit do not add dontaudit rules to the binary policy\n");
+ printf(" -P, --preserve-tunables treat tunables as booleans\n");
++ printf(" -m, --multiple-decls allow some statements to be re-declared\n");
+ printf(" -N, --disable-neverallow do not check neverallow rules\n");
+ printf(" -G, --expand-generated Expand and remove auto-generated attributes\n");
+ printf(" -X, --expand-size <SIZE> Expand type attributes with fewer than <SIZE>\n");
+@@ -89,6 +90,7 @@ int main(int argc, char *argv[])
+ int target = SEPOL_TARGET_SELINUX;
+ int mls = -1;
+ int disable_dontaudit = 0;
++ int multiple_decls = 0;
+ int disable_neverallow = 0;
+ int preserve_tunables = 0;
+ int handle_unknown = -1;
+@@ -108,6 +110,7 @@ int main(int argc, char *argv[])
+ {"policyversion", required_argument, 0, 'c'},
+ {"handle-unknown", required_argument, 0, 'U'},
+ {"disable-dontaudit", no_argument, 0, 'D'},
++ {"multiple-decls", no_argument, 0, 'm'},
+ {"disable-neverallow", no_argument, 0, 'N'},
+ {"preserve-tunables", no_argument, 0, 'P'},
+ {"output", required_argument, 0, 'o'},
+@@ -119,7 +122,7 @@ int main(int argc, char *argv[])
+ int i;
+
+ while (1) {
+- opt_char = getopt_long(argc, argv, "o:f:U:hvt:M:PDNc:GX:", long_opts, &opt_index);
++ opt_char = getopt_long(argc, argv, "o:f:U:hvt:M:PDmNc:GX:", long_opts, &opt_index);
+ if (opt_char == -1) {
+ break;
+ }
+@@ -175,6 +178,9 @@ int main(int argc, char *argv[])
+ case 'D':
+ disable_dontaudit = 1;
+ break;
++ case 'm':
++ multiple_decls = 1;
++ break;
+ case 'N':
+ disable_neverallow = 1;
+ break;
+@@ -223,6 +229,7 @@ int main(int argc, char *argv[])
+
+ cil_db_init(&db);
+ cil_set_disable_dontaudit(db, disable_dontaudit);
++ cil_set_multiple_decls(db, multiple_decls);
+ cil_set_disable_neverallow(db, disable_neverallow);
+ cil_set_preserve_tunables(db, preserve_tunables);
+ if (handle_unknown != -1) {
+--
+2.15.1
+
diff --git a/patches/platform_external_selinux/0002-libsepol-cil-Keep-type-attribute-declarations-when-a.patch b/patches/platform_external_selinux/0002-libsepol-cil-Keep-type-attribute-declarations-when-a.patch
new file mode 100644
index 0000000..f88b855
--- /dev/null
+++ b/patches/platform_external_selinux/0002-libsepol-cil-Keep-type-attribute-declarations-when-a.patch
@@ -0,0 +1,89 @@
+From 0a0c8e77b3a55c70ef55cd78aa5c2a4bce5b0862 Mon Sep 17 00:00:00 2001
+From: Dan Cashman <dcashman@google.com>
+Date: Wed, 11 Oct 2017 12:59:43 -0700
+Subject: [PATCH 2/5] libsepol: cil: Keep type[attribute] declarations when
+ attributizing.
+
+cil_android_attributize() uses a source policy to identify types and
+attributes to be versioned according to the given version number, and
+then proceeds to modify the provided target policy to provide this
+versioning. Previously, the versioned policy relied on a base policy
+for the declarations of these type[attribute]s, but with multiple_decl
+support added, the declarations can be made in both places. This will
+make the policy more robust and allow for greater flexibility and the
+types of base policy used.
+
+Bug: 37915794
+Test: Builds 'n' boots. non_plat_sepolicy.cil now contains the public
+type[attribute] declarations.
+
+Change-Id: Iaa084211a9e2774a7ed391888fb21c4c0cf955db
+---
+ libsepol/cil/include/cil/android.h | 2 ++
+ libsepol/cil/src/android.c | 17 ++++++++---------
+ 2 files changed, 10 insertions(+), 9 deletions(-)
+
+diff --git a/libsepol/cil/include/cil/android.h b/libsepol/cil/include/cil/android.h
+index 082d7fd2..5aceda62 100644
+--- a/libsepol/cil/include/cil/android.h
++++ b/libsepol/cil/include/cil/android.h
+@@ -21,6 +21,8 @@ int cil_android_attrib_mapping(struct cil_db **mdb, struct cil_db *srcdb, const
+ /*
+ * cil_android_attributize - extract attributizable elements of the policy in
+ * srcdb and convert all usage of those elements in tgtdb to versioned attributes.
++ * Keep the attributes and type definitions so that tgtdb policy is more robust
++ * against future changes to the public policy.
+ * tgtdb - initialized and parsed cil_db reference to modify.
+ * srcdb - initialized and parsed cil_db reference to source public policy
+ * from which to extract attributizable elements.
+diff --git a/libsepol/cil/src/android.c b/libsepol/cil/src/android.c
+index 1d80046b..53df4187 100644
+--- a/libsepol/cil/src/android.c
++++ b/libsepol/cil/src/android.c
+@@ -200,23 +200,27 @@ static char *__cil_attrib_get_versname(char *old, const char *vers)
+
+ /*
+ * Change type to attribute - create new versioned name based on old, create
+- * typeattribute node and replace existing type node.
++ * typeattribute node add to the existing type node.
+ */
+ static int __cil_attrib_convert_type(struct cil_tree_node *node, struct version_args *args)
+ {
+ int rc = SEPOL_ERR;
+ struct cil_type *type = (struct cil_type *)node->data;
+ struct cil_typeattribute *typeattr = NULL;
++ struct cil_tree_node *new_ast_node = NULL;
+ char *new_key;
+
+ cil_typeattribute_init(&typeattr);
+
+ new_key = __cil_attrib_get_versname(type->datum.name, args->num);
+
+- cil_symtab_datum_remove_node(&type->datum, node);
+- cil_destroy_type(type);
++ /* create new tree node to contain typeattribute and add to tree */
++ cil_tree_node_init(&new_ast_node);
++ new_ast_node->parent = node->parent;
++ new_ast_node->next = node->next;
++ node->next = new_ast_node;
+
+- rc = cil_gen_node(args->db, node, (struct cil_symtab_datum *) typeattr,
++ rc = cil_gen_node(args->db, new_ast_node, (struct cil_symtab_datum *) typeattr,
+ new_key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE);
+ if (rc != SEPOL_OK) {
+ goto exit;
+@@ -422,11 +426,6 @@ static int cil_attrib_typeattribute(struct cil_tree_node *node, struct version_a
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+- } else if (__cil_get_plat_flavor(args->vers_map, key) == PLAT_ATTRIB) {
+- // platform attribute declaration to be provided by platform policy
+- cil_symtab_datum_remove_node(&typeattr->datum, node);
+- cil_destroy_typeattribute(typeattr);
+- node->flavor = CIL_NONE; // traversal relies on this node sticking around, empty it.
+ }
+
+ return SEPOL_OK;
+--
+2.15.1
+
diff --git a/patches/platform_external_selinux/0003-libsepol-cil-Create-new-keep-field-for-type-attribut.patch b/patches/platform_external_selinux/0003-libsepol-cil-Create-new-keep-field-for-type-attribut.patch
new file mode 100644
index 0000000..86f94f1
--- /dev/null
+++ b/patches/platform_external_selinux/0003-libsepol-cil-Create-new-keep-field-for-type-attribut.patch
@@ -0,0 +1,138 @@
+From 92fac49b74a4d83bd07b086e35f3e7dfe84fd429 Mon Sep 17 00:00:00 2001
+From: James Carter <jwcart2@tycho.nsa.gov>
+Date: Fri, 17 Nov 2017 08:09:52 -0500
+Subject: [PATCH 3/5] libsepol/cil: Create new keep field for type attribute
+ sets
+
+Daniel Cashman <dcashman@android.com> discovered the following:
+When using cil_db multiple_decls, the different cil_attribute nodes
+all point to the same underlying cil_attribute struct. This leads
+to problems, though, when modifying the used value in the struct.
+__cil_post_db_attr() changes the value of the field to based on
+the output of cil_typeattribute_used(), for use later in
+cil_typeattribute_to_policydb and cil_typeattribute_to_bitmap, but
+due to the multiple declarations, cil_typeattribute_used() could be
+called again by a second node. In this second call, the value used
+is the modifed value of CIL_TRUE or CIL_FALSE, not the flags actually
+needed. This could result in the field being reset again, to an
+incorrect CIL_FALSE value.
+
+Add the field "keep" to struct cil_typeattributeset, set its value
+using cil_typeattribute_used(), and use it when determining whether
+the attribute is to be kept or if it should be expanded.
+
+Signed-off-by: James Carter <jwcart2@tycho.nsa.gov>
+---
+ libsepol/cil/src/cil.c | 1 +
+ libsepol/cil/src/cil_binary.c | 8 ++++----
+ libsepol/cil/src/cil_internal.h | 1 +
+ libsepol/cil/src/cil_policy.c | 2 +-
+ libsepol/cil/src/cil_post.c | 2 +-
+ libsepol/cil/src/cil_reset_ast.c | 1 +
+ 6 files changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
+index e8bbbfdf..a5a3e263 100644
+--- a/libsepol/cil/src/cil.c
++++ b/libsepol/cil/src/cil.c
+@@ -2038,6 +2038,7 @@ void cil_typeattribute_init(struct cil_typeattribute **attr)
+ (*attr)->expr_list = NULL;
+ (*attr)->types = NULL;
+ (*attr)->used = CIL_FALSE;
++ (*attr)->keep = CIL_FALSE;
+ }
+
+ void cil_typeattributeset_init(struct cil_typeattributeset **attrset)
+diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
+index e1481a43..1818ffa9 100644
+--- a/libsepol/cil/src/cil_binary.c
++++ b/libsepol/cil/src/cil_binary.c
+@@ -567,7 +567,7 @@ int cil_typeattribute_to_policydb(policydb_t *pdb, struct cil_typeattribute *cil
+ char *key = NULL;
+ type_datum_t *sepol_attr = NULL;
+
+- if (!cil_attr->used) {
++ if (!cil_attr->keep) {
+ return SEPOL_OK;
+ }
+
+@@ -632,7 +632,7 @@ int cil_typeattribute_to_bitmap(policydb_t *pdb, const struct cil_db *db, struct
+ ebitmap_node_t *tnode;
+ unsigned int i;
+
+- if (!cil_attr->used) {
++ if (!cil_attr->keep) {
+ return SEPOL_OK;
+ }
+
+@@ -1442,7 +1442,7 @@ static int __cil_should_expand_attribute( const struct cil_db *db, struct cil_sy
+
+ attr = (struct cil_typeattribute *)datum;
+
+- return !attr->used || (ebitmap_cardinality(attr->types) < db->attrs_expand_size);
++ return !attr->keep || (ebitmap_cardinality(attr->types) < db->attrs_expand_size);
+ }
+
+ int __cil_avrule_to_avtab(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrule, cond_node_t *cond_node, enum cil_flavor cond_flavor)
+@@ -2525,7 +2525,7 @@ int __cil_constrain_expr_datum_to_sepol_expr(policydb_t *pdb, const struct cil_d
+ if (rc != SEPOL_OK) {
+ if (FLAVOR(item->data) == CIL_TYPEATTRIBUTE) {
+ struct cil_typeattribute *attr = item->data;
+- if (!attr->used) {
++ if (!attr->keep) {
+ rc = 0;
+ }
+ }
+diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
+index abfacd8d..942b28f0 100644
+--- a/libsepol/cil/src/cil_internal.h
++++ b/libsepol/cil/src/cil_internal.h
+@@ -527,6 +527,7 @@ struct cil_typeattribute {
+ struct cil_list *expr_list;
+ ebitmap_t *types;
+ int used; // whether or not this attribute was used in a binary policy rule
++ int keep;
+ };
+
+ struct cil_typeattributeset {
+diff --git a/libsepol/cil/src/cil_policy.c b/libsepol/cil/src/cil_policy.c
+index 77179e63..3e511330 100644
+--- a/libsepol/cil/src/cil_policy.c
++++ b/libsepol/cil/src/cil_policy.c
+@@ -1085,7 +1085,7 @@ static void cil_typeattributes_to_policy(FILE *out, struct cil_list *types, stru
+ type = i1->data;
+ cil_list_for_each(i2, attributes) {
+ attribute = i2->data;
+- if (!attribute->used)
++ if (!attribute->keep)
+ continue;
+ if (ebitmap_get_bit(attribute->types, type->value)) {
+ if (first) {
+diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c
+index 1941fab3..a30de0e1 100644
+--- a/libsepol/cil/src/cil_post.c
++++ b/libsepol/cil/src/cil_post.c
+@@ -1250,7 +1250,7 @@ static int __cil_post_db_attr_helper(struct cil_tree_node *node, uint32_t *finis
+ rc = __evaluate_type_expression(attr, db);
+ if (rc != SEPOL_OK) goto exit;
+ }
+- attr->used = cil_typeattribute_used(attr, db);
++ attr->keep = cil_typeattribute_used(attr, db);
+ break;
+ }
+ case CIL_ROLEATTRIBUTE: {
+diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c
+index 676e156e..142179ee 100644
+--- a/libsepol/cil/src/cil_reset_ast.c
++++ b/libsepol/cil/src/cil_reset_ast.c
+@@ -186,6 +186,7 @@ static void cil_reset_typeattr(struct cil_typeattribute *attr)
+ attr->expr_list = NULL;
+ }
+ attr->used = CIL_FALSE;
++ attr->keep = CIL_FALSE;
+ }
+
+ static void cil_reset_typeattributeset(struct cil_typeattributeset *tas)
+--
+2.15.1
+
diff --git a/patches/platform_external_selinux/0004-Enable-multipl_decls-by-default.-This-is-needed-beca.patch b/patches/platform_external_selinux/0004-Enable-multipl_decls-by-default.-This-is-needed-beca.patch
new file mode 100644
index 0000000..edf02fa
--- /dev/null
+++ b/patches/platform_external_selinux/0004-Enable-multipl_decls-by-default.-This-is-needed-beca.patch
@@ -0,0 +1,27 @@
+From 6afcaac2da4ea0fad2e3aea4b579eddd02523e73 Mon Sep 17 00:00:00 2001
+From: Pierre-Hugues Husson <phh@phh.me>
+Date: Fri, 2 Mar 2018 22:49:55 +0100
+Subject: [PATCH 4/5] Enable multipl_decls by default. This is needed because
+ 8.0 init doesn't add -m
+
+Change-Id: I43dc661d519f7b8576d72a828d8cbd444592bf5e
+---
+ secilc/secilc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/secilc/secilc.c b/secilc/secilc.c
+index 0be6975b..e30572e5 100644
+--- a/secilc/secilc.c
++++ b/secilc/secilc.c
+@@ -90,7 +90,7 @@ int main(int argc, char *argv[])
+ int target = SEPOL_TARGET_SELINUX;
+ int mls = -1;
+ int disable_dontaudit = 0;
+- int multiple_decls = 0;
++ int multiple_decls = 1;
+ int disable_neverallow = 0;
+ int preserve_tunables = 0;
+ int handle_unknown = -1;
+--
+2.15.1
+
diff --git a/patches/platform_external_selinux/0005-Delete-identical-genfscon-s.patch b/patches/platform_external_selinux/0005-Delete-identical-genfscon-s.patch
new file mode 100644
index 0000000..bf664e1
--- /dev/null
+++ b/patches/platform_external_selinux/0005-Delete-identical-genfscon-s.patch
@@ -0,0 +1,42 @@
+From c334f823d0eccac2656ceceb707367680cca32f2 Mon Sep 17 00:00:00 2001
+From: Pierre-Hugues Husson <phh@phh.me>
+Date: Sat, 3 Mar 2018 19:02:29 +0100
+Subject: [PATCH 5/5] Delete identical genfscon-s
+
+Change-Id: I9775187b9da3568390ab66ebd59cb774b1283ad1
+---
+ libsepol/cil/src/cil_post.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c
+index a30de0e1..605847d1 100644
+--- a/libsepol/cil/src/cil_post.c
++++ b/libsepol/cil/src/cil_post.c
+@@ -53,6 +53,16 @@
+ static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db);
+ static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db);
+
++static int compact(void* array, int count, int len, int (*compar)(const void *, const void *)) {
++ char *a = (char*)array;
++ int j = 0;
++ for(int i=1; i<count; i++) {
++ if(compar(a+i*len, a+j*len) != 0) j++;
++ if(i != j) memcpy(a+j*len, a+i*len, len);
++ }
++ return j;
++}
++
+ static int cil_verify_is_list(struct cil_list *list, enum cil_flavor flavor)
+ {
+ struct cil_list_item *curr;
+@@ -1977,6 +1987,7 @@ static int cil_post_db(struct cil_db *db)
+
+ qsort(db->netifcon->array, db->netifcon->count, sizeof(db->netifcon->array), cil_post_netifcon_compare);
+ qsort(db->genfscon->array, db->genfscon->count, sizeof(db->genfscon->array), cil_post_genfscon_compare);
++ db->genfscon->count = compact(db->genfscon->array, db->genfscon->count, sizeof(db->genfscon->array), cil_post_genfscon_compare);
+ qsort(db->portcon->array, db->portcon->count, sizeof(db->portcon->array), cil_post_portcon_compare);
+ qsort(db->nodecon->array, db->nodecon->count, sizeof(db->nodecon->array), cil_post_nodecon_compare);
+ qsort(db->fsuse->array, db->fsuse->count, sizeof(db->fsuse->array), cil_post_fsuse_compare);
+--
+2.15.1
+