From 713312fdfd4a4abde64372ed3a1604db9b36d21c Mon Sep 17 00:00:00 2001 From: jinlun Date: Tue, 11 Jun 2024 10:56:11 +0800 Subject: [PATCH] Synchronize the code to be consistent with 22.03-LTS-SP3 --- backport-hashtab-update.patch | 91 +++++++ ...pol-Validate-conditional-expressions.patch | 75 +++++ ...ck-for-category-value-before-printin.patch | 35 +++ ...pol-adjust-type-for-saturation-check.patch | 39 +++ ...avoid-integer-overflow-in-add_i_to_a.patch | 34 +++ ...rt-libsepol-avoid-leak-in-OOM-branch.patch | 39 +++ ...memory-corruption-on-realloc-failure.patch | 63 +++++ ...tab-check-read-counts-for-saturation.patch | 37 +++ ...epol-check-for-overflow-in-put_entry.patch | 33 +++ ...not-allow-classpermissionset-to-use-.patch | 87 ++++++ ...class-permission-verification-in-CIL.patch | 257 ++++++++++++++++++ ...-non-mls-validatetrans-rules-as-such.patch | 51 ++++ ...rt-libsepol-enhance-saturation-check.patch | 133 +++++++++ ...ort-libsepol-expand-skip-invalid-cat.patch | 38 +++ ...al-type-to-avoid-implicit-conversion.patch | 28 ++ ...port-libsepol-more-strict-validation.patch | 55 ++++ ...avtab-entries-with-invalid-specifier.patch | 61 +++++ ...libsepol-reject-invalid-class-datums.patch | 54 ++++ ...ject-linking-modules-with-no-avrules.patch | 47 ++++ ...ject-unsupported-policy-capabilities.patch | 75 +++++ ...se-correct-type-to-avoid-truncations.patch | 50 ++++ backport-libsepol-validate-MLS-levels.patch | 67 +++++ ...low-category-is-not-bigger-than-high.patch | 28 ++ ...e-empty-common-classes-in-scope-indi.patch | 35 +++ ...lidate-expanded-user-range-and-level.patch | 80 ++++++ backport-libsepol-validate-ocontexts.patch | 103 +++++++ ...lidate-old-style-range-trans-classes.patch | 41 +++ ...e-the-identifier-for-initials-SID-is.patch | 50 ++++ libsepol.spec | 40 ++- 29 files changed, 1823 insertions(+), 3 deletions(-) create mode 100644 backport-hashtab-update.patch create mode 100644 backport-libsepol-Validate-conditional-expressions.patch create mode 100644 backport-libsepol-add-check-for-category-value-before-printin.patch create mode 100644 backport-libsepol-adjust-type-for-saturation-check.patch create mode 100644 backport-libsepol-avoid-integer-overflow-in-add_i_to_a.patch create mode 100644 backport-libsepol-avoid-leak-in-OOM-branch.patch create mode 100644 backport-libsepol-avoid-memory-corruption-on-realloc-failure.patch create mode 100644 backport-libsepol-avtab-check-read-counts-for-saturation.patch create mode 100644 backport-libsepol-check-for-overflow-in-put_entry.patch create mode 100644 backport-libsepol-cil-Do-not-allow-classpermissionset-to-use-.patch create mode 100644 backport-libsepol-cil-Fix-class-permission-verification-in-CIL.patch create mode 100644 backport-libsepol-dump-non-mls-validatetrans-rules-as-such.patch create mode 100644 backport-libsepol-enhance-saturation-check.patch create mode 100644 backport-libsepol-expand-skip-invalid-cat.patch create mode 100644 backport-libsepol-expand-use-identical-type-to-avoid-implicit-conversion.patch create mode 100644 backport-libsepol-more-strict-validation.patch create mode 100644 backport-libsepol-reject-avtab-entries-with-invalid-specifier.patch create mode 100644 backport-libsepol-reject-invalid-class-datums.patch create mode 100644 backport-libsepol-reject-linking-modules-with-no-avrules.patch create mode 100644 backport-libsepol-reject-unsupported-policy-capabilities.patch create mode 100644 backport-libsepol-use-correct-type-to-avoid-truncations.patch create mode 100644 backport-libsepol-validate-MLS-levels.patch create mode 100644 backport-libsepol-validate-check-low-category-is-not-bigger-than-high.patch create mode 100644 backport-libsepol-validate-empty-common-classes-in-scope-indi.patch create mode 100644 backport-libsepol-validate-expanded-user-range-and-level.patch create mode 100644 backport-libsepol-validate-ocontexts.patch create mode 100644 backport-libsepol-validate-old-style-range-trans-classes.patch create mode 100644 backport-libsepol-validate-the-identifier-for-initials-SID-is.patch diff --git a/backport-hashtab-update.patch b/backport-hashtab-update.patch new file mode 100644 index 0000000..6031182 --- /dev/null +++ b/backport-hashtab-update.patch @@ -0,0 +1,91 @@ +From 0d1445067c67d38e7d5c14155999afb10cc2e1a9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Fri, 14 Jul 2023 20:44:12 +0200 +Subject: [PATCH] hashtab: update +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Avoid overflowing number of elements in hashtab_insert(). + +Use identical type for hashed values to avoid implicit conversions. + +Declare tag parameter of hashtab_hash_eval() const since it is only +printed. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/include/sepol/policydb/hashtab.h | 2 +- + libsepol/src/hashtab.c | 14 +++++++------- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/libsepol/include/sepol/policydb/hashtab.h b/libsepol/include/sepol/policydb/hashtab.h +index 060e8c9c5..3fcd1fdce 100644 +--- a/libsepol/include/sepol/policydb/hashtab.h ++++ b/libsepol/include/sepol/policydb/hashtab.h +@@ -108,7 +108,7 @@ extern int hashtab_map(hashtab_t h, + hashtab_datum_t d, + void *args), void *args); + +-extern void hashtab_hash_eval(hashtab_t h, char *tag); ++extern void hashtab_hash_eval(hashtab_t h, const char *tag); + + #ifdef __cplusplus + } +diff --git a/libsepol/src/hashtab.c b/libsepol/src/hashtab.c +index 4a827fd31..b1a9bdc2f 100644 +--- a/libsepol/src/hashtab.c ++++ b/libsepol/src/hashtab.c +@@ -103,10 +103,10 @@ static void hashtab_check_resize(hashtab_t h) + + int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum) + { +- int hvalue; ++ unsigned int hvalue; + hashtab_ptr_t prev, cur, newnode; + +- if (!h) ++ if (!h || h->nel == UINT32_MAX) + return SEPOL_ENOMEM; + + hashtab_check_resize(h); +@@ -144,7 +144,7 @@ int hashtab_remove(hashtab_t h, hashtab_key_t key, + void (*destroy) (hashtab_key_t k, + hashtab_datum_t d, void *args), void *args) + { +- int hvalue; ++ unsigned int hvalue; + hashtab_ptr_t cur, last; + + if (!h) +@@ -176,7 +176,7 @@ int hashtab_remove(hashtab_t h, hashtab_key_t key, + hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t key) + { + +- int hvalue; ++ unsigned int hvalue; + hashtab_ptr_t cur; + + if (!h) +@@ -240,10 +240,10 @@ int hashtab_map(hashtab_t h, + return SEPOL_OK; + } + +-void hashtab_hash_eval(hashtab_t h, char *tag) ++void hashtab_hash_eval(hashtab_t h, const char *tag) + { + unsigned int i; +- int chain_len, slots_used, max_chain_len; ++ size_t chain_len, slots_used, max_chain_len; + hashtab_ptr_t cur; + + slots_used = 0; +@@ -264,6 +264,6 @@ void hashtab_hash_eval(hashtab_t h, char *tag) + } + + printf +- ("%s: %d entries and %d/%d buckets used, longest chain length %d\n", ++ ("%s: %d entries and %zu/%d buckets used, longest chain length %zu\n", + tag, h->nel, slots_used, h->size, max_chain_len); + } diff --git a/backport-libsepol-Validate-conditional-expressions.patch b/backport-libsepol-Validate-conditional-expressions.patch new file mode 100644 index 0000000..3715b18 --- /dev/null +++ b/backport-libsepol-Validate-conditional-expressions.patch @@ -0,0 +1,75 @@ +From c3f0124b1817dd4bdc79c86491d77a7a2b08d479 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Wed, 16 Mar 2022 16:15:57 -0400 +Subject: [PATCH] libsepol: Validate conditional expressions + +When validating a policydb, validate the conditional expressions +including the values of the booleans within them. + +Found by oss-fuzz (#45523) + +Signed-off-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/c3f0124b1817dd4bdc79c86491d77a7a2b08d479 +Conflict: NA +--- + libsepol/src/policydb_validate.c | 43 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 43 insertions(+) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index 40e68ac..da3c7c5 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -470,9 +470,52 @@ bad: + return -1; + } + ++static int validate_cond_expr(sepol_handle_t *handle, struct cond_expr *expr, validate_t *bool) ++{ ++ int depth = -1; ++ ++ for (; expr; expr = expr->next) { ++ switch(expr->expr_type) { ++ case COND_BOOL: ++ if (validate_value(expr->bool, bool)) ++ goto bad; ++ if (depth == (COND_EXPR_MAXDEPTH - 1)) ++ goto bad; ++ depth++; ++ break; ++ case COND_NOT: ++ if (depth < 0) ++ goto bad; ++ break; ++ case COND_OR: ++ case COND_AND: ++ case COND_XOR: ++ case COND_EQ: ++ case COND_NEQ: ++ if (depth < 1) ++ goto bad; ++ depth--; ++ break; ++ default: ++ goto bad; ++ } ++ } ++ ++ if (depth != 0) ++ goto bad; ++ ++ return 0; ++ ++bad: ++ ERR(handle, "Invalid cond expression"); ++ return -1; ++} ++ + static int validate_cond_list(sepol_handle_t *handle, cond_list_t *cond, validate_t flavors[]) + { + for (; cond; cond = cond->next) { ++ if (validate_cond_expr(handle, cond->expr, &flavors[SYM_BOOLS])) ++ goto bad; + if (validate_cond_av_list(handle, cond->true_list, flavors)) + goto bad; + if (validate_cond_av_list(handle, cond->false_list, flavors)) diff --git a/backport-libsepol-add-check-for-category-value-before-printin.patch b/backport-libsepol-add-check-for-category-value-before-printin.patch new file mode 100644 index 0000000..fe6537d --- /dev/null +++ b/backport-libsepol-add-check-for-category-value-before-printin.patch @@ -0,0 +1,35 @@ +From d3c2992ed0358c8e86a83c7f55fc529cba545298 Mon Sep 17 00:00:00 2001 +From: Huaxin Lu +Date: Thu, 16 Nov 2023 07:32:07 +0800 +Subject: [PATCH] libsepol: add check for category value before printing + +In mls_semantic_level_expand(), there is a explicitly determine +whether category is 0, which may cause an potential integer +overflow in error branch. + +Signed-off-by: Huaxin Lu +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/d3c2992ed0358c8e86a83c7f55fc529cba545298 +Conflict: NA +--- + libsepol/src/expand.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c +index ee5f9185..e63414b1 100644 +--- a/libsepol/src/expand.c ++++ b/libsepol/src/expand.c +@@ -945,8 +945,8 @@ int mls_semantic_level_expand(mls_semantic_level_t * sl, mls_level_t * l, + for (cat = sl->cat; cat; cat = cat->next) { + if (!cat->low || cat->low > cat->high) { + ERR(h, "Category range is not valid %s.%s", +- p->p_cat_val_to_name[cat->low - 1], +- p->p_cat_val_to_name[cat->high - 1]); ++ cat->low > 0 ? p->p_cat_val_to_name[cat->low - 1] : "Invalid", ++ cat->high > 0 ? p->p_cat_val_to_name[cat->high - 1] : "Invalid"); + return -1; + } + for (i = cat->low - 1; i < cat->high; i++) { +-- +2.33.0 diff --git a/backport-libsepol-adjust-type-for-saturation-check.patch b/backport-libsepol-adjust-type-for-saturation-check.patch new file mode 100644 index 0000000..df0804c --- /dev/null +++ b/backport-libsepol-adjust-type-for-saturation-check.patch @@ -0,0 +1,39 @@ +From 44375cb4a21dfdf3ac037237c5529049123336c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 9 Nov 2023 14:51:19 +0100 +Subject: [PATCH] libsepol: adjust type for saturation check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Change the type for the number of primary names in a symtab to uint32_t, +which conforms to the bytes read and the type used in the symtab. +The type is important for the saturation check via is_saturated(), since +it checks against -1 casted to the specific type. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/44375cb4a21dfdf3ac037237c5529049123336c2 +Conflict: NA +--- + libsepol/src/policydb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c +index f608aba4..bc7bc9dc 100644 +--- a/libsepol/src/policydb.c ++++ b/libsepol/src/policydb.c +@@ -4120,8 +4120,8 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) + { + + unsigned int i, j, r_policyvers; +- uint32_t buf[5]; +- size_t len, nprim, nel; ++ uint32_t buf[5], nprim; ++ size_t len, nel; + char *policydb_str; + const struct policydb_compat_info *info; + unsigned int policy_type, bufindex; +-- +2.33.0 diff --git a/backport-libsepol-avoid-integer-overflow-in-add_i_to_a.patch b/backport-libsepol-avoid-integer-overflow-in-add_i_to_a.patch new file mode 100644 index 0000000..b4c0d59 --- /dev/null +++ b/backport-libsepol-avoid-integer-overflow-in-add_i_to_a.patch @@ -0,0 +1,34 @@ +From a55cd37461f2e1ef4cec3b09aa8b99f2d12a529d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Mon, 11 Dec 2023 15:48:25 +0100 +Subject: [PATCH] libsepol: avoid integer overflow in add_i_to_a() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/a55cd37461f2e1ef4cec3b09aa8b99f2d12a529d +Conflict: NA +--- + libsepol/src/util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsepol/src/util.c b/libsepol/src/util.c +index 571f6c93..4a6f7d11 100644 +--- a/libsepol/src/util.c ++++ b/libsepol/src/util.c +@@ -40,7 +40,9 @@ struct val_to_name { + * 0). Return 0 on success, -1 on out of memory. */ + int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a) + { +- if (cnt == NULL || a == NULL) ++ uint32_t *new; ++ ++ if (cnt == NULL || *cnt == UINT32_MAX || a == NULL) + return -1; + + /* FIX ME: This is not very elegant! We use an array that we +-- +2.33.0 diff --git a/backport-libsepol-avoid-leak-in-OOM-branch.patch b/backport-libsepol-avoid-leak-in-OOM-branch.patch new file mode 100644 index 0000000..ec28e1c --- /dev/null +++ b/backport-libsepol-avoid-leak-in-OOM-branch.patch @@ -0,0 +1,39 @@ +From 3b05202621539843069bb1477da0d6cfdd384ebc Mon Sep 17 00:00:00 2001 +From: root +Date: Mon, 8 Jan 2024 19:51:09 +0800 +Subject: [PATCH] libsepol: avoid leak in OOM branch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In case the member sid_key failed to allocate, free the parent struct. + +Reported by Clang Analyzer: + + module_to_cil.c:2607:9: warning: Potential leak of memory pointed to by 'item' [unix.Malloc] + 2607 | return rc; + | ^~ + +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/5e425b4165b801666e478b19efbf8ddb14d82a02 +Conflict: Context adaptation +--- + libsepol/src/module_to_cil.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c +index cc8066d..9a45cee 100644 +--- a/libsepol/src/module_to_cil.c ++++ b/libsepol/src/module_to_cil.c +@@ -2570,6 +2570,7 @@ static int ocontext_isid_to_cil(struct policydb *pdb, const char *const *sid_to_ + item->sid_key = strdup(sid); + if (!item->sid_key) { + log_err("Out of memory"); ++ free(item); + rc = -1; + goto exit; + } +-- +2.33.0 diff --git a/backport-libsepol-avoid-memory-corruption-on-realloc-failure.patch b/backport-libsepol-avoid-memory-corruption-on-realloc-failure.patch new file mode 100644 index 0000000..0f27f9e --- /dev/null +++ b/backport-libsepol-avoid-memory-corruption-on-realloc-failure.patch @@ -0,0 +1,63 @@ +From 541aab88459128e2d48bd1fad2c190154a5288c0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 9 Nov 2023 14:53:15 +0100 +Subject: [PATCH] libsepol: avoid memory corruption on realloc failure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use a single pointer variable for the realloc(3) result to not +immediately override the source pointer. + +Also don't unnecessarily copy the first character. + +Reported by Clang Analyzer: + + services.c:810:14: warning: Assigned value is garbage or undefined [core.uninitialized.Assign] + 810 | **r_buf = **new_buf; + | ^ ~~~~~~~~~ + +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/541aab88459128e2d48bd1fad2c190154a5288c0 +Conflict: NA +--- + libsepol/src/services.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/libsepol/src/services.c b/libsepol/src/services.c +index aa1ad52c..0eeee7ec 100644 +--- a/libsepol/src/services.c ++++ b/libsepol/src/services.c +@@ -787,8 +787,8 @@ mls_ops: + + if (r_buf && ((s[0] == 0) || ((s[0] == 1 && + (flags & SHOW_GRANTED) == SHOW_GRANTED)))) { +- int len, new_buf_len; +- char *p, **new_buf = r_buf; ++ int len; ++ char *p; + /* + * These contain the constraint components that are added to the + * callers reason buffer. +@@ -801,13 +801,13 @@ mls_ops: + len = snprintf(p, reason_buf_len - reason_buf_used, + "%s", buffers[x]); + if (len < 0 || len >= reason_buf_len - reason_buf_used) { +- new_buf_len = reason_buf_len + REASON_BUF_SIZE; +- *new_buf = realloc(*r_buf, new_buf_len); +- if (!*new_buf) { ++ int new_buf_len = reason_buf_len + REASON_BUF_SIZE; ++ char *new_buf = realloc(*r_buf, new_buf_len); ++ if (!new_buf) { + ERR(NULL, "failed to realloc reason buffer"); + goto out1; + } +- **r_buf = **new_buf; ++ *r_buf = new_buf; + reason_buf_len = new_buf_len; + continue; + } else { +-- +2.33.0 diff --git a/backport-libsepol-avtab-check-read-counts-for-saturation.patch b/backport-libsepol-avtab-check-read-counts-for-saturation.patch new file mode 100644 index 0000000..ec8a436 --- /dev/null +++ b/backport-libsepol-avtab-check-read-counts-for-saturation.patch @@ -0,0 +1,37 @@ +From f9fd25005f815d996c4344967a8ad13dee853303 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 1 Nov 2023 17:37:25 +0100 +Subject: [PATCH] libsepol: avtab: check read counts for saturation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Ensure counts are not set to the maximum value of their type. +Also limit their size during fuzzing to prevent OOM reports. + +Reported-by: oss-fuzz (issue 60572), caused at the time by the filetrans + prefix proposal +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/f9fd25005f815d996c4344967a8ad13dee853303 +Conflict: NA +--- + libsepol/src/avtab.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c +index 1ef5ee00..7c2328b7 100644 +--- a/libsepol/src/avtab.c ++++ b/libsepol/src/avtab.c +@@ -600,7 +600,7 @@ int avtab_read(avtab_t * a, struct policy_file *fp, uint32_t vers) + goto bad; + } + nel = le32_to_cpu(buf[0]); +- if (!nel) { ++ if (zero_or_saturated(nel)) { + ERR(fp->handle, "table is empty"); + goto bad; + } +-- +2.33.0 diff --git a/backport-libsepol-check-for-overflow-in-put_entry.patch b/backport-libsepol-check-for-overflow-in-put_entry.patch new file mode 100644 index 0000000..c29cac0 --- /dev/null +++ b/backport-libsepol-check-for-overflow-in-put_entry.patch @@ -0,0 +1,33 @@ +From df666f70534ef225b97899f997b4077aeb285972 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 6 Jul 2023 15:57:18 +0200 +Subject: [PATCH] libsepol: check for overflow in put_entry() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +put_entry() is used during writing binary policies. Avoid short writes +due to an overflow. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/services.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/libsepol/src/services.c b/libsepol/src/services.c +index 72772dbd29..6bddc287e1 100644 +--- a/libsepol/src/services.c ++++ b/libsepol/src/services.c +@@ -1711,7 +1711,10 @@ int next_entry(void *buf, struct policy_file *fp, size_t bytes) + size_t put_entry(const void *ptr, size_t size, size_t n, + struct policy_file *fp) + { +- size_t bytes = size * n; ++ size_t bytes; ++ ++ if (__builtin_mul_overflow(size, n, &bytes)) ++ return 0; + + switch (fp->type) { + case PF_USE_STDIO: diff --git a/backport-libsepol-cil-Do-not-allow-classpermissionset-to-use-.patch b/backport-libsepol-cil-Do-not-allow-classpermissionset-to-use-.patch new file mode 100644 index 0000000..8f9578b --- /dev/null +++ b/backport-libsepol-cil-Do-not-allow-classpermissionset-to-use-.patch @@ -0,0 +1,87 @@ +From 903e8cf26e2ab874618e0fdaef537bc3d9a8b69d Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Fri, 13 Oct 2023 09:26:50 -0400 +Subject: [PATCH] libsepol/cil: Do not allow classpermissionset to use + anonymous classpermission + +Macros can use classpermission arguments. These are used in two +different ways. Either a named classpermission is passed (which is +declared using a classpermisison rule) or an anonymous classpermission +is passed (something like "(CLASS (PERM))"). + +Usually this will look like either of the following: +Ex1/ +(classpermission cp1) +(classpermisisonset cp1 (CLASS (PERM))) +(macro m1 ((classpermisison ARG1)) + (allow t1 self ARG1) +) +(call m1 (cp1)) +or +Ex2/ +(macro m2 ((classpermission ARG2)) + (allow t2 self ARG2) +) +(call m2 ((CLASS (PERM)))) + +The following would also be valid: +Ex3/ +(classpermission cp3) +(macro m3 ((classpermission ARG3)) + (classpermissionset ARG3 (CLASS (PERM))) + (allow t3 self ARG3) +) +(call m3 (cp3)) + +The oss-fuzzer did the equivalent of the following: + +(classpermission cp4) +(macro m4 ((classpermission ARG4)) + (classpermissionset ARG4 (CLASS (PERM1))) + (allow t4 self ARG4) +) +(call m4 (CLASS (PERM2))) + +It passed an anonymous classpermission into a macro where there +was a classpermissionset rule. Suprisingly, everything worked well +until it was time to destroy the AST. There is no way to distinguish +between the anonymous classpermission being passed in which needs +to be destroyed and the classpermission in the classpermissionset +rule which is destroyed when the classpermissionset rule is +destroyed. This led to CIL trying to destroy the classpermission +in the classpermissionset rule twice. + +To fix this, when resolving the classpermission name in the +classpermissionset rule, check if the datum returned is for +an anonymous classpermission (it has no name) and return an +error if it is. + +This fixes oss-fuzz issue 60670. + +Signed-off-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/903e8cf26e2ab874618e0fdaef537bc3d9a8b69d +Conflict: Context adaptation +--- + libsepol/cil/src/cil_resolve_ast.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c +index 4e8a375d6..427a320c9 100644 +--- a/libsepol/cil/src/cil_resolve_ast.c ++++ b/libsepol/cil/src/cil_resolve_ast.c +@@ -253,6 +253,12 @@ int cil_resolve_classpermissionset(struct cil_tree_node *current, struct cil_cla + goto exit; + } + ++ if (!datum->fqn) { ++ cil_tree_log(current, CIL_ERR, "Anonymous classpermission used in a classpermissionset"); ++ rc = SEPOL_ERR; ++ goto exit; ++ } ++ + rc = cil_resolve_classperms_list(current, cps->classperms, extra_args); + if (rc != SEPOL_OK) { + goto exit; +-- +2.33.0 diff --git a/backport-libsepol-cil-Fix-class-permission-verification-in-CIL.patch b/backport-libsepol-cil-Fix-class-permission-verification-in-CIL.patch new file mode 100644 index 0000000..bf3853a --- /dev/null +++ b/backport-libsepol-cil-Fix-class-permission-verification-in-CIL.patch @@ -0,0 +1,257 @@ +From e81c466bca9a06e2ada7d783fe31dd44c9e04432 Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Thu, 20 Apr 2023 08:58:01 -0400 +Subject: [PATCH] libsepol/cil: Fix class permission verification in CIL +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Before the CIL post processing phase (where expressions are evaluated, +various ebitmaps are set, etc) there is a pre-verification where +checks are made to find self references or loops in bounds, attribute +sets, and class permissions. The class permission checking is faulty +in two ways. + +First, it does not check for the use of "all" in a permission expression +for a class that has no permissions. An error will still be generated +later and secilc will exit cleanly, but without an error message that +explains the problem. + +Second, it does not properly handle lists in permission expressions. +For example, "(C ((P)))" is a legitimate class permission. The +permissions expression contains one item that is a list containing +one permission. This permission expression will be properly evaluated. +Unfortunately, the class permission verification assumes that each +item in the permission expression is either an operator or a +permission datum and a segmenation fault will occur. + +Refactor the class permission checking to give a proper error when +"all" is used in a permission expression for a class that has no +permissions and so that it can handle lists in permission +expressions. Also, check for the actual flavor of each item in +the permission expression and return an error if an unexpected +flavor is found. + +The failure to properly handle lists in permission expressions was +found by oss-fuzz (#58085). + +Tested-by: Christian Göttsche +Signed-off-by: James Carter +--- + libsepol/cil/src/cil_verify.c | 167 +++++++++++++++++++++++----------- + 1 file changed, 114 insertions(+), 53 deletions(-) + +diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c +index 4640dc59de..3f58969df2 100644 +--- a/libsepol/cil/src/cil_verify.c ++++ b/libsepol/cil/src/cil_verify.c +@@ -1700,31 +1700,109 @@ static int __add_perm_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_d + return SEPOL_OK; + } + +-static int __cil_verify_classperms(struct cil_list *classperms, +- struct cil_symtab_datum *orig, +- struct cil_symtab_datum *parent, +- struct cil_symtab_datum *cur, +- enum cil_flavor flavor, +- unsigned steps, unsigned limit) ++static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig, struct cil_symtab_datum *cur, unsigned steps, unsigned limit); ++ ++static int __cil_verify_map_perm(struct cil_class *class, struct cil_perm *perm, struct cil_symtab_datum *orig, unsigned steps, unsigned limit) ++{ ++ int rc; ++ ++ if (!perm->classperms) { ++ cil_tree_log(NODE(class), CIL_ERR, "No class permissions for map class %s, permission %s", DATUM(class)->name, DATUM(perm)->name); ++ goto exit; ++ } ++ ++ rc = __cil_verify_classperms(perm->classperms, orig, &perm->datum, steps, limit); ++ if (rc != SEPOL_OK) { ++ cil_tree_log(NODE(class), CIL_ERR, "There was an error verifying class permissions for map class %s, permission %s", DATUM(class)->name, DATUM(perm)->name); ++ goto exit; ++ } ++ ++ return SEPOL_OK; ++ ++exit: ++ return SEPOL_ERR; ++} ++ ++ ++static int __cil_verify_perms(struct cil_class *class, struct cil_list *perms, struct cil_symtab_datum *orig, unsigned steps, unsigned limit) + { + int rc = SEPOL_ERR; +- struct cil_list_item *curr; ++ int count = 0; ++ struct cil_list_item *i = NULL; + +- if (classperms == NULL) { +- if (flavor == CIL_MAP_PERM) { +- cil_tree_log(NODE(cur), CIL_ERR, "Map class %s does not have a classmapping for %s", parent->name, cur->name); ++ if (!perms) { ++ cil_tree_log(NODE(class), CIL_ERR, "No permissions for class %s in class permissions", DATUM(class)->name); ++ goto exit; ++ } ++ ++ cil_list_for_each(i, perms) { ++ count++; ++ if (i->flavor == CIL_LIST) { ++ rc = __cil_verify_perms(class, i->data, orig, steps, limit); ++ if (rc != SEPOL_OK) { ++ goto exit; ++ } ++ } else if (i->flavor == CIL_DATUM) { ++ struct cil_perm *perm = i->data; ++ if (FLAVOR(perm) == CIL_MAP_PERM) { ++ rc = __cil_verify_map_perm(class, perm, orig, steps, limit); ++ if (rc != SEPOL_OK) { ++ goto exit; ++ } ++ } ++ } else if (i->flavor == CIL_OP) { ++ enum cil_flavor op = (enum cil_flavor)(uintptr_t)i->data; ++ if (op == CIL_ALL) { ++ struct cil_list *perm_list; ++ struct cil_list_item *j = NULL; ++ int count2 = 0; ++ cil_list_init(&perm_list, CIL_MAP_PERM); ++ cil_symtab_map(&class->perms, __add_perm_to_list, perm_list); ++ cil_list_for_each(j, perm_list) { ++ count2++; ++ struct cil_perm *perm = j->data; ++ if (FLAVOR(perm) == CIL_MAP_PERM) { ++ rc = __cil_verify_map_perm(class, perm, orig, steps, limit); ++ if (rc != SEPOL_OK) { ++ cil_list_destroy(&perm_list, CIL_FALSE); ++ goto exit; ++ } ++ } ++ } ++ cil_list_destroy(&perm_list, CIL_FALSE); ++ if (count2 == 0) { ++ cil_tree_log(NODE(class), CIL_ERR, "Operator \"all\" used for %s which has no permissions associated with it", DATUM(class)->name); ++ goto exit; ++ } ++ } + } else { +- cil_tree_log(NODE(cur), CIL_ERR, "Classpermission %s does not have a classpermissionset", cur->name); ++ cil_tree_log(NODE(class), CIL_ERR, "Permission list for %s has an unexpected flavor: %d", DATUM(class)->name, i->flavor); ++ goto exit; + } ++ } ++ ++ if (count == 0) { ++ cil_tree_log(NODE(class), CIL_ERR, "Empty permissions list for class %s in class permissions", DATUM(class)->name); ++ goto exit; ++ } ++ ++ return SEPOL_OK; ++ ++exit: ++ return SEPOL_ERR; ++} ++ ++static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig, struct cil_symtab_datum *cur, unsigned steps, unsigned limit) ++{ ++ int rc; ++ struct cil_list_item *i; ++ ++ if (classperms == NULL) { + goto exit; + } + + if (steps > 0 && orig == cur) { +- if (flavor == CIL_MAP_PERM) { +- cil_tree_log(NODE(cur), CIL_ERR, "Found circular class permissions involving the map class %s and permission %s", parent->name, cur->name); +- } else { +- cil_tree_log(NODE(cur), CIL_ERR, "Found circular class permissions involving the set %s", cur->name); +- } ++ cil_tree_log(NODE(cur), CIL_ERR, "Found circular class permissions involving %s", cur->name); + goto exit; + } else { + steps++; +@@ -1735,44 +1813,20 @@ static int __cil_verify_classperms(struct cil_list *classperms, + } + } + +- cil_list_for_each(curr, classperms) { +- if (curr->flavor == CIL_CLASSPERMS) { +- struct cil_classperms *cp = curr->data; +- if (FLAVOR(cp->class) != CIL_CLASS) { /* MAP */ +- struct cil_list_item *i = NULL; +- cil_list_for_each(i, cp->perms) { +- if (i->flavor != CIL_OP) { +- struct cil_perm *cmp = i->data; +- rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit); +- if (rc != SEPOL_OK) { +- goto exit; +- } +- } else { +- enum cil_flavor op = (enum cil_flavor)(uintptr_t)i->data; +- if (op == CIL_ALL) { +- struct cil_class *mc = cp->class; +- struct cil_list *perm_list; +- struct cil_list_item *j = NULL; +- +- cil_list_init(&perm_list, CIL_MAP_PERM); +- cil_symtab_map(&mc->perms, __add_perm_to_list, perm_list); +- cil_list_for_each(j, perm_list) { +- struct cil_perm *cmp = j->data; +- rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit); +- if (rc != SEPOL_OK) { +- cil_list_destroy(&perm_list, CIL_FALSE); +- goto exit; +- } +- } +- cil_list_destroy(&perm_list, CIL_FALSE); +- } +- } +- } ++ cil_list_for_each(i, classperms) { ++ if (i->flavor == CIL_CLASSPERMS) { ++ struct cil_classperms *cp = i->data; ++ rc = __cil_verify_perms(cp->class, cp->perms, orig, steps, limit); ++ if (rc != SEPOL_OK) { ++ goto exit; + } + } else { /* SET */ +- struct cil_classperms_set *cp_set = curr->data; ++ struct cil_classperms_set *cp_set = i->data; + struct cil_classpermission *cp = cp_set->set; +- rc = __cil_verify_classperms(cp->classperms, orig, NULL, &cp->datum, CIL_CLASSPERMISSION, steps, limit); ++ if (!cp->classperms) { ++ cil_tree_log(NODE(cur), CIL_ERR, "Classpermission %s does not have a classpermissionset", DATUM(cp)->name); ++ } ++ rc = __cil_verify_classperms(cp->classperms, orig, &cp->datum, steps, limit); + if (rc != SEPOL_OK) { + goto exit; + } +@@ -1787,9 +1841,15 @@ static int __cil_verify_classperms(struct cil_list *classperms, + + static int __cil_verify_classpermission(struct cil_tree_node *node) + { ++ int rc; + struct cil_classpermission *cp = node->data; + +- return __cil_verify_classperms(cp->classperms, &cp->datum, NULL, &cp->datum, CIL_CLASSPERMISSION, 0, 2); ++ rc = __cil_verify_classperms(cp->classperms, &cp->datum, &cp->datum, 0, 2); ++ if (rc != SEPOL_OK) { ++ cil_tree_log(node, CIL_ERR, "Error verifying class permissions for classpermission %s", DATUM(cp)->name); ++ } ++ ++ return rc; + } + + struct cil_verify_map_args { +@@ -1804,8 +1864,9 @@ static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, + struct cil_perm *cmp = (struct cil_perm *)d; + int rc; + +- rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &map_args->class->datum, &cmp->datum, CIL_MAP_PERM, 0, 2); ++ rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &cmp->datum, 0, 2); + if (rc != SEPOL_OK) { ++ cil_tree_log(NODE(cmp), CIL_ERR, "Error verifying class permissions for map class %s, permission %s", DATUM(map_args->class)->name, DATUM(cmp)->name); + map_args->rc = rc; + } + diff --git a/backport-libsepol-dump-non-mls-validatetrans-rules-as-such.patch b/backport-libsepol-dump-non-mls-validatetrans-rules-as-such.patch new file mode 100644 index 0000000..b426cab --- /dev/null +++ b/backport-libsepol-dump-non-mls-validatetrans-rules-as-such.patch @@ -0,0 +1,51 @@ +From f5d664ebeb09d837a0551f6df0c8f038937a1b67 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Fri, 12 May 2023 11:23:11 +0200 +Subject: [PATCH] libsepol: dump non-mls validatetrans rules as such +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The functions constraint_expr_to_str() prepare a string representation +for validatetrans and mlsvalidatetrans rules. To decide what keyword to +use the type of expression is consulted. Currently the extra target +type (CEXPR_XTARGET) is considered to be an MLS statement while its not, +e.g.: + + validatetrans CLASS1 t3 == ATTR1; + +Actually check for MLS expression types only. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/kernel_to_cil.c | 2 +- + libsepol/src/kernel_to_conf.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c +index e9cd89c299..7e279e3ff5 100644 +--- a/libsepol/src/kernel_to_cil.c ++++ b/libsepol/src/kernel_to_cil.c +@@ -172,7 +172,7 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr + goto exit; + } + +- if (curr->attr >= CEXPR_XTARGET) { ++ if (curr->attr >= CEXPR_L1L2) { + *use_mls = 1; + } + +diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c +index c48a71147a..4c93cc10c3 100644 +--- a/libsepol/src/kernel_to_conf.c ++++ b/libsepol/src/kernel_to_conf.c +@@ -169,7 +169,7 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr + goto exit; + } + +- if (curr->attr >= CEXPR_XTARGET) { ++ if (curr->attr >= CEXPR_L1L2) { + *use_mls = 1; + } + diff --git a/backport-libsepol-enhance-saturation-check.patch b/backport-libsepol-enhance-saturation-check.patch new file mode 100644 index 0000000..777c883 --- /dev/null +++ b/backport-libsepol-enhance-saturation-check.patch @@ -0,0 +1,133 @@ +From bd1b7848c66b69bdb1ef25332c90c47d61656437 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 9 Nov 2023 14:51:20 +0100 +Subject: [PATCH] libsepol: enhance saturation check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Several values while parsing kernel policies, like symtab sizes or +string lengths, are checked for saturation. They may not be set to the +maximum value, to avoid overflows or occupying a reserved value, and +many of those sizes must not be 0. This is currently handled via the +two macros is_saturated() and zero_or_saturated(). + +Both macros are tweaked for the fuzzer, because the fuzzer can create +input with huge sizes. While there is no subsequent data to provide +the announced sizes, which will be caught later, memory of the requested +size is allocated, which would lead to OOM reports. Thus the sizes for +the fuzzer are limited to 2^16. This has the drawback of the fuzzer +not checking the complete input space. + +Check the sizes in question for actual enough bytes available in the +input. This is (only) possible for mapped memory, which the fuzzer +uses. + +Application like setools do currently not benefit from this change, +since they load the policy via a stream. There are currently multiple +interfaces to load a policy, so reworking them to use mapped memory by +default might be subject for future work. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/bd1b7848c66b69bdb1ef25332c90c47d61656437 +Conflict: Context adaptation +--- + src/avtab.c | 2 +- + src/policydb.c | 9 ++++++--- + src/private.h | 18 ++++++++++++++++-- + src/services.c | 2 +- + 4 files changed, 24 insertions(+), 7 deletions(-) + +diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c +index 32cd052..e87361b 100644 +--- a/libsepol/src/avtab.c ++++ b/libsepol/src/avtab.c +@@ -600,7 +600,7 @@ int avtab_read(avtab_t * a, struct policy_file *fp, uint32_t vers) + goto bad; + } + nel = le32_to_cpu(buf[0]); +- if (zero_or_saturated(nel)) { ++ if (zero_or_saturated(nel) || exceeds_available_bytes(fp, nel, sizeof(uint32_t) * 3)) { + ERR(fp->handle, "table is empty"); + goto bad; + } +diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c +index c601908..9ce6999 100644 +--- a/libsepol/src/policydb.c ++++ b/libsepol/src/policydb.c +@@ -3927,6 +3927,9 @@ static int scope_index_read(scope_index_t * scope_index, + if (rc < 0) + return -1; + scope_index->class_perms_len = le32_to_cpu(buf[0]); ++ if (is_saturated(scope_index->class_perms_len) || ++ exceeds_available_bytes(fp, scope_index->class_perms_len, sizeof(uint32_t) * 3)) ++ return -1; + if (scope_index->class_perms_len == 0) { + scope_index->class_perms_map = NULL; + return 0; +@@ -4107,7 +4110,8 @@ static int scope_read(policydb_t * p, int symnum, struct policy_file *fp) + goto cleanup; + scope->scope = le32_to_cpu(buf[0]); + scope->decl_ids_len = le32_to_cpu(buf[1]); +- if (scope->decl_ids_len == 0) { ++ if (zero_or_saturated(scope->decl_ids_len) || ++ exceeds_available_bytes(fp, scope->decl_ids_len, sizeof(uint32_t))) { + ERR(fp->handle, "invalid scope with no declaration"); + goto cleanup; + } +@@ -4397,6 +4401,9 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) + if (rc < 0) + goto bad; + nprim = le32_to_cpu(buf[0]); ++ if (is_saturated(nprim) || ++ exceeds_available_bytes(fp, nprim, sizeof(uint32_t) * 3)) ++ goto bad; + nel = le32_to_cpu(buf[1]); + if (nel && !nprim) { + ERR(fp->handle, "unexpected items in symbol table with no symbol"); +diff --git a/libsepol/src/private.h b/libsepol/src/private.h +index a16d957..1993d77 100644 +--- a/libsepol/src/private.h ++++ b/libsepol/src/private.h +@@ -44,8 +44,22 @@ + + #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) + +-#define is_saturated(x) (x == (typeof(x))-1) +-#define zero_or_saturated(x) ((x == 0) || is_saturated(x)) ++static inline int exceeds_available_bytes(const struct policy_file *fp, size_t x, size_t req_elem_size) ++{ ++ size_t req_size; ++ ++ /* Remaining input size is only available for mmap'ed memory */ ++ if (fp->type != PF_USE_MEMORY) ++ return 0; ++ ++ if (__builtin_mul_overflow(x, req_elem_size, &req_size)) ++ return 1; ++ ++ return req_size > fp->len; ++} ++ ++#define is_saturated(x) ((x) == (typeof(x))-1) ++#define zero_or_saturated(x) (((x) == 0) || is_saturated(x)) + + #define spaceship_cmp(a, b) (((a) > (b)) - ((a) < (b))) + +diff --git a/libsepol/src/services.c b/libsepol/src/services.c +index 017cfaf..8a80b3a 100644 +--- a/libsepol/src/services.c ++++ b/libsepol/src/services.c +@@ -1742,7 +1742,7 @@ int str_read(char **strp, struct policy_file *fp, size_t len) + int rc; + char *str; + +- if (zero_or_saturated(len)) { ++ if (zero_or_saturated(len) || exceeds_available_bytes(fp, len, sizeof(char))) { + errno = EINVAL; + return -1; + } +-- +2.33.0 diff --git a/backport-libsepol-expand-skip-invalid-cat.patch b/backport-libsepol-expand-skip-invalid-cat.patch new file mode 100644 index 0000000..a6a37b0 --- /dev/null +++ b/backport-libsepol-expand-skip-invalid-cat.patch @@ -0,0 +1,38 @@ +From cae65d9a10623bb9063a2e3ca5357bb1602d55af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Fri, 12 May 2023 11:30:01 +0200 +Subject: [PATCH] libsepol: expand: skip invalid cat +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bail out on expanding levels with invalid low category. + +UBSAN report: + + expand.c:952:21: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'uint32_t' (aka 'unsigned int') + +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/cae65d9a10623bb9063a2e3ca5357bb1602d55af +Conflict: NA +--- + libsepol/src/expand.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c +index c08d3a35..8795229a 100644 +--- a/libsepol/src/expand.c ++++ b/libsepol/src/expand.c +@@ -943,7 +943,7 @@ int mls_semantic_level_expand(mls_semantic_level_t * sl, mls_level_t * l, + return -1; + } + for (cat = sl->cat; cat; cat = cat->next) { +- if (cat->low > cat->high) { ++ if (!cat->low || cat->low > cat->high) { + ERR(h, "Category range is not valid %s.%s", + p->p_cat_val_to_name[cat->low - 1], + p->p_cat_val_to_name[cat->high - 1]); +-- +2.33.0 diff --git a/backport-libsepol-expand-use-identical-type-to-avoid-implicit-conversion.patch b/backport-libsepol-expand-use-identical-type-to-avoid-implicit-conversion.patch new file mode 100644 index 0000000..6493c32 --- /dev/null +++ b/backport-libsepol-expand-use-identical-type-to-avoid-implicit-conversion.patch @@ -0,0 +1,28 @@ +From ace9ec17ffaa1ad0be165cd8ad77998cb368ca2c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Fri, 14 Jul 2023 20:44:13 +0200 +Subject: [PATCH] libsepol: expand: use identical type to avoid implicit + conversion +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/expand.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c +index 8795229a39..4c9f84cf9d 100644 +--- a/libsepol/src/expand.c ++++ b/libsepol/src/expand.c +@@ -2350,7 +2350,7 @@ static int type_attr_map(hashtab_key_t key + policydb_t *p = state->out; + unsigned int i; + ebitmap_node_t *tnode; +- int value; ++ uint32_t value; + + type = (type_datum_t *) datum; + value = type->s.value; diff --git a/backport-libsepol-more-strict-validation.patch b/backport-libsepol-more-strict-validation.patch new file mode 100644 index 0000000..5044516 --- /dev/null +++ b/backport-libsepol-more-strict-validation.patch @@ -0,0 +1,55 @@ +From 6ed7dcf2f6f71d6db5fa89e0b965c10a165f315c Mon Sep 17 00:00:00 2001 +From: root +Date: Mon, 8 Jan 2024 17:09:46 +0800 +Subject: [PATCH] libsepol: more strict validation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Ensure the ibendport port is not 0 (similar to the kernel). + +More general depth test for boolean expressions. + +Ensure the boolean id is not set for logic operators. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/7b754f703d704c9d9931497536771e6124ca2418 +Conflict: Context adaptation +--- + libsepol/src/policydb_validate.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index da3c7c5..09f0813 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -479,13 +479,15 @@ static int validate_cond_expr(sepol_handle_t *handle, struct cond_expr *expr, va + case COND_BOOL: + if (validate_value(expr->bool, bool)) + goto bad; +- if (depth == (COND_EXPR_MAXDEPTH - 1)) ++ if (depth >= (COND_EXPR_MAXDEPTH - 1)) + goto bad; + depth++; + break; + case COND_NOT: + if (depth < 0) + goto bad; ++ if (expr->bool != 0) ++ goto bad; + break; + case COND_OR: + case COND_AND: +@@ -494,6 +496,8 @@ static int validate_cond_expr(sepol_handle_t *handle, struct cond_expr *expr, va + case COND_NEQ: + if (depth < 1) + goto bad; ++ if (expr->bool != 0) ++ goto bad; + depth--; + break; + default: +-- +2.33.0 diff --git a/backport-libsepol-reject-avtab-entries-with-invalid-specifier.patch b/backport-libsepol-reject-avtab-entries-with-invalid-specifier.patch new file mode 100644 index 0000000..9e7bede --- /dev/null +++ b/backport-libsepol-reject-avtab-entries-with-invalid-specifier.patch @@ -0,0 +1,61 @@ +From b1b3467a476b109f20ad581d73c56262205a021e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 1 Nov 2023 17:37:24 +0100 +Subject: [PATCH] libsepol: reject avtab entries with invalid specifier +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Neverallow avtab entries are not supported (normal and extended). Reject +them to avoid lookup confusions via avtab_search(), e.g. when searching +for a invalid key of AVTAB_TRANSITION|AVTAB_NEVERALLOW and the result of +only AVTAB_NEVERALLOW has no transition value. + +Simplify the check for the number of specifiers by using the compiler +popcount builtin (already used in libsepol). + +Reported-by: oss-fuzz (issue 60568), caused at the time by the filetrans + prefix proposal +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/b1b3467a476b109f20ad581d73c56262205a021e +Conflict: NA +--- + libsepol/src/avtab.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c +index 6ab49c5e..1ef5ee00 100644 +--- a/libsepol/src/avtab.c ++++ b/libsepol/src/avtab.c +@@ -441,7 +441,6 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a, + avtab_key_t key; + avtab_datum_t datum; + avtab_extended_perms_t xperms; +- unsigned set; + unsigned int i; + int rc; + +@@ -535,13 +534,13 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a, + key.target_class = le16_to_cpu(buf16[items++]); + key.specified = le16_to_cpu(buf16[items++]); + +- set = 0; +- for (i = 0; i < ARRAY_SIZE(spec_order); i++) { +- if (key.specified & spec_order[i]) +- set++; ++ if (key.specified & ~(AVTAB_AV | AVTAB_TYPE | AVTAB_XPERMS | AVTAB_ENABLED)) { ++ ERR(fp->handle, "invalid specifier"); ++ return -1; + } +- if (!set || set > 1) { +- ERR(fp->handle, "more than one specifier"); ++ ++ if (__builtin_popcount(key.specified & ~AVTAB_ENABLED) != 1) { ++ ERR(fp->handle, "not exactly one specifier"); + return -1; + } + +-- +2.33.0 diff --git a/backport-libsepol-reject-invalid-class-datums.patch b/backport-libsepol-reject-invalid-class-datums.patch new file mode 100644 index 0000000..5dd026d --- /dev/null +++ b/backport-libsepol-reject-invalid-class-datums.patch @@ -0,0 +1,54 @@ +From 68c3a9991679702a7adc6e040e5703a7abb50b16 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 28 Nov 2023 19:23:32 +0100 +Subject: [PATCH] libsepol: reject invalid class datums +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Internally class values are stored in multiple placed in a 16-bit wide +integer. Reject class values exceeding the maximum representable value. +This avoids truncations in the helper +policydb_string_to_security_class(), which gets called before validation +of the policy: + + policydb.c:4082:9: runtime error: implicit conversion from type 'uint32_t' (aka 'unsigned int') of value 2113929220 (32-bit, unsigned) to type 'sepol_security_class_t' (aka 'unsigned short') changed the value to 4 (16-bit, unsigned) + +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/68c3a9991679702a7adc6e040e5703a7abb50b16 +Conflict: Context adaptation +--- + libsepol/src/policydb.c | 2 ++ + libsepol/src/policydb_validate.c | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c +index 6ba4f9168..f10a8a95a 100644 +--- a/libsepol/src/policydb.c ++++ b/libsepol/src/policydb.c +@@ -2250,6 +2250,8 @@ static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp) + if (is_saturated(len2)) + goto bad; + cladatum->s.value = le32_to_cpu(buf[2]); ++ if (cladatum->s.value > UINT16_MAX) ++ goto bad; + + if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) + goto bad; +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index 6d8641f..69a436b 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -199,7 +199,7 @@ bad: + + static int validate_class_datum(sepol_handle_t *handle, class_datum_t *class, validate_t flavors[]) + { +- if (validate_value(class->s.value, &flavors[SYM_CLASSES])) ++ if (class->s.value > UINT16_MAX || validate_value(class->s.value, &flavors[SYM_CLASSES])) + goto bad; + if (validate_constraint_nodes(handle, class->constraints, flavors)) + goto bad; +-- +2.33.0 diff --git a/backport-libsepol-reject-linking-modules-with-no-avrules.patch b/backport-libsepol-reject-linking-modules-with-no-avrules.patch new file mode 100644 index 0000000..0856aea --- /dev/null +++ b/backport-libsepol-reject-linking-modules-with-no-avrules.patch @@ -0,0 +1,47 @@ +From 4724538b62e4eb846057b227ce12052749bd4473 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 28 Nov 2023 19:23:34 +0100 +Subject: [PATCH] libsepol: reject linking modules with no avrules +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Standard policy modules generated by compilers have at least one global +av rule. Reject modules otherwise, e.g. generated by a fuzzer. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/4724538b62e4eb846057b227ce12052749bd4473 +Conflict: NA +--- + libsepol/src/link.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/libsepol/src/link.c b/libsepol/src/link.c +index 3b7742bc..b8272308 100644 +--- a/libsepol/src/link.c ++++ b/libsepol/src/link.c +@@ -2019,7 +2019,7 @@ static int debug_requirements(link_state_t * state, policydb_t * p) + memset(&req, 0, sizeof(req)); + + for (cur = p->global; cur != NULL; cur = cur->next) { +- if (cur->enabled != NULL) ++ if (cur->enabled != NULL || cur->branch_list == NULL) + continue; + + ret = is_decl_requires_met(state, cur->branch_list, &req); +@@ -2142,6 +2142,11 @@ static int enable_avrules(link_state_t * state, policydb_t * pol) + /* 1) enable all of the non-else blocks */ + for (block = pol->global; block != NULL; block = block->next) { + block->enabled = block->branch_list; ++ if (!block->enabled) { ++ ERR(state->handle, "Global block has no avrules!"); ++ ret = SEPOL_ERR; ++ goto out; ++ } + block->enabled->enabled = 1; + for (decl = block->branch_list->next; decl != NULL; + decl = decl->next) +-- +2.33.0 diff --git a/backport-libsepol-reject-unsupported-policy-capabilities.patch b/backport-libsepol-reject-unsupported-policy-capabilities.patch new file mode 100644 index 0000000..95f64fa --- /dev/null +++ b/backport-libsepol-reject-unsupported-policy-capabilities.patch @@ -0,0 +1,75 @@ +From e22b7dee0d8de9bc49992fa80b9ceb53925ea36c Mon Sep 17 00:00:00 2001 +From: root +Date: Mon, 8 Jan 2024 17:16:30 +0800 +Subject: [PATCH] libsepol: reject unsupported policy capabilities +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Kernel policies with unsupported policy capabilities enabled can +currently be parsed, since they result just in a bit set inside an +ebitmap. Writing such a loaded policy into the traditional language or +CIL will fail however, since the unsupported policy capabilities can not +be converted into a name. + +Reject kernel policies with invalid policy capabilities. + +Reported-by: oss-fuzz (issue 60573) + +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/7cf2bfb59313eeef59e916834c3243b7a0ce7b4f +Conflict: Context adaptation +--- + libsepol/src/policydb_validate.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index 09f0813..9553812 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -1,6 +1,7 @@ + + #include + #include ++#include + #include + + #include "debug.h" +@@ -771,6 +772,23 @@ bad: + return -1; + } + ++static int validate_policycaps(sepol_handle_t *handle, const policydb_t *p) ++{ ++ ebitmap_node_t *node; ++ uint32_t i; ++ ++ ebitmap_for_each_positive_bit(&p->policycaps, node, i) { ++ if (!sepol_polcap_getname(i)) ++ goto bad; ++ } ++ ++ return 0; ++ ++bad: ++ ERR(handle, "Invalid policy capability"); ++ return -1; ++} ++ + static void validate_array_destroy(validate_t flavors[]) + { + unsigned int i; +@@ -790,6 +808,9 @@ int policydb_validate(sepol_handle_t *handle, policydb_t *p) + if (validate_array_init(p, flavors)) + goto bad; + ++ if (validate_policycaps(handle, p)) ++ goto bad; ++ + if (p->policy_type == POLICY_KERN) { + if (validate_avtab(handle, &p->te_avtab, flavors)) + goto bad; +-- +2.33.0 diff --git a/backport-libsepol-use-correct-type-to-avoid-truncations.patch b/backport-libsepol-use-correct-type-to-avoid-truncations.patch new file mode 100644 index 0000000..216abc9 --- /dev/null +++ b/backport-libsepol-use-correct-type-to-avoid-truncations.patch @@ -0,0 +1,50 @@ +From 4f1435dd51f832fa3b122e5e98be2a5ab176780c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 28 Nov 2023 19:23:29 +0100 +Subject: [PATCH] libsepol: use correct type to avoid truncations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Avoid truncations of the read 32 bit unsigned integer: + + conditional.c:764:8: runtime error: implicit conversion from type 'uint32_t' (aka 'unsigned int') of value 3758096384 (32-bit, unsigned) to type 'int' changed the value to -536870912 (32-bit, signed) + conditional.c:831:8: runtime error: implicit conversion from type 'uint32_t' (aka 'unsigned int') of value 4280295456 (32-bit, unsigned) to type 'int' changed the value to -14671840 (32-bit, signed) + +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/4f1435dd51f832fa3b122e5e98be2a5ab176780c +Conflict: NA +--- + libsepol/src/conditional.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/libsepol/src/conditional.c b/libsepol/src/conditional.c +index 24380ea0..420c7b6c 100644 +--- a/libsepol/src/conditional.c ++++ b/libsepol/src/conditional.c +@@ -746,8 +746,8 @@ static int expr_isvalid(policydb_t * p, cond_expr_t * expr) + + static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp) + { +- uint32_t buf[2]; +- int len, i, rc; ++ uint32_t buf[2], i, len; ++ int rc; + cond_expr_t *expr = NULL, *last = NULL; + + rc = next_entry(buf, fp, sizeof(uint32_t)); +@@ -821,8 +821,8 @@ static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp) + int cond_read_list(policydb_t * p, cond_list_t ** list, void *fp) + { + cond_node_t *node, *last = NULL; +- uint32_t buf[1]; +- int i, len, rc; ++ uint32_t buf[1], i, len; ++ int rc; + + rc = next_entry(buf, fp, sizeof(uint32_t)); + if (rc < 0) +-- +2.33.0 diff --git a/backport-libsepol-validate-MLS-levels.patch b/backport-libsepol-validate-MLS-levels.patch new file mode 100644 index 0000000..e06455d --- /dev/null +++ b/backport-libsepol-validate-MLS-levels.patch @@ -0,0 +1,67 @@ +From 8fdb3eb2725040a81e8a600cf6edd3ff4d93c81f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 9 Dec 2021 17:49:15 +0100 +Subject: [PATCH] libsepol: validate MLS levels +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Validate the level map of the policy to ensure no level refers to a non +existent category. + +READ of size 8 at 0x602000000c58 thread T0 + #0 0x568d2c in cats_ebitmap_len ./libsepol/src/kernel_to_conf.c:1003:14 + #1 0x568d2c in cats_ebitmap_to_str ./libsepol/src/kernel_to_conf.c:1038:19 + #2 0x55e371 in write_level_rules_to_conf ./libsepol/src/kernel_to_conf.c:1106:11 + #3 0x55e371 in write_mls_rules_to_conf ./libsepol/src/kernel_to_conf.c:1140:7 + #4 0x55adb1 in sepol_kernel_policydb_to_conf ./libsepol/src/kernel_to_conf.c:3103:7 + #5 0x55a34f in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:38:9 + #6 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o + #7 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o + #8 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o + #9 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2) + #10 0x7f741d0d67ec in __libc_start_main csu/../csu/libc-start.c:332:16 + #11 0x423689 in _start (./out/binpolicy-fuzzer+0x423689) + +Signed-off-by: Christian Göttsche + +Reference: https://github.com/SELinuxProject/selinux/commit/8fdb3eb2725040a81e8a600cf6edd3ff4d93c81f +Conflict: Context adaptation +--- + libsepol/src/policydb_validate.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index d4dfab5cd1..03ab4445a8 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -294,6 +294,27 @@ bad: + return -1; + } + ++static int validate_mls_level(mls_level_t *level, validate_t *sens, validate_t *cats) ++{ ++ if (validate_value(level->sens, sens)) ++ goto bad; ++ if (validate_ebitmap(&level->cat, cats)) ++ goto bad; ++ ++ return 0; ++ ++ bad: ++ return -1; ++} ++ ++static int validate_level_datum(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) ++{ ++ level_datum_t *level = d; ++ validate_t *flavors = args; ++ ++ 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) + { + if (validate_mls_level(&range->level[0], sens, cats)) +-- +2.33.0 diff --git a/backport-libsepol-validate-check-low-category-is-not-bigger-than-high.patch b/backport-libsepol-validate-check-low-category-is-not-bigger-than-high.patch new file mode 100644 index 0000000..6c1bfea --- /dev/null +++ b/backport-libsepol-validate-check-low-category-is-not-bigger-than-high.patch @@ -0,0 +1,28 @@ +From ac015a3996e894754350ea8ae97e66644899a2c4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Fri, 12 May 2023 11:29:59 +0200 +Subject: [PATCH] libsepol: validate: check low category is not bigger than + high +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/policydb_validate.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index e0d290ff32..b34f83ecb5 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -545,6 +545,8 @@ static int validate_mls_semantic_cat(const mls_semantic_cat_t *cat, const valida + goto bad; + if (validate_value(cat->high, cats)) + goto bad; ++ if (cat->low > cat->high) ++ goto bad; + } + + return 0; diff --git a/backport-libsepol-validate-empty-common-classes-in-scope-indi.patch b/backport-libsepol-validate-empty-common-classes-in-scope-indi.patch new file mode 100644 index 0000000..d8b2f3d --- /dev/null +++ b/backport-libsepol-validate-empty-common-classes-in-scope-indi.patch @@ -0,0 +1,35 @@ +From e54bedce80267b4fbd79b16f548a278c097bd675 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Mon, 11 Dec 2023 15:55:40 +0100 +Subject: [PATCH] libsepol: validate empty common classes in scope indices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Validate no common classes inside scope indices are defined. + +Reported-by: oss-fuzz (issue 64849) +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/e54bedce80267b4fbd79b16f548a278c097bd675 +Conflict: Context adaptation +--- + libsepol/src/policydb_validate.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index bd8e9f8f3..d86f885e4 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -730,6 +730,8 @@ bad: + + static int validate_scope_index(sepol_handle_t *handle, scope_index_t *scope_index, validate_t flavors[]) + { ++ if (!ebitmap_is_empty(&scope_index->scope[SYM_COMMONS])) ++ goto bad; + if (validate_ebitmap(&scope_index->p_classes_scope, &flavors[SYM_CLASSES])) + goto bad; + if (validate_ebitmap(&scope_index->p_roles_scope, &flavors[SYM_ROLES])) +-- +2.33.0 diff --git a/backport-libsepol-validate-expanded-user-range-and-level.patch b/backport-libsepol-validate-expanded-user-range-and-level.patch new file mode 100644 index 0000000..15e2769 --- /dev/null +++ b/backport-libsepol-validate-expanded-user-range-and-level.patch @@ -0,0 +1,80 @@ +From fffb16093c6eb4a316f530ac5813459277dfd40b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 9 Dec 2021 17:49:16 +0100 +Subject: [PATCH] libsepol: validate expanded user range and level +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Check those contains valid values. + + ==57532==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000001178 at pc 0x000000564c04 bp 0x7ffed7a5ad90 sp 0x7ffed7a5ad88 + READ of size 8 at 0x603000001178 thread T0 + #0 0x564c03 in level_to_str ./libsepol/src/kernel_to_conf.c:1901:19 + #1 0x564c03 in range_to_str ./libsepol/src/kernel_to_conf.c:1926:9 + #2 0x564c03 in write_user_decl_rules_to_conf ./libsepol/src/kernel_to_conf.c:2367:12 + #3 0x55b137 in sepol_kernel_policydb_to_conf ./libsepol/src/kernel_to_conf.c:3184:7 + #4 0x55a34f in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:38:9 + #5 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o + #6 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o + #7 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o + #8 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2) + #9 0x7f2c2e1a77ec in __libc_start_main csu/../csu/libc-start.c:332:16 + #10 0x423689 in _start (./out/binpolicy-fuzzer+0x423689) + +Signed-off-by: Christian Göttsche + +Reference: https://github.com/SELinuxProject/selinux/commit/fffb16093c6eb4a316f530ac5813459277dfd40b +Conflict: Context adaptation +--- + libsepol/src/policydb_validate.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index 03ab4445a8..adaa3fb2d8 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -294,7 +294,20 @@ bad: + return -1; + } + +-static int validate_user_datum(sepol_handle_t *handle, user_datum_t *user, validate_t flavors[]) ++static int validate_mls_range(mls_range_t *range, validate_t *sens, validate_t *cats) ++{ ++ if (validate_mls_level(&range->level[0], sens, cats)) ++ goto bad; ++ if (validate_mls_level(&range->level[1], sens, cats)) ++ goto bad; ++ ++ return 0; ++ ++ bad: ++ return -1; ++} ++ ++static int validate_user_datum(sepol_handle_t *handle, user_datum_t *user, validate_t flavors[], int mls) + { + if (validate_value(user->s.value, &flavors[SYM_USERS])) + goto bad; +@@ -304,6 +317,10 @@ 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])) ++ goto bad; ++ if (mls && 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; + +@@ -364,7 +381,7 @@ static int validate_datum_arrays(sepol_handle_t *handle, policydb_t *p, validate + if (p->user_val_to_struct[i]) { + if (ebitmap_get_bit(&flavors[SYM_USERS].gaps, i)) + goto bad; +- if (validate_user_datum(handle, p->user_val_to_struct[i], flavors)) ++ if (validate_user_datum(handle, p->user_val_to_struct[i], flavors, p->mls)) + goto bad; + } else { + if (!ebitmap_get_bit(&flavors[SYM_USERS].gaps, i)) +-- +2.33.0 diff --git a/backport-libsepol-validate-ocontexts.patch b/backport-libsepol-validate-ocontexts.patch new file mode 100644 index 0000000..9010e9e --- /dev/null +++ b/backport-libsepol-validate-ocontexts.patch @@ -0,0 +1,103 @@ +From 8628133757c2100118ef5bd2f135eb1bc4a6f33c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 9 Dec 2021 17:49:22 +0100 +Subject: [PATCH] libsepol: validate ocontexts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Check the literal contexts in ocontext statements are defined. + + ==91274==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f60b0afe8c6 bp 0x7ffd42edc990 sp 0x7ffd42edc148 T0) + ==91274==The signal is caused by a READ memory access. + ==91274==Hint: address points to the zero page. + #0 0x7f60b0afe8c6 string/../sysdeps/x86_64/multiarch/../strlen.S:120 + #1 0x4bd128 in __interceptor_strlen (./out/binpolicy-fuzzer+0x4bd128) + #2 0x5eb387 in create_str_helper ./libsepol/src/kernel_to_common.c:69:10 + #3 0x5eb11e in create_str ./libsepol/src/kernel_to_common.c:99:8 + #4 0x56ad7b in context_to_str ./libsepol/src/kernel_to_conf.c:2408:9 + #5 0x56a717 in write_sid_context_rules_to_conf ./libsepol/src/kernel_to_conf.c:2441:9 + #6 0x55b26c in write_selinux_isid_rules_to_conf ./libsepol/src/kernel_to_conf.c:2476:9 + #7 0x55b26c in sepol_kernel_policydb_to_conf ./libsepol/src/kernel_to_conf.c:3206:8 + #8 0x55a34f in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:38:9 + #9 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o + #10 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o + #11 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o + #12 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2) + #13 0x7f60b0a887ec in __libc_start_main csu/../csu/libc-start.c:332:16 + #14 0x423689 in _start (./out/binpolicy-fuzzer+0x423689) + +Signed-off-by: Christian Göttsche + +Reference: https://github.com/SELinuxProject/selinux/commit/8628133757c2100118ef5bd2f135eb1bc4a6f33c +Conflict: NA +--- + libsepol/src/policydb_validate.c | 46 ++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index 57eb2550..bedf3b90 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -736,6 +736,49 @@ 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) ++{ ++ if (validate_value(con->user, &flavors[SYM_USERS])) ++ return -1; ++ if (validate_value(con->role, &flavors[SYM_ROLES])) ++ return -1; ++ if (validate_value(con->type, &flavors[SYM_TYPES])) ++ return -1; ++ if (mls && validate_mls_range(&con->range, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) ++ return -1; ++ ++ return 0; ++} ++ ++static int validate_ocontexts(sepol_handle_t *handle, policydb_t *p, validate_t flavors[]) ++{ ++ ocontext_t *octx; ++ unsigned int i; ++ ++ for (i = 0; i < OCON_NUM; i++) { ++ for (octx = p->ocontexts[i]; octx; octx = octx->next) { ++ if (validate_context(&octx->context[0], flavors, p->mls)) ++ goto bad; ++ ++ if (p->target_platform == SEPOL_TARGET_SELINUX) { ++ switch (i) { ++ case OCON_FS: ++ case OCON_NETIF: ++ if (validate_context(&octx->context[1], flavors, p->mls)) ++ goto bad; ++ break; ++ } ++ } ++ } ++ } ++ ++ return 0; ++ ++bad: ++ ERR(handle, "Invalid ocontext"); ++ return -1; ++} ++ + /* + * Functions to validate a module policydb + */ +@@ -936,6 +979,9 @@ int validate_policydb(sepol_handle_t *handle, policydb_t *p) + goto bad; + } + ++ if (validate_ocontexts(handle, p, flavors)) ++ goto bad; ++ + if (validate_scopes(handle, p->scope, p->global)) + goto bad; + +-- +2.33.0 diff --git a/backport-libsepol-validate-old-style-range-trans-classes.patch b/backport-libsepol-validate-old-style-range-trans-classes.patch new file mode 100644 index 0000000..56cca6b --- /dev/null +++ b/backport-libsepol-validate-old-style-range-trans-classes.patch @@ -0,0 +1,41 @@ +From 4cf37608b563327ce433ce392931a9eb8bda9524 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Fri, 12 May 2023 11:29:58 +0200 +Subject: [PATCH] libsepol: validate old style range trans classes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For old style range transition rules the class defaults to process. +However the policy might not declare the process class leading to +setting a wrong bit later on via: + + if (ebitmap_set_bit(&rtr->tclasses, rt->target_class - 1, 1)) + +UBSAN report: + + policydb.c:3684:56: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'uint32_t' (aka 'unsigned int') + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libsepol/src/policydb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c +index b79c19b94c..605d290a71 100644 +--- a/libsepol/src/policydb.c ++++ b/libsepol/src/policydb.c +@@ -3650,10 +3650,10 @@ static int range_read(policydb_t * p, struct policy_file *fp) + if (rc < 0) + goto err; + rt->target_class = le32_to_cpu(buf[0]); +- if (!value_isvalid(rt->target_class, p->p_classes.nprim)) +- goto err; + } else + rt->target_class = p->process_class; ++ if (!value_isvalid(rt->target_class, p->p_classes.nprim)) ++ goto err; + r = calloc(1, sizeof(*r)); + if (!r) + goto err; diff --git a/backport-libsepol-validate-the-identifier-for-initials-SID-is.patch b/backport-libsepol-validate-the-identifier-for-initials-SID-is.patch new file mode 100644 index 0000000..09e201e --- /dev/null +++ b/backport-libsepol-validate-the-identifier-for-initials-SID-is.patch @@ -0,0 +1,50 @@ +From cf6ddded1650098c05f4245df41395420cf41838 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 9 Nov 2023 14:51:21 +0100 +Subject: [PATCH] libsepol: validate the identifier for initials SID is valid +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Check the identifier for initial SIDs is less than the maximum known ID. +The kernel will ignore all unknown IDs, see +security/selinux/ss/policydb.c:policydb_load_isids(). + +Without checking huge IDs result in OOM events, while writing policies, +e.g. in write_sids_to_conf() or write_sids_to_cil(), due to allocation +of large (continuous) string lists. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter + +Reference: https://github.com/SELinuxProject/selinux/commit/cf6ddded1650098c05f4245df41395420cf41838 +Conflict: Context adaptation +--- + libsepol/src/policydb_validate.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c +index 016ab6550..32ad5a18b 100644 +--- a/libsepol/src/policydb_validate.c ++++ b/libsepol/src/policydb_validate.c +@@ -5,6 +5,7 @@ + #include + + #include "debug.h" ++#include "kernel_to_common.h" + #include "policydb_validate.h" + + typedef struct validate { +@@ -635,6 +636,10 @@ static int validate_ocontexts(sepol_handle_t *handle, policydb_t *p, validate_t + + if (p->target_platform == SEPOL_TARGET_SELINUX) { + switch (i) { ++ case OCON_ISID: ++ if (octx->sid[0] == SEPOL_SECSID_NULL || octx->sid[0] >= SELINUX_SID_SZ) ++ goto bad; ++ break; + case OCON_FS: + case OCON_NETIF: + if (validate_context(&octx->context[1], flavors, p->mls)) +-- +2.33.0 diff --git a/libsepol.spec b/libsepol.spec index 4646844..aff2b3d 100644 --- a/libsepol.spec +++ b/libsepol.spec @@ -1,6 +1,6 @@ Name: libsepol Version: 3.3 -Release: 5 +Release: 7 Summary: SELinux binary policy manipulation library License: LGPLv2+ URL: https://github.com/SELinuxProject/selinux/wiki/Releases @@ -13,7 +13,35 @@ Patch0004: backport-libsepol-do-not-modify-policy-during-write.patch Patch0005: backport-libsepol-enclose-macro-parameters-and-replacement-lists-in-parentheses.patch Patch0006: backport-libsepol-rename-validate_policydb-to-policydb_validate.patch Patch0007: backport-libsepol-fix-missing-double-quotes-in-typetransition-CIL-rule.patch -Patch0008: backport-libsepol-reorder-calloc-3-arguments.patch +Patch0008: backport-hashtab-update.patch +Patch0009: backport-libsepol-check-for-overflow-in-put_entry.patch +Patch0010: backport-libsepol-dump-non-mls-validatetrans-rules-as-such.patch +Patch0011: backport-libsepol-expand-use-identical-type-to-avoid-implicit-conversion.patch +Patch0012: backport-libsepol-cil-Fix-class-permission-verification-in-CIL.patch +Patch0013: backport-libsepol-validate-old-style-range-trans-classes.patch +Patch0014: backport-libsepol-validate-check-low-category-is-not-bigger-than-high.patch +Patch0015: backport-libsepol-Validate-conditional-expressions.patch +Patch0016: backport-libsepol-reject-avtab-entries-with-invalid-specifier.patch +Patch0017: backport-libsepol-avtab-check-read-counts-for-saturation.patch +Patch0018: backport-libsepol-expand-skip-invalid-cat.patch +Patch0019: backport-libsepol-more-strict-validation.patch +Patch0020: backport-libsepol-reject-unsupported-policy-capabilities.patch +Patch0021: backport-libsepol-adjust-type-for-saturation-check.patch +Patch0022: backport-libsepol-enhance-saturation-check.patch +Patch0023: backport-libsepol-avoid-leak-in-OOM-branch.patch +Patch0024: backport-libsepol-avoid-memory-corruption-on-realloc-failure.patch +Patch0025: backport-libsepol-cil-Do-not-allow-classpermissionset-to-use-.patch +Patch0026: backport-libsepol-add-check-for-category-value-before-printin.patch +Patch0027: backport-libsepol-use-correct-type-to-avoid-truncations.patch +Patch0028: backport-libsepol-reject-invalid-class-datums.patch +Patch0029: backport-libsepol-reject-linking-modules-with-no-avrules.patch +Patch0030: backport-libsepol-avoid-integer-overflow-in-add_i_to_a.patch +Patch0031: backport-libsepol-validate-empty-common-classes-in-scope-indi.patch +Patch0032: backport-libsepol-validate-expanded-user-range-and-level.patch +Patch0033: backport-libsepol-validate-MLS-levels.patch +Patch0034: backport-libsepol-validate-ocontexts.patch +Patch0035: backport-libsepol-validate-the-identifier-for-initials-SID-is.patch +Patch0036: backport-libsepol-reorder-calloc-3-arguments.patch BuildRequires: gcc flex @@ -73,9 +101,15 @@ make DESTDIR="%{buildroot}" LIBDIR="%{_libdir}" SHLIBDIR="%{_libdir}" install %{_mandir}/man3/* %changelog -* Tue Mar 26 2024 gengqihu - 3.3-5 +* Tue Mar 26 2024 gengqihu - 3.3-7 - backport bugfix from upstream +* Mon Mar 4 2024 zhengxiaoxiao - 3.3-6 +- backport upstream patch + +* Mon Nov 27 2023 luhuaxin - 3.3-5 +- backport upstream patch + * Fri Nov 18 2022 jinlun - 3.3-4 - backport upstream patch and update release to adapt baseline