Re: [PATCH 1/2] libsepol: Fix sid handling when writing out policy from binary
Stephen Smalley <[email protected]> Wed, 5 Nov 2025 13:58:53 -0500
| Newsgroups | org.kernel.vger.selinux-refpolicy,org.kernel.vger.selinux |
|---|---|
| Message-ID | <CAEjxPJ4N9DEAWPLEWc5k1VYkSwfinycZN5OgJeG=4-Pep0+zaA@mail.gmail.com> |
On Tue, Nov 4, 2025 at 3:52 PM James Carter <[email protected]> wrote: > > Initial sids are stored only as unsigned 32-bit numbers in a > binary policy. When a binary kernel policy is converted to CIL > or a policy.conf or a binary base module is converted to CIL, a > mapping in kernel_to_common.h is used to determine the name of > the initial sid. > > A problem can occur when policy converted from binary to text is > once again compiled. The initial sids will not be the correct > number if there are gaps in the list of initial sids. This will > cause the effected initial sids to be interpreted by the kernel > as a different initial sid. > > When writing out sid and sidorder statements in CIL, write out > all the initial sids from kernel (which is initial sid #1) to the > initial sid with the highest number associated with it. In the > same way, when writing out sid statements for a policy.conf, all > the initial sids from the first to the highest numbered must be > written out with no gaps. > > No changes are needed when writing out statements associating > an initial sid with a security context. There can be gaps in > these statements. The numbering is taken from the declarations. > > Signed-off-by: James Carter <[email protected]> With this applied, I confirmed that building refpolicy with the patch in [1] did not disturb the initial SID index values. I also saw no regressions wrt existing policy. Acked-by: Stephen Smalley <[email protected]> Tested-by: Stephen Smalley <[email protected]> [1] https://lore.kernel.org/selinux-refpolicy/[email protected]/ > --- > libsepol/src/kernel_to_cil.c | 47 +++----------- > libsepol/src/kernel_to_common.c | 48 +++++++++++++++ > libsepol/src/kernel_to_common.h | 1 + > libsepol/src/kernel_to_conf.c | 41 +++--------- > libsepol/src/module_to_cil.c | 106 ++++++++++++++++---------------- > 5 files changed, 121 insertions(+), 122 deletions(-) > > diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c > index 4da63ba5..06cf4498 100644 > --- a/libsepol/src/kernel_to_cil.c > +++ b/libsepol/src/kernel_to_cil.c > @@ -565,54 +565,31 @@ exit: > static int write_sids_to_cil(FILE *out, const char *const *sid_to_str, > unsigned num_sids, struct ocontext *isids) > { > - struct ocontext *isid; > struct strs *strs; > char *sid; > char *prev; > - char unknown[18]; > unsigned i; > - int rc; > > - rc = strs_init(&strs, num_sids+1); > - if (rc != 0) { > - goto exit; > + strs = isids_to_strs(sid_to_str, num_sids, isids); > + if (!strs) { > + ERR(NULL, "Error writing sid rules to CIL"); > + return -1; > } > > - for (isid = isids; isid != NULL; isid = isid->next) { > - i = isid->sid[0]; > - if (i < num_sids && sid_to_str[i]) { > - sid = strdup(sid_to_str[i]); > - } else { > - snprintf(unknown, 18, "%s%u", "UNKNOWN", i); > - sid = strdup(unknown); > - } > - if (!sid) { > - ERR(NULL, "Out of memory"); > - rc = -1; > - goto exit; > - } > - rc = strs_add_at_index(strs, sid, i); > - if (rc != 0) { > - free(sid); > - goto exit; > - } > + if (strs_num_items(strs) == 0) { > + strs_destroy(&strs); > + return 0; > } > > - for (i=0; i<strs_num_items(strs); i++) { > + for (i=1; i < strs_num_items(strs); i++) { > sid = strs_read_at_index(strs, i); > - if (!sid) { > - continue; > - } > sepol_printf(out, "(sid %s)\n", sid); > } > > sepol_printf(out, "(sidorder ("); > prev = NULL; > - for (i=0; i<strs_num_items(strs); i++) { > + for (i=1; i < strs_num_items(strs); i++) { > sid = strs_read_at_index(strs, i); > - if (!sid) { > - continue; > - } > if (prev) { > sepol_printf(out, "%s ", prev); > } > @@ -623,14 +600,10 @@ static int write_sids_to_cil(FILE *out, const char *const *sid_to_str, > } > sepol_printf(out, "))\n"); > > -exit: > strs_free_all(strs); > strs_destroy(&strs); > - if (rc != 0) { > - ERR(NULL, "Error writing sid rules to CIL"); > - } > > - return rc; > + return 0; > } > > static int write_sid_decl_rules_to_cil(FILE *out, struct policydb *pdb) > diff --git a/libsepol/src/kernel_to_common.c b/libsepol/src/kernel_to_common.c > index e4338ec6..99e46865 100644 > --- a/libsepol/src/kernel_to_common.c > +++ b/libsepol/src/kernel_to_common.c > @@ -382,6 +382,54 @@ int strs_stack_empty(const struct strs *stack) > return strs_num_items(stack) == 0; > } > > +struct strs *isids_to_strs(const char *const *sid_to_str, unsigned num_sids, struct ocontext *isids) > +{ > + struct ocontext *isid; > + struct strs *strs; > + char *sid; > + char unknown[18]; > + unsigned i, max; > + int rc; > + > + rc = strs_init(&strs, num_sids+1); > + if (rc != 0) { > + goto exit; > + } > + > + max = 0; > + for (isid = isids; isid != NULL; isid = isid->next) { > + i = isid->sid[0]; > + if (i > max) { > + max = i; > + } > + } > + > + for (i=1; i <= max; i++) { > + if (i < num_sids && sid_to_str[i]) { > + sid = strdup(sid_to_str[i]); > + } else { > + snprintf(unknown, 18, "%s%u", "UNKNOWN", i); > + sid = strdup(unknown); > + } > + if (!sid) { > + ERR(NULL, "Out of memory"); > + goto exit; > + } > + rc = strs_add_at_index(strs, sid, i); > + if (rc != 0) { > + free(sid); > + goto exit; > + } > + } > + > + return strs; > + > +exit: > + strs_free_all(strs); > + strs_destroy(&strs); > + return NULL; > +} > + > static int compare_ranges(uint64_t l1, uint64_t h1, uint64_t l2, uint64_t h2) > { > uint64_t d1, d2; > diff --git a/libsepol/src/kernel_to_common.h b/libsepol/src/kernel_to_common.h > index 3ba97dfc..d3283658 100644 > --- a/libsepol/src/kernel_to_common.h > +++ b/libsepol/src/kernel_to_common.h > @@ -115,4 +115,5 @@ int strs_stack_push(struct strs *stack, char *s); > char *strs_stack_pop(struct strs *stack); > int strs_stack_empty(const struct strs *stack); > > +struct strs *isids_to_strs(const char *const *sid_to_str, unsigned num_sids, struct ocontext *isids); > int sort_ocontexts(struct policydb *pdb); > diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c > index 6d608443..a8126d58 100644 > --- a/libsepol/src/kernel_to_conf.c > +++ b/libsepol/src/kernel_to_conf.c > @@ -463,53 +463,30 @@ static int write_class_decl_rules_to_conf(FILE *out, struct policydb *pdb) > static int write_sids_to_conf(FILE *out, const char *const *sid_to_str, > unsigned num_sids, struct ocontext *isids) > { > - struct ocontext *isid; > struct strs *strs; > char *sid; > - char unknown[18]; > unsigned i; > - int rc; > > - rc = strs_init(&strs, num_sids+1); > - if (rc != 0) { > - goto exit; > + strs = isids_to_strs(sid_to_str, num_sids, isids); > + if (!strs) { > + ERR(NULL, "Error writing sid rules to policy.conf"); > + return -1; > } > > - for (isid = isids; isid != NULL; isid = isid->next) { > - i = isid->sid[0]; > - if (i < num_sids && sid_to_str[i]) { > - sid = strdup(sid_to_str[i]); > - } else { > - snprintf(unknown, sizeof(unknown), "%s%u", "UNKNOWN", i); > - sid = strdup(unknown); > - } > - if (!sid) { > - rc = -1; > - goto exit; > - } > - rc = strs_add_at_index(strs, sid, i); > - if (rc != 0) { > - free(sid); > - goto exit; > - } > + if (strs_num_items(strs) == 0) { > + strs_destroy(&strs); > + return 0; > } > > - for (i=0; i<strs_num_items(strs); i++) { > + for (i=1; i < strs_num_items(strs); i++) { > sid = strs_read_at_index(strs, i); > - if (!sid) { > - continue; > - } > sepol_printf(out, "sid %s\n", sid); > } > > -exit: > strs_free_all(strs); > strs_destroy(&strs); > - if (rc != 0) { > - ERR(NULL, "Error writing sid rules to policy.conf"); > - } > > - return rc; > + return 0; > } > > static int write_sid_decl_rules_to_conf(FILE *out, struct policydb *pdb) > diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c > index 8647d928..1c4e80d1 100644 > --- a/libsepol/src/module_to_cil.c > +++ b/libsepol/src/module_to_cil.c > @@ -2544,71 +2544,71 @@ static int context_to_cil(struct policydb *pdb, struct context_struct *con) > static int ocontext_isid_to_cil(struct policydb *pdb, const char *const *sid_to_string, > unsigned num_sids, struct ocontext *isids) > { > - int rc = -1; > - > struct ocontext *isid; > - > - struct sid_item { > - char *sid_key; > - struct sid_item *next; > - }; > - > - struct sid_item *head = NULL; > - struct sid_item *item = NULL; > + struct ocontext **isid_array; > + struct strs *strs; > char *sid; > - char unknown[18]; > + char *prev; > unsigned i; > > - for (isid = isids; isid != NULL; isid = isid->next) { > - i = isid->sid[0]; > - if (i < num_sids && sid_to_string[i]) { > - sid = (char*)sid_to_string[i]; > - } else { > - snprintf(unknown, 18, "%s%u", "UNKNOWN", i); > - sid = unknown; > - } > - cil_println(0, "(sid %s)", sid); > - cil_printf("(sidcontext %s ", sid); > - context_to_cil(pdb, &isid->context[0]); > - cil_printf(")\n"); > + strs = isids_to_strs(sid_to_string, num_sids, isids); > + if (!strs) { > + ERR(NULL, "Error writing sid rules to CIL"); > + return -1; > + } > > - // get the sid names in the correct order (reverse from the isids > - // ocontext) for sidorder statement > - item = malloc(sizeof(*item)); > - if (item == NULL) { > - ERR(NULL, "Out of memory"); > - rc = -1; > - goto exit; > - } > - item->sid_key = strdup(sid); > - if (!item->sid_key) { > - ERR(NULL, "Out of memory"); > - free(item); > - rc = -1; > - goto exit; > + if (strs_num_items(strs) == 0) { > + strs_destroy(&strs); > + return 0; > + } > + > + for (i=1; i < strs_num_items(strs); i++) { > + sid = strs_read_at_index(strs, i); > + cil_printf("(sid %s)\n", sid); > + } > + > + cil_printf("(sidorder ("); > + prev = NULL; > + for (i=1; i < strs_num_items(strs); i++) { > + sid = strs_read_at_index(strs, i); > + if (prev) { > + cil_printf("%s ", prev); > } > - item->next = head; > - head = item; > + prev = sid; > + } > + if (prev) { > + cil_printf("%s", prev); > } > + cil_printf("))\n"); > > - if (head != NULL) { > - cil_printf("(sidorder ("); > - for (item = head; item != NULL; item = item->next) { > - cil_printf("%s ", item->sid_key); > + isid_array = calloc(strs_num_items(strs), sizeof(struct ocontext *)); > + if (!isid_array) { > + ERR(NULL, "Out of memory"); > + strs_free_all(strs); > + strs_destroy(&strs); > + return -1; > + } > + for (isid = isids; isid != NULL; isid = isid->next) { > + i = isid->sid[0]; > + if (i < strs_num_items(strs)) { > + isid_array[i] = isid; > + } > + } > + for (i=1; i < strs_num_items(strs); i++) { > + if (isid_array[i]) { > + sid = strs_read_at_index(strs, i); > + cil_printf("(sidcontext %s ", sid); > + isid = isid_array[i]; > + context_to_cil(pdb, &isid->context[0]); > + cil_printf(")\n"); > } > - cil_printf("))\n"); > } > + free(isid_array); > > - rc = 0; > + strs_free_all(strs); > + strs_destroy(&strs); > > -exit: > - while(head) { > - item = head; > - head = item->next; > - free(item->sid_key); > - free(item); > - } > - return rc; > + return 0; > } > > static int ocontext_selinux_isid_to_cil(struct policydb *pdb, struct ocontext *isids) > -- > 2.50.0 >