From f7d3e92ab497a46195a30f21a17454b0f517b6e2 Mon Sep 17 00:00:00 2001 From: Petr Lautrbach Date: Fri, 20 Nov 2020 11:47:30 +0100 Subject: [PATCH] libsepol-3.1-5 - Drop and obsolete libsepol-compat subpackage - cil: Give error for more than one true or false block --- ...e-error-for-more-than-one-true-or-fa.patch | 170 ++++++++++++++++++ ...sepol-free-memory-when-realloc-fails.patch | 81 +++++++++ libsepol.spec | 8 +- 3 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 0012-libsepol-cil-Give-error-for-more-than-one-true-or-fa.patch create mode 100644 0013-libsepol-free-memory-when-realloc-fails.patch diff --git a/0012-libsepol-cil-Give-error-for-more-than-one-true-or-fa.patch b/0012-libsepol-cil-Give-error-for-more-than-one-true-or-fa.patch new file mode 100644 index 0000000..3e5885b --- /dev/null +++ b/0012-libsepol-cil-Give-error-for-more-than-one-true-or-fa.patch @@ -0,0 +1,170 @@ +From 3b26f0566698926ba38cbf3fa702f3ff78862c5e Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Tue, 20 Oct 2020 09:28:56 -0400 +Subject: [PATCH] libsepol/cil: Give error for more than one true or false + block + +Both tunableif and booleanif use conditional blocks (either true or +false). No ordering is imposed, so a false block can be first (or even +the only) block. Checks are made to ensure that the first and second +(if it exists) blocks are either true or false, but no checks are made +to ensure that there is only one true and/or one false block. If there +are more than one true or false block, only the first will be used and +the other will be ignored. + +Create a function, cil_verify_conditional_blocks(), that gives an error +along with a message if more than one true or false block is specified +and call that function when building tunableif and booleanif blocks in +the AST. + +Signed-off-by: James Carter +Acked-by: Ondrej Mosnacek +--- + libsepol/cil/src/cil_build_ast.c | 44 +++++--------------------------- + libsepol/cil/src/cil_verify.c | 35 +++++++++++++++++++++++++ + libsepol/cil/src/cil_verify.h | 1 + + 3 files changed, 42 insertions(+), 38 deletions(-) + +diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c +index 3aabb05ec534..a895583404a7 100644 +--- a/libsepol/cil/src/cil_build_ast.c ++++ b/libsepol/cil/src/cil_build_ast.c +@@ -2821,7 +2821,6 @@ int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struc + int syntax_len = sizeof(syntax)/sizeof(*syntax); + struct cil_booleanif *bif = NULL; + struct cil_tree_node *next = NULL; +- struct cil_tree_node *cond = NULL; + int rc = SEPOL_ERR; + + if (db == NULL || parse_current == NULL || ast_node == NULL) { +@@ -2841,27 +2840,12 @@ int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struc + goto exit; + } + +- cond = parse_current->next->next; +- +- /* Destroying expr tree after stack is created*/ +- if (cond->cl_head->data != CIL_KEY_CONDTRUE && +- cond->cl_head->data != CIL_KEY_CONDFALSE) { +- rc = SEPOL_ERR; +- cil_log(CIL_ERR, "Conditional neither true nor false\n"); ++ rc = cil_verify_conditional_blocks(parse_current->next->next); ++ if (rc != SEPOL_OK) { + goto exit; + } + +- if (cond->next != NULL) { +- cond = cond->next; +- if (cond->cl_head->data != CIL_KEY_CONDTRUE && +- cond->cl_head->data != CIL_KEY_CONDFALSE) { +- rc = SEPOL_ERR; +- cil_log(CIL_ERR, "Conditional neither true nor false\n"); +- goto exit; +- } +- } +- +- ++ /* Destroying expr tree */ + next = parse_current->next->next; + cil_tree_subtree_destroy(parse_current->next); + parse_current->next = next; +@@ -2905,7 +2889,6 @@ int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct + int syntax_len = sizeof(syntax)/sizeof(*syntax); + struct cil_tunableif *tif = NULL; + struct cil_tree_node *next = NULL; +- struct cil_tree_node *cond = NULL; + int rc = SEPOL_ERR; + + if (db == NULL || parse_current == NULL || ast_node == NULL) { +@@ -2924,27 +2907,12 @@ int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct + goto exit; + } + +- cond = parse_current->next->next; +- +- if (cond->cl_head->data != CIL_KEY_CONDTRUE && +- cond->cl_head->data != CIL_KEY_CONDFALSE) { +- rc = SEPOL_ERR; +- cil_log(CIL_ERR, "Conditional neither true nor false\n"); ++ rc = cil_verify_conditional_blocks(parse_current->next->next); ++ if (rc != SEPOL_OK) { + goto exit; + } + +- if (cond->next != NULL) { +- cond = cond->next; +- +- if (cond->cl_head->data != CIL_KEY_CONDTRUE && +- cond->cl_head->data != CIL_KEY_CONDFALSE) { +- rc = SEPOL_ERR; +- cil_log(CIL_ERR, "Conditional neither true nor false\n"); +- goto exit; +- } +- } +- +- /* Destroying expr tree after stack is created*/ ++ /* Destroying expr tree */ + next = parse_current->next->next; + cil_tree_subtree_destroy(parse_current->next); + parse_current->next = next; +diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c +index c73bbeee371b..6706e21921fe 100644 +--- a/libsepol/cil/src/cil_verify.c ++++ b/libsepol/cil/src/cil_verify.c +@@ -324,6 +324,41 @@ exit: + return SEPOL_ERR; + } + ++int cil_verify_conditional_blocks(struct cil_tree_node *current) ++{ ++ int found_true = CIL_FALSE; ++ int found_false = CIL_FALSE; ++ ++ if (current->cl_head->data == CIL_KEY_CONDTRUE) { ++ found_true = CIL_TRUE; ++ } else if (current->cl_head->data == CIL_KEY_CONDFALSE) { ++ found_false = CIL_TRUE; ++ } else { ++ cil_tree_log(current, CIL_ERR, "Expected true or false block in conditional"); ++ return SEPOL_ERR; ++ } ++ ++ current = current->next; ++ if (current != NULL) { ++ if (current->cl_head->data == CIL_KEY_CONDTRUE) { ++ if (found_true) { ++ cil_tree_log(current, CIL_ERR, "More than one true block in conditional"); ++ return SEPOL_ERR; ++ } ++ } else if (current->cl_head->data == CIL_KEY_CONDFALSE) { ++ if (found_false) { ++ cil_tree_log(current, CIL_ERR, "More than one false block in conditional"); ++ return SEPOL_ERR; ++ } ++ } else { ++ cil_tree_log(current, CIL_ERR, "Expected true or false block in conditional"); ++ return SEPOL_ERR; ++ } ++ } ++ ++ return SEPOL_OK; ++} ++ + int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list) + { + struct cil_list_item *i; +diff --git a/libsepol/cil/src/cil_verify.h b/libsepol/cil/src/cil_verify.h +index bda1565fced5..905761b0a19c 100644 +--- a/libsepol/cil/src/cil_verify.h ++++ b/libsepol/cil/src/cil_verify.h +@@ -61,6 +61,7 @@ int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[] + int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor); + int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor); + int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op); ++int cil_verify_conditional_blocks(struct cil_tree_node *current); + int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list); + int __cil_verify_ranges(struct cil_list *list); + int __cil_verify_ordered_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args); +-- +2.29.2 + diff --git a/0013-libsepol-free-memory-when-realloc-fails.patch b/0013-libsepol-free-memory-when-realloc-fails.patch new file mode 100644 index 0000000..b57fb8d --- /dev/null +++ b/0013-libsepol-free-memory-when-realloc-fails.patch @@ -0,0 +1,81 @@ +From a2bd2a8ea5ef687e8b4dc2694f7d5e99a1ec2a06 Mon Sep 17 00:00:00 2001 +From: Nicolas Iooss +Date: Thu, 12 Nov 2020 21:24:06 +0100 +Subject: [PATCH] libsepol: free memory when realloc() fails + +In get_class_info(), if realloc(class_buf, new_class_buf_len) fails to +grow the memory, the function returns NULL without freeing class_buf. +This leads to a memory leak which is reported by clang's static +analyzer: +https://580-118970575-gh.circle-artifacts.com/0/output-scan-build/2020-11-11-194150-6152-1/report-42a899.html#EndPath + +Fix the memory leak by calling free(class_buf). + +While at it, use size_t insted of int to store the size of the buffer +which is growing. + +Signed-off-by: Nicolas Iooss +--- + libsepol/src/services.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +diff --git a/libsepol/src/services.c b/libsepol/src/services.c +index beb0711f6680..72b39657cd2e 100644 +--- a/libsepol/src/services.c ++++ b/libsepol/src/services.c +@@ -312,17 +312,20 @@ static char *get_class_info(sepol_security_class_t tclass, + else + state_num = mls + 2; + +- int class_buf_len = 0; +- int new_class_buf_len; +- int len, buf_used; ++ size_t class_buf_len = 0; ++ size_t new_class_buf_len; ++ size_t buf_used; ++ int len; + char *class_buf = NULL, *p; + char *new_class_buf = NULL; + + while (1) { + new_class_buf_len = class_buf_len + EXPR_BUF_SIZE; + new_class_buf = realloc(class_buf, new_class_buf_len); +- if (!new_class_buf) +- return NULL; ++ if (!new_class_buf) { ++ free(class_buf); ++ return NULL; ++ } + class_buf_len = new_class_buf_len; + class_buf = new_class_buf; + buf_used = 0; +@@ -330,7 +333,7 @@ static char *get_class_info(sepol_security_class_t tclass, + + /* Add statement type */ + len = snprintf(p, class_buf_len - buf_used, "%s", statements[state_num]); +- if (len < 0 || len >= class_buf_len - buf_used) ++ if (len < 0 || (size_t)len >= class_buf_len - buf_used) + continue; + + /* Add class entry */ +@@ -338,7 +341,7 @@ static char *get_class_info(sepol_security_class_t tclass, + buf_used += len; + len = snprintf(p, class_buf_len - buf_used, "%s ", + policydb->p_class_val_to_name[tclass - 1]); +- if (len < 0 || len >= class_buf_len - buf_used) ++ if (len < 0 || (size_t)len >= class_buf_len - buf_used) + continue; + + /* Add permission entries (validatetrans does not have perms) */ +@@ -351,7 +354,7 @@ static char *get_class_info(sepol_security_class_t tclass, + } else { + len = snprintf(p, class_buf_len - buf_used, "("); + } +- if (len < 0 || len >= class_buf_len - buf_used) ++ if (len < 0 || (size_t)len >= class_buf_len - buf_used) + continue; + break; + } +-- +2.29.2 + diff --git a/libsepol.spec b/libsepol.spec index 502e613..b58d5b7 100644 --- a/libsepol.spec +++ b/libsepol.spec @@ -1,7 +1,7 @@ Summary: SELinux binary policy manipulation library Name: libsepol Version: 3.1 -Release: 4%{?dist} +Release: 5%{?dist} License: LGPLv2+ Source0: https://github.com/SELinuxProject/selinux/releases/download/20200710/libsepol-3.1.tar.gz URL: https://github.com/SELinuxProject/selinux/wiki @@ -21,6 +21,8 @@ Patch0008: 0008-libsepol-silence-potential-NULL-pointer-dereference-.patch Patch0009: 0009-libsepol-Get-rid-of-the-old-and-duplicated-symbols.patch Patch0010: 0010-libsepol-Drop-deprecated-functions.patch Patch0011: 0011-libsepol-Bump-libsepol.so-version.patch +Patch0012: 0012-libsepol-cil-Give-error-for-more-than-one-true-or-fa.patch +Patch0013: 0013-libsepol-free-memory-when-realloc-fails.patch # Patch list end BuildRequires: make BuildRequires: gcc @@ -106,6 +108,10 @@ rm -rf ${RPM_BUILD_ROOT}%{_mandir}/ru/man8 %{_libdir}/libsepol.so.2 %changelog +* Fri Nov 20 2020 Petr Lautrbach - 3.1-5 +- Drop and obsolete libsepol-compat subpackage +- cil: Give error for more than one true or false block + * Fri Oct 23 2020 Petr Lautrbach - 3.1-4 - Drop deprecated functions and duplicated symbols - Dange library version to libsepol.so.2