Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libsepol for openSUSE:Factory checked in at 2024-07-12 17:04:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libsepol (Old) and /work/SRC/openSUSE:Factory/.libsepol.new.17339 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "libsepol" Fri Jul 12 17:04:21 2024 rev:56 rq:1185748 version:3.7 Changes: -------- --- /work/SRC/openSUSE:Factory/libsepol/libsepol.changes 2024-01-08 23:43:53.115308503 +0100 +++ /work/SRC/openSUSE:Factory/.libsepol.new.17339/libsepol.changes 2024-07-12 17:04:26.547676225 +0200 @@ -1,0 +2,24 @@ +Mon Jul 1 08:01:08 UTC 2024 - Cathy Hu <cathy.hu@suse.com> + +- Update to version 3.7 + https://github.com/SELinuxProject/selinux/releases/tag/3.7 + * User-visible changes: + * libsepol: improve policy lookup failure message + * libsepol: include prefix for module policy versions + * libsepol: validate type-attribute-map for old policies + * libsepol: only exempt gaps checking for kernel policies + * Bugfixes: + * libsepol/src/Makefile: fix reallocarray detection + * libsepol/cil: Fix detected RESOURCE_LEAK (CWE-772) + * libsepol: ensure transitivity in compare functions + * oss-fuzz fixes: + * libsepol: check scope permissions refer to valid class + * libsepol: validate attribute-type maps + * libsepol: reject self flag in type rules in old policies + * libsepol: validate class permissions + * libsepol: validate access vector permissions + * libsepol: reject MLS support in pre-MLS policies + * libsepol: Fix buffer overflow when using sepol_av_to_string() + * libsepol: Use a dynamic buffer in sepol_av_to_string() + +------------------------------------------------------------------- Old: ---- libsepol-3.6.tar.gz libsepol-3.6.tar.gz.asc New: ---- libsepol-3.7.tar.gz libsepol-3.7.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libsepol.spec ++++++ --- /var/tmp/diff_new_pack.v3mzoy/_old 2024-07-12 17:04:29.323778224 +0200 +++ /var/tmp/diff_new_pack.v3mzoy/_new 2024-07-12 17:04:29.327778371 +0200 @@ -1,7 +1,7 @@ # # spec file for package libsepol # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %define libname libsepol2 Name: libsepol -Version: 3.6 +Version: 3.7 Release: 0 Summary: SELinux binary policy manipulation library License: LGPL-2.1-or-later ++++++ libsepol-3.6.tar.gz -> libsepol-3.7.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/VERSION new/libsepol-3.7/VERSION --- old/libsepol-3.6/VERSION 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/VERSION 2024-06-26 17:30:41.000000000 +0200 @@ -1 +1 @@ -3.6 +3.7 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/cil/src/cil_binary.c new/libsepol-3.7/cil/src/cil_binary.c --- old/libsepol-3.6/cil/src/cil_binary.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/cil/src/cil_binary.c 2024-06-26 17:30:41.000000000 +0200 @@ -904,10 +904,10 @@ rc = mls_level_cpy(mls_level, sepol_level->level); if (rc != SEPOL_OK) { + free(mls_level); goto exit; } sepol_alias->level = mls_level; - sepol_alias->defined = 1; sepol_alias->isalias = 1; return SEPOL_OK; @@ -3163,8 +3163,6 @@ } } - sepol_level->defined = 1; - return SEPOL_OK; exit: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/cil/src/cil_post.c new/libsepol-3.7/cil/src/cil_post.c --- old/libsepol-3.6/cil/src/cil_post.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/cil/src/cil_post.c 2024-06-26 17:30:41.000000000 +0200 @@ -52,6 +52,8 @@ #define GEN_REQUIRE_ATTR "cil_gen_require" /* Also in libsepol/src/module_to_cil.c */ #define TYPEATTR_INFIX "_typeattr_" /* Also in libsepol/src/module_to_cil.c */ +#define spaceship_cmp(a, b) (((a) > (b)) - ((a) < (b))) + struct fc_data { unsigned int meta; size_t stem_len; @@ -263,8 +265,8 @@ if (rc) return rc; - rc = (aibpkeycon->pkey_high - aibpkeycon->pkey_low) - - (bibpkeycon->pkey_high - bibpkeycon->pkey_low); + rc = spaceship_cmp(aibpkeycon->pkey_high - aibpkeycon->pkey_low, + bibpkeycon->pkey_high - bibpkeycon->pkey_low); if (rc == 0) { if (aibpkeycon->pkey_low < bibpkeycon->pkey_low) rc = -1; @@ -281,8 +283,8 @@ struct cil_portcon *aportcon = *(struct cil_portcon**)a; struct cil_portcon *bportcon = *(struct cil_portcon**)b; - rc = (aportcon->port_high - aportcon->port_low) - - (bportcon->port_high - bportcon->port_low); + rc = spaceship_cmp(aportcon->port_high - aportcon->port_low, + bportcon->port_high - bportcon->port_low); if (rc == 0) { if (aportcon->port_low < bportcon->port_low) { rc = -1; @@ -394,8 +396,8 @@ struct cil_iomemcon *aiomemcon = *(struct cil_iomemcon**)a; struct cil_iomemcon *biomemcon = *(struct cil_iomemcon**)b; - rc = (aiomemcon->iomem_high - aiomemcon->iomem_low) - - (biomemcon->iomem_high - biomemcon->iomem_low); + rc = spaceship_cmp(aiomemcon->iomem_high - aiomemcon->iomem_low, + biomemcon->iomem_high - biomemcon->iomem_low); if (rc == 0) { if (aiomemcon->iomem_low < biomemcon->iomem_low) { rc = -1; @@ -413,8 +415,8 @@ struct cil_ioportcon *aioportcon = *(struct cil_ioportcon**)a; struct cil_ioportcon *bioportcon = *(struct cil_ioportcon**)b; - rc = (aioportcon->ioport_high - aioportcon->ioport_low) - - (bioportcon->ioport_high - bioportcon->ioport_low); + rc = spaceship_cmp(aioportcon->ioport_high - aioportcon->ioport_low, + bioportcon->ioport_high - bioportcon->ioport_low); if (rc == 0) { if (aioportcon->ioport_low < bioportcon->ioport_low) { rc = -1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/cil/src/cil_verify.c new/libsepol-3.7/cil/src/cil_verify.c --- old/libsepol-3.6/cil/src/cil_verify.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/cil/src/cil_verify.c 2024-06-26 17:30:41.000000000 +0200 @@ -1842,6 +1842,9 @@ int count2 = 0; cil_list_init(&perm_list, CIL_MAP_PERM); cil_symtab_map(&class->perms, __add_perm_to_list, perm_list); + if (class->common != NULL) { + cil_symtab_map(&class->common->perms, __add_perm_to_list, perm_list); + } cil_list_for_each(j, perm_list) { count2++; struct cil_perm *perm = j->data; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/include/sepol/policydb/avrule_block.h new/libsepol-3.7/include/sepol/policydb/avrule_block.h --- old/libsepol-3.6/include/sepol/policydb/avrule_block.h 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/include/sepol/policydb/avrule_block.h 2024-06-26 17:30:41.000000000 +0200 @@ -35,8 +35,8 @@ extern cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl, cond_list_t * cond); -extern int is_id_enabled(char *id, policydb_t * p, int symbol_table); -extern int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p); +extern int is_id_enabled(const char *id, const policydb_t * p, int symbol_table); +extern int is_perm_existent(const class_datum_t *cladatum, const char *perm_id); #ifdef __cplusplus } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/include/sepol/policydb/policydb.h new/libsepol-3.7/include/sepol/policydb/policydb.h --- old/libsepol-3.6/include/sepol/policydb/policydb.h 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/include/sepol/policydb/policydb.h 2024-06-26 17:30:41.000000000 +0200 @@ -217,7 +217,7 @@ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */ unsigned char isalias; /* is this sensitivity an alias for another? */ - unsigned char defined; + unsigned char notdefined; /* Only set to non-zero in checkpolicy */ } level_datum_t; /* Category attributes */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/include/sepol/policydb/util.h new/libsepol-3.7/include/sepol/policydb/util.h --- old/libsepol-3.6/include/sepol/policydb/util.h 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/include/sepol/policydb/util.h 2024-06-26 17:30:41.000000000 +0200 @@ -31,7 +31,7 @@ extern int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a); -extern char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, +extern char *sepol_av_to_string(const policydb_t *policydbp, sepol_security_class_t tclass, sepol_access_vector_t av); char *sepol_extended_perms_to_string(const avtab_extended_perms_t *xperms); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/Makefile new/libsepol-3.7/src/Makefile --- old/libsepol-3.6/src/Makefile 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/Makefile 2024-06-26 17:30:41.000000000 +0200 @@ -31,7 +31,7 @@ # check for reallocarray(3) availability H := \# -ifeq (yes,$(shell printf '${H}define _GNU_SOURCE\n${H}include <stdlib.h>\nint main(void){void*p=reallocarray(NULL, 1, sizeof(char));return 0;}' | $(CC) -x c -o /dev/null - >/dev/null 2>&1 && echo yes)) +ifeq (yes,$(shell printf '${H}include <stdlib.h>\nint main(void){return reallocarray(NULL,0,0)==NULL;}' | $(CC) $(CFLAGS) $(LDFLAGS) -x c -o /dev/null - >/dev/null 2>&1 && echo yes)) override CFLAGS += -DHAVE_REALLOCARRAY endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/assertion.c new/libsepol-3.7/src/assertion.c --- old/libsepol-3.6/src/assertion.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/assertion.c 2024-06-26 17:30:41.000000000 +0200 @@ -48,26 +48,30 @@ unsigned int stype, unsigned int ttype, const class_perm_node_t *curperm, uint32_t perms) { + char *permstr = sepol_av_to_string(p, curperm->tclass, perms); + if (avrule->source_filename) { ERR(handle, "neverallow on line %lu of %s (or line %lu of %s) violated by allow %s %s:%s {%s };", avrule->source_line, avrule->source_filename, avrule->line, policy_name(p), p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], - sepol_av_to_string(p, curperm->tclass, perms)); + permstr ?: "<format-failure>"); } else if (avrule->line) { ERR(handle, "neverallow on line %lu violated by allow %s %s:%s {%s };", avrule->line, p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], - sepol_av_to_string(p, curperm->tclass, perms)); + permstr ?: "<format-failure>"); } else { ERR(handle, "neverallow violated by allow %s %s:%s {%s };", p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], - sepol_av_to_string(p, curperm->tclass, perms)); + permstr ?: "<format-failure>"); } + + free(permstr); } static int match_any_class_permissions(class_perm_node_t *cp, uint32_t class, uint32_t data) @@ -200,13 +204,17 @@ /* failure on the regular permissions */ if (!found_xperm) { + char *permstr = sepol_av_to_string(p, curperm->tclass, perms); + ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" "allow %s %s:%s {%s };", avrule->source_line, avrule->source_filename, avrule->line, policy_name(p), p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], - sepol_av_to_string(p, curperm->tclass, perms)); + permstr ?: "<format-failure>"); + + free(permstr); errors++; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/avrule_block.c new/libsepol-3.7/src/avrule_block.c --- old/libsepol-3.6/src/avrule_block.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/avrule_block.c 2024-06-26 17:30:41.000000000 +0200 @@ -152,11 +152,11 @@ * marked as SCOPE_DECL, and any of its declaring block has been enabled, * then return 1. Otherwise return 0. Can only be called after the * decl_val_to_struct index has been created */ -int is_id_enabled(char *id, policydb_t * p, int symbol_table) +int is_id_enabled(const char *id, const policydb_t * p, int symbol_table) { - scope_datum_t *scope = + const scope_datum_t *scope = (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id); - avrule_decl_t *decl; + const avrule_decl_t *decl; uint32_t len; if (scope == NULL) { @@ -189,21 +189,13 @@ return 0; } -/* Check if a particular permission is present within the given class, - * and that the class is enabled. Returns 1 if both conditions are - * true, 0 if neither could be found or if the class id disabled. */ -int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p) +/* Check if a particular permission is present within the given class. + * Whether the class is enabled is NOT checked. + * Returns 1 if permission is present, 0 otherwise */ +int is_perm_existent(const class_datum_t *cladatum, const char *perm_id) { - class_datum_t *cladatum; - perm_datum_t *perm; - if (!is_id_enabled(class_id, p, SYM_CLASSES)) { - return 0; - } - cladatum = - (class_datum_t *) hashtab_search(p->p_classes.table, class_id); - if (cladatum == NULL) { - return 0; - } + const perm_datum_t *perm; + perm = hashtab_search(cladatum->permissions.table, perm_id); if (perm == NULL && cladatum->comdatum != 0) { /* permission was not in this class. before giving diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/hashtab.c new/libsepol-3.7/src/hashtab.c --- old/libsepol-3.6/src/hashtab.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/hashtab.c 2024-06-26 17:30:41.000000000 +0200 @@ -112,15 +112,17 @@ hashtab_check_resize(h); hvalue = h->hash_value(h, key); - prev = NULL; - cur = h->htable[hvalue]; - while (cur && h->keycmp(h, key, cur->key) > 0) { - prev = cur; - cur = cur->next; - } - if (cur && (h->keycmp(h, key, cur->key) == 0)) - return SEPOL_EEXIST; + for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { + int cmp; + + cmp = h->keycmp(h, key, cur->key); + if (cmp > 0) + continue; + if (cmp == 0) + return SEPOL_EEXIST; + break; + } newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t)); if (newnode == NULL) @@ -151,14 +153,19 @@ return SEPOL_ENOENT; hvalue = h->hash_value(h, key); - last = NULL; - cur = h->htable[hvalue]; - while (cur != NULL && h->keycmp(h, key, cur->key) > 0) { - last = cur; - cur = cur->next; + + for (last = NULL, cur = h->htable[hvalue]; cur; last = cur, cur = cur->next) { + int cmp; + + cmp = h->keycmp(h, key, cur->key); + if (cmp > 0) + continue; + if (cmp == 0) + break; + return SEPOL_ENOENT; } - if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) + if (cur == NULL) return SEPOL_ENOENT; if (last == NULL) @@ -183,14 +190,18 @@ return NULL; hvalue = h->hash_value(h, key); - cur = h->htable[hvalue]; - while (cur != NULL && h->keycmp(h, key, cur->key) > 0) - cur = cur->next; + for (cur = h->htable[hvalue]; cur; cur = cur->next) { + int cmp; - if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) - return NULL; + cmp = h->keycmp(h, key, cur->key); + if (cmp > 0) + continue; + if (cmp == 0) + return cur->datum; + break; + } - return cur->datum; + return NULL; } void hashtab_destroy(hashtab_t h) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/hierarchy.c new/libsepol-3.7/src/hierarchy.c --- old/libsepol-3.6/src/hierarchy.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/hierarchy.c 2024-06-26 17:30:41.000000000 +0200 @@ -443,12 +443,15 @@ p->p_type_val_to_name[child - 1], p->p_type_val_to_name[parent - 1]); for (; cur; cur = cur->next) { + char *permstr = sepol_av_to_string(p, cur->key.target_class, cur->datum.data); + ERR(handle, " %s %s : %s { %s }", p->p_type_val_to_name[cur->key.source_type - 1], p->p_type_val_to_name[cur->key.target_type - 1], p->p_class_val_to_name[cur->key.target_class - 1], - sepol_av_to_string(p, cur->key.target_class, - cur->datum.data)); + permstr ?: "<format-failure>"); + + free(permstr); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/kernel_to_cil.c new/libsepol-3.7/src/kernel_to_cil.c --- old/libsepol-3.6/src/kernel_to_cil.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/kernel_to_cil.c 2024-06-26 17:30:41.000000000 +0200 @@ -297,6 +297,17 @@ } perms = sepol_av_to_string(pdb, class->s.value, curr->permissions); + if (!perms) { + ERR(NULL, "Failed to generate permission string"); + rc = -1; + goto exit; + } + if (*perms == '\0') { + ERR(NULL, "No permissions in permission string"); + free(perms); + rc = -1; + goto exit; + } if (is_mls) { key_word = "mlsconstrain"; @@ -307,6 +318,7 @@ } rc = strs_create_and_add(strs, "(%s (%s (%s)) %s)", key_word, classkey, perms+1, expr); + free(perms); free(expr); if (rc != 0) { goto exit; @@ -1769,8 +1781,14 @@ ERR(NULL, "Failed to generate permission string"); goto exit; } + if (*perms == '\0') { + ERR(NULL, "No permissions in permission string"); + free(perms); + goto exit; + } rule = create_str("(%s %s %s (%s (%s)))", flavor, src, tgt, class, perms+1); + free(perms); } else if (key->specified & AVTAB_XPERMS) { perms = xperms_to_str(datum->xperms); if (perms == NULL) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/kernel_to_common.c new/libsepol-3.7/src/kernel_to_common.c --- old/libsepol-3.6/src/kernel_to_common.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/kernel_to_common.c 2024-06-26 17:30:41.000000000 +0200 @@ -503,7 +503,7 @@ if (rc) return rc; - return (*aa)->u.ibendport.port - (*bb)->u.ibendport.port; + return spaceship_cmp((*aa)->u.ibendport.port, (*bb)->u.ibendport.port); } static int pirq_data_cmp(const void *a, const void *b) @@ -575,7 +575,7 @@ return 0; } - data = calloc(sizeof(*data), num); + data = calloc(num, sizeof(*data)); if (!data) { ERR(NULL, "Out of memory"); return -1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/kernel_to_conf.c new/libsepol-3.7/src/kernel_to_conf.c --- old/libsepol-3.6/src/kernel_to_conf.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/kernel_to_conf.c 2024-06-26 17:30:41.000000000 +0200 @@ -292,6 +292,17 @@ } perms = sepol_av_to_string(pdb, class->s.value, curr->permissions); + if (!perms) { + ERR(NULL, "Failed to generate permission string"); + rc = -1; + goto exit; + } + if (*perms == '\0') { + ERR(NULL, "No permissions in permission string"); + free(perms); + rc = -1; + goto exit; + } if (strchr(perms, ' ')) { perm_prefix = "{ "; perm_suffix = " }"; @@ -311,6 +322,7 @@ flavor, classkey, perm_prefix, perms+1, perm_suffix, expr); + free(perms); free(expr); if (rc != 0) { goto exit; @@ -811,7 +823,7 @@ num = strs_num_items(strs); if (num > 0) { - sens_alias_map = calloc(sizeof(*sens_alias_map), pdb->p_levels.nprim); + sens_alias_map = calloc(pdb->p_levels.nprim, sizeof(*sens_alias_map)); if (!sens_alias_map) { rc = -1; goto exit; @@ -942,7 +954,7 @@ num = strs_num_items(strs); if (num > 0) { - cat_alias_map = calloc(sizeof(*cat_alias_map), pdb->p_cats.nprim); + cat_alias_map = calloc(pdb->p_cats.nprim, sizeof(*cat_alias_map)); if (!cat_alias_map) { rc = -1; goto exit; @@ -1682,7 +1694,7 @@ { uint32_t data = datum->data; type_datum_t *type; - const char *flavor, *src, *tgt, *class, *perms, *new; + const char *flavor, *src, *tgt, *class, *new; char *rule = NULL, *permstring; switch (0xFFF & key->specified) { @@ -1730,13 +1742,19 @@ class = pdb->p_class_val_to_name[key->target_class - 1]; if (key->specified & AVTAB_AV) { - perms = sepol_av_to_string(pdb, key->target_class, data); - if (perms == NULL) { + permstring = sepol_av_to_string(pdb, key->target_class, data); + if (permstring == NULL) { ERR(NULL, "Failed to generate permission string"); goto exit; } + if (*permstring == '\0') { + ERR(NULL, "No permissions in permission string"); + free(permstring); + goto exit; + } rule = create_str("%s %s %s:%s { %s };", - flavor, src, tgt, class, perms+1); + flavor, src, tgt, class, permstring+1); + free(permstring); } else if (key->specified & AVTAB_XPERMS) { permstring = sepol_extended_perms_to_string(datum->xperms); if (permstring == NULL) { @@ -2106,7 +2124,7 @@ return 0; } - cond_data = calloc(sizeof(struct cond_data), num); + cond_data = calloc(num, sizeof(struct cond_data)); if (!cond_data) { rc = -1; goto exit; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/link.c new/libsepol-3.7/src/link.c --- old/libsepol-3.6/src/link.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/link.c 2024-06-26 17:30:41.000000000 +0200 @@ -749,7 +749,7 @@ return 0; } -static int (*copy_callback_f[SYM_NUM]) (hashtab_key_t key, +static int (*const copy_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { NULL, class_copy_callback, role_copy_callback, type_copy_callback, user_copy_callback, bool_copy_callback, sens_copy_callback, @@ -1215,7 +1215,7 @@ return -1; } -static int (*fix_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, +static int (*const fix_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { NULL, NULL, role_fix_callback, type_fix_callback, user_fix_callback, NULL, NULL, NULL}; @@ -1925,7 +1925,7 @@ * Note that if a declaration had no requirement at all (e.g., an ELSE * block) this returns 1. */ static int is_decl_requires_met(link_state_t * state, - avrule_decl_t * decl, + const avrule_decl_t * decl, struct missing_requirement *req) { /* (This algorithm is very unoptimized. It performs many @@ -1933,9 +1933,9 @@ * which symbols have been verified, so that they do not need * to be re-checked.) */ unsigned int i, j; - ebitmap_t *bitmap; - char *id, *perm_id; - policydb_t *pol = state->base; + const ebitmap_t *bitmap; + const char *id, *perm_id; + const policydb_t *pol = state->base; ebitmap_node_t *node; /* check that all symbols have been satisfied */ @@ -1961,27 +1961,29 @@ } /* check that all classes and permissions have been satisfied */ for (i = 0; i < decl->required.class_perms_len; i++) { + const class_datum_t *cladatum = pol->class_val_to_struct[i]; + const scope_datum_t *scope; + + bitmap = &decl->required.class_perms_map[i]; + id = pol->p_class_val_to_name[i]; + + + if (!is_id_enabled(id, state->base, SYM_CLASSES)) { + return 0; + } + + scope = hashtab_search(state->base->p_classes_scope.table, id); + if (scope == NULL) { + ERR(state->handle, + "Could not find scope information for class %s", + id); + return -1; + } - bitmap = decl->required.class_perms_map + i; ebitmap_for_each_positive_bit(bitmap, node, j) { struct find_perm_arg fparg; - class_datum_t *cladatum; uint32_t perm_value = j + 1; int rc; - scope_datum_t *scope; - - id = pol->p_class_val_to_name[i]; - cladatum = pol->class_val_to_struct[i]; - - scope = - hashtab_search(state->base->p_classes_scope.table, - id); - if (scope == NULL) { - ERR(state->handle, - "Could not find scope information for class %s", - id); - return -1; - } fparg.valuep = perm_value; fparg.key = NULL; @@ -1996,7 +1998,7 @@ perm_id = fparg.key; assert(perm_id != NULL); - if (!is_perm_enabled(id, perm_id, state->base)) { + if (!is_perm_existent(cladatum, perm_id)) { if (req != NULL) { req->symbol_type = SYM_CLASSES; req->symbol_value = i + 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/module_to_cil.c new/libsepol-3.7/src/module_to_cil.c --- old/libsepol-3.6/src/module_to_cil.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/module_to_cil.c 2024-06-26 17:30:41.000000000 +0200 @@ -593,10 +593,17 @@ rc = -1; goto exit; } + if (*perms == '\0') { + ERR(NULL, "No permissions in permission string"); + free(perms); + rc = -1; + goto exit; + } cil_println(indent, "(%s %s %s (%s (%s)))", rule, src, tgt, pdb->p_class_val_to_name[classperm->tclass - 1], perms + 1); + free(perms); } else { cil_println(indent, "(%s %s %s %s %s)", rule, src, tgt, @@ -1680,7 +1687,7 @@ const struct class_perm_datum *aa = a; const struct class_perm_datum *bb = b; - return aa->val - bb->val; + return spaceship_cmp(aa->val, bb->val); } static int common_to_cil(char *key, void *data, void *UNUSED(arg)) @@ -1967,7 +1974,19 @@ if (is_constraint) { perms = sepol_av_to_string(pdb, class->s.value, node->permissions); + if (perms == NULL) { + ERR(NULL, "Failed to generate permission string"); + rc = -1; + goto exit; + } + if (*perms == '\0') { + ERR(NULL, "No permissions in permission string"); + free(perms); + rc = -1; + goto exit; + } cil_println(indent, "(%sconstrain (%s (%s)) %s)", mls, classkey, perms + 1, expr); + free(perms); } else { cil_println(indent, "(%svalidatetrans %s %s)", mls, classkey, expr); } @@ -2390,7 +2409,7 @@ static int sens_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope) { - struct level_datum *level = datum; + level_datum_t *level = datum; if (scope == SCOPE_DECL) { if (!level->isalias) { @@ -2932,8 +2951,8 @@ int rc = -1; int ocon; - static int (**ocon_funcs)(struct policydb *pdb, struct ocontext *ocon); - static int (*ocon_selinux_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { + static int (*const *ocon_funcs)(struct policydb *pdb, struct ocontext *ocon); + static int (*const ocon_selinux_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { ocontext_selinux_isid_to_cil, ocontext_selinux_fs_to_cil, ocontext_selinux_port_to_cil, @@ -2944,7 +2963,7 @@ ocontext_selinux_ibpkey_to_cil, ocontext_selinux_ibendport_to_cil, }; - static int (*ocon_xen_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { + static int (*const ocon_xen_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { ocontext_xen_isid_to_cil, ocontext_xen_pirq_to_cil, ocontext_xen_ioport_to_cil, @@ -3385,7 +3404,7 @@ } -static int (*func_to_cil[SYM_NUM])(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack, char *key, void *datum, int scope) = { +static int (*const func_to_cil[SYM_NUM])(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack, char *key, void *datum, int scope) = { NULL, // commons, only stored in the global symtab, handled elsewhere class_to_cil, role_to_cil, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/policydb.c new/libsepol-3.7/src/policydb.c --- old/libsepol-3.6/src/policydb.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/policydb.c 2024-06-26 17:30:41.000000000 +0200 @@ -1126,7 +1126,7 @@ return 0; } -static int (*index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, +static int (*const index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { common_index, class_index, role_index, type_index, user_index, cond_index_bool, sens_index, cat_index,}; @@ -1390,8 +1390,10 @@ if (key) free(key); levdatum = (level_datum_t *) datum; - mls_level_destroy(levdatum->level); - free(levdatum->level); + if (!levdatum->isalias || !levdatum->notdefined) { + mls_level_destroy(levdatum->level); + free(levdatum->level); + } level_datum_destroy(levdatum); free(levdatum); return 0; @@ -1407,7 +1409,7 @@ return 0; } -static int (*destroy_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, +static int (*const destroy_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { common_destroy, class_destroy, role_destroy, type_destroy, user_destroy, cond_destroy_bool, sens_destroy, cat_destroy,}; @@ -3408,7 +3410,7 @@ return -1; } -static int (*read_f[SYM_NUM]) (policydb_t * p, hashtab_t h, +static int (*const read_f[SYM_NUM]) (policydb_t * p, hashtab_t h, struct policy_file * fp) = { common_read, class_read, role_read, type_read, user_read, cond_read_bool, sens_read, cat_read,}; @@ -4448,7 +4450,7 @@ } } /* add the type itself as the degenerate case */ - if (ebitmap_set_bit(&p->type_attr_map[i], i, 1)) + if (p->type_val_to_struct[i] && ebitmap_set_bit(&p->type_attr_map[i], i, 1)) goto bad; if (p->type_val_to_struct[i] && p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) { if (ebitmap_set_bit(&p->attr_type_map[i], i, 1)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/policydb_validate.c new/libsepol-3.7/src/policydb_validate.c --- old/libsepol-3.6/src/policydb_validate.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/policydb_validate.c 2024-06-26 17:30:41.000000000 +0200 @@ -11,6 +11,7 @@ #define bool_xor(a, b) (!(a) != !(b)) #define bool_xnor(a, b) (!bool_xor(a, b)) +#define PERMISSION_MASK(nprim) ((nprim) == PERM_SYMTAB_SIZE ? (~UINT32_C(0)) : ((UINT32_C(1) << (nprim)) - 1)) typedef struct validate { uint32_t nprim; @@ -23,6 +24,12 @@ const policydb_t *policy; } map_arg_t; +typedef struct perm_arg { + uint32_t visited; + const uint32_t nprim; + const uint32_t inherited_nprim; +} perm_arg_t; + static int create_gap_ebitmap(char **val_to_name, uint32_t nprim, ebitmap_t *gaps) { uint32_t i; @@ -56,7 +63,7 @@ goto bad; if (validate_init(&flavors[SYM_ROLES], p->p_role_val_to_name, p->p_roles.nprim)) goto bad; - if (p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) { + if (p->policy_type != POLICY_KERN || p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) { if (validate_init(&flavors[SYM_TYPES], p->p_type_val_to_name, p->p_types.nprim)) goto bad; } else { @@ -227,17 +234,21 @@ return -1; } -static int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms, const constraint_node_t *cons, validate_t flavors[]) +static int validate_constraint_nodes(sepol_handle_t *handle, uint32_t nperms, const constraint_node_t *cons, validate_t flavors[]) { const constraint_expr_t *cexp; + const int is_validatetrans = (nperms == UINT32_MAX); int depth; + if (cons && nperms == 0) + goto bad; + for (; cons; cons = cons->next) { - if (nperms == 0 && cons->permissions != 0) + if (is_validatetrans && cons->permissions != 0) goto bad; - if (nperms > 0 && cons->permissions == 0) + if (!is_validatetrans && cons->permissions == 0) goto bad; - if (nperms > 0 && nperms != PERM_SYMTAB_SIZE && cons->permissions >= (UINT32_C(1) << nperms)) + if (!is_validatetrans && nperms != PERM_SYMTAB_SIZE && cons->permissions >= (UINT32_C(1) << nperms)) goto bad; if (!cons->expr) @@ -251,7 +262,7 @@ goto bad; depth++; - if (cexp->attr & CEXPR_XTARGET && nperms != 0) + if (cexp->attr & CEXPR_XTARGET && !is_validatetrans) goto bad; if (!(cexp->attr & CEXPR_TYPE)) { if (validate_empty_type_set(cexp->type_names)) @@ -366,11 +377,49 @@ return -1; } +static int perm_visit(__attribute__((__unused__)) hashtab_key_t k, hashtab_datum_t d, void *args) +{ + perm_arg_t *pargs = args; + const perm_datum_t *perdatum = d; + + if (!value_isvalid(perdatum->s.value, pargs->nprim)) + return -1; + + if (pargs->inherited_nprim != 0 && value_isvalid(perdatum->s.value, pargs->inherited_nprim)) + return -1; + + if ((UINT32_C(1) << (perdatum->s.value - 1)) & pargs->visited) + return -1; + + pargs->visited |= (UINT32_C(1) << (perdatum->s.value - 1)); + return 0; +} + +static int validate_permission_symtab(sepol_handle_t *handle, const symtab_t *permissions, uint32_t inherited_nprim) +{ + /* Check each entry has a different valid value and is not overriding an inherited one */ + + perm_arg_t pargs = { .visited = 0, .nprim = permissions->nprim, .inherited_nprim = inherited_nprim }; + + if (hashtab_map(permissions->table, perm_visit, &pargs)) + goto bad; + + return 0; + +bad: + ERR(handle, "Invalid permission table"); + 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.table->nel == 0 || common->permissions.nprim > PERM_SYMTAB_SIZE) + if (common->permissions.nprim == 0 || common->permissions.nprim > PERM_SYMTAB_SIZE) + goto bad; + if (common->permissions.nprim != common->permissions.table->nel) + goto bad; + if (validate_permission_symtab(handle, &common->permissions, 0)) goto bad; return 0; @@ -393,11 +442,17 @@ goto bad; if (class->comdatum && validate_common_datum(handle, class->comdatum, flavors)) goto bad; - if (class->permissions.nprim > PERM_SYMTAB_SIZE) + /* empty classes are permitted */ + if (class->permissions.nprim > PERM_SYMTAB_SIZE || class->permissions.table->nel > PERM_SYMTAB_SIZE) + goto bad; + if (class->permissions.nprim != + (class->permissions.table->nel + (class->comdatum ? class->comdatum->permissions.table->nel : 0))) + goto bad; + if (validate_permission_symtab(handle, &class->permissions, class->comdatum ? class->comdatum->permissions.nprim : 0)) goto bad; if (validate_constraint_nodes(handle, class->permissions.nprim, class->constraints, flavors)) goto bad; - if (validate_constraint_nodes(handle, 0, class->validatetrans, flavors)) + if (validate_constraint_nodes(handle, UINT32_MAX, class->validatetrans, flavors)) goto bad; switch (class->default_user) { @@ -618,12 +673,37 @@ return -1; } -static int validate_level_datum(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) +static int validate_level_datum(sepol_handle_t *handle, const level_datum_t *level, validate_t flavors[], const policydb_t *p) +{ + if (level->notdefined != 0) + goto bad; + + if (validate_mls_level(level->level, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) + goto bad; + + if (level->isalias) { + const mls_level_t *l1 = level->level; + const mls_level_t *l2; + const level_datum_t *actual = (level_datum_t *) hashtab_search(p->p_levels.table, p->p_sens_val_to_name[l1->sens - 1]); + if (!actual) + goto bad; + l2 = actual->level; + if (!ebitmap_cmp(&l1->cat, &l2->cat)) + goto bad; + } + + return 0; + + bad: + ERR(handle, "Invalid level datum"); + return -1; +} + +static int validate_level_datum_wrapper(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { - level_datum_t *level = d; - validate_t *flavors = args; + map_arg_t *margs = args; - return validate_mls_level(level->level, &flavors[SYM_LEVELS], &flavors[SYM_CATS]); + return validate_level_datum(margs->handle, d, margs->flavors, margs->policy); } static int validate_mls_range(const mls_range_t *range, const validate_t *sens, const validate_t *cats) @@ -723,7 +803,7 @@ * For policy versions between 20 and 23, attributes exist in the policy, * but only in the type_attr_map, so all gaps must be assumed to be valid. */ - if (p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) { + if (p->policy_type != POLICY_KERN || p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) { for (i = 0; i < p->p_types.nprim; i++) { if (bool_xnor(p->type_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_TYPES].gaps, i))) goto bad; @@ -774,7 +854,7 @@ if (hashtab_map(p->p_users.table, validate_user_datum_wrapper, &margs)) goto bad; - if (p->mls && hashtab_map(p->p_levels.table, validate_level_datum, flavors)) + if (p->mls && hashtab_map(p->p_levels.table, validate_level_datum_wrapper, &margs)) goto bad; if (hashtab_map(p->p_cats.table, validate_datum, &flavors[SYM_CATS])) @@ -851,6 +931,26 @@ bad: return -1; } + +static int validate_access_vector(sepol_handle_t *handle, const policydb_t *p, sepol_security_class_t tclass, + sepol_access_vector_t av) +{ + const class_datum_t *cladatum = p->class_val_to_struct[tclass - 1]; + + /* + * Check that at least one permission bit is valid. + * Older compilers might set invalid bits for the wildcard permission. + */ + if (!(av & PERMISSION_MASK(cladatum->permissions.nprim))) + goto bad; + + return 0; + +bad: + ERR(handle, "Invalid access vector"); + return -1; +} + static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void *args) { map_arg_t *margs = args; @@ -858,6 +958,16 @@ if (validate_avtab_key(k, 0, margs->policy, margs->flavors)) return -1; + if (k->specified & AVTAB_AV) { + uint32_t data = d->data; + + if ((0xFFF & k->specified) == AVTAB_AUDITDENY) + data = ~data; + + if (validate_access_vector(margs->handle, margs->policy, k->target_class, data)) + return -1; + } + if ((k->specified & AVTAB_TYPE) && validate_simpletype(d->data, margs->policy, margs->flavors)) return -1; @@ -890,6 +1000,15 @@ if (validate_avtab_key(key, 1, p, flavors)) goto bad; + if (key->specified & AVTAB_AV) { + uint32_t data = datum->data; + + if ((0xFFF & key->specified) == AVTAB_AUDITDENY) + data = ~data; + + if (validate_access_vector(handle, p, key->target_class, data)) + goto bad; + } if ((key->specified & AVTAB_TYPE) && validate_simpletype(datum->data, p, flavors)) goto bad; } @@ -957,7 +1076,12 @@ switch(avrule->flags) { case 0: + break; case RULE_SELF: + if (p->policyvers != POLICY_KERN && + p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS && + (avrule->specified & AVRULE_TYPE)) + goto bad; break; case RULE_NOTSELF: switch(avrule->specified) { @@ -1344,6 +1468,8 @@ static int validate_scope_index(sepol_handle_t *handle, const scope_index_t *scope_index, validate_t flavors[]) { + uint32_t i; + if (!ebitmap_is_empty(&scope_index->scope[SYM_COMMONS])) goto bad; if (validate_ebitmap(&scope_index->p_classes_scope, &flavors[SYM_CLASSES])) @@ -1360,8 +1486,10 @@ goto bad; if (validate_ebitmap(&scope_index->p_cat_scope, &flavors[SYM_CATS])) goto bad; - if (scope_index->class_perms_len > flavors[SYM_CLASSES].nprim) - goto bad; + + for (i = 0; i < scope_index->class_perms_len; i++) + if (validate_value(i + 1, &flavors[SYM_CLASSES])) + goto bad; return 0; @@ -1384,8 +1512,16 @@ goto bad; /* currently only the RULE_SELF flag can be set */ - if ((filename_trans->flags & ~RULE_SELF) != 0) + switch (filename_trans->flags) { + case 0: + break; + case RULE_SELF: + if (p->policyvers != POLICY_KERN && p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS) + goto bad; + break; + default: goto bad; + } } return 0; @@ -1523,17 +1659,41 @@ return -1; } +static int validate_attrtype_map(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) +{ + const ebitmap_t *maps = p->attr_type_map; + uint32_t 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 attr type map"); + return -1; +} + static int validate_properties(sepol_handle_t *handle, const policydb_t *p) { switch (p->policy_type) { case POLICY_KERN: if (p->policyvers < POLICYDB_VERSION_MIN || p->policyvers > POLICYDB_VERSION_MAX) goto bad; + if (p->mls && p->policyvers < POLICYDB_VERSION_MLS) + goto bad; break; case POLICY_BASE: case POLICY_MOD: if (p->policyvers < MOD_POLICYDB_VERSION_MIN || p->policyvers > MOD_POLICYDB_VERSION_MAX) goto bad; + if (p->mls && p->policyvers < MOD_POLICYDB_VERSION_MLS) + goto bad; break; default: goto bad; @@ -1652,10 +1812,11 @@ if (validate_range_transitions(handle, p, flavors)) goto bad; - if (p->policyvers >= POLICYDB_VERSION_AVTAB) { - if (validate_typeattr_map(handle, p, flavors)) - goto bad; - } + if (validate_typeattr_map(handle, p, flavors)) + goto bad; + + if (validate_attrtype_map(handle, p, flavors)) + goto bad; validate_array_destroy(flavors); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/services.c new/libsepol-3.7/src/services.c --- old/libsepol-3.6/src/services.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/services.c 2024-06-26 17:30:41.000000000 +0200 @@ -347,9 +347,11 @@ p += len; buf_used += len; if (state_num < 2) { + char *permstr = sepol_av_to_string(policydb, tclass, constraint->permissions); + len = snprintf(p, class_buf_len - buf_used, "{%s } (", - sepol_av_to_string(policydb, tclass, - constraint->permissions)); + permstr ?: "<format-failure>"); + free(permstr); } else { len = snprintf(p, class_buf_len - buf_used, "("); } @@ -1237,7 +1239,25 @@ const char *sepol_av_perm_to_string(sepol_security_class_t tclass, sepol_access_vector_t av) { - return sepol_av_to_string(policydb, tclass, av); + static char avbuf[1024]; + char *avstr = sepol_av_to_string(policydb, tclass, av); + size_t len; + + memset(avbuf, 0, sizeof(avbuf)); + + if (avstr) { + len = strlen(avstr); + if (len < sizeof(avbuf)) { + strcpy(avbuf, avstr); + } else { + sprintf(avbuf, "<access-vector overflowed buffer>"); + } + free(avstr); + } else { + sprintf(avbuf, "<format-failure>"); + } + + return avbuf; } /* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/util.c new/libsepol-3.7/src/util.c --- old/libsepol-3.6/src/util.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/util.c 2024-06-26 17:30:41.000000000 +0200 @@ -32,7 +32,7 @@ struct val_to_name { unsigned int val; - char *name; + const char *name; }; /* Add an unsigned integer to a dynamically reallocated array. *cnt @@ -82,20 +82,27 @@ return 0; } -char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, +char *sepol_av_to_string(const policydb_t *policydbp, sepol_security_class_t tclass, sepol_access_vector_t av) { struct val_to_name v; - static char avbuf[1024]; - class_datum_t *cladatum; - char *perm = NULL, *p; - unsigned int i; + const class_datum_t *cladatum = policydbp->class_val_to_struct[tclass - 1]; + uint32_t i; int rc; - int avlen = 0, len; + char *buffer = NULL, *p; + int len; + size_t remaining, size = 64; + +retry: + if (__builtin_mul_overflow(size, 2, &size)) + goto err; + p = realloc(buffer, size); + if (!p) + goto err; + *p = '\0'; /* Just in case there are no permissions */ + buffer = p; + remaining = size; - memset(avbuf, 0, sizeof avbuf); - cladatum = policydbp->class_val_to_struct[tclass - 1]; - p = avbuf; for (i = 0; i < cladatum->permissions.nprim; i++) { if (av & (UINT32_C(1) << i)) { v.val = i + 1; @@ -106,22 +113,23 @@ permissions.table, perm_name, &v); } - if (rc) - perm = v.name; - if (perm) { - len = - snprintf(p, sizeof(avbuf) - avlen, " %s", - perm); - if (len < 0 - || (size_t) len >= (sizeof(avbuf) - avlen)) - return NULL; + if (rc == 1) { + len = snprintf(p, remaining, " %s", v.name); + if (len < 0) + goto err; + if ((size_t) len >= remaining) + goto retry; p += len; - avlen += len; + remaining -= len; } } } - return avbuf; + return buffer; + +err: + free(buffer); + return NULL; } #define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsepol-3.6/src/write.c new/libsepol-3.7/src/write.c --- old/libsepol-3.6/src/write.c 2023-12-13 15:46:22.000000000 +0100 +++ new/libsepol-3.7/src/write.c 2024-06-26 17:30:41.000000000 +0200 @@ -1103,8 +1103,10 @@ buf[1] = cpu_to_le32(cladatum->default_role); 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, + "class %s default_range set to GLBLUB but %spolicy version is %d (%d required), discarding", + p->p_class_val_to_name[cladatum->s.value - 1], + p->policy_type == POLICY_KERN ? "" : "module ", + p->policyvers, p->policy_type == POLICY_KERN? POLICYDB_VERSION_GLBLUB:MOD_POLICYDB_VERSION_GLBLUB); default_range = 0; } @@ -1342,7 +1344,7 @@ return POLICYDB_SUCCESS; } -static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, +static int (*const write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { common_write, class_write, role_write, type_write, user_write, cond_write_bool, sens_write, cat_write,}; @@ -2219,7 +2221,8 @@ p->policy_type == POLICY_BASE) || (p->policyvers < MOD_POLICYDB_VERSION_MLS && p->policy_type == POLICY_MOD)) { - ERR(fp->handle, "policy version %d cannot support MLS", + ERR(fp->handle, "%spolicy version %d cannot support MLS", + p->policy_type == POLICY_KERN ? "" : "module ", p->policyvers); return POLICYDB_ERROR; } @@ -2252,8 +2255,10 @@ info = policydb_lookup_compat(p->policyvers, p->policy_type, p->target_platform); if (!info) { - ERR(fp->handle, "compatibility lookup failed for policy " - "version %d", p->policyvers); + ERR(fp->handle, "compatibility lookup failed for %s%s policy version %d", + p->target_platform == SEPOL_TARGET_SELINUX ? "selinux" : "xen", + p->policy_type == POLICY_KERN ? "" : " module", + p->policyvers); return POLICYDB_ERROR; }
participants (1)
-
Source-Sync