diff options
author | Dan Cashman <dcashman@google.com> | 2017-08-07 14:58:55 -0700 |
---|---|---|
committer | Dan Cashman <dcashman@google.com> | 2017-08-07 17:00:18 -0700 |
commit | 706ddd16f3f4a3e5e9754904957fe2efe5066989 (patch) | |
tree | 0c05bc5318a2d0834cfc341cfe68a95d846f071a /libselinux/src/label_file.c | |
parent | 7e29d17754156636a79c60f7ce195039b94d7197 (diff) | |
parent | bd75c5695c629a20aeb7c9d723290e2d7bb8a3f3 (diff) | |
download | android_external_selinux-706ddd16f3f4a3e5e9754904957fe2efe5066989.tar.gz android_external_selinux-706ddd16f3f4a3e5e9754904957fe2efe5066989.tar.bz2 android_external_selinux-706ddd16f3f4a3e5e9754904957fe2efe5066989.zip |
Merge remote-tracking branch 'aosp/upstream-master' into mymerge
Bug: 63861738
Test: Builds 'n' boots
Change-Id: Idfb333d4cc1568dd2273f74731f12d52a413c07b
Diffstat (limited to 'libselinux/src/label_file.c')
-rw-r--r-- | libselinux/src/label_file.c | 180 |
1 files changed, 172 insertions, 8 deletions
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c index 70f68382..b3b36bc2 100644 --- a/libselinux/src/label_file.c +++ b/libselinux/src/label_file.c @@ -389,10 +389,12 @@ end_arch_check: spec->prefix_len = prefix_len; } - rc = regex_load_mmap(mmap_area, &spec->regex, reg_arch_matches); + rc = regex_load_mmap(mmap_area, &spec->regex, reg_arch_matches, + &spec->regex_compiled); if (rc < 0) goto out; + __pthread_mutex_init(&spec->regex_lock, NULL); data->nspec++; } @@ -559,6 +561,148 @@ static int process_file(const char *path, const char *suffix, return -1; } +static void selabel_subs_fini(struct selabel_sub *ptr) +{ + struct selabel_sub *next; + + while (ptr) { + next = ptr->next; + free(ptr->src); + free(ptr->dst); + free(ptr); + ptr = next; + } +} + +static char *selabel_sub(struct selabel_sub *ptr, const char *src) +{ + char *dst = NULL; + int len; + + while (ptr) { + if (strncmp(src, ptr->src, ptr->slen) == 0 ) { + if (src[ptr->slen] == '/' || + src[ptr->slen] == 0) { + if ((src[ptr->slen] == '/') && + (strcmp(ptr->dst, "/") == 0)) + len = ptr->slen + 1; + else + len = ptr->slen; + if (asprintf(&dst, "%s%s", ptr->dst, &src[len]) < 0) + return NULL; + return dst; + } + } + ptr = ptr->next; + } + return NULL; +} + +static int selabel_subs_init(const char *path, struct selabel_digest *digest, + struct selabel_sub **out_subs) +{ + char buf[1024]; + FILE *cfg = fopen(path, "re"); + struct selabel_sub *list = NULL, *sub = NULL; + struct stat sb; + int status = -1; + + *out_subs = NULL; + 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 = NULL; + char *src = buf; + char *dst = NULL; + + while (*src && isspace(*src)) + src++; + if (src[0] == '#') continue; + ptr = src; + while (*ptr && ! isspace(*ptr)) + ptr++; + *ptr++ = '\0'; + if (! *src) continue; + + dst = ptr; + while (*dst && isspace(*dst)) + dst++; + ptr=dst; + while (*ptr && ! isspace(*ptr)) + ptr++; + *ptr='\0'; + if (! *dst) + continue; + + sub = malloc(sizeof(*sub)); + if (! sub) + goto err; + memset(sub, 0, sizeof(*sub)); + + sub->src=strdup(src); + if (! sub->src) + goto err; + + sub->dst=strdup(dst); + if (! sub->dst) + goto err; + + sub->slen = strlen(src); + sub->next = list; + list = sub; + sub = NULL; + } + + if (digest_add_specfile(digest, cfg, NULL, sb.st_size, path) < 0) + goto err; + + *out_subs = list; + status = 0; + +out: + fclose(cfg); + return status; +err: + if (sub) + free(sub->src); + free(sub); + while (list) { + sub = list->next; + free(list->src); + free(list->dst); + free(list); + list = sub; + } + goto out; +} + +static char *selabel_sub_key(struct saved_data *data, const char *key) +{ + char *ptr = NULL; + char *dptr = NULL; + + ptr = selabel_sub(data->subs, key); + if (ptr) { + dptr = selabel_sub(data->dist_subs, ptr); + if (dptr) { + free(ptr); + ptr = dptr; + } + } else { + ptr = selabel_sub(data->dist_subs, key); + } + if (ptr) + return ptr; + + return NULL; +} + static void closef(struct selabel_handle *rec); static int init(struct selabel_handle *rec, const struct selinux_opt *opts, @@ -620,20 +764,30 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, char subs_file[PATH_MAX + 1]; /* Process local and distribution substitution files */ if (!path_provided) { - rec->dist_subs = - selabel_subs_init(selinux_file_context_subs_dist_path(), - rec->dist_subs, rec->digest); - rec->subs = selabel_subs_init(selinux_file_context_subs_path(), - rec->subs, rec->digest); + status = selabel_subs_init( + selinux_file_context_subs_dist_path(), + rec->digest, &data->dist_subs); + if (status) + goto finish; + status = selabel_subs_init(selinux_file_context_subs_path(), + rec->digest, &data->subs); + if (status) + goto finish; rec->spec_files[0] = strdup(selinux_file_context_path()); if (rec->spec_files[0] == NULL) goto finish; } else { for (i = 0; i < num_paths; i++) { snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", rec->spec_files[i]); - rec->dist_subs = selabel_subs_init(subs_file, rec->dist_subs, rec->digest); + status = selabel_subs_init(subs_file, rec->digest, + &data->dist_subs); + if (status) + goto finish; snprintf(subs_file, sizeof(subs_file), "%s.subs", rec->spec_files[i]); - rec->subs = selabel_subs_init(subs_file, rec->subs, rec->digest); + status = selabel_subs_init(subs_file, rec->digest, + &data->subs); + if (status) + goto finish; } } #else @@ -698,11 +852,15 @@ static void closef(struct selabel_handle *rec) /* make sure successive ->func_close() calls are harmless */ rec->data = NULL; + selabel_subs_fini(data->subs); + selabel_subs_fini(data->dist_subs); + for (i = 0; i < data->nspec; i++) { spec = &data->spec_arr[i]; free(spec->lr.ctx_trans); free(spec->lr.ctx_raw); regex_data_free(spec->regex); + __pthread_mutex_destroy(&spec->regex_lock); if (spec->from_mmap) continue; free(spec->regex_str); @@ -745,6 +903,7 @@ static struct spec *lookup_common(struct selabel_handle *rec, char *clean_key = NULL; const char *prev_slash, *next_slash; unsigned int sofar = 0; + char *sub = NULL; if (!data->nspec) { errno = ENOENT; @@ -767,6 +926,10 @@ static struct spec *lookup_common(struct selabel_handle *rec, key = clean_key; } + sub = selabel_sub_key(data, key); + if (sub) + key = sub; + buf = key; file_stem = find_stem_from_file(data, &buf); mode &= S_IFMT; @@ -815,6 +978,7 @@ static struct spec *lookup_common(struct selabel_handle *rec, finish: free(clean_key); + free(sub); return ret; } |