From 1b0d1244a763a1b0e323bd81c07ec3042c23d905 Mon Sep 17 00:00:00 2001 From: Petr Lautrbach Date: Mon, 21 Nov 2022 11:26:09 +0100 Subject: [PATCH] libsepol-3.4-4 Rebase on upstream f56a72ac9e86 --- 0001-libsepol-Drop-unused-assignment.patch | 30 + ...idation-of-user-declarations-in-modu.patch | 76 ++ ...otential-NULL-dereference-on-optiona.patch | 36 + ...ize-s-in-constraint_expr_eval_reason.patch | 37 + 0005-libsepol-utils-improve-wording.patch | 38 + ...ol-do-not-modify-policy-during-write.patch | 53 + 0007-libsepol-break-circular-include.patch | 44 + ...include-necessary-headers-in-headers.patch | 49 + ...-macro-parameters-and-replacement-li.patch | 117 ++ 0010-libsepol-tests-add-ebitmap-tests.patch | 1114 +++++++++++++++++ 0011-libsepol-add-ebitmap_init_range.patch | 146 +++ ...-libsepol-cil-use-ebitmap_init_range.patch | 107 ++ 0013-libsepol-optimize-ebitmap_not.patch | 82 ++ 0014-libsepol-optimize-ebitmap_and.patch | 76 ++ 0015-libsepol-optimize-ebitmap_xor.patch | 83 ++ ...perfluous-memset-calls-in-ebitmap-op.patch | 51 + ...validate_policydb-to-policydb_valida.patch | 62 + ...t-const-avtab_t-pointer-in-avtab_map.patch | 52 + ...-on-const-pointers-during-validation.patch | 486 +++++++ 0020-libsepol-rename-parameter-name.patch | 59 + 0021-libsepol-more-strict-validation.patch | 519 ++++++++ ...efactor-ebitmap-conversion-in-link.c.patch | 312 +++++ ...sing-double-quotes-in-typetransition.patch | 34 + ...ocs-provide-a-top-level-LICENSE-file.patch | 26 + ...tore-error-on-context-rule-conflicts.patch | 51 + libsepol.spec | 32 +- 26 files changed, 3770 insertions(+), 2 deletions(-) create mode 100644 0001-libsepol-Drop-unused-assignment.patch create mode 100644 0002-libsepol-fix-validation-of-user-declarations-in-modu.patch create mode 100644 0003-libsepol-avoid-potential-NULL-dereference-on-optiona.patch create mode 100644 0004-libsepol-initialize-s-in-constraint_expr_eval_reason.patch create mode 100644 0005-libsepol-utils-improve-wording.patch create mode 100644 0006-libsepol-do-not-modify-policy-during-write.patch create mode 100644 0007-libsepol-break-circular-include.patch create mode 100644 0008-libsepol-include-necessary-headers-in-headers.patch create mode 100644 0009-libsepol-enclose-macro-parameters-and-replacement-li.patch create mode 100644 0010-libsepol-tests-add-ebitmap-tests.patch create mode 100644 0011-libsepol-add-ebitmap_init_range.patch create mode 100644 0012-libsepol-cil-use-ebitmap_init_range.patch create mode 100644 0013-libsepol-optimize-ebitmap_not.patch create mode 100644 0014-libsepol-optimize-ebitmap_and.patch create mode 100644 0015-libsepol-optimize-ebitmap_xor.patch create mode 100644 0016-libsepol-skip-superfluous-memset-calls-in-ebitmap-op.patch create mode 100644 0017-libsepol-rename-validate_policydb-to-policydb_valida.patch create mode 100644 0018-libsepol-support-const-avtab_t-pointer-in-avtab_map.patch create mode 100644 0019-libsepol-operate-on-const-pointers-during-validation.patch create mode 100644 0020-libsepol-rename-parameter-name.patch create mode 100644 0021-libsepol-more-strict-validation.patch create mode 100644 0022-libsepol-refactor-ebitmap-conversion-in-link.c.patch create mode 100644 0023-libsepol-fix-missing-double-quotes-in-typetransition.patch create mode 100644 0024-docs-provide-a-top-level-LICENSE-file.patch create mode 100644 0025-libsepol-cil-restore-error-on-context-rule-conflicts.patch diff --git a/0001-libsepol-Drop-unused-assignment.patch b/0001-libsepol-Drop-unused-assignment.patch new file mode 100644 index 0000000..02fa647 --- /dev/null +++ b/0001-libsepol-Drop-unused-assignment.patch @@ -0,0 +1,30 @@ +From 3f23f07f01d3617d96519dd3c08e53b6bf65fe8c Mon Sep 17 00:00:00 2001 +From: Petr Lautrbach +Date: Tue, 7 Jun 2022 13:55:57 +0200 +Subject: [PATCH] libsepol: Drop unused assignment +Content-type: text/plain + +Fixes: +cil/src/cil_build_ast.c:4622:4: warning[deadcode.DeadStores]: Value stored to 'rc' is never read + +Signed-off-by: Petr Lautrbach +Acked-by: James Carter +--- + libsepol/cil/src/cil_build_ast.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c +index 26fa79069b96..4177c9f6778c 100644 +--- a/libsepol/cil/src/cil_build_ast.c ++++ b/libsepol/cil/src/cil_build_ast.c +@@ -4619,7 +4619,6 @@ int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, str + } else { + cil_log(CIL_ERR, "Invalid file type \"%s\"\n", file_type); + } +- rc = SEPOL_ERR; + goto exit; + } + context_node = parse_current->next->next->next->next; +-- +2.38.1 + diff --git a/0002-libsepol-fix-validation-of-user-declarations-in-modu.patch b/0002-libsepol-fix-validation-of-user-declarations-in-modu.patch new file mode 100644 index 0000000..60293fa --- /dev/null +++ b/0002-libsepol-fix-validation-of-user-declarations-in-modu.patch @@ -0,0 +1,76 @@ +From 88a703399f3f44be2502fd4ecd22ac3d3c560694 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 7 Jun 2022 17:01:45 +0200 +Subject: [PATCH] libsepol: fix validation of user declarations in modules +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Users are allowed to be declared in modules. Modules do not get expanded +leaving the `struct user_datum` members `exp_range` and `exp_dfltlevel` +empty. +Do no validate the expanded range and level for modular polices. + +Reported-by: bauen1 +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/policydb_validate.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index da18282bafc8..99d4eb7f670e 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -18,7 +18,7 @@ typedef struct validate { + typedef struct map_arg { + validate_t *flavors; + sepol_handle_t *handle; +- int mls; ++ policydb_t *policy; + } map_arg_t; + + static int create_gap_ebitmap(char **val_to_name, uint32_t nprim, ebitmap_t *gaps) +@@ -571,7 +571,7 @@ static int validate_mls_range(mls_range_t *range, validate_t *sens, validate_t * + return -1; + } + +-static int validate_user_datum(sepol_handle_t *handle, user_datum_t *user, validate_t flavors[], int mls) ++static int validate_user_datum(sepol_handle_t *handle, user_datum_t *user, validate_t flavors[], policydb_t *p) + { + if (validate_value(user->s.value, &flavors[SYM_USERS])) + goto bad; +@@ -581,9 +581,9 @@ static int validate_user_datum(sepol_handle_t *handle, user_datum_t *user, valid + goto bad; + if (validate_mls_semantic_level(&user->dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) + goto bad; +- if (mls && validate_mls_range(&user->exp_range, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) ++ if (p->mls && p->policy_type != POLICY_MOD && validate_mls_range(&user->exp_range, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) + goto bad; +- if (mls && validate_mls_level(&user->exp_dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) ++ if (p->mls && p->policy_type != POLICY_MOD && validate_mls_level(&user->exp_dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) + goto bad; + if (user->bounds && validate_value(user->bounds, &flavors[SYM_USERS])) + goto bad; +@@ -599,7 +599,7 @@ static int validate_user_datum_wrapper(__attribute__((unused)) hashtab_key_t k, + { + map_arg_t *margs = args; + +- return validate_user_datum(margs->handle, d, margs->flavors, margs->mls); ++ return validate_user_datum(margs->handle, d, margs->flavors, margs->policy); + } + + static int validate_bool_datum(sepol_handle_t *handle, cond_bool_datum_t *boolean, validate_t flavors[]) +@@ -689,7 +689,7 @@ static int validate_datum(__attribute__ ((unused))hashtab_key_t k, hashtab_datum + + static int validate_datum_array_entries(sepol_handle_t *handle, policydb_t *p, validate_t flavors[]) + { +- map_arg_t margs = { flavors, handle, p->mls }; ++ map_arg_t margs = { flavors, handle, p }; + + if (hashtab_map(p->p_commons.table, validate_common_datum_wrapper, &margs)) + goto bad; +-- +2.38.1 + diff --git a/0003-libsepol-avoid-potential-NULL-dereference-on-optiona.patch b/0003-libsepol-avoid-potential-NULL-dereference-on-optiona.patch new file mode 100644 index 0000000..b13596a --- /dev/null +++ b/0003-libsepol-avoid-potential-NULL-dereference-on-optiona.patch @@ -0,0 +1,36 @@ +From f505a73b06302ba5e84f8c56851121d4a410c1ea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Fri, 10 Jun 2022 17:06:23 +0200 +Subject: [PATCH] libsepol: avoid potential NULL dereference on optional + parameter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +The parameter `reason` of `context_struct_compute_av()` is optional and +can be passed in as NULL, like from `type_attribute_bounds_av()`. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/services.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/libsepol/src/services.c b/libsepol/src/services.c +index d7510e9dae51..24412d8372d8 100644 +--- a/libsepol/src/services.c ++++ b/libsepol/src/services.c +@@ -894,7 +894,8 @@ static void type_attribute_bounds_av(context_struct_t *scontext, + /* mask violated permissions */ + avd->allowed &= ~masked; + +- *reason |= SEPOL_COMPUTEAV_BOUNDS; ++ if (reason) ++ *reason |= SEPOL_COMPUTEAV_BOUNDS; + } + + /* +-- +2.38.1 + diff --git a/0004-libsepol-initialize-s-in-constraint_expr_eval_reason.patch b/0004-libsepol-initialize-s-in-constraint_expr_eval_reason.patch new file mode 100644 index 0000000..8f645d1 --- /dev/null +++ b/0004-libsepol-initialize-s-in-constraint_expr_eval_reason.patch @@ -0,0 +1,37 @@ +From d2fecbb97b79875fe4b135a45206413a77469a27 Mon Sep 17 00:00:00 2001 +From: Nicolas Iooss +Date: Wed, 29 Jun 2022 09:20:55 +0200 +Subject: [PATCH] libsepol: initialize s in constraint_expr_eval_reason +Content-type: text/plain + +clang's static analyzer reports that s[0] can be uninitialized when used +in: + + sprintf(tmp_buf, "%s %s\n", + xcontext ? "Validatetrans" : "Constraint", + s[0] ? "GRANTED" : "DENIED"); + +Silence this false-positive issue by making s always initialized. + +Signed-off-by: Nicolas Iooss +Acked-by: James Carter +--- + libsepol/src/services.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsepol/src/services.c b/libsepol/src/services.c +index 24412d8372d8..062510ab0ea1 100644 +--- a/libsepol/src/services.c ++++ b/libsepol/src/services.c +@@ -394,7 +394,7 @@ static int constraint_expr_eval_reason(context_struct_t *scontext, + role_datum_t *r1, *r2; + mls_level_t *l1, *l2; + constraint_expr_t *e; +- int s[CEXPR_MAXDEPTH]; ++ int s[CEXPR_MAXDEPTH] = {}; + int sp = -1; + char tmp_buf[128]; + +-- +2.38.1 + diff --git a/0005-libsepol-utils-improve-wording.patch b/0005-libsepol-utils-improve-wording.patch new file mode 100644 index 0000000..9bdfee3 --- /dev/null +++ b/0005-libsepol-utils-improve-wording.patch @@ -0,0 +1,38 @@ +From 36bf1be1cab5f1be258cd32882e85335b3301355 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 29 Jun 2022 13:05:12 +0200 +Subject: [PATCH] libsepol/utils: improve wording +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +A request is denied with SEPOL_COMPUTEAV_RBAC if the source role is not +allowed to transition to the target role, granted via a + + allow source_role target_role; + +statement. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/utils/sepol_check_access.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsepol/utils/sepol_check_access.c b/libsepol/utils/sepol_check_access.c +index bd2ea89600f3..5d2bf6794c8b 100644 +--- a/libsepol/utils/sepol_check_access.c ++++ b/libsepol/utils/sepol_check_access.c +@@ -109,7 +109,7 @@ int main(int argc, char *argv[]) + if (reason & SEPOL_COMPUTEAV_RBAC) { + if (i > 0) + printf(", "); +- printf("transition-constraint"); ++ printf("role-transition"); + i++; + } + if (reason & SEPOL_COMPUTEAV_BOUNDS) { +-- +2.38.1 + diff --git a/0006-libsepol-do-not-modify-policy-during-write.patch b/0006-libsepol-do-not-modify-policy-during-write.patch new file mode 100644 index 0000000..9eaf7e2 --- /dev/null +++ b/0006-libsepol-do-not-modify-policy-during-write.patch @@ -0,0 +1,53 @@ +From 2651989d3b94dd15459fbef4384f114b24850665 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 30 Jun 2022 19:03:01 +0200 +Subject: [PATCH] libsepol: do not modify policy during write +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Do not modify the in memory default_range value of a class datum while +writing a policy. + +While on it fix indentation. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/write.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/libsepol/src/write.c b/libsepol/src/write.c +index 48ed21ea683a..a9fdf93a8ee1 100644 +--- a/libsepol/src/write.c ++++ b/libsepol/src/write.c +@@ -1097,16 +1097,18 @@ static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) + p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) || + (p->policy_type == POLICY_BASE && + p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) { ++ char default_range = cladatum->default_range; ++ + buf[0] = cpu_to_le32(cladatum->default_user); + buf[1] = cpu_to_le32(cladatum->default_role); +- if (!glblub_version && cladatum->default_range == DEFAULT_GLBLUB) { ++ if (!glblub_version && default_range == DEFAULT_GLBLUB) { + WARN(fp->handle, +- "class %s default_range set to GLBLUB but policy version is %d (%d required), discarding", +- p->p_class_val_to_name[cladatum->s.value - 1], p->policyvers, +- p->policy_type == POLICY_KERN? POLICYDB_VERSION_GLBLUB:MOD_POLICYDB_VERSION_GLBLUB); +- cladatum->default_range = 0; +- } +- buf[2] = cpu_to_le32(cladatum->default_range); ++ "class %s default_range set to GLBLUB but policy version is %d (%d required), discarding", ++ p->p_class_val_to_name[cladatum->s.value - 1], p->policyvers, ++ p->policy_type == POLICY_KERN? POLICYDB_VERSION_GLBLUB:MOD_POLICYDB_VERSION_GLBLUB); ++ default_range = 0; ++ } ++ buf[2] = cpu_to_le32(default_range); + items = put_entry(buf, sizeof(uint32_t), 3, fp); + if (items != 3) + return POLICYDB_ERROR; +-- +2.38.1 + diff --git a/0007-libsepol-break-circular-include.patch b/0007-libsepol-break-circular-include.patch new file mode 100644 index 0000000..53975a8 --- /dev/null +++ b/0007-libsepol-break-circular-include.patch @@ -0,0 +1,44 @@ +From 12beafe7ce512283cea177469fec08742482e48a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 13 Jul 2022 15:43:41 +0200 +Subject: [PATCH] libsepol: break circular include +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Since `struct type_set` is forward declared including +policydb/policydb.h is not necessary and creates a circular include. + +Also drop the unnecessary forward declaration of `struct policydb`. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/include/sepol/policydb/constraint.h | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/libsepol/include/sepol/policydb/constraint.h b/libsepol/include/sepol/policydb/constraint.h +index b91fc4e9f2fb..82335e2192ad 100644 +--- a/libsepol/include/sepol/policydb/constraint.h ++++ b/libsepol/include/sepol/policydb/constraint.h +@@ -18,7 +18,6 @@ + #ifndef _SEPOL_POLICYDB_CONSTRAINT_H_ + #define _SEPOL_POLICYDB_CONSTRAINT_H_ + +-#include + #include + #include + +@@ -70,8 +69,6 @@ typedef struct constraint_node { + struct constraint_node *next; /* next constraint */ + } constraint_node_t; + +-struct policydb; +- + extern int constraint_expr_init(constraint_expr_t * expr); + extern void constraint_expr_destroy(constraint_expr_t * expr); + +-- +2.38.1 + diff --git a/0008-libsepol-include-necessary-headers-in-headers.patch b/0008-libsepol-include-necessary-headers-in-headers.patch new file mode 100644 index 0000000..f29a174 --- /dev/null +++ b/0008-libsepol-include-necessary-headers-in-headers.patch @@ -0,0 +1,49 @@ +From 85e73a22ff0165f3bb577ca671d5b2ae21f6b282 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 13 Jul 2022 15:43:42 +0200 +Subject: [PATCH] libsepol: include necessary headers in headers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Include policydb header file required for typedef policydb_t. + +This is for example helpful when working with an IDE, which needs to +resolve those symbols. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/include/sepol/policydb/util.h | 2 ++ + libsepol/src/mls.h | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/libsepol/include/sepol/policydb/util.h b/libsepol/include/sepol/policydb/util.h +index ee236a25fafe..db8da213f89f 100644 +--- a/libsepol/include/sepol/policydb/util.h ++++ b/libsepol/include/sepol/policydb/util.h +@@ -23,6 +23,8 @@ + #ifndef __SEPOL_UTIL_H__ + #define __SEPOL_UTIL_H__ + ++#include ++ + #ifdef __cplusplus + extern "C" { + #endif +diff --git a/libsepol/src/mls.h b/libsepol/src/mls.h +index eb4a1cb8b522..befd12c5ed05 100644 +--- a/libsepol/src/mls.h ++++ b/libsepol/src/mls.h +@@ -25,6 +25,7 @@ + + #include "policydb_internal.h" + #include ++#include + #include "handle.h" + + extern int mls_from_string(sepol_handle_t * handle, +-- +2.38.1 + diff --git a/0009-libsepol-enclose-macro-parameters-and-replacement-li.patch b/0009-libsepol-enclose-macro-parameters-and-replacement-li.patch new file mode 100644 index 0000000..b637ae3 --- /dev/null +++ b/0009-libsepol-enclose-macro-parameters-and-replacement-li.patch @@ -0,0 +1,117 @@ +From 65b3f695be306ad8f525d4db2befd55336bd0a09 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 13 Jul 2022 15:43:43 +0200 +Subject: [PATCH] libsepol: enclose macro parameters and replacement lists in + parentheses +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/include/sepol/errcodes.h | 13 ++++++------- + libsepol/include/sepol/policydb/policydb.h | 10 +++++----- + libsepol/src/kernel_to_cil.c | 2 +- + libsepol/src/module_to_cil.c | 2 +- + libsepol/src/util.c | 2 +- + 5 files changed, 14 insertions(+), 15 deletions(-) + +diff --git a/libsepol/include/sepol/errcodes.h b/libsepol/include/sepol/errcodes.h +index 6e9ff3161eec..e5fe71e36590 100644 +--- a/libsepol/include/sepol/errcodes.h ++++ b/libsepol/include/sepol/errcodes.h +@@ -16,15 +16,14 @@ extern "C" { + * codes that don't map to system error codes should be defined + * outside of the range of system error codes. + */ +-#define SEPOL_ERR -1 +-#define SEPOL_ENOTSUP -2 /* feature not supported in module language */ +-#define SEPOL_EREQ -3 /* requirements not met */ ++#define SEPOL_ERR (-1) ++#define SEPOL_ENOTSUP (-2) /* feature not supported in module language */ ++#define SEPOL_EREQ (-3) /* requirements not met */ + + /* Error codes that map to system error codes */ +-#define SEPOL_ENOMEM -ENOMEM +-#define SEPOL_ERANGE -ERANGE +-#define SEPOL_EEXIST -EEXIST +-#define SEPOL_ENOENT -ENOENT ++#define SEPOL_ENOMEM (-ENOMEM) ++#define SEPOL_EEXIST (-EEXIST) ++#define SEPOL_ENOENT (-ENOENT) + + #ifdef __cplusplus + } +diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h +index de0068a6c6f2..ef1a014a5130 100644 +--- a/libsepol/include/sepol/policydb/policydb.h ++++ b/libsepol/include/sepol/policydb/policydb.h +@@ -251,9 +251,9 @@ typedef struct class_perm_node { + struct class_perm_node *next; + } class_perm_node_t; + +-#define xperm_test(x, p) (UINT32_C(1) & (p[x >> 5] >> (x & 0x1f))) +-#define xperm_set(x, p) (p[x >> 5] |= (UINT32_C(1) << (x & 0x1f))) +-#define xperm_clear(x, p) (p[x >> 5] &= ~(UINT32_C(1) << (x & 0x1f))) ++#define xperm_test(x, p) (UINT32_C(1) & ((p)[(x) >> 5] >> ((x) & 0x1f))) ++#define xperm_set(x, p) ((p)[(x) >> 5] |= (UINT32_C(1) << ((x) & 0x1f))) ++#define xperm_clear(x, p) ((p)[(x) >> 5] &= ~(UINT32_C(1) << ((x) & 0x1f))) + #define EXTENDED_PERMS_LEN 8 + + typedef struct av_extended_perms { +@@ -795,9 +795,9 @@ extern int policydb_set_target_platform(policydb_t *p, int platform); + + #define policydb_has_boundary_feature(p) \ + (((p)->policy_type == POLICY_KERN \ +- && p->policyvers >= POLICYDB_VERSION_BOUNDARY) || \ ++ && (p)->policyvers >= POLICYDB_VERSION_BOUNDARY) || \ + ((p)->policy_type != POLICY_KERN \ +- && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY)) ++ && (p)->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY)) + + /* the config flags related to unknown classes/perms are bits 2 and 3 */ + #define DENY_UNKNOWN SEPOL_DENY_UNKNOWN +diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c +index 9128ac553315..5a1336a33031 100644 +--- a/libsepol/src/kernel_to_cil.c ++++ b/libsepol/src/kernel_to_cil.c +@@ -1626,7 +1626,7 @@ exit: + return rc; + } + +-#define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p)) ++#define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p)) + + static char *xperms_to_str(avtab_extended_perms_t *xperms) + { +diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c +index b35bf055f073..b900290a7e9c 100644 +--- a/libsepol/src/module_to_cil.c ++++ b/libsepol/src/module_to_cil.c +@@ -624,7 +624,7 @@ exit: + return rc; + } + +-#define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p)) ++#define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p)) + + static int xperms_to_cil(const av_extended_perms_t *xperms) + { +diff --git a/libsepol/src/util.c b/libsepol/src/util.c +index 1cd1308d1687..0a2edc852b45 100644 +--- a/libsepol/src/util.c ++++ b/libsepol/src/util.c +@@ -124,7 +124,7 @@ char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, + return avbuf; + } + +-#define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p)) ++#define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p)) + + char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms) + { +-- +2.38.1 + diff --git a/0010-libsepol-tests-add-ebitmap-tests.patch b/0010-libsepol-tests-add-ebitmap-tests.patch new file mode 100644 index 0000000..126954e --- /dev/null +++ b/0010-libsepol-tests-add-ebitmap-tests.patch @@ -0,0 +1,1114 @@ +From 490cd409e3ac020d02716fc4b4ff3a9b66b64e87 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 19 Jul 2022 17:30:38 +0200 +Subject: [PATCH] libsepol/tests: add ebitmap tests +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Preparation for several ebitmap related optimizations. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/tests/libsepol-tests.c | 2 + + libsepol/tests/test-ebitmap.c | 1048 +++++++++++++++++++++++++++++++ + libsepol/tests/test-ebitmap.h | 10 + + 3 files changed, 1060 insertions(+) + create mode 100644 libsepol/tests/test-ebitmap.c + create mode 100644 libsepol/tests/test-ebitmap.h + +diff --git a/libsepol/tests/libsepol-tests.c b/libsepol/tests/libsepol-tests.c +index dc8fd5ce5f6c..5ae6bedc7db0 100644 +--- a/libsepol/tests/libsepol-tests.c ++++ b/libsepol/tests/libsepol-tests.c +@@ -19,6 +19,7 @@ + */ + + #include "test-cond.h" ++#include "test-ebitmap.h" + #include "test-linker.h" + #include "test-expander.h" + #include "test-deps.h" +@@ -64,6 +65,7 @@ static bool do_tests(int interactive, int verbose) + if (CUE_SUCCESS != CU_initialize_registry()) + return CU_get_error(); + ++ DECLARE_SUITE(ebitmap); + DECLARE_SUITE(cond); + DECLARE_SUITE(linker); + DECLARE_SUITE(expander); +diff --git a/libsepol/tests/test-ebitmap.c b/libsepol/tests/test-ebitmap.c +new file mode 100644 +index 000000000000..fad5bd7561e3 +--- /dev/null ++++ b/libsepol/tests/test-ebitmap.c +@@ -0,0 +1,1048 @@ ++#include "test-ebitmap.h" ++ ++#include ++#include ++ ++#include ++#include ++ ++#define RANDOM_ROUNDS 10 ++ ++ ++static int ebitmap_init_random(ebitmap_t *e, unsigned int length, int set_chance) ++{ ++ unsigned int i; ++ int rc; ++ ++ if (set_chance <= 0 || set_chance > 100) ++ return -EINVAL; ++ ++ ebitmap_init(e); ++ ++ for (i = 0; i < length; i++) { ++ if ((random() % 100) < set_chance) { ++ rc = ebitmap_set_bit(e, i, 1); ++ if (rc) ++ return rc; ++ } ++ } ++ ++ return 0; ++} ++ ++static void test_ebitmap_init_destroy(void) ++{ ++ ebitmap_t e; ++ ++ /* verify idempotence */ ++ ebitmap_init(&e); ++ ebitmap_init(&e); ++ ebitmap_init(&e); ++ ++ CU_ASSERT(ebitmap_is_empty(&e)); ++ CU_ASSERT_PTR_NULL(ebitmap_startnode(&e)); ++ ++ /* verify idempotence */ ++ ebitmap_destroy(&e); ++ ebitmap_destroy(&e); ++ ebitmap_destroy(&e); ++ ++ CU_ASSERT(ebitmap_is_empty(&e)); ++ CU_ASSERT_PTR_NULL(ebitmap_startnode(&e)); ++} ++ ++static void test_ebitmap_cmp(void) ++{ ++ ebitmap_t e1, e2; ++ ++ ebitmap_init(&e1); ++ ebitmap_init(&e2); ++ ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 10, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 63, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 63, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 64, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 64, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1022, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1022, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1023, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1023, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1024, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1024, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1025, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1025, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 255, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 255, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 256, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 256, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 639, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 639, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 640, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 640, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 900, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 900, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++ ++ ebitmap_destroy(&e2); ++ ++ CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ++ ++ ebitmap_destroy(&e1); ++ ++ CU_ASSERT(ebitmap_cmp(&e1, &e2)); ++} ++ ++static void test_ebitmap_set_and_get(void) ++{ ++ ebitmap_t e; ++ ++ ebitmap_init(&e); ++ ++ CU_ASSERT(ebitmap_is_empty(&e)); ++ CU_ASSERT_TRUE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 0); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 0); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 10), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, UINT32_MAX, 1), -EINVAL); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 10, 0), 0); ++ CU_ASSERT(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 0); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 0); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 10), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 10, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 1); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 10); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 10), 1); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 100, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 2); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 100); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 100), 1); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 50, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 3); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 100); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 50), 1); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1023, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 4); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1023), 1); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1024, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 5); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1024); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1024), 1); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1050, 1), 0); ++ CU_ASSERT_FALSE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 6); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1050); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1050), 1); ++ ++ { ++ ebitmap_node_t *n; ++ unsigned int bit, count; ++ ++ /* iterate all allocated bits */ ++ count = 0; ++ ebitmap_for_each_bit(&e, n, bit) { ++ CU_ASSERT( bit < 64 || ++ (64 <= bit && bit < 128) || ++ (960 <= bit && bit < 1024) || ++ (1024 <= bit && bit < 1088)); ++ count++; ++ } ++ CU_ASSERT_EQUAL(count, 4 * 64); ++ ++ count = 0; ++ ebitmap_for_each_positive_bit(&e, n, bit) { ++ CU_ASSERT(bit == 10 || ++ bit == 50 || ++ bit == 100 || ++ bit == 1023 || ++ bit == 1024 || ++ bit == 1050); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, bit), 1); ++ count++; ++ } ++ CU_ASSERT_EQUAL(count, 6); ++ } ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1024, 0), 0); ++ CU_ASSERT_FALSE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 5); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1050); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1024), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1050, 0), 0); ++ CU_ASSERT_FALSE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 4); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1050), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 100, 0), 0); ++ CU_ASSERT_FALSE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 3); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 100), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 10, 0), 0); ++ CU_ASSERT_FALSE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 2); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 10), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 50, 0), 0); ++ CU_ASSERT_FALSE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 1); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 50), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1023, 0), 0); ++ CU_ASSERT_TRUE(ebitmap_is_empty(&e)); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 0); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 0); ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1023), 0); ++ ++ ebitmap_destroy(&e); ++} ++ ++static void test_ebitmap_or(void) ++{ ++ ebitmap_t e1, e2, e3, e4; ++ ++ ebitmap_init(&e1); ++ ebitmap_init(&e2); ++ ebitmap_init(&e3); ++ ebitmap_init(&e4); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 100, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 101, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 318, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 319, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 383, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 384, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 449, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1013, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 11, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 101, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 430, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 665, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 10, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 11, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 100, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 101, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 318, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 319, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 383, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 384, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 430, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 449, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 665, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 1013, 1), 0); ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_or(&dst, &e1, &e1), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e1)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_or(&dst, &e2, &e2), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e2)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_or(&dst, &e1, &e2), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e3)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_or(&dst, &e3, &e3), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e3)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_or(&dst, &e3, &e4), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e3)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_or(&dst, &e4, &e4), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e4)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ ebitmap_destroy(&e4); ++ ebitmap_destroy(&e3); ++ ebitmap_destroy(&e2); ++ ebitmap_destroy(&e1); ++} ++ ++static void test_ebitmap_and(void) ++{ ++ { ++ ebitmap_t e1, e2, e12, e3, e4; ++ ++ ebitmap_init(&e1); ++ ebitmap_init(&e2); ++ ebitmap_init(&e12); ++ ebitmap_init(&e3); ++ ebitmap_init(&e4); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 100, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 101, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 318, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 319, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 383, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 384, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 449, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1013, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 11, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 101, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 319, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 665, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 101, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 319, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 10, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 11, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 100, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 101, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 318, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 319, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 383, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 384, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 430, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 449, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 665, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 1013, 1), 0); ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_and(&dst, &e1, &e1), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e1)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_and(&dst, &e2, &e2), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e2)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_and(&dst, &e1, &e2), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e12)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_and(&dst, &e3, &e3), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e3)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_and(&dst, &e1, &e3), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e1)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_and(&dst, &e2, &e3), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e2)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_and(&dst, &e4, &e4), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e4)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_and(&dst, &e3, &e4), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e4)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ ebitmap_destroy(&e4); ++ ebitmap_destroy(&e3); ++ ebitmap_destroy(&e12); ++ ebitmap_destroy(&e2); ++ ebitmap_destroy(&e1); ++ } ++ ++ { ++ ebitmap_t e5; ++ ebitmap_t e6; ++ ebitmap_t e56; ++ ebitmap_t dst; ++ ++ ebitmap_init(&e5); ++ ebitmap_init(&e6); ++ ebitmap_init(&e56); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 63, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 191, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 192, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 318, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 319, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 64, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 192, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 319, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 320, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 192, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 319, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_and(&dst, &e5, &e6), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e56)); ++ ++ ebitmap_destroy(&dst); ++ ebitmap_destroy(&e56); ++ ebitmap_destroy(&e6); ++ ebitmap_destroy(&e5); ++ } ++} ++ ++static void test_ebitmap_xor(void) ++{ ++ { ++ ebitmap_t e1, e2, e3, e4; ++ ++ ebitmap_init(&e1); ++ ebitmap_init(&e2); ++ ebitmap_init(&e3); ++ ebitmap_init(&e4); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 5, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 3, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 6, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 9, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 3, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 5, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 6, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 9, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 10, 1), 0); ++ ++ { ++ ebitmap_t dst1, dst2; ++ ++ CU_ASSERT_EQUAL(ebitmap_xor(&dst1, &e1, &e1), 0); ++ CU_ASSERT(ebitmap_cmp(&dst1, &e4)); ++ CU_ASSERT_EQUAL(ebitmap_xor(&dst2, &dst1, &e1), 0); ++ CU_ASSERT(ebitmap_cmp(&dst2, &e1)); ++ ++ ebitmap_destroy(&dst2); ++ ebitmap_destroy(&dst1); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e2, &e2), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e4)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e3, &e3), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e4)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e4, &e4), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e4)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e1, &e2), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e3)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e2, &e4), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e2)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ ebitmap_destroy(&e4); ++ ebitmap_destroy(&e3); ++ ebitmap_destroy(&e2); ++ ebitmap_destroy(&e1); ++ } ++ ++ { ++ ebitmap_t e5; ++ ebitmap_t e6; ++ ebitmap_t e56; ++ ebitmap_t dst; ++ ++ ebitmap_init(&e5); ++ ebitmap_init(&e6); ++ ebitmap_init(&e56); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 63, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 191, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 192, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 318, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 319, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 64, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 192, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 319, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 320, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 63, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 64, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 191, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 318, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 320, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e5, &e6), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e56)); ++ ++ ebitmap_destroy(&dst); ++ ebitmap_destroy(&e56); ++ ebitmap_destroy(&e6); ++ ebitmap_destroy(&e5); ++ } ++} ++ ++static void test_ebitmap_not(void) ++{ ++ { ++ ebitmap_t e1, e2, e3, e4; ++ ++ ebitmap_init(&e1); ++ ebitmap_init(&e2); ++ ebitmap_init(&e3); ++ ebitmap_init(&e4); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 0, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 5, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 2, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 3, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 4, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 6, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 7, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 8, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 9, 1), 0); ++ ++ { ++ ebitmap_t dst1, dst2; ++ ++ CU_ASSERT_EQUAL(ebitmap_not(&dst1, &e3, 10), 0); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&dst1), 9); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&dst1), 10); ++ ++ CU_ASSERT_EQUAL(ebitmap_not(&dst2, &dst1, 10), 0); ++ CU_ASSERT(ebitmap_cmp(&dst2, &e3)); ++ ++ ebitmap_destroy(&dst2); ++ ebitmap_destroy(&dst1); ++ } ++ ++ { ++ ebitmap_t dst1, dst2; ++ ++ CU_ASSERT_EQUAL(ebitmap_not(&dst1, &e1, 11), 0); ++ CU_ASSERT(ebitmap_cmp(&dst1, &e2)); ++ CU_ASSERT_EQUAL(ebitmap_not(&dst2, &dst1, 11), 0); ++ CU_ASSERT(ebitmap_cmp(&dst2, &e1)); ++ ++ ebitmap_destroy(&dst2); ++ ebitmap_destroy(&dst1); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_not(&dst, &e1, 8), 0); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&dst), 7); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&dst), 5); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_not(&dst, &e1, 12), 0); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&dst), 11); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&dst), 8); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ ebitmap_destroy(&e3); ++ ebitmap_destroy(&e2); ++ ebitmap_destroy(&e1); ++ } ++ ++ { ++ ebitmap_t e5; ++ ebitmap_t e5not; ++ ebitmap_node_t *n; ++ unsigned int bit; ++ ++ ebitmap_init(&e5); ++ ebitmap_init(&e5not); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 63, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 191, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 192, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 318, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 319, 1), 0); ++ ++ for (bit = 0; bit < 317; bit++) ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5not, bit, 1), 0); ++ ebitmap_for_each_positive_bit(&e5, n, bit) ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5not, bit, 0), 0); ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_not(&dst, &e5, 317), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e5not)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_not(&dst, &e5, 318), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&dst, &e5not)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5not, 317, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e5not)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_not(&dst, &e5, 319), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e5not)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ ebitmap_destroy(&e5not); ++ ebitmap_destroy(&e5); ++ } ++} ++ ++static void test_ebitmap_andnot(void) ++{ ++ { ++ ebitmap_t e1, e2, e12, e3, e4; ++ ++ ebitmap_init(&e1); ++ ebitmap_init(&e2); ++ ebitmap_init(&e12); ++ ebitmap_init(&e3); ++ ebitmap_init(&e4); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 100, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 101, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 430, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1013, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 11, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 101, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 665, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 10, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 100, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 430, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 1013, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 10, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 11, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 100, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 101, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 430, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 665, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 1013, 1), 0); ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e1, &e1, 1024), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e4)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e2, &e2, 1024), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e4)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e1, &e2, 1024), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e12)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e3, &e3, 1024), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e4)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e1, &e3, 1024), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e4)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e2, &e12, 1024), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e2)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e4, &e4, 1024), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e4)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e3, &e4, 1024), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e3)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ ebitmap_destroy(&e4); ++ ebitmap_destroy(&e3); ++ ebitmap_destroy(&e12); ++ ebitmap_destroy(&e2); ++ ebitmap_destroy(&e1); ++ } ++ ++ { ++ ebitmap_t e5; ++ ebitmap_t e6; ++ ebitmap_t e56; ++ ++ ebitmap_init(&e5); ++ ebitmap_init(&e6); ++ ebitmap_init(&e56); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 63, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 191, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 192, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 318, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 319, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 64, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 192, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 319, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 320, 1), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 63, 1), 0); ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 191, 1), 0); ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e5, &e6, 317), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e56)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e5, &e6, 318), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e56)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e5, &e6, 319), 0); ++ CU_ASSERT_FALSE(ebitmap_cmp(&dst, &e56)); ++ ++ CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 318, 1), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e56)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ { ++ ebitmap_t dst; ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e5, &e6, 320), 0); ++ CU_ASSERT(ebitmap_cmp(&dst, &e56)); ++ ++ ebitmap_destroy(&dst); ++ } ++ ++ ebitmap_destroy(&e56); ++ ebitmap_destroy(&e6); ++ ebitmap_destroy(&e5); ++ } ++} ++ ++static void test_ebitmap__random_impl(unsigned int length, int set_chance) ++{ ++ ebitmap_t e1, e2, dst_cpy, dst_or, dst_and, dst_xor1, dst_xor2, dst_not1, dst_not2, dst_andnot; ++ unsigned int i; ++ ++ CU_ASSERT_EQUAL(ebitmap_init_random(&e1, length, set_chance), 0); ++ CU_ASSERT_EQUAL(ebitmap_init_random(&e2, length, set_chance), 0); ++ ++ CU_ASSERT_EQUAL(ebitmap_cpy(&dst_cpy, &e1), 0); ++ CU_ASSERT(ebitmap_cmp(&dst_cpy, &e1)); ++ ++ CU_ASSERT_EQUAL(ebitmap_or(&dst_or, &e1, &e2), 0); ++ for (i = 0; i < length; i++) ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_or, i), ebitmap_get_bit(&e1, i) | ebitmap_get_bit(&e2, i)); ++ ++ CU_ASSERT_EQUAL(ebitmap_and(&dst_and, &e1, &e2), 0); ++ for (i = 0; i < length; i++) ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_and, i), ebitmap_get_bit(&e1, i) & ebitmap_get_bit(&e2, i)); ++ ++ CU_ASSERT_EQUAL(ebitmap_xor(&dst_xor1, &e1, &e2), 0); ++ for (i = 0; i < length; i++) ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_xor1, i), ebitmap_get_bit(&e1, i) ^ ebitmap_get_bit(&e2, i)); ++ CU_ASSERT_EQUAL(ebitmap_xor(&dst_xor2, &dst_xor1, &e2), 0); ++ CU_ASSERT(ebitmap_cmp(&dst_xor2, &e1)); ++ ++ CU_ASSERT_EQUAL(ebitmap_not(&dst_not1, &e1, length), 0); ++ for (i = 0; i < length; i++) ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_not1, i), !ebitmap_get_bit(&e1, i)); ++ CU_ASSERT_EQUAL(ebitmap_not(&dst_not2, &dst_not1, length), 0); ++ CU_ASSERT(ebitmap_cmp(&dst_not2, &e1)); ++ ++ CU_ASSERT_EQUAL(ebitmap_andnot(&dst_andnot, &e1, &e2, length), 0); ++ for (i = 0; i < length; i++) ++ CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_andnot, i), ebitmap_get_bit(&e1, i) & !ebitmap_get_bit(&e2, i)); ++ ++ ebitmap_destroy(&dst_andnot); ++ ebitmap_destroy(&dst_not2); ++ ebitmap_destroy(&dst_not1); ++ ebitmap_destroy(&dst_xor2); ++ ebitmap_destroy(&dst_xor1); ++ ebitmap_destroy(&dst_and); ++ ebitmap_destroy(&dst_or); ++ ebitmap_destroy(&dst_cpy); ++ ebitmap_destroy(&e2); ++ ebitmap_destroy(&e1); ++} ++ ++static void test_ebitmap__random(void) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < RANDOM_ROUNDS; i++) ++ test_ebitmap__random_impl(5, 10); ++ ++ for (i = 0; i < RANDOM_ROUNDS; i++) ++ test_ebitmap__random_impl(5, 90); ++ ++ for (i = 0; i < RANDOM_ROUNDS; i++) ++ test_ebitmap__random_impl(1024, 50); ++ ++ for (i = 0; i < RANDOM_ROUNDS; i++) ++ test_ebitmap__random_impl(8000, 5); ++ ++ for (i = 0; i < RANDOM_ROUNDS; i++) ++ test_ebitmap__random_impl(8000, 95); ++} ++ ++/* ++ * External hooks ++ */ ++ ++int ebitmap_test_init(void) ++{ ++ srandom(time(NULL)); ++ ++ /* silence ebitmap_set_bit() failure message */ ++ sepol_debug(0); ++ ++ return 0; ++} ++ ++int ebitmap_test_cleanup(void) ++{ ++ return 0; ++} ++ ++#define ADD_TEST(name) \ ++ do { \ ++ if (NULL == CU_add_test(suite, #name, test_##name)) { \ ++ return CU_get_error(); \ ++ } \ ++ } while (0) ++ ++int ebitmap_add_tests(CU_pSuite suite) ++{ ++ ADD_TEST(ebitmap_init_destroy); ++ ADD_TEST(ebitmap_cmp); ++ ADD_TEST(ebitmap_set_and_get); ++ ADD_TEST(ebitmap_or); ++ ADD_TEST(ebitmap_and); ++ ADD_TEST(ebitmap_xor); ++ ADD_TEST(ebitmap_not); ++ ADD_TEST(ebitmap_andnot); ++ ADD_TEST(ebitmap__random); ++ return 0; ++} +diff --git a/libsepol/tests/test-ebitmap.h b/libsepol/tests/test-ebitmap.h +new file mode 100644 +index 000000000000..952a042109e3 +--- /dev/null ++++ b/libsepol/tests/test-ebitmap.h +@@ -0,0 +1,10 @@ ++#ifndef TEST_EBITMAP_H__ ++#define TEST_EBITMAP_H__ ++ ++#include ++ ++int ebitmap_test_init(void); ++int ebitmap_test_cleanup(void); ++int ebitmap_add_tests(CU_pSuite suite); ++ ++#endif /* TEST_EBITMAP_H__ */ +-- +2.38.1 + diff --git a/0011-libsepol-add-ebitmap_init_range.patch b/0011-libsepol-add-ebitmap_init_range.patch new file mode 100644 index 0000000..4fdbecf --- /dev/null +++ b/0011-libsepol-add-ebitmap_init_range.patch @@ -0,0 +1,146 @@ +From 6f9e682c15baaa8af2c2592fac8e99c29fefecd2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 19 Jul 2022 17:30:39 +0200 +Subject: [PATCH] libsepol: add ebitmap_init_range +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Add an initializer for ebitmaps that sets all bits in a given range to +save node traversals for each bit to set, compared to calling +ebitmap_init() followed by iterating ebitmap_set_bit(). + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/include/sepol/policydb/ebitmap.h | 1 + + libsepol/src/ebitmap.c | 49 +++++++++++++++++++++++ + libsepol/tests/test-ebitmap.c | 32 +++++++++++++++ + 3 files changed, 82 insertions(+) + +diff --git a/libsepol/include/sepol/policydb/ebitmap.h b/libsepol/include/sepol/policydb/ebitmap.h +index 81d0c7a67347..85b7ccfb2604 100644 +--- a/libsepol/include/sepol/policydb/ebitmap.h ++++ b/libsepol/include/sepol/policydb/ebitmap.h +@@ -94,6 +94,7 @@ extern int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2); + extern int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2); + extern int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit); + extern int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value); ++extern int ebitmap_init_range(ebitmap_t * e, unsigned int minbit, unsigned int maxbit); + extern unsigned int ebitmap_highest_set_bit(const ebitmap_t * e); + extern void ebitmap_destroy(ebitmap_t * e); + extern int ebitmap_read(ebitmap_t * e, void *fp); +diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c +index bd98c0f8cbea..0f9afd621fed 100644 +--- a/libsepol/src/ebitmap.c ++++ b/libsepol/src/ebitmap.c +@@ -349,6 +349,55 @@ int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value) + return 0; + } + ++int ebitmap_init_range(ebitmap_t * e, unsigned int minbit, unsigned int maxbit) ++{ ++ ebitmap_node_t *new, *prev = NULL; ++ uint32_t minstartbit = minbit & ~(MAPSIZE - 1); ++ uint32_t maxstartbit = maxbit & ~(MAPSIZE - 1); ++ uint32_t minhighbit = minstartbit + MAPSIZE; ++ uint32_t maxhighbit = maxstartbit + MAPSIZE; ++ uint32_t startbit; ++ MAPTYPE mask; ++ ++ ebitmap_init(e); ++ ++ if (minbit > maxbit) ++ return -EINVAL; ++ ++ if (minhighbit == 0 || maxhighbit == 0) ++ return -EOVERFLOW; ++ ++ for (startbit = minstartbit; startbit <= maxstartbit; startbit += MAPSIZE) { ++ new = malloc(sizeof(ebitmap_node_t)); ++ if (!new) ++ return -ENOMEM; ++ ++ new->next = NULL; ++ new->startbit = startbit; ++ ++ if (startbit != minstartbit && startbit != maxstartbit) { ++ new->map = ~((MAPTYPE)0); ++ } else if (startbit != maxstartbit) { ++ new->map = ~((MAPTYPE)0) << (minbit - startbit); ++ } else if (startbit != minstartbit) { ++ new->map = ~((MAPTYPE)0) >> (MAPSIZE - (maxbit - startbit + 1)); ++ } else { ++ mask = ~((MAPTYPE)0) >> (MAPSIZE - (maxbit - minbit + 1)); ++ new->map = (mask << (minbit - startbit)); ++ } ++ ++ if (prev) ++ prev->next = new; ++ else ++ e->node = new; ++ prev = new; ++ } ++ ++ e->highbit = maxhighbit; ++ ++ return 0; ++} ++ + unsigned int ebitmap_highest_set_bit(const ebitmap_t * e) + { + const ebitmap_node_t *n; +diff --git a/libsepol/tests/test-ebitmap.c b/libsepol/tests/test-ebitmap.c +index fad5bd7561e3..8774555e65e6 100644 +--- a/libsepol/tests/test-ebitmap.c ++++ b/libsepol/tests/test-ebitmap.c +@@ -253,6 +253,37 @@ static void test_ebitmap_set_and_get(void) + ebitmap_destroy(&e); + } + ++static void test_ebitmap_init_range(void) ++{ ++ ebitmap_t e1, e2, e3, e4, e5, e6; ++ ++ CU_ASSERT_EQUAL(ebitmap_init_range(&e1, 0, 0), 0); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e1), 0); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e1), 1); ++ ++ CU_ASSERT_EQUAL(ebitmap_init_range(&e2, 0, 5), 0); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e2), 5); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e2), 6); ++ ++ CU_ASSERT_EQUAL(ebitmap_init_range(&e3, 20, 100), 0); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e3), 100); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e3), 81); ++ ++ CU_ASSERT_EQUAL(ebitmap_init_range(&e4, 100, 400), 0); ++ CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e4), 400); ++ CU_ASSERT_EQUAL(ebitmap_cardinality(&e4), 301); ++ ++ CU_ASSERT_EQUAL(ebitmap_init_range(&e5, 10, 5), -EINVAL); ++ CU_ASSERT_EQUAL(ebitmap_init_range(&e6, 0, UINT32_MAX), -EOVERFLOW); ++ ++ ebitmap_destroy(&e6); ++ ebitmap_destroy(&e5); ++ ebitmap_destroy(&e4); ++ ebitmap_destroy(&e3); ++ ebitmap_destroy(&e2); ++ ebitmap_destroy(&e1); ++} ++ + static void test_ebitmap_or(void) + { + ebitmap_t e1, e2, e3, e4; +@@ -1038,6 +1069,7 @@ int ebitmap_add_tests(CU_pSuite suite) + ADD_TEST(ebitmap_init_destroy); + ADD_TEST(ebitmap_cmp); + ADD_TEST(ebitmap_set_and_get); ++ ADD_TEST(ebitmap_init_range); + ADD_TEST(ebitmap_or); + ADD_TEST(ebitmap_and); + ADD_TEST(ebitmap_xor); +-- +2.38.1 + diff --git a/0012-libsepol-cil-use-ebitmap_init_range.patch b/0012-libsepol-cil-use-ebitmap_init_range.patch new file mode 100644 index 0000000..05f523d --- /dev/null +++ b/0012-libsepol-cil-use-ebitmap_init_range.patch @@ -0,0 +1,107 @@ +From bc8f7b502b4b526ab13e17c62caacddadf2d8f2d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 19 Jul 2022 17:30:40 +0200 +Subject: [PATCH] libsepol/cil: use ebitmap_init_range +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Especially in the case of __cil_permissionx_expr_range_to_bitmap_helper() +it substitutes hundreds of thousand of calls to ebitmap_set_bit() during +semodule(8) on a policy widely using extended permissions. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/cil/src/cil_post.c | 30 +++++++++--------------------- + 1 file changed, 9 insertions(+), 21 deletions(-) + +diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c +index 714ce227e5f9..6e95225f93f1 100644 +--- a/libsepol/cil/src/cil_post.c ++++ b/libsepol/cil/src/cil_post.c +@@ -1191,7 +1191,6 @@ static int __cil_cat_expr_range_to_bitmap_helper(struct cil_list_item *i1, struc + struct cil_tree_node *n2 = d2->nodes->head->data; + struct cil_cat *c1 = (struct cil_cat *)d1; + struct cil_cat *c2 = (struct cil_cat *)d2; +- int i; + + if (n1->flavor == CIL_CATSET || n2->flavor == CIL_CATSET) { + cil_log(CIL_ERR, "Category sets cannont be used in a category range\n"); +@@ -1213,12 +1212,10 @@ static int __cil_cat_expr_range_to_bitmap_helper(struct cil_list_item *i1, struc + goto exit; + } + +- for (i = c1->value; i <= c2->value; i++) { +- if (ebitmap_set_bit(bitmap, i, 1)) { +- cil_log(CIL_ERR, "Failed to set cat bit\n"); +- ebitmap_destroy(bitmap); +- goto exit; +- } ++ if (ebitmap_init_range(bitmap, c1->value, c2->value)) { ++ cil_log(CIL_ERR, "Failed to set cat bit\n"); ++ ebitmap_destroy(bitmap); ++ goto exit; + } + + return SEPOL_OK; +@@ -1234,7 +1231,6 @@ static int __cil_permissionx_expr_range_to_bitmap_helper(struct cil_list_item *i + char *p2 = i2->data; + uint16_t v1; + uint16_t v2; +- uint32_t i; + + rc = __cil_permx_str_to_int(p1, &v1); + if (rc != SEPOL_OK) { +@@ -1246,12 +1242,10 @@ static int __cil_permissionx_expr_range_to_bitmap_helper(struct cil_list_item *i + goto exit; + } + +- for (i = v1; i <= v2; i++) { +- if (ebitmap_set_bit(bitmap, i, 1)) { +- cil_log(CIL_ERR, "Failed to set permissionx bit\n"); +- ebitmap_destroy(bitmap); +- goto exit; +- } ++ if (ebitmap_init_range(bitmap, v1, v2)) { ++ cil_log(CIL_ERR, "Failed to set permissionx bits\n"); ++ ebitmap_destroy(bitmap); ++ goto exit; + } + + return SEPOL_OK; +@@ -1318,9 +1312,7 @@ static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, + enum cil_flavor op = (enum cil_flavor)(uintptr_t)curr->data; + + if (op == CIL_ALL) { +- ebitmap_init(&b1); /* all zeros */ +- rc = ebitmap_not(&tmp, &b1, max); +- ebitmap_destroy(&b1); ++ rc = ebitmap_init_range(&tmp, 0, max - 1); + if (rc != SEPOL_OK) { + cil_log(CIL_INFO, "Failed to expand 'all' operator\n"); + ebitmap_destroy(&tmp); +@@ -1328,19 +1320,15 @@ static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, + } + } else if (op == CIL_RANGE) { + if (flavor == CIL_CAT) { +- ebitmap_init(&tmp); + rc = __cil_cat_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp); + if (rc != SEPOL_OK) { + cil_log(CIL_INFO, "Failed to expand category range\n"); +- ebitmap_destroy(&tmp); + goto exit; + } + } else if (flavor == CIL_PERMISSIONX) { +- ebitmap_init(&tmp); + rc = __cil_permissionx_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp); + if (rc != SEPOL_OK) { + cil_log(CIL_INFO, "Failed to expand category range\n"); +- ebitmap_destroy(&tmp); + goto exit; + } + } else { +-- +2.38.1 + diff --git a/0013-libsepol-optimize-ebitmap_not.patch b/0013-libsepol-optimize-ebitmap_not.patch new file mode 100644 index 0000000..98a661a --- /dev/null +++ b/0013-libsepol-optimize-ebitmap_not.patch @@ -0,0 +1,82 @@ +From 12a8a00bf21df7aad13348b7300f7e4474d10809 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 19 Jul 2022 17:30:41 +0200 +Subject: [PATCH] libsepol: optimize ebitmap_not +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Iterate on nodes instead of single bits to save node resolution for each +single bit. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/ebitmap.c | 48 ++++++++++++++++++++++++++++++++++++------ + 1 file changed, 42 insertions(+), 6 deletions(-) + +diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c +index 0f9afd621fed..c9164c5e77bb 100644 +--- a/libsepol/src/ebitmap.c ++++ b/libsepol/src/ebitmap.c +@@ -101,14 +101,50 @@ int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) + + int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit) + { +- unsigned int i; ++ const ebitmap_node_t *n; ++ ebitmap_node_t *new, *prev = NULL; ++ uint32_t startbit, cur_startbit; ++ MAPTYPE map; ++ + ebitmap_init(dst); +- for (i=0; i < maxbit; i++) { +- int val = ebitmap_get_bit(e1, i); +- int rc = ebitmap_set_bit(dst, i, !val); +- if (rc < 0) +- return rc; ++ ++ n = e1->node; ++ for (cur_startbit = 0; cur_startbit < maxbit; cur_startbit += MAPSIZE) { ++ if (n && n->startbit == cur_startbit) { ++ startbit = n->startbit; ++ map = ~n->map; ++ ++ n = n->next; ++ } else { ++ startbit = cur_startbit; ++ map = ~((MAPTYPE) 0); ++ } ++ ++ if (maxbit - cur_startbit < MAPSIZE) ++ map &= (((MAPTYPE)1) << (maxbit - cur_startbit)) - 1; ++ ++ if (map != 0) { ++ new = malloc(sizeof(ebitmap_node_t)); ++ if (!new) { ++ ebitmap_destroy(dst); ++ return -ENOMEM; ++ } ++ ++ new->startbit = startbit; ++ new->map = map; ++ new->next = NULL; ++ ++ if (prev) ++ prev->next = new; ++ else ++ dst->node = new; ++ prev = new; ++ } + } ++ ++ if (prev) ++ dst->highbit = prev->startbit + MAPSIZE; ++ + return 0; + } + +-- +2.38.1 + diff --git a/0014-libsepol-optimize-ebitmap_and.patch b/0014-libsepol-optimize-ebitmap_and.patch new file mode 100644 index 0000000..5bc306a --- /dev/null +++ b/0014-libsepol-optimize-ebitmap_and.patch @@ -0,0 +1,76 @@ +From efcd00814879603c3cf7c689ec12705fffc144ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 19 Jul 2022 17:30:42 +0200 +Subject: [PATCH] libsepol: optimize ebitmap_and +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Iterate on nodes instead of single bits to save node resolution for each +single bit. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/ebitmap.c | 41 +++++++++++++++++++++++++++++++++++------ + 1 file changed, 35 insertions(+), 6 deletions(-) + +diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c +index c9164c5e77bb..6dbbddfdb467 100644 +--- a/libsepol/src/ebitmap.c ++++ b/libsepol/src/ebitmap.c +@@ -74,15 +74,44 @@ int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1) + + int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) + { +- unsigned int i, length = min(ebitmap_length(e1), ebitmap_length(e2)); ++ const ebitmap_node_t *n1, *n2; ++ ebitmap_node_t *new, *prev = NULL; ++ + ebitmap_init(dst); +- for (i=0; i < length; i++) { +- if (ebitmap_get_bit(e1, i) && ebitmap_get_bit(e2, i)) { +- int rc = ebitmap_set_bit(dst, i, 1); +- if (rc < 0) +- return rc; ++ ++ n1 = e1->node; ++ n2 = e2->node; ++ while (n1 && n2) { ++ if (n1->startbit == n2->startbit) { ++ if (n1->map & n2->map) { ++ new = malloc(sizeof(ebitmap_node_t)); ++ if (!new) { ++ ebitmap_destroy(dst); ++ return -ENOMEM; ++ } ++ new->startbit = n1->startbit; ++ new->map = n1->map & n2->map; ++ new->next = NULL; ++ ++ if (prev) ++ prev->next = new; ++ else ++ dst->node = new; ++ prev = new; ++ } ++ ++ n1 = n1->next; ++ n2 = n2->next; ++ } else if (n1->startbit > n2->startbit) { ++ n2 = n2->next; ++ } else { ++ n1 = n1->next; + } + } ++ ++ if (prev) ++ dst->highbit = prev->startbit + MAPSIZE; ++ + return 0; + } + +-- +2.38.1 + diff --git a/0015-libsepol-optimize-ebitmap_xor.patch b/0015-libsepol-optimize-ebitmap_xor.patch new file mode 100644 index 0000000..eb5b3a1 --- /dev/null +++ b/0015-libsepol-optimize-ebitmap_xor.patch @@ -0,0 +1,83 @@ +From f1740455253d0b7ccbcff3d81c8bfe96e2233762 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 19 Jul 2022 17:30:43 +0200 +Subject: [PATCH] libsepol: optimize ebitmap_xor +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Iterate on nodes instead of single bits to save node resolution for each +single bit. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/ebitmap.c | 49 ++++++++++++++++++++++++++++++++++++------ + 1 file changed, 43 insertions(+), 6 deletions(-) + +diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c +index 6dbbddfdb467..7d26f9493120 100644 +--- a/libsepol/src/ebitmap.c ++++ b/libsepol/src/ebitmap.c +@@ -117,14 +117,51 @@ int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) + + int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) + { +- unsigned int i, length = max(ebitmap_length(e1), ebitmap_length(e2)); ++ const ebitmap_node_t *n1, *n2; ++ ebitmap_node_t *new, *prev = NULL; ++ uint32_t startbit; ++ MAPTYPE map; ++ + ebitmap_init(dst); +- for (i=0; i < length; i++) { +- int val = ebitmap_get_bit(e1, i) ^ ebitmap_get_bit(e2, i); +- int rc = ebitmap_set_bit(dst, i, val); +- if (rc < 0) +- return rc; ++ ++ n1 = e1->node; ++ n2 = e2->node; ++ while (n1 || n2) { ++ if (n1 && n2 && n1->startbit == n2->startbit) { ++ startbit = n1->startbit; ++ map = n1->map ^ n2->map; ++ n1 = n1->next; ++ n2 = n2->next; ++ } else if (!n2 || (n1 && n1->startbit < n2->startbit)) { ++ startbit = n1->startbit; ++ map = n1->map; ++ n1 = n1->next; ++ } else { ++ startbit = n2->startbit; ++ map = n2->map; ++ n2 = n2->next; ++ } ++ ++ if (map != 0) { ++ new = malloc(sizeof(ebitmap_node_t)); ++ if (!new) { ++ ebitmap_destroy(dst); ++ return -ENOMEM; ++ } ++ new->startbit = startbit; ++ new->map = map; ++ new->next = NULL; ++ if (prev) ++ prev->next = new; ++ else ++ dst->node = new; ++ prev = new; ++ } + } ++ ++ if (prev) ++ dst->highbit = prev->startbit + MAPSIZE; ++ + return 0; + } + +-- +2.38.1 + diff --git a/0016-libsepol-skip-superfluous-memset-calls-in-ebitmap-op.patch b/0016-libsepol-skip-superfluous-memset-calls-in-ebitmap-op.patch new file mode 100644 index 0000000..630d800 --- /dev/null +++ b/0016-libsepol-skip-superfluous-memset-calls-in-ebitmap-op.patch @@ -0,0 +1,51 @@ +From fc7bb9f05a3e8658b3745cc65a8b8e624498e56c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 19 Jul 2022 17:30:44 +0200 +Subject: [PATCH] libsepol: skip superfluous memset calls in ebitmap operations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +The three members of struct ebitmap_node are all unconditionally +initialized. Hinder compilers to optimize malloc() and memset() into +calloc(), which might be slightly slower. Especially affects +ebitmap_or(). + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/ebitmap.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c +index 7d26f9493120..3ec1042fe70a 100644 +--- a/libsepol/src/ebitmap.c ++++ b/libsepol/src/ebitmap.c +@@ -31,7 +31,6 @@ int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2) + ebitmap_destroy(dst); + return -ENOMEM; + } +- memset(new, 0, sizeof(ebitmap_node_t)); + if (n1 && n2 && n1->startbit == n2->startbit) { + new->startbit = n1->startbit; + new->map = n1->map | n2->map; +@@ -290,7 +289,6 @@ int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src) + ebitmap_destroy(dst); + return -ENOMEM; + } +- memset(new, 0, sizeof(ebitmap_node_t)); + new->startbit = n->startbit; + new->map = n->map; + new->next = 0; +@@ -430,7 +428,6 @@ int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value) + new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t)); + if (!new) + return -ENOMEM; +- memset(new, 0, sizeof(ebitmap_node_t)); + + new->startbit = startbit; + new->map = (MAPBIT << (bit - new->startbit)); +-- +2.38.1 + diff --git a/0017-libsepol-rename-validate_policydb-to-policydb_valida.patch b/0017-libsepol-rename-validate_policydb-to-policydb_valida.patch new file mode 100644 index 0000000..83eb144 --- /dev/null +++ b/0017-libsepol-rename-validate_policydb-to-policydb_valida.patch @@ -0,0 +1,62 @@ +From 938530171bcfbd0175b819eaa05960e9f4568ac0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 21 Jul 2022 17:24:40 +0200 +Subject: [PATCH] libsepol: rename validate_policydb to policydb_validate +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Most global functions operating on a policy database use policydb as +prefix. + +Since this function is not exported there should not be any external +use. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/policydb.c | 2 +- + libsepol/src/policydb_validate.c | 2 +- + libsepol/src/policydb_validate.h | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c +index fc260eb664b1..8a65df053f88 100644 +--- a/libsepol/src/policydb.c ++++ b/libsepol/src/policydb.c +@@ -4570,7 +4570,7 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) + } + } + +- if (validate_policydb(fp->handle, p)) ++ if (policydb_validate(fp->handle, p)) + goto bad; + + return POLICYDB_SUCCESS; +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index 99d4eb7f670e..e1dad2362f90 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -1330,7 +1330,7 @@ static void validate_array_destroy(validate_t flavors[]) + /* + * Validate policydb + */ +-int validate_policydb(sepol_handle_t *handle, policydb_t *p) ++int policydb_validate(sepol_handle_t *handle, policydb_t *p) + { + validate_t flavors[SYM_NUM] = {}; + +diff --git a/libsepol/src/policydb_validate.h b/libsepol/src/policydb_validate.h +index d9f7229bf765..b7f9f1913cf3 100644 +--- a/libsepol/src/policydb_validate.h ++++ b/libsepol/src/policydb_validate.h +@@ -4,4 +4,4 @@ + #include + + int value_isvalid(uint32_t value, uint32_t nprim); +-int validate_policydb(sepol_handle_t *handle, policydb_t *p); ++int policydb_validate(sepol_handle_t *handle, policydb_t *p); +-- +2.38.1 + diff --git a/0018-libsepol-support-const-avtab_t-pointer-in-avtab_map.patch b/0018-libsepol-support-const-avtab_t-pointer-in-avtab_map.patch new file mode 100644 index 0000000..9288e43 --- /dev/null +++ b/0018-libsepol-support-const-avtab_t-pointer-in-avtab_map.patch @@ -0,0 +1,52 @@ +From d192e4d937c082ffe2519a18aa6086a3f6602cb0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 21 Jul 2022 17:24:41 +0200 +Subject: [PATCH] libsepol: support const avtab_t pointer in avtab_map() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +The access vector table itself is not modified in avtab_map() thus +support passing a const pointer. + +Logically the content might be changed by the passed callback, but C +does not support transitive const-ness well, and C also does not support +function overloading, e.g. like for strchr(3). + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/include/sepol/policydb/avtab.h | 2 +- + libsepol/src/avtab.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libsepol/include/sepol/policydb/avtab.h b/libsepol/include/sepol/policydb/avtab.h +index 10ecde9aaf82..e4c48576177e 100644 +--- a/libsepol/include/sepol/policydb/avtab.h ++++ b/libsepol/include/sepol/policydb/avtab.h +@@ -112,7 +112,7 @@ extern avtab_datum_t *avtab_search(avtab_t * h, avtab_key_t * k); + + extern void avtab_destroy(avtab_t * h); + +-extern int avtab_map(avtab_t * h, ++extern int avtab_map(const avtab_t * h, + int (*apply) (avtab_key_t * k, + avtab_datum_t * d, void *args), void *args); + +diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c +index 7920b60a3a43..82fec783e0c3 100644 +--- a/libsepol/src/avtab.c ++++ b/libsepol/src/avtab.c +@@ -330,7 +330,7 @@ void avtab_destroy(avtab_t * h) + h->mask = 0; + } + +-int avtab_map(avtab_t * h, ++int avtab_map(const avtab_t * h, + int (*apply) (avtab_key_t * k, + avtab_datum_t * d, void *args), void *args) + { +-- +2.38.1 + diff --git a/0019-libsepol-operate-on-const-pointers-during-validation.patch b/0019-libsepol-operate-on-const-pointers-during-validation.patch new file mode 100644 index 0000000..26fafdc --- /dev/null +++ b/0019-libsepol-operate-on-const-pointers-during-validation.patch @@ -0,0 +1,486 @@ +From 9e6f8ed70e50bc7d7f0dda4ed5072fb15f1a8208 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 21 Jul 2022 17:24:42 +0200 +Subject: [PATCH] libsepol: operate on const pointers during validation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +The actual policy should not be modified during validation, thus use +const pointers. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/policydb_validate.c | 114 +++++++++++++++---------------- + libsepol/src/policydb_validate.h | 2 +- + 2 files changed, 58 insertions(+), 58 deletions(-) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index e1dad2362f90..a567c4119e10 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -8,7 +8,7 @@ + #include "policydb_validate.h" + + #define bool_xor(a, b) (!(a) != !(b)) +-#define bool_xnor(a, b) !bool_xor(a, b) ++#define bool_xnor(a, b) (!bool_xor(a, b)) + + typedef struct validate { + uint32_t nprim; +@@ -18,7 +18,7 @@ typedef struct validate { + typedef struct map_arg { + validate_t *flavors; + sepol_handle_t *handle; +- policydb_t *policy; ++ const policydb_t *policy; + } map_arg_t; + + static int create_gap_ebitmap(char **val_to_name, uint32_t nprim, ebitmap_t *gaps) +@@ -46,7 +46,7 @@ static int validate_init(validate_t *flavor, char **val_to_name, uint32_t nprim) + return 0; + } + +-static int validate_array_init(policydb_t *p, validate_t flavors[]) ++static int validate_array_init(const policydb_t *p, validate_t flavors[]) + { + if (validate_init(&flavors[SYM_CLASSES], p->p_class_val_to_name, p->p_classes.nprim)) + goto bad; +@@ -91,7 +91,7 @@ int value_isvalid(uint32_t value, uint32_t nprim) + return 1; + } + +-static int validate_value(uint32_t value, validate_t *flavor) ++static int validate_value(uint32_t value, const validate_t *flavor) + { + if (!value || value > flavor->nprim) + goto bad; +@@ -104,7 +104,7 @@ bad: + return -1; + } + +-static int validate_ebitmap(ebitmap_t *map, validate_t *flavor) ++static int validate_ebitmap(const ebitmap_t *map, const validate_t *flavor) + { + if (ebitmap_length(map) > 0 && ebitmap_highest_set_bit(map) >= flavor->nprim) + goto bad; +@@ -117,7 +117,7 @@ bad: + return -1; + } + +-static int validate_type_set(type_set_t *type_set, validate_t *type) ++static int validate_type_set(const type_set_t *type_set, const validate_t *type) + { + if (validate_ebitmap(&type_set->types, type)) + goto bad; +@@ -139,7 +139,7 @@ bad: + return -1; + } + +-static int validate_empty_type_set(type_set_t *type_set) ++static int validate_empty_type_set(const type_set_t *type_set) + { + if (!ebitmap_is_empty(&type_set->types)) + goto bad; +@@ -154,7 +154,7 @@ bad: + return -1; + } + +-static int validate_role_set(role_set_t *role_set, validate_t *role) ++static int validate_role_set(const role_set_t *role_set, const validate_t *role) + { + if (validate_ebitmap(&role_set->roles, role)) + goto bad; +@@ -176,8 +176,8 @@ bad: + + static int validate_scope(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) + { +- scope_datum_t *scope_datum = (scope_datum_t *)d; +- uint32_t *nprim = (uint32_t *)args; ++ const scope_datum_t *scope_datum = (scope_datum_t *)d; ++ const uint32_t *nprim = (uint32_t *)args; + unsigned int i; + + switch (scope_datum->scope) { +@@ -199,9 +199,9 @@ bad: + return -1; + } + +-static int validate_scopes(sepol_handle_t *handle, symtab_t scopes[], avrule_block_t *block) ++static int validate_scopes(sepol_handle_t *handle, const symtab_t scopes[], const avrule_block_t *block) + { +- avrule_decl_t *decl; ++ const avrule_decl_t *decl; + unsigned int i; + unsigned int num_decls = 0; + +@@ -223,9 +223,9 @@ bad: + return -1; + } + +-static int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms, constraint_node_t *cons, validate_t flavors[]) ++static int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms, const constraint_node_t *cons, validate_t flavors[]) + { +- constraint_expr_t *cexp; ++ const constraint_expr_t *cexp; + + for (; cons; cons = cons->next) { + if (nperms == 0 && cons->permissions != 0) +@@ -339,7 +339,7 @@ bad: + return -1; + } + +-static int validate_class_datum(sepol_handle_t *handle, class_datum_t *class, validate_t flavors[]) ++static int validate_class_datum(sepol_handle_t *handle, const class_datum_t *class, validate_t flavors[]) + { + if (validate_value(class->s.value, &flavors[SYM_CLASSES])) + goto bad; +@@ -405,7 +405,7 @@ static int validate_class_datum_wrapper(__attribute__((unused)) hashtab_key_t k, + return validate_class_datum(margs->handle, d, margs->flavors); + } + +-static int validate_common_datum(sepol_handle_t *handle, common_datum_t *common) ++static int validate_common_datum(sepol_handle_t *handle, const common_datum_t *common) + { + if (common->permissions.nprim > PERM_SYMTAB_SIZE) + goto bad; +@@ -424,7 +424,7 @@ static int validate_common_datum_wrapper(__attribute__((unused)) hashtab_key_t k + return validate_common_datum(margs->handle, d); + } + +-static int validate_role_datum(sepol_handle_t *handle, role_datum_t *role, validate_t flavors[]) ++static int validate_role_datum(sepol_handle_t *handle, const role_datum_t *role, validate_t flavors[]) + { + if (validate_value(role->s.value, &flavors[SYM_ROLES])) + goto bad; +@@ -451,7 +451,7 @@ static int validate_role_datum_wrapper(__attribute__((unused)) hashtab_key_t k, + return validate_role_datum(margs->handle, d, margs->flavors); + } + +-static int validate_type_datum(sepol_handle_t *handle, type_datum_t *type, validate_t flavors[]) ++static int validate_type_datum(sepol_handle_t *handle, const type_datum_t *type, validate_t flavors[]) + { + if (validate_value(type->s.value, &flavors[SYM_TYPES])) + goto bad; +@@ -494,7 +494,7 @@ static int validate_type_datum_wrapper(__attribute__((unused)) hashtab_key_t k, + return validate_type_datum(margs->handle, d, margs->flavors); + } + +-static int validate_mls_semantic_cat(mls_semantic_cat_t *cat, validate_t *cats) ++static int validate_mls_semantic_cat(const mls_semantic_cat_t *cat, const validate_t *cats) + { + for (; cat; cat = cat->next) { + if (validate_value(cat->low, cats)) +@@ -509,7 +509,7 @@ bad: + return -1; + } + +-static int validate_mls_semantic_level(mls_semantic_level_t *level, validate_t *sens, validate_t *cats) ++static int validate_mls_semantic_level(const mls_semantic_level_t *level, const validate_t *sens, const validate_t *cats) + { + if (level->sens == 0) + return 0; +@@ -524,7 +524,7 @@ bad: + return -1; + } + +-static int validate_mls_semantic_range(mls_semantic_range_t *range, validate_t *sens, validate_t *cats) ++static int validate_mls_semantic_range(const mls_semantic_range_t *range, const validate_t *sens, const validate_t *cats) + { + if (validate_mls_semantic_level(&range->level[0], sens, cats)) + goto bad; +@@ -537,7 +537,7 @@ bad: + return -1; + } + +-static int validate_mls_level(mls_level_t *level, validate_t *sens, validate_t *cats) ++static int validate_mls_level(const mls_level_t *level, const validate_t *sens, const validate_t *cats) + { + if (validate_value(level->sens, sens)) + goto bad; +@@ -558,7 +558,7 @@ static int validate_level_datum(__attribute__ ((unused)) hashtab_key_t k, hashta + return validate_mls_level(level->level, &flavors[SYM_LEVELS], &flavors[SYM_CATS]); + } + +-static int validate_mls_range(mls_range_t *range, validate_t *sens, validate_t *cats) ++static int validate_mls_range(const mls_range_t *range, const validate_t *sens, const validate_t *cats) + { + if (validate_mls_level(&range->level[0], sens, cats)) + goto bad; +@@ -571,7 +571,7 @@ static int validate_mls_range(mls_range_t *range, validate_t *sens, validate_t * + return -1; + } + +-static int validate_user_datum(sepol_handle_t *handle, user_datum_t *user, validate_t flavors[], policydb_t *p) ++static int validate_user_datum(sepol_handle_t *handle, const user_datum_t *user, validate_t flavors[], const policydb_t *p) + { + if (validate_value(user->s.value, &flavors[SYM_USERS])) + goto bad; +@@ -602,7 +602,7 @@ static int validate_user_datum_wrapper(__attribute__((unused)) hashtab_key_t k, + return validate_user_datum(margs->handle, d, margs->flavors, margs->policy); + } + +-static int validate_bool_datum(sepol_handle_t *handle, cond_bool_datum_t *boolean, validate_t flavors[]) ++static int validate_bool_datum(sepol_handle_t *handle, const cond_bool_datum_t *boolean, validate_t flavors[]) + { + if (validate_value(boolean->s.value, &flavors[SYM_BOOLS])) + goto bad; +@@ -637,7 +637,7 @@ static int validate_bool_datum_wrapper(__attribute__((unused)) hashtab_key_t k, + return validate_bool_datum(margs->handle, d, margs->flavors); + } + +-static int validate_datum_array_gaps(sepol_handle_t *handle, policydb_t *p, validate_t flavors[]) ++static int validate_datum_array_gaps(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) + { + unsigned int i; + +@@ -687,7 +687,7 @@ static int validate_datum(__attribute__ ((unused))hashtab_key_t k, hashtab_datum + return !value_isvalid(s->value, *nprim); + } + +-static int validate_datum_array_entries(sepol_handle_t *handle, policydb_t *p, validate_t flavors[]) ++static int validate_datum_array_entries(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) + { + map_arg_t margs = { flavors, handle, p }; + +@@ -726,7 +726,7 @@ bad: + * Functions to validate a kernel policydb + */ + +-static int validate_avtab_key(avtab_key_t *key, int conditional, validate_t flavors[]) ++static int validate_avtab_key(const avtab_key_t *key, int conditional, validate_t flavors[]) + { + if (validate_value(key->source_type, &flavors[SYM_TYPES])) + goto bad; +@@ -771,7 +771,7 @@ static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void * + return 0; + } + +-static int validate_avtab(sepol_handle_t *handle, avtab_t *avtab, validate_t flavors[]) ++static int validate_avtab(sepol_handle_t *handle, const avtab_t *avtab, validate_t flavors[]) + { + if (avtab_map(avtab, validate_avtab_key_and_datum, flavors)) { + ERR(handle, "Invalid avtab"); +@@ -781,9 +781,9 @@ static int validate_avtab(sepol_handle_t *handle, avtab_t *avtab, validate_t fla + return 0; + } + +-static int validate_cond_av_list(sepol_handle_t *handle, cond_av_list_t *cond_av, validate_t flavors[]) ++static int validate_cond_av_list(sepol_handle_t *handle, const cond_av_list_t *cond_av, validate_t flavors[]) + { +- avtab_ptr_t avtab_ptr; ++ const struct avtab_node *avtab_ptr; + + for (; cond_av; cond_av = cond_av->next) { + for (avtab_ptr = cond_av->node; avtab_ptr; avtab_ptr = avtab_ptr->next) { +@@ -797,9 +797,9 @@ static int validate_cond_av_list(sepol_handle_t *handle, cond_av_list_t *cond_av + return 0; + } + +-static int validate_avrules(sepol_handle_t *handle, avrule_t *avrule, int conditional, validate_t flavors[]) ++static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int conditional, validate_t flavors[]) + { +- class_perm_node_t *class; ++ const class_perm_node_t *class; + + for (; avrule; avrule = avrule->next) { + if (validate_type_set(&avrule->stypes, &flavors[SYM_TYPES])) +@@ -862,7 +862,7 @@ bad: + return -1; + } + +-static int validate_bool_id_array(sepol_handle_t *handle, uint32_t bool_ids[], unsigned int nbools, validate_t *bool) ++static int validate_bool_id_array(sepol_handle_t *handle, const uint32_t bool_ids[], unsigned int nbools, const validate_t *bool) + { + unsigned int i; + +@@ -881,7 +881,7 @@ bad: + return -1; + } + +-static int validate_cond_expr(sepol_handle_t *handle, struct cond_expr *expr, validate_t *bool) ++static int validate_cond_expr(sepol_handle_t *handle, const struct cond_expr *expr, const validate_t *bool) + { + int depth = -1; + +@@ -922,7 +922,7 @@ bad: + return -1; + } + +-static int validate_cond_list(sepol_handle_t *handle, cond_list_t *cond, validate_t flavors[]) ++static int validate_cond_list(sepol_handle_t *handle, const cond_list_t *cond, validate_t flavors[]) + { + for (; cond; cond = cond->next) { + if (validate_cond_expr(handle, cond->expr, &flavors[SYM_BOOLS])) +@@ -946,7 +946,7 @@ bad: + return -1; + } + +-static int validate_role_transes(sepol_handle_t *handle, role_trans_t *role_trans, validate_t flavors[]) ++static int validate_role_transes(sepol_handle_t *handle, const role_trans_t *role_trans, validate_t flavors[]) + { + for (; role_trans; role_trans = role_trans->next) { + if (validate_value(role_trans->role, &flavors[SYM_ROLES])) +@@ -966,7 +966,7 @@ bad: + return -1; + } + +-static int validate_role_allows(sepol_handle_t *handle, role_allow_t *role_allow, validate_t flavors[]) ++static int validate_role_allows(sepol_handle_t *handle, const role_allow_t *role_allow, validate_t flavors[]) + { + for (; role_allow; role_allow = role_allow->next) { + if (validate_value(role_allow->role, &flavors[SYM_ROLES])) +@@ -984,8 +984,8 @@ bad: + + static int validate_filename_trans(hashtab_key_t k, hashtab_datum_t d, void *args) + { +- filename_trans_key_t *ftk = (filename_trans_key_t *)k; +- filename_trans_datum_t *ftd = d; ++ const filename_trans_key_t *ftk = (filename_trans_key_t *)k; ++ const filename_trans_datum_t *ftd = d; + validate_t *flavors = (validate_t *)args; + + if (validate_value(ftk->ttype, &flavors[SYM_TYPES])) +@@ -1015,7 +1015,7 @@ static int validate_filename_trans_hashtab(sepol_handle_t *handle, hashtab_t fil + return 0; + } + +-static int validate_context(context_struct_t *con, validate_t flavors[], int mls) ++static int validate_context(const context_struct_t *con, validate_t flavors[], int mls) + { + if (validate_value(con->user, &flavors[SYM_USERS])) + return -1; +@@ -1029,9 +1029,9 @@ static int validate_context(context_struct_t *con, validate_t flavors[], int mls + return 0; + } + +-static int validate_ocontexts(sepol_handle_t *handle, policydb_t *p, validate_t flavors[]) ++static int validate_ocontexts(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) + { +- ocontext_t *octx; ++ const ocontext_t *octx; + unsigned int i; + + for (i = 0; i < OCON_NUM; i++) { +@@ -1067,10 +1067,10 @@ bad: + return -1; + } + +-static int validate_genfs(sepol_handle_t *handle, policydb_t *p, validate_t flavors[]) ++static int validate_genfs(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) + { +- genfs_t *genfs; +- ocontext_t *octx; ++ const genfs_t *genfs; ++ const ocontext_t *octx; + + for (genfs = p->genfs; genfs; genfs = genfs->next) { + for (octx = genfs->head; octx; octx = octx->next) { +@@ -1090,7 +1090,7 @@ bad: + * Functions to validate a module policydb + */ + +-static int validate_role_trans_rules(sepol_handle_t *handle, role_trans_rule_t *role_trans, validate_t flavors[]) ++static int validate_role_trans_rules(sepol_handle_t *handle, const role_trans_rule_t *role_trans, validate_t flavors[]) + { + for (; role_trans; role_trans = role_trans->next) { + if (validate_role_set(&role_trans->roles, &flavors[SYM_ROLES])) +@@ -1110,7 +1110,7 @@ bad: + return -1; + } + +-static int validate_role_allow_rules(sepol_handle_t *handle, role_allow_rule_t *role_allow, validate_t flavors[]) ++static int validate_role_allow_rules(sepol_handle_t *handle, const role_allow_rule_t *role_allow, validate_t flavors[]) + { + for (; role_allow; role_allow = role_allow->next) { + if (validate_role_set(&role_allow->roles, &flavors[SYM_ROLES])) +@@ -1126,7 +1126,7 @@ bad: + return -1; + } + +-static int validate_range_trans_rules(sepol_handle_t *handle, range_trans_rule_t *range_trans, validate_t flavors[]) ++static int validate_range_trans_rules(sepol_handle_t *handle, const range_trans_rule_t *range_trans, validate_t flavors[]) + { + for (; range_trans; range_trans = range_trans->next) { + if (validate_type_set(&range_trans->stypes, &flavors[SYM_TYPES])) +@@ -1146,7 +1146,7 @@ bad: + return -1; + } + +-static int validate_scope_index(sepol_handle_t *handle, scope_index_t *scope_index, validate_t flavors[]) ++static int validate_scope_index(sepol_handle_t *handle, const scope_index_t *scope_index, validate_t flavors[]) + { + if (validate_ebitmap(&scope_index->p_classes_scope, &flavors[SYM_CLASSES])) + goto bad; +@@ -1173,7 +1173,7 @@ bad: + } + + +-static int validate_filename_trans_rules(sepol_handle_t *handle, filename_trans_rule_t *filename_trans, validate_t flavors[]) ++static int validate_filename_trans_rules(sepol_handle_t *handle, const filename_trans_rule_t *filename_trans, validate_t flavors[]) + { + for (; filename_trans; filename_trans = filename_trans->next) { + if (validate_type_set(&filename_trans->stypes, &flavors[SYM_TYPES])) +@@ -1197,7 +1197,7 @@ bad: + return -1; + } + +-static int validate_symtabs(sepol_handle_t *handle, symtab_t symtabs[], validate_t flavors[]) ++static int validate_symtabs(sepol_handle_t *handle, const symtab_t symtabs[], validate_t flavors[]) + { + unsigned int i; + +@@ -1211,9 +1211,9 @@ static int validate_symtabs(sepol_handle_t *handle, symtab_t symtabs[], validate + return 0; + } + +-static int validate_avrule_blocks(sepol_handle_t *handle, avrule_block_t *avrule_block, validate_t flavors[]) ++static int validate_avrule_blocks(sepol_handle_t *handle, const avrule_block_t *avrule_block, validate_t flavors[]) + { +- avrule_decl_t *decl; ++ const avrule_decl_t *decl; + + for (; avrule_block; avrule_block = avrule_block->next) { + for (decl = avrule_block->branch_list; decl != NULL; decl = decl->next) { +@@ -1253,7 +1253,7 @@ bad: + return -1; + } + +-static int validate_permissives(sepol_handle_t *handle, policydb_t *p, validate_t flavors[]) ++static int validate_permissives(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) + { + ebitmap_node_t *node; + unsigned i; +@@ -1270,7 +1270,7 @@ bad: + return -1; + } + +-static int validate_properties(sepol_handle_t *handle, policydb_t *p) ++static int validate_properties(sepol_handle_t *handle, const policydb_t *p) + { + switch (p->policy_type) { + case POLICY_KERN: +@@ -1330,7 +1330,7 @@ static void validate_array_destroy(validate_t flavors[]) + /* + * Validate policydb + */ +-int policydb_validate(sepol_handle_t *handle, policydb_t *p) ++int policydb_validate(sepol_handle_t *handle, const policydb_t *p) + { + validate_t flavors[SYM_NUM] = {}; + +diff --git a/libsepol/src/policydb_validate.h b/libsepol/src/policydb_validate.h +index b7f9f1913cf3..86a531683bfe 100644 +--- a/libsepol/src/policydb_validate.h ++++ b/libsepol/src/policydb_validate.h +@@ -4,4 +4,4 @@ + #include + + int value_isvalid(uint32_t value, uint32_t nprim); +-int policydb_validate(sepol_handle_t *handle, policydb_t *p); ++int policydb_validate(sepol_handle_t *handle, const policydb_t *p); +-- +2.38.1 + diff --git a/0020-libsepol-rename-parameter-name.patch b/0020-libsepol-rename-parameter-name.patch new file mode 100644 index 0000000..a6400a1 --- /dev/null +++ b/0020-libsepol-rename-parameter-name.patch @@ -0,0 +1,59 @@ +From 858f66083170216873c75d8e325b5da217da7605 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 21 Jul 2022 17:24:43 +0200 +Subject: [PATCH] libsepol: rename parameter name +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Do not use `bool` as a parameter name, for future C version support. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/policydb_validate.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index a567c4119e10..0f39977177bd 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -862,7 +862,7 @@ bad: + return -1; + } + +-static int validate_bool_id_array(sepol_handle_t *handle, const uint32_t bool_ids[], unsigned int nbools, const validate_t *bool) ++static int validate_bool_id_array(sepol_handle_t *handle, const uint32_t bool_ids[], unsigned int nbools, const validate_t *boolean) + { + unsigned int i; + +@@ -870,7 +870,7 @@ static int validate_bool_id_array(sepol_handle_t *handle, const uint32_t bool_id + goto bad; + + for (i=0; i < nbools; i++) { +- if (validate_value(bool_ids[i], bool)) ++ if (validate_value(bool_ids[i], boolean)) + goto bad; + } + +@@ -881,14 +881,14 @@ bad: + return -1; + } + +-static int validate_cond_expr(sepol_handle_t *handle, const struct cond_expr *expr, const validate_t *bool) ++static int validate_cond_expr(sepol_handle_t *handle, const struct cond_expr *expr, const validate_t *boolean) + { + int depth = -1; + + for (; expr; expr = expr->next) { + switch(expr->expr_type) { + case COND_BOOL: +- if (validate_value(expr->bool, bool)) ++ if (validate_value(expr->bool, boolean)) + goto bad; + if (depth == (COND_EXPR_MAXDEPTH - 1)) + goto bad; +-- +2.38.1 + diff --git a/0021-libsepol-more-strict-validation.patch b/0021-libsepol-more-strict-validation.patch new file mode 100644 index 0000000..66f84fb --- /dev/null +++ b/0021-libsepol-more-strict-validation.patch @@ -0,0 +1,519 @@ +From d2d24b9331782194ae2e2f3c481965d2a7104f90 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 21 Jul 2022 17:24:44 +0200 +Subject: [PATCH] libsepol: more strict validation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Validate that + + - each constraint has at least one expression + - classes reference a valid common class identifier + - the role flavor is either ROLE or ATTRIB + - types reference a valid primary identifier + - types refer to a raw type, not an attribute, as bounds + - extended permissions in avtabs have a valid specifier + - type av rules refer to a raw type (e.g. type_transition) + - conditionals have at least one expression + - the state and flags of conditionals are valid + - filename transitions have at least one datum + - low ports are not bigger than high ones in port ocontexts + - genfs declarations refer to a valid class identifier + - genfs declarations contains a filesystem name + - filename transitions refer to a raw type + - permissive types are raw ones + - the range transition hashmap is valid + - the type-attribute-maps are valid + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/policydb_validate.c | 259 +++++++++++++++++++++++++------ + 1 file changed, 209 insertions(+), 50 deletions(-) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index 0f39977177bd..521ea4ff51d5 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -48,6 +48,8 @@ static int validate_init(validate_t *flavor, char **val_to_name, uint32_t nprim) + + static int validate_array_init(const policydb_t *p, validate_t flavors[]) + { ++ if (validate_init(&flavors[SYM_COMMONS], p->p_common_val_to_name, p->p_commons.nprim)) ++ goto bad; + if (validate_init(&flavors[SYM_CLASSES], p->p_class_val_to_name, p->p_classes.nprim)) + goto bad; + if (validate_init(&flavors[SYM_ROLES], p->p_role_val_to_name, p->p_roles.nprim)) +@@ -235,6 +237,9 @@ static int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms + if (nperms > 0 && nperms != PERM_SYMTAB_SIZE && cons->permissions >= (UINT32_C(1) << nperms)) + goto bad; + ++ if (!cons->expr) ++ goto bad; ++ + for (cexp = cons->expr; cexp; cexp = cexp->next) { + if (cexp->expr_type == CEXPR_NAMES) { + if (cexp->attr & CEXPR_XTARGET && nperms != 0) +@@ -339,10 +344,33 @@ bad: + return -1; + } + ++static int validate_common_datum(sepol_handle_t *handle, const common_datum_t *common, validate_t flavors[]) ++{ ++ if (validate_value(common->s.value, &flavors[SYM_COMMONS])) ++ goto bad; ++ if (common->permissions.nprim > PERM_SYMTAB_SIZE) ++ goto bad; ++ ++ return 0; ++ ++bad: ++ ERR(handle, "Invalid common class datum"); ++ return -1; ++} ++ ++static int validate_common_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) ++{ ++ map_arg_t *margs = args; ++ ++ return validate_common_datum(margs->handle, d, margs->flavors); ++} ++ + static int validate_class_datum(sepol_handle_t *handle, const class_datum_t *class, validate_t flavors[]) + { + if (validate_value(class->s.value, &flavors[SYM_CLASSES])) + goto bad; ++ if (class->comdatum && validate_common_datum(handle, class->comdatum, flavors)) ++ goto bad; + if (class->permissions.nprim > PERM_SYMTAB_SIZE) + goto bad; + if (validate_constraint_nodes(handle, class->permissions.nprim, class->constraints, flavors)) +@@ -405,25 +433,6 @@ static int validate_class_datum_wrapper(__attribute__((unused)) hashtab_key_t k, + return validate_class_datum(margs->handle, d, margs->flavors); + } + +-static int validate_common_datum(sepol_handle_t *handle, const common_datum_t *common) +-{ +- if (common->permissions.nprim > PERM_SYMTAB_SIZE) +- goto bad; +- +- return 0; +- +-bad: +- ERR(handle, "Invalid common class datum"); +- return -1; +-} +- +-static int validate_common_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) +-{ +- map_arg_t *margs = args; +- +- return validate_common_datum(margs->handle, d); +-} +- + static int validate_role_datum(sepol_handle_t *handle, const role_datum_t *role, validate_t flavors[]) + { + if (validate_value(role->s.value, &flavors[SYM_ROLES])) +@@ -437,6 +446,14 @@ static int validate_role_datum(sepol_handle_t *handle, const role_datum_t *role, + if (validate_ebitmap(&role->roles, &flavors[SYM_ROLES])) + goto bad; + ++ switch(role->flavor) { ++ case ROLE_ROLE: ++ case ROLE_ATTRIB: ++ break; ++ default: ++ goto bad; ++ } ++ + return 0; + + bad: +@@ -451,19 +468,46 @@ static int validate_role_datum_wrapper(__attribute__((unused)) hashtab_key_t k, + return validate_role_datum(margs->handle, d, margs->flavors); + } + +-static int validate_type_datum(sepol_handle_t *handle, const type_datum_t *type, validate_t flavors[]) ++static int validate_simpletype(uint32_t value, const policydb_t *p, validate_t flavors[]) + { +- if (validate_value(type->s.value, &flavors[SYM_TYPES])) ++ const type_datum_t *type; ++ ++ if (validate_value(value, &flavors[SYM_TYPES])) ++ goto bad; ++ ++ type = p->type_val_to_struct[value - 1]; ++ if (!type) + goto bad; +- if (validate_ebitmap(&type->types, &flavors[SYM_TYPES])) ++ ++ if (type->flavor == TYPE_ATTRIB) ++ goto bad; ++ ++ return 0; ++ ++bad: ++ return -1; ++} ++ ++static int validate_type_datum(sepol_handle_t *handle, const type_datum_t *type, const policydb_t *p, validate_t flavors[]) ++{ ++ if (validate_value(type->s.value, &flavors[SYM_TYPES])) + goto bad; +- if (type->bounds && validate_value(type->bounds, &flavors[SYM_TYPES])) ++ if (type->primary && validate_value(type->primary, &flavors[SYM_TYPES])) + goto bad; + + switch (type->flavor) { + case TYPE_TYPE: +- case TYPE_ATTRIB: + case TYPE_ALIAS: ++ if (!ebitmap_is_empty(&type->types)) ++ goto bad; ++ if (type->bounds && validate_simpletype(type->bounds, p, flavors)) ++ goto bad; ++ break; ++ case TYPE_ATTRIB: ++ if (validate_ebitmap(&type->types, &flavors[SYM_TYPES])) ++ goto bad; ++ if (type->bounds) ++ goto bad; + break; + default: + goto bad; +@@ -491,7 +535,7 @@ static int validate_type_datum_wrapper(__attribute__((unused)) hashtab_key_t k, + { + map_arg_t *margs = args; + +- return validate_type_datum(margs->handle, d, margs->flavors); ++ return validate_type_datum(margs->handle, d, margs->policy, margs->flavors); + } + + static int validate_mls_semantic_cat(const mls_semantic_cat_t *cat, const validate_t *cats) +@@ -758,22 +802,42 @@ bad: + return -1; + } + ++static int validate_xperms(const avtab_extended_perms_t *xperms) ++{ ++ switch (xperms->specified) { ++ case AVTAB_XPERMS_IOCTLDRIVER: ++ case AVTAB_XPERMS_IOCTLFUNCTION: ++ break; ++ default: ++ goto bad; ++ } ++ ++ return 0; ++ ++bad: ++ return -1; ++} + static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void *args) + { +- validate_t *flavors = (validate_t *)args; ++ map_arg_t *margs = args; ++ ++ if (validate_avtab_key(k, 0, margs->flavors)) ++ return -1; + +- if (validate_avtab_key(k, 0, flavors)) ++ if ((k->specified & AVTAB_TYPE) && validate_simpletype(d->data, margs->policy, margs->flavors)) + return -1; + +- if ((k->specified & AVTAB_TYPE) && validate_value(d->data, &flavors[SYM_TYPES])) ++ if ((k->specified & AVTAB_XPERMS) && validate_xperms(d->xperms)) + return -1; + + return 0; + } + +-static int validate_avtab(sepol_handle_t *handle, const avtab_t *avtab, validate_t flavors[]) ++static int validate_avtab(sepol_handle_t *handle, const avtab_t *avtab, const policydb_t *p, validate_t flavors[]) + { +- if (avtab_map(avtab, validate_avtab_key_and_datum, flavors)) { ++ map_arg_t margs = { flavors, handle, p }; ++ ++ if (avtab_map(avtab, validate_avtab_key_and_datum, &margs)) { + ERR(handle, "Invalid avtab"); + return -1; + } +@@ -797,20 +861,15 @@ static int validate_cond_av_list(sepol_handle_t *handle, const cond_av_list_t *c + return 0; + } + +-static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int conditional, validate_t flavors[]) ++static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int conditional, const policydb_t *p, validate_t flavors[]) + { +- const class_perm_node_t *class; ++ const class_perm_node_t *classperm; + + for (; avrule; avrule = avrule->next) { + if (validate_type_set(&avrule->stypes, &flavors[SYM_TYPES])) + goto bad; + if (validate_type_set(&avrule->ttypes, &flavors[SYM_TYPES])) + goto bad; +- class = avrule->perms; +- for (; class; class = class->next) { +- if (validate_value(class->tclass, &flavors[SYM_CLASSES])) +- goto bad; +- } + + switch(avrule->specified) { + case AVRULE_ALLOWED: +@@ -833,6 +892,13 @@ static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int + goto bad; + } + ++ for (classperm = avrule->perms; classperm; classperm = classperm->next) { ++ if (validate_value(classperm->tclass, &flavors[SYM_CLASSES])) ++ goto bad; ++ if ((avrule->specified & AVRULE_TYPE) && validate_simpletype(classperm->data, p, flavors)) ++ goto bad; ++ } ++ + if (avrule->specified & AVRULE_XPERMS) { + if (!avrule->xperms) + goto bad; +@@ -885,6 +951,9 @@ static int validate_cond_expr(sepol_handle_t *handle, const struct cond_expr *ex + { + int depth = -1; + ++ if (!expr) ++ goto bad; ++ + for (; expr; expr = expr->next) { + switch(expr->expr_type) { + case COND_BOOL: +@@ -922,7 +991,7 @@ bad: + return -1; + } + +-static int validate_cond_list(sepol_handle_t *handle, const cond_list_t *cond, validate_t flavors[]) ++static int validate_cond_list(sepol_handle_t *handle, const cond_list_t *cond, const policydb_t *p, validate_t flavors[]) + { + for (; cond; cond = cond->next) { + if (validate_cond_expr(handle, cond->expr, &flavors[SYM_BOOLS])) +@@ -931,12 +1000,28 @@ static int validate_cond_list(sepol_handle_t *handle, const cond_list_t *cond, v + goto bad; + if (validate_cond_av_list(handle, cond->false_list, flavors)) + goto bad; +- if (validate_avrules(handle, cond->avtrue_list, 1, flavors)) ++ if (validate_avrules(handle, cond->avtrue_list, 1, p, flavors)) + goto bad; +- if (validate_avrules(handle, cond->avfalse_list, 1, flavors)) ++ if (validate_avrules(handle, cond->avfalse_list, 1, p, flavors)) + goto bad; + if (validate_bool_id_array(handle, cond->bool_ids, cond->nbools, &flavors[SYM_BOOLS])) + goto bad; ++ ++ switch (cond->cur_state) { ++ case 0: ++ case 1: ++ break; ++ default: ++ goto bad; ++ } ++ ++ switch (cond->flags) { ++ case 0: ++ case COND_NODE_FLAGS_TUNABLE: ++ break; ++ default: ++ goto bad; ++ } + } + + return 0; +@@ -992,6 +1077,8 @@ static int validate_filename_trans(hashtab_key_t k, hashtab_datum_t d, void *arg + goto bad; + if (validate_value(ftk->tclass, &flavors[SYM_CLASSES])) + goto bad; ++ if (!ftd) ++ goto bad; + for (; ftd; ftd = ftd->next) { + if (validate_ebitmap(&ftd->stypes, &flavors[SYM_TYPES])) + goto bad; +@@ -1046,6 +1133,10 @@ static int validate_ocontexts(sepol_handle_t *handle, const policydb_t *p, valid + if (validate_context(&octx->context[1], flavors, p->mls)) + goto bad; + break; ++ case OCON_PORT: ++ if (octx->u.port.low_port > octx->u.port.high_port) ++ goto bad; ++ break; + case OCON_FSUSE: + switch (octx->v.behavior) { + case SECURITY_FS_USE_XATTR: +@@ -1076,7 +1167,12 @@ static int validate_genfs(sepol_handle_t *handle, const policydb_t *p, validate_ + for (octx = genfs->head; octx; octx = octx->next) { + if (validate_context(&octx->context[0], flavors, p->mls)) + goto bad; ++ if (octx->v.sclass && validate_value(octx->v.sclass, &flavors[SYM_CLASSES])) ++ goto bad; + } ++ ++ if (!genfs->fstype) ++ goto bad; + } + + return 0; +@@ -1173,7 +1269,7 @@ bad: + } + + +-static int validate_filename_trans_rules(sepol_handle_t *handle, const filename_trans_rule_t *filename_trans, validate_t flavors[]) ++static int validate_filename_trans_rules(sepol_handle_t *handle, const filename_trans_rule_t *filename_trans, const policydb_t *p, validate_t flavors[]) + { + for (; filename_trans; filename_trans = filename_trans->next) { + if (validate_type_set(&filename_trans->stypes, &flavors[SYM_TYPES])) +@@ -1182,7 +1278,7 @@ static int validate_filename_trans_rules(sepol_handle_t *handle, const filename_ + goto bad; + if (validate_value(filename_trans->tclass,&flavors[SYM_CLASSES] )) + goto bad; +- if (validate_value(filename_trans->otype, &flavors[SYM_TYPES])) ++ if (validate_simpletype(filename_trans->otype, p, flavors)) + goto bad; + + /* currently only the RULE_SELF flag can be set */ +@@ -1211,15 +1307,15 @@ static int validate_symtabs(sepol_handle_t *handle, const symtab_t symtabs[], va + return 0; + } + +-static int validate_avrule_blocks(sepol_handle_t *handle, const avrule_block_t *avrule_block, validate_t flavors[]) ++static int validate_avrule_blocks(sepol_handle_t *handle, const avrule_block_t *avrule_block, const policydb_t *p, validate_t flavors[]) + { + const avrule_decl_t *decl; + + for (; avrule_block; avrule_block = avrule_block->next) { + for (decl = avrule_block->branch_list; decl != NULL; decl = decl->next) { +- if (validate_cond_list(handle, decl->cond_list, flavors)) ++ if (validate_cond_list(handle, decl->cond_list, p, flavors)) + goto bad; +- if (validate_avrules(handle, decl->avrules, 0, flavors)) ++ if (validate_avrules(handle, decl->avrules, 0, p, flavors)) + goto bad; + if (validate_role_trans_rules(handle, decl->role_tr_rules, flavors)) + goto bad; +@@ -1231,7 +1327,7 @@ static int validate_avrule_blocks(sepol_handle_t *handle, const avrule_block_t * + goto bad; + if (validate_scope_index(handle, &decl->declared, flavors)) + goto bad; +- if (validate_filename_trans_rules(handle, decl->filename_trans_rules, flavors)) ++ if (validate_filename_trans_rules(handle, decl->filename_trans_rules, p, flavors)) + goto bad; + if (validate_symtabs(handle, decl->symtab, flavors)) + goto bad; +@@ -1259,7 +1355,7 @@ static int validate_permissives(sepol_handle_t *handle, const policydb_t *p, val + unsigned i; + + ebitmap_for_each_positive_bit(&p->permissive_map, node, i) { +- if (validate_value(i, &flavors[SYM_TYPES])) ++ if (validate_simpletype(i, p, flavors)) + goto bad; + } + +@@ -1270,6 +1366,61 @@ bad: + return -1; + } + ++static int validate_range_transition(hashtab_key_t key, hashtab_datum_t data, void *args) ++{ ++ const range_trans_t *rt = (const range_trans_t *)key; ++ const mls_range_t *r = data; ++ const map_arg_t *margs = args; ++ const validate_t *flavors = margs->flavors; ++ ++ if (validate_value(rt->source_type, &flavors[SYM_TYPES])) ++ goto bad; ++ if (validate_value(rt->target_type, &flavors[SYM_TYPES])) ++ goto bad; ++ if (validate_value(rt->target_class, &flavors[SYM_CLASSES])) ++ goto bad; ++ ++ if (validate_mls_range(r, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) ++ goto bad; ++ ++ return 0; ++ ++bad: ++ return -1; ++} ++ ++static int validate_range_transitions(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) ++{ ++ map_arg_t margs = { flavors, handle, p }; ++ ++ if (hashtab_map(p->range_tr, validate_range_transition, &margs)) { ++ ERR(handle, "Invalid range transition"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int validate_typeattr_map(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) ++{ ++ const ebitmap_t *maps = p->type_attr_map; ++ unsigned int i; ++ ++ if (p->policy_type == POLICY_KERN) { ++ for (i = 0; i < p->p_types.nprim; i++) { ++ if (validate_ebitmap(&maps[i], &flavors[SYM_TYPES])) ++ goto bad; ++ } ++ } else if (maps) ++ goto bad; ++ ++ return 0; ++ ++bad: ++ ERR(handle, "Invalid type attr map"); ++ return -1; ++} ++ + static int validate_properties(sepol_handle_t *handle, const policydb_t *p) + { + switch (p->policy_type) { +@@ -1341,10 +1492,10 @@ int policydb_validate(sepol_handle_t *handle, const policydb_t *p) + goto bad; + + if (p->policy_type == POLICY_KERN) { +- if (validate_avtab(handle, &p->te_avtab, flavors)) ++ if (validate_avtab(handle, &p->te_avtab, p, flavors)) + goto bad; + if (p->policyvers >= POLICYDB_VERSION_BOOL) +- if (validate_cond_list(handle, p->cond_list, flavors)) ++ if (validate_cond_list(handle, p->cond_list, p, flavors)) + goto bad; + if (validate_role_transes(handle, p->role_tr, flavors)) + goto bad; +@@ -1354,7 +1505,7 @@ int policydb_validate(sepol_handle_t *handle, const policydb_t *p) + if (validate_filename_trans_hashtab(handle, p->filename_trans, flavors)) + goto bad; + } else { +- if (validate_avrule_blocks(handle, p->global, flavors)) ++ if (validate_avrule_blocks(handle, p->global, p, flavors)) + goto bad; + } + +@@ -1376,6 +1527,14 @@ int policydb_validate(sepol_handle_t *handle, const policydb_t *p) + if (validate_permissives(handle, p, flavors)) + goto bad; + ++ if (validate_range_transitions(handle, p, flavors)) ++ goto bad; ++ ++ if (p->policyvers >= POLICYDB_VERSION_AVTAB) { ++ if (validate_typeattr_map(handle, p, flavors)) ++ goto bad; ++ } ++ + validate_array_destroy(flavors); + + return 0; +-- +2.38.1 + diff --git a/0022-libsepol-refactor-ebitmap-conversion-in-link.c.patch b/0022-libsepol-refactor-ebitmap-conversion-in-link.c.patch new file mode 100644 index 0000000..7515795 --- /dev/null +++ b/0022-libsepol-refactor-ebitmap-conversion-in-link.c.patch @@ -0,0 +1,312 @@ +From 1e3c557425d03130887821675aee1beeb7c9cd9d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 21 Jul 2022 17:05:08 +0200 +Subject: [PATCH] libsepol: refactor ebitmap conversion in link.c +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Refactor the ebitmap conversions in link.c into its own function. + +Do not log an OOM message twice on type_set_or_convert() failure. + +Drop the now unused state parameter from type_set_or_convert() and +type_set_convert(). + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/link.c | 140 +++++++++++++++----------------------------- + 1 file changed, 47 insertions(+), 93 deletions(-) + +diff --git a/libsepol/src/link.c b/libsepol/src/link.c +index 7e8313cbc391..cbe4cea40123 100644 +--- a/libsepol/src/link.c ++++ b/libsepol/src/link.c +@@ -958,26 +958,28 @@ static int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum, + + /*********** callbacks that fix bitmaps ***********/ + +-static int type_set_convert(type_set_t * types, type_set_t * dst, +- policy_module_t * mod, link_state_t * state +- __attribute__ ((unused))) ++static int ebitmap_convert(const ebitmap_t *src, ebitmap_t *dst, const uint32_t *map) + { +- unsigned int i; +- ebitmap_node_t *tnode; +- ebitmap_for_each_positive_bit(&types->types, tnode, i) { +- assert(mod->map[SYM_TYPES][i]); +- if (ebitmap_set_bit +- (&dst->types, mod->map[SYM_TYPES][i] - 1, 1)) { +- goto cleanup; +- } +- } +- ebitmap_for_each_positive_bit(&types->negset, tnode, i) { +- assert(mod->map[SYM_TYPES][i]); +- if (ebitmap_set_bit +- (&dst->negset, mod->map[SYM_TYPES][i] - 1, 1)) { +- goto cleanup; +- } ++ unsigned int bit; ++ ebitmap_node_t *node; ++ ebitmap_for_each_positive_bit(src, node, bit) { ++ assert(map[bit]); ++ if (ebitmap_set_bit(dst, map[bit] - 1, 1)) ++ return -1; + } ++ ++ return 0; ++} ++ ++static int type_set_convert(const type_set_t * types, type_set_t * dst, ++ const policy_module_t * mod) ++{ ++ if (ebitmap_convert(&types->types, &dst->types, mod->map[SYM_TYPES])) ++ goto cleanup; ++ ++ if (ebitmap_convert(&types->negset, &dst->negset, mod->map[SYM_TYPES])) ++ goto cleanup; ++ + dst->flags = types->flags; + return 0; + +@@ -988,13 +990,13 @@ static int type_set_convert(type_set_t * types, type_set_t * dst, + /* OR 2 typemaps together and at the same time map the src types to + * the correct values in the dst typeset. + */ +-static int type_set_or_convert(type_set_t * types, type_set_t * dst, +- policy_module_t * mod, link_state_t * state) ++static int type_set_or_convert(const type_set_t * types, type_set_t * dst, ++ const policy_module_t * mod) + { + type_set_t ts_tmp; + + type_set_init(&ts_tmp); +- if (type_set_convert(types, &ts_tmp, mod, state) == -1) { ++ if (type_set_convert(types, &ts_tmp, mod) == -1) { + goto cleanup; + } + if (type_set_or_eq(dst, &ts_tmp)) { +@@ -1004,7 +1006,6 @@ static int type_set_or_convert(type_set_t * types, type_set_t * dst, + return 0; + + cleanup: +- ERR(state->handle, "Out of memory!"); + type_set_destroy(&ts_tmp); + return -1; + } +@@ -1012,18 +1013,11 @@ static int type_set_or_convert(type_set_t * types, type_set_t * dst, + static int role_set_or_convert(role_set_t * roles, role_set_t * dst, + policy_module_t * mod, link_state_t * state) + { +- unsigned int i; + ebitmap_t tmp; +- ebitmap_node_t *rnode; + + ebitmap_init(&tmp); +- ebitmap_for_each_positive_bit(&roles->roles, rnode, i) { +- assert(mod->map[SYM_ROLES][i]); +- if (ebitmap_set_bit +- (&tmp, mod->map[SYM_ROLES][i] - 1, 1)) { +- goto cleanup; +- } +- } ++ if (ebitmap_convert(&roles->roles, &tmp, mod->map[SYM_ROLES])) ++ goto cleanup; + if (ebitmap_union(&dst->roles, &tmp)) { + goto cleanup; + } +@@ -1088,13 +1082,11 @@ static int mls_range_convert(mls_semantic_range_t * src, mls_semantic_range_t * + static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum, + void *data) + { +- unsigned int i; + char *id = key; + role_datum_t *role, *dest_role = NULL; + link_state_t *state = (link_state_t *) data; + ebitmap_t e_tmp; + policy_module_t *mod = state->cur; +- ebitmap_node_t *rnode; + hashtab_t role_tab; + + role = (role_datum_t *) datum; +@@ -1111,30 +1103,20 @@ static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum, + } + + ebitmap_init(&e_tmp); +- ebitmap_for_each_positive_bit(&role->dominates, rnode, i) { +- assert(mod->map[SYM_ROLES][i]); +- if (ebitmap_set_bit +- (&e_tmp, mod->map[SYM_ROLES][i] - 1, 1)) { +- goto cleanup; +- } +- } ++ if (ebitmap_convert(&role->dominates, &e_tmp, mod->map[SYM_ROLES])) ++ goto cleanup; + if (ebitmap_union(&dest_role->dominates, &e_tmp)) { + goto cleanup; + } +- if (type_set_or_convert(&role->types, &dest_role->types, mod, state)) { ++ if (type_set_or_convert(&role->types, &dest_role->types, mod)) { + goto cleanup; + } + ebitmap_destroy(&e_tmp); + + if (role->flavor == ROLE_ATTRIB) { + ebitmap_init(&e_tmp); +- ebitmap_for_each_positive_bit(&role->roles, rnode, i) { +- assert(mod->map[SYM_ROLES][i]); +- if (ebitmap_set_bit +- (&e_tmp, mod->map[SYM_ROLES][i] - 1, 1)) { +- goto cleanup; +- } +- } ++ if (ebitmap_convert(&role->roles, &e_tmp, mod->map[SYM_ROLES])) ++ goto cleanup; + if (ebitmap_union(&dest_role->roles, &e_tmp)) { + goto cleanup; + } +@@ -1152,13 +1134,11 @@ static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum, + static int type_fix_callback(hashtab_key_t key, hashtab_datum_t datum, + void *data) + { +- unsigned int i; + char *id = key; + type_datum_t *type, *new_type = NULL; + link_state_t *state = (link_state_t *) data; + ebitmap_t e_tmp; + policy_module_t *mod = state->cur; +- ebitmap_node_t *tnode; + symtab_t *typetab; + + type = (type_datum_t *) datum; +@@ -1181,13 +1161,8 @@ static int type_fix_callback(hashtab_key_t key, hashtab_datum_t datum, + } + + ebitmap_init(&e_tmp); +- ebitmap_for_each_positive_bit(&type->types, tnode, i) { +- assert(mod->map[SYM_TYPES][i]); +- if (ebitmap_set_bit +- (&e_tmp, mod->map[SYM_TYPES][i] - 1, 1)) { +- goto cleanup; +- } +- } ++ if (ebitmap_convert(&type->types, &e_tmp, mod->map[SYM_TYPES])) ++ goto cleanup; + if (ebitmap_union(&new_type->types, &e_tmp)) { + goto cleanup; + } +@@ -1269,9 +1244,8 @@ static int copy_avrule_list(avrule_t * list, avrule_t ** dst, + new_rule->specified = cur->specified; + new_rule->flags = cur->flags; + if (type_set_convert +- (&cur->stypes, &new_rule->stypes, module, state) == -1 +- || type_set_convert(&cur->ttypes, &new_rule->ttypes, module, +- state) == -1) { ++ (&cur->stypes, &new_rule->stypes, module) == -1 ++ || type_set_convert(&cur->ttypes, &new_rule->ttypes, module) == -1) { + goto cleanup; + } + +@@ -1355,8 +1329,6 @@ static int copy_role_trans_list(role_trans_rule_t * list, + policy_module_t * module, link_state_t * state) + { + role_trans_rule_t *cur, *new_rule = NULL, *tail; +- unsigned int i; +- ebitmap_node_t *cnode; + + cur = list; + tail = *dst; +@@ -1374,19 +1346,12 @@ static int copy_role_trans_list(role_trans_rule_t * list, + if (role_set_or_convert + (&cur->roles, &new_rule->roles, module, state) + || type_set_or_convert(&cur->types, &new_rule->types, +- module, state)) { ++ module)) { + goto cleanup; + } + +- ebitmap_for_each_positive_bit(&cur->classes, cnode, i) { +- assert(module->map[SYM_CLASSES][i]); +- if (ebitmap_set_bit(&new_rule->classes, +- module-> +- map[SYM_CLASSES][i] - 1, +- 1)) { +- goto cleanup; +- } +- } ++ if (ebitmap_convert(&cur->classes, &new_rule->classes, module->map[SYM_CLASSES])) ++ goto cleanup; + + new_rule->new_role = module->map[SYM_ROLES][cur->new_role - 1]; + +@@ -1476,8 +1441,8 @@ static int copy_filename_trans_list(filename_trans_rule_t * list, + if (!new_rule->name) + goto err; + +- if (type_set_or_convert(&cur->stypes, &new_rule->stypes, module, state) || +- type_set_or_convert(&cur->ttypes, &new_rule->ttypes, module, state)) ++ if (type_set_or_convert(&cur->stypes, &new_rule->stypes, module) || ++ type_set_or_convert(&cur->ttypes, &new_rule->ttypes, module)) + goto err; + + new_rule->tclass = module->map[SYM_CLASSES][cur->tclass - 1]; +@@ -1497,8 +1462,6 @@ static int copy_range_trans_list(range_trans_rule_t * rules, + policy_module_t * mod, link_state_t * state) + { + range_trans_rule_t *rule, *new_rule = NULL; +- unsigned int i; +- ebitmap_node_t *cnode; + + for (rule = rules; rule; rule = rule->next) { + new_rule = +@@ -1512,21 +1475,15 @@ static int copy_range_trans_list(range_trans_rule_t * rules, + *dst = new_rule; + + if (type_set_convert(&rule->stypes, &new_rule->stypes, +- mod, state)) ++ mod)) + goto cleanup; + + if (type_set_convert(&rule->ttypes, &new_rule->ttypes, +- mod, state)) ++ mod)) + goto cleanup; + +- ebitmap_for_each_positive_bit(&rule->tclasses, cnode, i) { +- assert(mod->map[SYM_CLASSES][i]); +- if (ebitmap_set_bit +- (&new_rule->tclasses, +- mod->map[SYM_CLASSES][i] - 1, 1)) { +- goto cleanup; +- } +- } ++ if (ebitmap_convert(&rule->tclasses, &new_rule->tclasses, mod->map[SYM_CLASSES])) ++ goto cleanup; + + if (mls_range_convert(&rule->trange, &new_rule->trange, mod, state)) + goto cleanup; +@@ -1688,15 +1645,12 @@ static int copy_scope_index(scope_index_t * src, scope_index_t * dest, + } + dest->class_perms_len = largest_mapped_class_value; + for (i = 0; i < src->class_perms_len; i++) { +- ebitmap_t *srcmap = src->class_perms_map + i; ++ const ebitmap_t *srcmap = src->class_perms_map + i; + ebitmap_t *destmap = + dest->class_perms_map + module->map[SYM_CLASSES][i] - 1; +- ebitmap_for_each_positive_bit(srcmap, node, j) { +- if (ebitmap_set_bit(destmap, module->perm_map[i][j] - 1, +- 1)) { +- goto cleanup; +- } +- } ++ ++ if (ebitmap_convert(srcmap, destmap, module->perm_map[i])) ++ goto cleanup; + } + + return 0; +-- +2.38.1 + diff --git a/0023-libsepol-fix-missing-double-quotes-in-typetransition.patch b/0023-libsepol-fix-missing-double-quotes-in-typetransition.patch new file mode 100644 index 0000000..bc1940e --- /dev/null +++ b/0023-libsepol-fix-missing-double-quotes-in-typetransition.patch @@ -0,0 +1,34 @@ +From eca72d8e47ac8b962f87c46aa77fb893aa0df0f8 Mon Sep 17 00:00:00 2001 +From: Juraj Marcin +Date: Thu, 25 Aug 2022 15:27:18 +0200 +Subject: [PATCH] libsepol: fix missing double quotes in typetransition CIL + rule +Content-type: text/plain + +CIL Reference Guide defines typetransition rule with double quotes +around object name, but those are not present in the format string. + +This patch fixes this issue, so the CIL output produced by +sepol_kernel_policydb_to_cil() is in the correct format. + +Signed-off-by: Juraj Marcin +--- + libsepol/src/kernel_to_cil.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c +index 5a1336a33031..ad4121d50ae1 100644 +--- a/libsepol/src/kernel_to_cil.c ++++ b/libsepol/src/kernel_to_cil.c +@@ -1894,7 +1894,7 @@ static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg) + 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)", ++ "(typetransition %s %s %s \"%s\" %s)", + 5, src, tgt, class, filename, new); + if (rc) + return rc; +-- +2.38.1 + diff --git a/0024-docs-provide-a-top-level-LICENSE-file.patch b/0024-docs-provide-a-top-level-LICENSE-file.patch new file mode 100644 index 0000000..a26d6fa --- /dev/null +++ b/0024-docs-provide-a-top-level-LICENSE-file.patch @@ -0,0 +1,26 @@ +From a0a216ff7d86004ddc36d516377f0a6ffe88076c Mon Sep 17 00:00:00 2001 +From: Paul Moore +Date: Fri, 30 Sep 2022 17:44:12 -0400 +Subject: [PATCH] docs: provide a top level LICENSE file +Content-type: text/plain + +Provide a top level LICENSE file explaining how multiple the SELinux +userspace is released under multiple different licenses. Also ensure +that all the different license files share a consistent file name, +LICENSE, to make it easier for people to identify the license files. + +This is to help meet the OpenSSF Best Practices requirements. + +Signed-off-by: Paul Moore +--- + libsepol/{COPYING => LICENSE} | 0 + 1 file changed, 0 insertions(+), 0 deletions(-) + rename libsepol/{COPYING => LICENSE} (100%) + +diff --git a/libsepol/COPYING b/libsepol/LICENSE +similarity index 100% +rename from libsepol/COPYING +rename to libsepol/LICENSE +-- +2.38.1 + diff --git a/0025-libsepol-cil-restore-error-on-context-rule-conflicts.patch b/0025-libsepol-cil-restore-error-on-context-rule-conflicts.patch new file mode 100644 index 0000000..47d1902 --- /dev/null +++ b/0025-libsepol-cil-restore-error-on-context-rule-conflicts.patch @@ -0,0 +1,51 @@ +From 3f11c7d19c449996d7c34190d6aa74220b104779 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 12 Oct 2022 16:27:51 +0200 +Subject: [PATCH] libsepol/cil: restore error on context rule conflicts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Commit bc26ddc59c8d ("libsepol/cil: Limit the amount of reporting for +context rule conflicts") reworked the processing of context rule +conflicts to limit the number of written conflicting statements to +increase readability of the printed error message. It forgot to set the +return value, signaling a context conflict, in the case the logging +level is higher than warning (e.g. in semodule(8), which defaults to +error). + +Reported-by: Milos Malik [1] +Fixes: bc26ddc59c8d ("libsepol/cil: Limit the amount of reporting for context rule conflicts") + +[1]: https://lore.kernel.org/selinux/87y1u1rkoo.fsf@redhat.com/ + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/cil/src/cil_post.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c +index 6e95225f93f1..11e572e274aa 100644 +--- a/libsepol/cil/src/cil_post.c ++++ b/libsepol/cil/src/cil_post.c +@@ -2290,6 +2290,7 @@ static int __cil_post_process_context_rules(struct cil_sort *sort, int (*compar) + } else { + removed++; + if (!db->multiple_decls || concompar(&sort->array[i], &sort->array[j]) != 0) { ++ rc = SEPOL_ERR; + conflicting++; + if (log_level >= CIL_WARN) { + struct cil_list_item li; +@@ -2297,7 +2298,6 @@ static int __cil_post_process_context_rules(struct cil_sort *sort, int (*compar) + li.flavor = flavor; + if (conflicting == 1) { + cil_log(CIL_WARN, "Found conflicting %s rules\n", flavor_str); +- rc = SEPOL_ERR; + li.data = sort->array[i]; + rc2 = cil_tree_walk(db->ast->root, __cil_post_report_conflict, + NULL, NULL, &li); +-- +2.38.1 + diff --git a/libsepol.spec b/libsepol.spec index 739050e..fcd3105 100644 --- a/libsepol.spec +++ b/libsepol.spec @@ -1,7 +1,7 @@ Summary: SELinux binary policy manipulation library Name: libsepol Version: 3.4 -Release: 3%{?dist} +Release: 4%{?dist} License: LGPL-2.1-or-later Source0: https://github.com/SELinuxProject/selinux/releases/download/3.4/libsepol-3.4.tar.gz URL: https://github.com/SELinuxProject/selinux/wiki @@ -10,6 +10,31 @@ URL: https://github.com/SELinuxProject/selinux/wiki # $ git format-patch -N libsepol-3.4 -- libsepol # $ i=1; for j in 0*patch; do printf "Patch%04d: %s\n" $i $j; i=$((i+1));done # Patch list start +Patch0001: 0001-libsepol-Drop-unused-assignment.patch +Patch0002: 0002-libsepol-fix-validation-of-user-declarations-in-modu.patch +Patch0003: 0003-libsepol-avoid-potential-NULL-dereference-on-optiona.patch +Patch0004: 0004-libsepol-initialize-s-in-constraint_expr_eval_reason.patch +Patch0005: 0005-libsepol-utils-improve-wording.patch +Patch0006: 0006-libsepol-do-not-modify-policy-during-write.patch +Patch0007: 0007-libsepol-break-circular-include.patch +Patch0008: 0008-libsepol-include-necessary-headers-in-headers.patch +Patch0009: 0009-libsepol-enclose-macro-parameters-and-replacement-li.patch +Patch0010: 0010-libsepol-tests-add-ebitmap-tests.patch +Patch0011: 0011-libsepol-add-ebitmap_init_range.patch +Patch0012: 0012-libsepol-cil-use-ebitmap_init_range.patch +Patch0013: 0013-libsepol-optimize-ebitmap_not.patch +Patch0014: 0014-libsepol-optimize-ebitmap_and.patch +Patch0015: 0015-libsepol-optimize-ebitmap_xor.patch +Patch0016: 0016-libsepol-skip-superfluous-memset-calls-in-ebitmap-op.patch +Patch0017: 0017-libsepol-rename-validate_policydb-to-policydb_valida.patch +Patch0018: 0018-libsepol-support-const-avtab_t-pointer-in-avtab_map.patch +Patch0019: 0019-libsepol-operate-on-const-pointers-during-validation.patch +Patch0020: 0020-libsepol-rename-parameter-name.patch +Patch0021: 0021-libsepol-more-strict-validation.patch +Patch0022: 0022-libsepol-refactor-ebitmap-conversion-in-link.c.patch +Patch0023: 0023-libsepol-fix-missing-double-quotes-in-typetransition.patch +Patch0024: 0024-docs-provide-a-top-level-LICENSE-file.patch +Patch0025: 0025-libsepol-cil-restore-error-on-context-rule-conflicts.patch # Patch list end BuildRequires: make BuildRequires: gcc @@ -93,7 +118,7 @@ rm -rf ${RPM_BUILD_ROOT}%{_mandir}/ru/man8 %{_includedir}/sepol/cil/*.h %files -%license COPYING +%license LICENSE %{_libdir}/libsepol.so.2 %files utils @@ -106,6 +131,9 @@ rm -rf ${RPM_BUILD_ROOT}%{_mandir}/ru/man8 %{_mandir}/man8/chkcon.8.gz %changelog +* Mon Nov 21 2022 Petr Lautrbach - 3.4-4 +- Rebase on upstream f56a72ac9e86 + * Thu Jul 21 2022 Fedora Release Engineering - 3.4-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild