diff --git a/Optimized-the-way-libsepol-policy-are-generated.patch b/Optimized-the-way-libsepol-policy-are-generated.patch new file mode 100644 index 0000000000000000000000000000000000000000..9db24dc47bd1e09a37e726c44c77c25e95838c18 --- /dev/null +++ b/Optimized-the-way-libsepol-policy-are-generated.patch @@ -0,0 +1,272 @@ +From ae864f32d4f70e789d5dc3eec74525e508df1720 Mon Sep 17 00:00:00 2001 +From: jinlun +Date: Mon, 28 Apr 2025 10:00:40 +0800 +Subject: [PATCH] Optimized the way libsepol policy are generated + +There are optimization patches in the kernel community that can save + the memory space of the policy, which causes the results of the + /sys/fs/selinux/policy generated by the kernel to be inconsistent + with the policy generated bt the call sepol_policydb_read. + +--- + libsepol-3.5/include/sepol/policydb.h | 3 + + .../include/sepol/policydb/policydb.h | 4 + + libsepol-3.5/src/hashtab.c | 9 +- + libsepol-3.5/src/libsepol.map.in | 1 + + libsepol-3.5/src/policydb.c | 86 +++++++++++++++++-- + libsepol-3.5/src/policydb_public.c | 5 ++ + 6 files changed, 98 insertions(+), 10 deletions(-) + +diff --git a/libsepol-3.5/include/sepol/policydb.h b/libsepol-3.5/include/sepol/policydb.h +index 792913d..0f74467 100644 +--- a/libsepol-3.5/include/sepol/policydb.h ++++ b/libsepol-3.5/include/sepol/policydb.h +@@ -111,6 +111,7 @@ extern int sepol_policydb_optimize(sepol_policydb_t * p); + * image contents. + */ + extern int sepol_policydb_read(sepol_policydb_t * p, sepol_policy_file_t * pf); ++extern int sepol_policydb_read_canonicalize(sepol_policydb_t * p, sepol_policy_file_t * pf); + + /* + * Write a policydb to a policy file. +diff --git a/libsepol-3.5/include/sepol/policydb/policydb.h b/libsepol-3.5/include/sepol/policydb/policydb.h +index ef1a014..5a84aba 100644 +--- a/libsepol-3.5/include/sepol/policydb/policydb.h ++++ b/libsepol-3.5/include/sepol/policydb/policydb.h +@@ -727,6 +727,10 @@ extern void policy_file_init(policy_file_t * x); + + extern int policydb_read(policydb_t * p, struct policy_file *fp, + unsigned int verbose); ++extern int policydb_read_canonicalize(policydb_t * p, struct policy_file *fp, ++ unsigned int verbose); ++ ++ + extern int avrule_read_list(policydb_t * p, avrule_t ** avrules, + struct policy_file *fp); + +diff --git a/libsepol-3.5/src/hashtab.c b/libsepol-3.5/src/hashtab.c +index 6f01d09..1d6825b 100644 +--- a/libsepol-3.5/src/hashtab.c ++++ b/libsepol-3.5/src/hashtab.c +@@ -34,15 +34,22 @@ + + #include "private.h" + ++static size_t hashtab_compute_size(size_t nel) ++{ ++ if (nel == 0) ++ return 0; ++ return (size_t)(1 << (32 - __builtin_clz((nel) - 1))); ++} + hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h, + const_hashtab_key_t key), + int (*keycmp) (hashtab_t h, + const_hashtab_key_t key1, + const_hashtab_key_t key2), +- unsigned int size) ++ unsigned int nel) + { + + hashtab_t p; ++ unsigned int size = hashtab_compute_size(nel); + + p = (hashtab_t) malloc(sizeof(hashtab_val_t)); + if (p == NULL) +diff --git a/libsepol-3.5/src/libsepol.map.in b/libsepol-3.5/src/libsepol.map.in +index 844924f..3061a66 100644 +--- a/libsepol-3.5/src/libsepol.map.in ++++ b/libsepol-3.5/src/libsepol.map.in +@@ -288,4 +288,5 @@ LIBSEPOL_3.4 { + sepol_string_to_av_perm; + sepol_string_to_security_class; + sepol_validate_transition_reason_buffer; ++ sepol_policydb_read_canonicalize; + } LIBSEPOL_3.0; +diff --git a/libsepol-3.5/src/policydb.c b/libsepol-3.5/src/policydb.c +index 21bcad7..ecc1480 100644 +--- a/libsepol-3.5/src/policydb.c ++++ b/libsepol-3.5/src/policydb.c +@@ -2090,7 +2090,7 @@ static int perm_read(policydb_t * p + return -1; + } + +-static int common_read(policydb_t * p, hashtab_t h, struct policy_file *fp) ++static int common_read_pre(policydb_t * p, hashtab_t h, struct policy_file *fp, int canonicalize) + { + char *key = 0; + common_datum_t *comdatum; +@@ -2113,12 +2113,18 @@ static int common_read(policydb_t * p, hashtab_t h, struct policy_file *fp) + + comdatum->s.value = le32_to_cpu(buf[1]); + +- if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE)) ++ nel = le32_to_cpu(buf[3]); ++ ++ if (!canonicalize) ++ rc = symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE); ++ else ++ rc = symtab_init(&comdatum->permissions, nel); ++ ++ if (rc) + goto bad; + comdatum->permissions.nprim = le32_to_cpu(buf[2]); + if (comdatum->permissions.nprim > PERM_SYMTAB_SIZE) + goto bad; +- nel = le32_to_cpu(buf[3]); + + key = malloc(len + 1); + if (!key) +@@ -2143,6 +2149,16 @@ static int common_read(policydb_t * p, hashtab_t h, struct policy_file *fp) + return -1; + } + ++static int common_read(policydb_t * p, hashtab_t h, struct policy_file *fp) ++{ ++ return common_read_pre(p, h, fp, 1); ++} ++ ++static int common_read_canonicalize(policydb_t * p, hashtab_t h, struct policy_file *fp) ++{ ++ return common_read_pre(p, h, fp, 1); ++} ++ + static int read_cons_helper(policydb_t * p, constraint_node_t ** nodep, + unsigned int ncons, + int allowxtarget, struct policy_file *fp) +@@ -2238,7 +2254,7 @@ static int read_cons_helper(policydb_t * p, constraint_node_t ** nodep, + return 0; + } + +-static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp) ++static int class_read_pre(policydb_t * p, hashtab_t h, struct policy_file *fp, int canonicalize) + { + char *key = 0; + class_datum_t *cladatum; +@@ -2265,12 +2281,17 @@ static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp) + if (cladatum->s.value > UINT16_MAX) + goto bad; + +- if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) ++ nel = le32_to_cpu(buf[4]); ++ if (!canonicalize) ++ rc = symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE); ++ else ++ rc = symtab_init(&cladatum->permissions, nel); ++ if (rc) + goto bad; ++ + cladatum->permissions.nprim = le32_to_cpu(buf[3]); + if (cladatum->permissions.nprim > PERM_SYMTAB_SIZE) + goto bad; +- nel = le32_to_cpu(buf[4]); + + ncons = le32_to_cpu(buf[5]); + +@@ -2351,6 +2372,16 @@ static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp) + return -1; + } + ++static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp) ++{ ++ return class_read_pre(p, h, fp, 0); ++} ++ ++static int class_read_canonicalize(policydb_t * p, hashtab_t h, struct policy_file *fp) ++{ ++ return class_read_pre(p, h, fp, 1); ++} ++ + static int role_read(policydb_t * p, hashtab_t h, struct policy_file *fp) + { + char *key = 0; +@@ -3507,6 +3538,11 @@ static int (*read_f[SYM_NUM]) (policydb_t * p, hashtab_t h, + common_read, class_read, role_read, type_read, user_read, + cond_read_bool, sens_read, cat_read,}; + ++static int (*read_f_canonicalize[SYM_NUM]) (policydb_t * p, hashtab_t h, ++ struct policy_file * fp) = { ++common_read_canonicalize, class_read_canonicalize, role_read, type_read, user_read, ++ cond_read_bool, sens_read, cat_read,}; ++ + /************** module reading functions below **************/ + + static avrule_t *avrule_read(policydb_t * p, struct policy_file *fp) +@@ -4226,7 +4262,7 @@ static sepol_access_vector_t policydb_string_to_av_perm( + * Read the configuration data from a policy database binary + * representation file into a policy database structure. + */ +-int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) ++int policydb_read_pre(policydb_t * p, struct policy_file *fp, unsigned verbose, int canonicalize) + { + + unsigned int i, j, r_policyvers; +@@ -4444,9 +4480,26 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) + ERR(fp->handle, "unexpected items in symbol table with no symbol"); + goto bad; + } +- for (j = 0; j < nel; j++) { +- if (read_f[i] (p, p->symtab[i].table, fp)) ++ ++ if (canonicalize) { ++ hashtab_destroy(p->symtab[i].table); ++ if (symtab_init(&p->symtab[i], nel)) + goto bad; ++ if (i == SYM_ROLES) { ++ if (roles_init(p)) ++ goto bad; ++ } ++ } ++ ++ ++ for (j = 0; j < nel; j++) { ++ if (canonicalize) { ++ if (read_f_canonicalize[i] (p, p->symtab[i].table, fp)) ++ goto bad; ++ } else { ++ if (read_f[i] (p, p->symtab[i].table, fp)) ++ goto bad; ++ } + } + + p->symtab[i].nprim = nprim; +@@ -4579,9 +4632,24 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) + + return POLICYDB_SUCCESS; + bad: ++ if (canonicalize) { ++ for (i = 0; i < SYM_NUM; i++) { ++ hashtab_destroy(p->symtab[i].table); ++ } ++ } + return POLICYDB_ERROR; + } + ++int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) ++{ ++ return policydb_read_pre(p, fp, verbose, 0); ++} ++ ++int policydb_read_canonicalize(policydb_t * p, struct policy_file *fp, unsigned verbose) ++{ ++ return policydb_read_pre(p, fp, verbose, 1); ++} ++ + int policydb_reindex_users(policydb_t * p) + { + unsigned int i = SYM_USERS; +diff --git a/libsepol-3.5/src/policydb_public.c b/libsepol-3.5/src/policydb_public.c +index 0218c94..bbc2583 100644 +--- a/libsepol-3.5/src/policydb_public.c ++++ b/libsepol-3.5/src/policydb_public.c +@@ -212,3 +212,8 @@ int sepol_policydb_compat_net(const sepol_policydb_t * p) + return (hashtab_search(p->p.p_classes.table, PACKET_CLASS_NAME) == + NULL); + } ++ ++int sepol_policydb_read_canonicalize(sepol_policydb_t * p, sepol_policy_file_t * pf) ++{ ++ return policydb_read_canonicalize(&p->p, &pf->pf, 0); ++} +-- +2.33.0 + diff --git a/backport-libsepol-Remove-special-handling-of-roles-in-module_to_cil.patch b/backport-libsepol-Remove-special-handling-of-roles-in-module_to_cil.patch new file mode 100644 index 0000000000000000000000000000000000000000..995d03bd94e5091c21c630eea846713a85e10c57 --- /dev/null +++ b/backport-libsepol-Remove-special-handling-of-roles-in-module_to_cil.patch @@ -0,0 +1,89 @@ +From 7450510d9032c0f4d936d4ecb005f0454f65a66e Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Mon, 21 Apr 2025 11:55:41 +0800 +Subject: [PATCH] libsepol-Remove-special-handling-of-roles-in-module_to_cil + +Reference:https://github.com/SELinuxProject/selinux/commit/be11f48b7a4a0782d79a40ec623e133221c55035 + +--- + libsepol/src/module_to_cil.c | 50 +----------------------------------- + 1 file changed, 1 insertion(+), 49 deletions(-) + +diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c +index 604eada..73e5240 100644 +--- a/libsepol/src/module_to_cil.c ++++ b/libsepol/src/module_to_cil.c +@@ -2132,39 +2132,7 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN + switch (role->flavor) { + case ROLE_ROLE: + if (scope == SCOPE_DECL) { +- // Only declare certain roles if we are reading a base module. +- // These roles are defined in the base module and sometimes in +- // other non-base modules. If we generated the roles regardless of +- // the policy type, it would result in duplicate declarations, +- // which isn't allowed in CIL. Patches have been made to refpolicy +- // to remove these duplicate role declarations, but we need to be +- // backwards compatible and support older policies. Since we know +- // these roles are always declared in base, only print them when we +- // see them in the base module. If the declarations appear in a +- // non-base module, ignore their declarations. +- // +- // Note that this is a hack, and if a policy author does not define +- // one of these roles in base, the declaration will not appear in +- // the resulting policy, likely resulting in a compilation error in +- // CIL. +- // +- // To make things more complicated, the auditadm_r and secadm_r +- // roles could actually be in either the base module or a non-base +- // module, or both. So we can't rely on this same behavior. So for +- // these roles, don't declare them here, even if they are in a base +- // or non-base module. Instead we will just declare them in the +- // base module elsewhere. +- int is_base_role = (!strcmp(key, "user_r") || +- !strcmp(key, "staff_r") || +- !strcmp(key, "sysadm_r") || +- !strcmp(key, "system_r") || +- !strcmp(key, "unconfined_r")); +- int is_builtin_role = (!strcmp(key, "auditadm_r") || +- !strcmp(key, "secadm_r")); +- if ((is_base_role && pdb->policy_type == SEPOL_POLICY_BASE) || +- (!is_base_role && !is_builtin_role)) { +- cil_println(indent, "(role %s)", key); +- } ++ cil_println(indent, "(role %s)", key); + } + + if (ebitmap_cardinality(&role->dominates) > 1) { +@@ -3950,17 +3918,6 @@ static int generate_default_object(void) + return 0; + } + +-static int generate_builtin_roles(void) +-{ +- // due to inconsistentencies between policies and CIL not allowing +- // duplicate roles, some roles are always created, regardless of if they +- // are declared in modules or not +- cil_println(0, "(role auditadm_r)"); +- cil_println(0, "(role secadm_r)"); +- +- return 0; +-} +- + static int generate_gen_require_attribute(void) + { + cil_println(0, "(typeattribute " GEN_REQUIRE_ATTR ")"); +@@ -4045,11 +4002,6 @@ int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked) + goto exit; + } + +- rc = generate_builtin_roles(); +- if (rc != 0) { +- goto exit; +- } +- + // default attribute to be used to mimic gen_require in CIL + rc = generate_gen_require_attribute(); + if (rc != 0) { +-- +2.33.0 + diff --git a/backport-libsepol-cil-Optionally-allow-duplicate-role-declaration.patch b/backport-libsepol-cil-Optionally-allow-duplicate-role-declaration.patch new file mode 100644 index 0000000000000000000000000000000000000000..27699f4241a310662e8f1934518349ff3fdde6a7 --- /dev/null +++ b/backport-libsepol-cil-Optionally-allow-duplicate-role-declaration.patch @@ -0,0 +1,40 @@ +From ae3c44c2d44b5e2f1c87b4b095d522a7f11add7a Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Mon, 21 Apr 2025 11:34:35 +0800 +Subject: [PATCH] libsepol-cil-Optionally-allow-duplicate-role-declarations + +Reference:https://github.com/SELinuxProject/selinux/commit/7492632a6b6a1081d0c057a2ecfc193be9989515 + +--- + libsepol/cil/src/cil_build_ast.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c +index 4177c9f..8264984 100644 +--- a/libsepol/cil/src/cil_build_ast.c ++++ b/libsepol/cil/src/cil_build_ast.c +@@ -92,6 +92,7 @@ static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, en + switch (f_new) { + case CIL_TYPE: + case CIL_TYPEATTRIBUTE: ++ case CIL_ROLE: + if (db->multiple_decls) { + return CIL_TRUE; + } +@@ -1750,7 +1751,12 @@ int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct + + rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)role, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLE); + if (rc != SEPOL_OK) { +- goto exit; ++ if (rc == SEPOL_EEXIST) { ++ cil_destroy_role(role); ++ role = NULL; ++ } else { ++ goto exit; ++ } + } + + return SEPOL_OK; +-- +2.33.0 + diff --git a/libsepol.spec b/libsepol.spec index 6e19c3721d87825615f7c1127448928de1d8a53e..24e49f7c74fcc794b4fdd0f19077aeb9ea549ccb 100644 --- a/libsepol.spec +++ b/libsepol.spec @@ -1,6 +1,6 @@ Name: libsepol Version: 3.5 -Release: 5 +Release: 9 Summary: SELinux binary policy manipulation library License: LGPLv2+ URL: https://github.com/SELinuxProject/selinux/wiki/Releases @@ -40,6 +40,10 @@ Patch0031: backport-libsepol-Initialize-strs-on-declaration.patch Patch0032: backport-libsepol-mls-Do-not-destroy-context-on-memory-error.patch Patch0033: backport-libsepol-cil-cil_post-Initialize-tmp-on-declaration.patch Patch0034: backport-libsepol-cil-Initialize-avtab_datum-on-declaration.patch +Patch0035: backport-libsepol-cil-Optionally-allow-duplicate-role-declaration.patch +Patch0036: backport-libsepol-Remove-special-handling-of-roles-in-module_to_cil.patch + +Patch9000: Optimized-the-way-libsepol-policy-are-generated.patch BuildRequires: gcc flex @@ -100,6 +104,18 @@ make DESTDIR="%{buildroot}" LIBDIR="%{_libdir}" SHLIBDIR="%{_libdir}" install %{_mandir}/man3/* %changelog +* Mon Apr 28 2025 changhan - 3.5-9 +- Change the author's mail + +* Mon Apr 28 2025 jinlun - 3.5-8 +- Optimized the way libsepol policy are generated + +* Mon Apr 21 2025 changhan - 3.5-7 +- backport libsepol: Remove special handling of roles in module_to_cil.c + +* Mon Apr 21 2025 changhan - 3.5-6 +- backport libsepol/cil: Optionally allow duplicate role declarations + * Tue Mar 18 2025 steven ygui - 3.5-5 - backport bugfix from upstream