diff options
Diffstat (limited to 'libselinux/src')
-rw-r--r-- | libselinux/src/Makefile | 4 | ||||
-rw-r--r-- | libselinux/src/label.c | 164 | ||||
-rw-r--r-- | libselinux/src/label_file.c | 180 | ||||
-rw-r--r-- | libselinux/src/label_file.h | 43 | ||||
-rw-r--r-- | libselinux/src/label_internal.h | 13 | ||||
-rw-r--r-- | libselinux/src/load_policy.c | 5 | ||||
-rw-r--r-- | libselinux/src/regex.c | 31 | ||||
-rw-r--r-- | libselinux/src/regex.h | 7 | ||||
-rw-r--r-- | libselinux/src/selinux_internal.h | 32 |
9 files changed, 288 insertions, 191 deletions
diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile index 4306dd0e..2408faea 100644 --- a/libselinux/src/Makefile +++ b/libselinux/src/Makefile @@ -17,7 +17,7 @@ PYLIBS ?= $(shell $(PKG_CONFIG) --libs $(PYPREFIX)) PYSITEDIR ?= $(DESTDIR)$(shell $(PYTHON) -c 'import site; print(site.getsitepackages()[0])') PYCEXT ?= $(shell $(PYTHON) -c 'import imp;print([s for s,m,t in imp.get_suffixes() if t == imp.C_EXTENSION][0])') RUBYINC ?= $(shell $(RUBY) -e 'puts "-I" + RbConfig::CONFIG["rubyarchhdrdir"] + " -I" + RbConfig::CONFIG["rubyhdrdir"]') -RUBYLIBS ?= $(shell $(RUBY) -e 'puts "-L" + RbConfig::CONFIG["libdir"] + " -lruby"') +RUBYLIBS ?= $(shell $(RUBY) -e 'puts "-L" + RbConfig::CONFIG["libdir"] + " -L" + RbConfig::CONFIG["archlibdir"] + " " + RbConfig::CONFIG["LIBRUBYARG_SHARED"]') RUBYINSTALL ?= $(DESTDIR)$(shell $(RUBY) -e 'puts RbConfig::CONFIG["vendorarchdir"]') LIBBASE ?= $(shell basename $(LIBDIR)) LIBSEPOLA ?= $(LIBDIR)/libsepol.a @@ -59,7 +59,7 @@ ifeq ($(COMPILER), gcc) EXTRA_CFLAGS = -fipa-pure-const -Wlogical-op -Wpacked-bitfield-compat -Wsync-nand \ -Wcoverage-mismatch -Wcpp -Wformat-contains-nul -Wnormalized=nfc -Wsuggest-attribute=const \ -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure -Wtrampolines -Wjump-misses-init \ - -Wno-suggest-attribute=pure -Wno-suggest-attribute=const -Wp,-D_FORTIFY_SOURCE=2 + -Wno-suggest-attribute=pure -Wno-suggest-attribute=const -Wp,-D_FORTIFY_SOURCE else EXTRA_CFLAGS = -Wunused-command-line-argument endif diff --git a/libselinux/src/label.c b/libselinux/src/label.c index 8e0a8628..c051e9f9 100644 --- a/libselinux/src/label.c +++ b/libselinux/src/label.c @@ -60,113 +60,6 @@ static selabel_initfunc initfuncs[] = { CONFIG_ANDROID_BACKEND(selabel_service_init), }; -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; -} - -struct selabel_sub *selabel_subs_init(const char *path, - struct selabel_sub *list, - struct selabel_digest *digest) -{ - char buf[1024]; - FILE *cfg = fopen(path, "re"); - struct selabel_sub *sub = NULL; - struct stat sb; - - if (!cfg) - return list; - - if (fstat(fileno(cfg), &sb) < 0) - return list; - - 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; - } - - if (digest_add_specfile(digest, cfg, NULL, sb.st_size, path) < 0) - goto err; - -out: - fclose(cfg); - return list; -err: - if (sub) - free(sub->src); - free(sub); - goto out; -} - static inline struct selabel_digest *selabel_is_digest_set (const struct selinux_opt *opts, unsigned n, @@ -252,27 +145,6 @@ out: } /* Public API helpers */ -static char *selabel_sub_key(struct selabel_handle *rec, const char *key) -{ - char *ptr = NULL; - char *dptr = NULL; - - ptr = selabel_sub(rec->subs, key); - if (ptr) { - dptr = selabel_sub(rec->dist_subs, ptr); - if (dptr) { - free(ptr); - ptr = dptr; - } - } else { - ptr = selabel_sub(rec->dist_subs, key); - } - if (ptr) - return ptr; - - return NULL; -} - static int selabel_fini(struct selabel_handle *rec, struct selabel_lookup_rec *lr, int translating) @@ -296,20 +168,13 @@ selabel_lookup_common(struct selabel_handle *rec, int translating, const char *key, int type) { struct selabel_lookup_rec *lr; - char *ptr = NULL; if (key == NULL) { errno = EINVAL; return NULL; } - ptr = selabel_sub_key(rec, key); - if (ptr) { - lr = rec->func_lookup(rec, ptr, type); - free(ptr); - } else { - lr = rec->func_lookup(rec, key, type); - } + lr = rec->func_lookup(rec, key, type); if (!lr) return NULL; @@ -324,20 +189,13 @@ selabel_lookup_bm_common(struct selabel_handle *rec, int translating, const char *key, int type, const char **aliases) { struct selabel_lookup_rec *lr; - char *ptr = NULL; if (key == NULL) { errno = EINVAL; return NULL; } - ptr = selabel_sub_key(rec, key); - if (ptr) { - lr = rec->func_lookup_best_match(rec, ptr, aliases, type); - free(ptr); - } else { - lr = rec->func_lookup_best_match(rec, key, aliases, type); - } + lr = rec->func_lookup_best_match(rec, key, aliases, type); if (!lr) return NULL; @@ -375,8 +233,6 @@ struct selabel_handle *selabel_open(unsigned int backend, rec->backend = backend; rec->validating = selabel_is_validate_set(opts, nopts); - rec->subs = NULL; - rec->dist_subs = NULL; rec->digest = selabel_is_digest_set(opts, nopts, rec->digest); if ((*initfuncs[backend])(rec, opts, nopts)) { @@ -415,9 +271,6 @@ int selabel_lookup_raw(struct selabel_handle *rec, char **con, bool selabel_partial_match(struct selabel_handle *rec, const char *key) { - char *ptr; - bool ret; - if (!rec->func_partial_match) { /* * If the label backend does not support partial matching, @@ -426,15 +279,7 @@ bool selabel_partial_match(struct selabel_handle *rec, const char *key) return true; } - ptr = selabel_sub_key(rec, key); - if (ptr) { - ret = rec->func_partial_match(rec, ptr); - free(ptr); - } else { - ret = rec->func_partial_match(rec, key); - } - - return ret; + return rec->func_partial_match(rec, key); } int selabel_lookup_best_match(struct selabel_handle *rec, char **con, @@ -501,8 +346,7 @@ int selabel_digest(struct selabel_handle *rec, void selabel_close(struct selabel_handle *rec) { size_t i; - selabel_subs_fini(rec->subs); - selabel_subs_fini(rec->dist_subs); + if (rec->spec_files) { for (i = 0; i < rec->spec_files_len; i++) free(rec->spec_files[i]); 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; } diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h index 4ac64d59..aa576d8e 100644 --- a/libselinux/src/label_file.h +++ b/libselinux/src/label_file.h @@ -2,6 +2,7 @@ #define _SELABEL_FILE_H_ #include <errno.h> +#include <pthread.h> #include <string.h> #include <sys/stat.h> @@ -16,6 +17,7 @@ #include "callbacks.h" #include "label_internal.h" +#include "selinux_internal.h" #define SELINUX_MAGIC_COMPILED_FCONTEXT 0xf97cff8a @@ -29,12 +31,21 @@ #define SELINUX_COMPILED_FCONTEXT_MAX_VERS \ SELINUX_COMPILED_FCONTEXT_REGEX_ARCH +struct selabel_sub { + char *src; + int slen; + char *dst; + struct selabel_sub *next; +}; + /* A file security context specification. */ struct spec { struct selabel_lookup_rec lr; /* holds contexts for lookup result */ char *regex_str; /* regular expession string for diagnostics */ char *type_str; /* type string for diagnostic messages */ struct regex_data * regex; /* backend dependent regular expression data */ + bool regex_compiled; /* bool to indicate if the regex is compiled */ + pthread_mutex_t regex_lock; /* lock for lazy compilation of regex */ mode_t mode; /* mode format value */ int matches; /* number of matching pathnames */ int stem_id; /* indicates which stem-compression item */ @@ -76,6 +87,10 @@ struct saved_data { int num_stems; int alloc_stems; struct mmap_area *mmap_areas; + + /* substitution support */ + struct selabel_sub *dist_subs; + struct selabel_sub *subs; }; static inline mode_t string_to_mode(char *mode) @@ -328,9 +343,27 @@ static inline int compile_regex(struct saved_data *data, struct spec *spec, struct stem *stem_arr = data->stem_arr; size_t len; int rc; - - if (spec->regex) + bool regex_compiled; + + /* We really want pthread_once() here, but since its + * init_routine does not take a parameter, it's not possible + * to use, so we generate the same effect with atomics and a + * mutex */ + regex_compiled = + __atomic_load_n(&spec->regex_compiled, __ATOMIC_ACQUIRE); + if (regex_compiled) { return 0; /* already done */ + } + + __pthread_mutex_lock(&spec->regex_lock); + /* Check if another thread compiled the regex while we waited + * on the mutex */ + regex_compiled = + __atomic_load_n(&spec->regex_compiled, __ATOMIC_ACQUIRE); + if (regex_compiled) { + __pthread_mutex_unlock(&spec->regex_lock); + return 0; + } /* Skip the fixed stem. */ reg_buf = spec->regex_str; @@ -343,6 +376,7 @@ static inline int compile_regex(struct saved_data *data, struct spec *spec, if (!anchored_regex) { if (errbuf) *errbuf = "out of memory"; + __pthread_mutex_unlock(&spec->regex_lock); return -1; } @@ -363,10 +397,13 @@ static inline int compile_regex(struct saved_data *data, struct spec *spec, sizeof(regex_error_format_buffer)); *errbuf = ®ex_error_format_buffer[0]; } + __pthread_mutex_unlock(&spec->regex_lock); return -1; } /* Done. */ + __atomic_store_n(&spec->regex_compiled, true, __ATOMIC_RELEASE); + __pthread_mutex_unlock(&spec->regex_lock); return 0; } @@ -428,6 +465,8 @@ static inline int process_line(struct selabel_handle *rec, /* process and store the specification in spec. */ spec_arr[nspec].stem_id = find_stem_from_spec(data, regex); spec_arr[nspec].regex_str = regex; + __pthread_mutex_init(&spec_arr[nspec].regex_lock, NULL); + spec_arr[nspec].regex_compiled = false; spec_arr[nspec].type_str = type; spec_arr[nspec].mode = 0; diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h index 62c1720e..6810018f 100644 --- a/libselinux/src/label_internal.h +++ b/libselinux/src/label_internal.h @@ -46,12 +46,6 @@ int selabel_service_init(struct selabel_handle *rec, /* * Labeling internal structures */ -struct selabel_sub { - char *src; - int slen; - char *dst; - struct selabel_sub *next; -}; /* * Calculate an SHA1 hash of all the files used to build the specs. @@ -75,10 +69,6 @@ extern int digest_add_specfile(struct selabel_digest *digest, FILE *fp, const char *path); extern void digest_gen_hash(struct selabel_digest *digest); -extern struct selabel_sub *selabel_subs_init(const char *path, - struct selabel_sub *list, - struct selabel_digest *digest); - struct selabel_lookup_rec { char * ctx_raw; char * ctx_trans; @@ -115,9 +105,6 @@ struct selabel_handle { char **spec_files; - /* substitution support */ - struct selabel_sub *dist_subs; - struct selabel_sub *subs; /* ptr to SHA1 hash information if SELABEL_OPT_DIGEST set */ struct selabel_digest *digest; }; diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c index 7f083117..e9f1264a 100644 --- a/libselinux/src/load_policy.c +++ b/libselinux/src/load_policy.c @@ -449,8 +449,11 @@ int selinux_init_load_policy(int *enforce) } } - if (seconfig == -1) + if (seconfig == -1) { + umount(selinux_mnt); + fini_selinuxmnt(); goto noload; + } /* Load the policy. */ return selinux_mkload_policy(0); diff --git a/libselinux/src/regex.c b/libselinux/src/regex.c index 0c5ad274..dfc15d63 100644 --- a/libselinux/src/regex.c +++ b/libselinux/src/regex.c @@ -1,10 +1,12 @@ #include <assert.h> +#include <pthread.h> #include <stdint.h> #include <stdio.h> #include <string.h> #include "regex.h" #include "label_file.h" +#include "selinux_internal.h" #ifdef USE_PCRE2 #define REGEX_ARCH_SIZE_T PCRE2_SIZE @@ -63,6 +65,7 @@ struct regex_data { * pattern in pcre2 */ pcre2_match_data *match_data; + pthread_mutex_t match_mutex; }; int regex_prepare_data(struct regex_data **regex, char const *pattern_string, @@ -106,11 +109,12 @@ char const *regex_version(void) } int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex, - int do_load_precompregex) + int do_load_precompregex, bool *regex_compiled) { int rc; uint32_t entry_len; + *regex_compiled = false; rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t)); if (rc < 0) return -1; @@ -138,6 +142,8 @@ int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex, pcre2_match_data_create_from_pattern((*regex)->regex, NULL); if (!(*regex)->match_data) goto err; + + *regex_compiled = true; } /* and skip the decoded bit */ @@ -199,6 +205,7 @@ void regex_data_free(struct regex_data *regex) pcre2_code_free(regex->regex); if (regex->match_data) pcre2_match_data_free(regex->match_data); + __pthread_mutex_destroy(®ex->match_mutex); free(regex); } } @@ -206,9 +213,11 @@ void regex_data_free(struct regex_data *regex) int regex_match(struct regex_data *regex, char const *subject, int partial) { int rc; + __pthread_mutex_lock(®ex->match_mutex); rc = pcre2_match( regex->regex, (PCRE2_SPTR)subject, PCRE2_ZERO_TERMINATED, 0, partial ? PCRE2_PARTIAL_SOFT : 0, regex->match_data, NULL); + __pthread_mutex_unlock(®ex->match_mutex); if (rc > 0) return REGEX_MATCH; switch (rc) { @@ -244,6 +253,14 @@ int regex_cmp(struct regex_data *regex1, struct regex_data *regex2) return SELABEL_EQUAL; } +struct regex_data *regex_data_create(void) +{ + struct regex_data *regex_data = + (struct regex_data *)calloc(1, sizeof(struct regex_data)); + __pthread_mutex_init(®ex_data->match_mutex, NULL); + return regex_data; +} + #else // !USE_PCRE2 char const *regex_arch_string(void) { @@ -302,7 +319,7 @@ char const *regex_version(void) } int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex, - int unused __attribute__((unused))) + int unused __attribute__((unused)), bool *regex_compiled) { int rc; uint32_t entry_len; @@ -347,6 +364,8 @@ int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex, if (rc < 0 || info_len != entry_len) goto err; } + + *regex_compiled = true; return 0; err: @@ -472,13 +491,13 @@ int regex_cmp(struct regex_data *regex1, struct regex_data *regex2) return SELABEL_EQUAL; } -#endif - struct regex_data *regex_data_create(void) { return (struct regex_data *)calloc(1, sizeof(struct regex_data)); } +#endif + void regex_format_error(struct regex_error_data const *error_data, char *buffer, size_t buf_size) { @@ -539,12 +558,16 @@ truncated: /* no break statements, fall-through is intended */ case 4: *ptr++ = '.'; + /* FALLTHRU */ case 3: *ptr++ = '.'; + /* FALLTHRU */ case 2: *ptr++ = '.'; + /* FALLTHRU */ case 1: *ptr++ = '\0'; + /* FALLTHRU */ default: break; } diff --git a/libselinux/src/regex.h b/libselinux/src/regex.h index 186c5ecc..eb8ca501 100644 --- a/libselinux/src/regex.h +++ b/libselinux/src/regex.h @@ -1,6 +1,7 @@ #ifndef SRC_REGEX_H_ #define SRC_REGEX_H_ +#include <stdbool.h> #include <stdio.h> #ifdef USE_PCRE2 @@ -98,13 +99,17 @@ int regex_prepare_data(struct regex_data **regex, char const *pattern_string, * with regex_data_create and must be freed with regex_data_free. * @arg do_load_precompregex If non-zero precompiled patterns get loaded from * the mmap region (ignored by PCRE1 back-end). + * @arg regex_compiled Set to true if a precompiled pattern was loaded + * into regex, otherwise set to false to indicate later + * compilation must occur * * @retval 0 on success * @retval -1 on error */ int regex_load_mmap(struct mmap_area *map_area, struct regex_data **regex, - int do_load_precompregex) hidden; + int do_load_precompregex, + bool *regex_compiled) hidden; /** * This function stores a precompiled regular expression to a file. * In the case of PCRE, it just dumps the binary representation of the diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h index 54949c13..dfc421cc 100644 --- a/libselinux/src/selinux_internal.h +++ b/libselinux/src/selinux_internal.h @@ -144,6 +144,38 @@ extern int selinux_page_size hidden; pthread_setspecific(KEY, VALUE); \ } while (0) +/* selabel_lookup() is only thread safe if we're compiled with pthreads */ + +#pragma weak pthread_mutex_init +#pragma weak pthread_mutex_destroy +#pragma weak pthread_mutex_lock +#pragma weak pthread_mutex_unlock + +#define __pthread_mutex_init(LOCK, ATTR) \ + do { \ + if (pthread_mutex_init != NULL) \ + pthread_mutex_init(LOCK, ATTR); \ + } while (0) + +#define __pthread_mutex_destroy(LOCK) \ + do { \ + if (pthread_mutex_destroy != NULL) \ + pthread_mutex_destroy(LOCK); \ + } while (0) + +#define __pthread_mutex_lock(LOCK) \ + do { \ + if (pthread_mutex_lock != NULL) \ + pthread_mutex_lock(LOCK); \ + } while (0) + +#define __pthread_mutex_unlock(LOCK) \ + do { \ + if (pthread_mutex_unlock != NULL) \ + pthread_mutex_unlock(LOCK); \ + } while (0) + + #define SELINUXDIR "/etc/selinux/" #define SELINUXCONFIG SELINUXDIR "config" |