This reverts commit 4d436e4bf80284ac3b645bad022a9757dbc2dd36. Needed to revert commit 92306daf5219e73f6e8bc9fc7699399457999bcd "libselinux: rework selabel_file(5) database", which broke Android file_context matching. Signed-off-by: James Carter <jwcart2@xxxxxxxxx> --- libselinux/src/label_file.c | 129 +++++++++++++++++------------------- libselinux/src/label_file.h | 20 ++---- 2 files changed, 66 insertions(+), 83 deletions(-) diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c index b7ff8c09..be1ee11a 100644 --- a/libselinux/src/label_file.c +++ b/libselinux/src/label_file.c @@ -1188,27 +1188,28 @@ static int process_file(const char *path, const char *suffix, return -1; } -static void selabel_subs_fini(struct selabel_sub *subs, uint32_t num) +static void selabel_subs_fini(struct selabel_sub *ptr) { - for (uint32_t i = 0; i < num; i++) { - free(subs[i].src); - free(subs[i].dst); + struct selabel_sub *next; + + while (ptr) { + next = ptr->next; + free(ptr->src); + free(ptr->dst); + free(ptr); + ptr = next; } - - free(subs); } -static char *selabel_apply_subs(const struct selabel_sub *subs, uint32_t num, const char *src) +static char *selabel_sub(const struct selabel_sub *ptr, const char *src) { - char *dst; - uint32_t len; - - for (uint32_t i = 0; i < num; i++) { - const struct selabel_sub *ptr = &subs[i]; + char *dst = NULL; + unsigned int len; + while (ptr) { if (strncmp(src, ptr->src, ptr->slen) == 0 ) { if (src[ptr->slen] == '/' || - src[ptr->slen] == '\0') { + src[ptr->slen] == 0) { if ((src[ptr->slen] == '/') && (strcmp(ptr->dst, "/") == 0)) len = ptr->slen + 1; @@ -1219,38 +1220,34 @@ static char *selabel_apply_subs(const struct selabel_sub *subs, uint32_t num, co return dst; } } + ptr = ptr->next; } - return NULL; } #if !defined(BUILD_HOST) && !defined(ANDROID) static int selabel_subs_init(const char *path, struct selabel_digest *digest, - struct selabel_sub **out_subs, - uint32_t *out_num, uint32_t *out_alloc) + struct selabel_sub **out_subs) { char buf[1024]; - FILE *cfg; + FILE *cfg = fopen(path, "re"); + struct selabel_sub *list = NULL, *sub = NULL; struct stat sb; - struct selabel_sub *tmp = NULL; - uint32_t tmp_num = 0, tmp_alloc = 0; - char *src_cpy = NULL, *dst_cpy = NULL; - int rc; + int status = -1; *out_subs = NULL; - *out_num = 0; - *out_alloc = 0; - - cfg = fopen(path, "re"); if (!cfg) { /* If the file does not exist, it is not fatal */ return (errno == ENOENT) ? 0 : -1; } + if (fstat(fileno(cfg), &sb) < 0) + goto out; + while (fgets_unlocked(buf, sizeof(buf) - 1, cfg)) { - char *ptr; + char *ptr = NULL; char *src = buf; - char *dst; + char *dst = NULL; size_t len; while (*src && isspace((unsigned char)*src)) @@ -1278,68 +1275,62 @@ static int selabel_subs_init(const char *path, struct selabel_digest *digest, goto err; } - src_cpy = strdup(src); - if (!src_cpy) + sub = calloc(1, sizeof(*sub)); + if (! sub) goto err; - dst_cpy = strdup(dst); - if (!dst_cpy) + sub->src = strdup(src); + if (! sub->src) goto err; - rc = GROW_ARRAY(tmp); - if (rc) + sub->dst = strdup(dst); + if (! sub->dst) goto err; - tmp[tmp_num++] = (struct selabel_sub) { - .src = src_cpy, - .slen = len, - .dst = dst_cpy, - }; - src_cpy = NULL; - dst_cpy = NULL; + sub->slen = len; + sub->next = list; + list = sub; + sub = NULL; } - rc = fstat(fileno(cfg), &sb); - if (rc < 0) - goto err; - if (digest_add_specfile(digest, cfg, NULL, sb.st_size, path) < 0) goto err; - *out_subs = tmp; - *out_num = tmp_num; - *out_alloc = tmp_alloc; + *out_subs = list; + status = 0; +out: fclose(cfg); - - return 0; - + return status; err: - free(dst_cpy); - free(src_cpy); - for (uint32_t i = 0; i < tmp_num; i++) { - free(tmp[i].src); - free(tmp[i].dst); + if (sub) + free(sub->src); + free(sub); + while (list) { + sub = list->next; + free(list->src); + free(list->dst); + free(list); + list = sub; } - free(tmp); - fclose_errno_safe(cfg); - return -1; + goto out; } #endif static char *selabel_sub_key(const struct saved_data *data, const char *key) { - char *ptr, *dptr; + char *ptr = NULL; + char *dptr = NULL; - ptr = selabel_apply_subs(data->subs, data->subs_num, key); + ptr = selabel_sub(data->subs, key); if (ptr) { - dptr = selabel_apply_subs(data->dist_subs, data->dist_subs_num, ptr); + dptr = selabel_sub(data->dist_subs, ptr); if (dptr) { free(ptr); ptr = dptr; } } else { - ptr = selabel_apply_subs(data->dist_subs, data->dist_subs_num, key); + ptr = selabel_sub(data->dist_subs, key); } return ptr; @@ -1384,25 +1375,23 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, if (!path) { status = selabel_subs_init( selinux_file_context_subs_dist_path(), - rec->digest, - &data->dist_subs, &data->dist_subs_num, &data->dist_subs_alloc); + rec->digest, &data->dist_subs); if (status) goto finish; status = selabel_subs_init(selinux_file_context_subs_path(), - rec->digest, - &data->subs, &data->subs_num, &data->subs_alloc); + rec->digest, &data->subs); if (status) goto finish; path = selinux_file_context_path(); } else { snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", path); status = selabel_subs_init(subs_file, rec->digest, - &data->dist_subs, &data->dist_subs_num, &data->dist_subs_alloc); + &data->dist_subs); if (status) goto finish; snprintf(subs_file, sizeof(subs_file), "%s.subs", path); status = selabel_subs_init(subs_file, rec->digest, - &data->subs, &data->subs_num, &data->subs_alloc); + &data->subs); if (status) goto finish; } @@ -1470,8 +1459,8 @@ static void closef(struct selabel_handle *rec) if (!data) return; - selabel_subs_fini(data->subs, data->subs_num); - selabel_subs_fini(data->dist_subs, data->dist_subs_num); + selabel_subs_fini(data->subs); + selabel_subs_fini(data->dist_subs); free_spec_node(data->root); free(data->root); diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h index d5dd2be1..b59db003 100644 --- a/libselinux/src/label_file.h +++ b/libselinux/src/label_file.h @@ -67,11 +67,11 @@ extern struct lookup_result *lookup_all(struct selabel_handle *rec, const char * extern enum selabel_cmp_result cmp(const struct selabel_handle *h1, const struct selabel_handle *h2); #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ -/* A path substitution entry */ struct selabel_sub { - char *src; /* source path prefix */ - char *dst; /* substituted path prefix */ - uint32_t slen; /* length of source path prefix */ + char *src; + unsigned int slen; + char *dst; + struct selabel_sub *next; }; /* A regular expression file security context specification */ @@ -159,17 +159,9 @@ struct saved_data { struct mmap_area *mmap_areas; - /* - * Array of distribution substitutions - */ + /* substitution support */ struct selabel_sub *dist_subs; - uint32_t dist_subs_num, dist_subs_alloc; - - /* - * Array of local substitutions - */ struct selabel_sub *subs; - uint32_t subs_num, subs_alloc; }; void free_spec_node(struct spec_node *node); @@ -795,6 +787,8 @@ static int insert_spec(const struct selabel_handle *rec, struct saved_data *data return 0; } +#undef GROW_ARRAY + /* This will always check for buffer over-runs and either read the next entry * if buf != NULL or skip over the entry (as these areas are mapped in the * current buffer). */ -- 2.47.1