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