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 <[email protected]>
+
+- 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;
        }
 

Reply via email to