On Sep 6, 2016 11:58, "Stephen Smalley" <[email protected]> wrote: > > On 08/29/2016 12:22 PM, [email protected] wrote: > > From: William Roberts <[email protected]> > > > > I noticed, via gprof, that the time spent in nodups_specs() > > accounts for 100% of the label_open() call. > > > > It seems as though the N^2 comparison using strcmp is very > > slow. > > > > Do two major things: > > 1. move the rec->validating check to the left, check the simple > > thing first before runnning the expensive strcmp(). strcmp() > > is used to check string equality, check lengths first. > > 2. strlen() is used all over to calculate lengths, just store > > it in a struct with the string so its usable elsewhere, rather > > than recalculating it. > > > > text 21.4% speedup: > > before text: 248 > > after text: 195 > > > > binary 24.6% speedup: > > before bin: 236 > > after bin: 178 > > > > Some things to ponder: > > 1. We can use C ABI safe pointer instead of len_str structure > > https://bitbucket.org/billcroberts/twist > > There are pros and cons to this approach, namely if someone > > calls free(x) instead of twist_free(x) > > It also currently has 0 support for stack based strings (simple > > enough to add). I think this approach is overkill here. > > Agreed. > > > > > 2. The location of the str_len struct and routines should likely > > move elsewhere. > > Agreed. > > > > > 3. The impact on Android is currently unmeasured, that's next. > > Also, bionic uses something from label_file.h for processing > > property_contexts for the Android property subsystem... so > > need to ensure that all works as advertised still. > > > > Things to do: > > 1. Cleanup the code locations, likely a util.h or a len_str.h, > > a better name would be nice. > > 2. Spell check this commit message > > Seems a bit prone to the str and len fields getting out of sync since > they are both directly manipulated.
Agreed I can handle that easily. As long as you're OK with the general concept I'll clean this up and send out after the process file changes. > > > > > Signed-off-by: William Roberts <[email protected]> > > --- > > libselinux/src/label.c | 8 ++-- > > libselinux/src/label_android_property.c | 44 +++++++++---------- > > libselinux/src/label_db.c | 7 +-- > > libselinux/src/label_file.c | 63 ++++++++++++++------------ > > libselinux/src/label_file.h | 78 +++++++++++++++++++-------------- > > libselinux/src/label_internal.h | 22 +++++++++- > > libselinux/src/label_media.c | 5 ++- > > libselinux/src/label_support.c | 32 ++++++++------ > > libselinux/src/label_x.c | 5 ++- > > libselinux/src/matchpathcon.c | 2 +- > > 10 files changed, 159 insertions(+), 107 deletions(-) > > > > diff --git a/libselinux/src/label.c b/libselinux/src/label.c > > index 963bfcb..11324ea 100644 > > --- a/libselinux/src/label.c > > +++ b/libselinux/src/label.c > > @@ -209,7 +209,7 @@ int selabel_validate(struct selabel_handle *rec, > > if (!rec->validating || contexts->validated) > > goto out; > > > > - rc = selinux_validate(&contexts->ctx_raw); > > + rc = selinux_validate(&contexts->ctx_raw.str); > > if (rc < 0) > > goto out; > > > > @@ -248,7 +248,7 @@ static int selabel_fini(struct selabel_handle *rec, > > return -1; > > > > if (translating && !lr->ctx_trans && > > - selinux_raw_to_trans_context(lr->ctx_raw, &lr->ctx_trans)) > > + selinux_raw_to_trans_context(lr->ctx_raw.str, &lr->ctx_trans)) > > return -1; > > > > return 0; > > @@ -369,7 +369,7 @@ int selabel_lookup_raw(struct selabel_handle *rec, char **con, > > if (!lr) > > return -1; > > > > - *con = strdup(lr->ctx_raw); > > + *con = strdup(lr->ctx_raw.str); > > return *con ? 0 : -1; > > } > > > > @@ -429,7 +429,7 @@ int selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con, > > if (!lr) > > return -1; > > > > - *con = strdup(lr->ctx_raw); > > + *con = strdup(lr->ctx_raw.str); > > return *con ? 0 : -1; > > } > > > > diff --git a/libselinux/src/label_android_property.c b/libselinux/src/label_android_property.c > > index 290b438..af0b9a8 100644 > > --- a/libselinux/src/label_android_property.c > > +++ b/libselinux/src/label_android_property.c > > @@ -16,7 +16,7 @@ > > /* A property security context specification. */ > > typedef struct spec { > > struct selabel_lookup_rec lr; /* holds contexts for lookup result */ > > - char *property_key; /* property key string */ > > + struct len_str property_key; /* property key string */ > > } spec_t; > > > > /* Our stored configuration */ > > @@ -33,13 +33,13 @@ static int cmp(const void *A, const void *B) > > { > > const struct spec *sp1 = A, *sp2 = B; > > > > - if (strncmp(sp1->property_key, "*", 1) == 0) > > + if (strncmp(sp1->property_key.str, "*", 1) == 0) > > return 1; > > - if (strncmp(sp2->property_key, "*", 1) == 0) > > + if (strncmp(sp2->property_key.str, "*", 1) == 0) > > return -1; > > > > - size_t L1 = strlen(sp1->property_key); > > - size_t L2 = strlen(sp2->property_key); > > + size_t L1 = sp1->property_key.len; > > + size_t L2 = sp2->property_key.len; > > > > return (L1 < L2) - (L1 > L2); > > } > > @@ -56,23 +56,23 @@ static int nodups_specs(struct saved_data *data, const char *path) > > for (ii = 0; ii < data->nspec; ii++) { > > curr_spec = &spec_arr[ii]; > > for (jj = ii + 1; jj < data->nspec; jj++) { > > - if (!strcmp(spec_arr[jj].property_key, > > - curr_spec->property_key)) { > > + if (len_str_eq(&spec_arr[jj].property_key, > > + &curr_spec->property_key)) { > > rc = -1; > > errno = EINVAL; > > - if (strcmp(spec_arr[jj].lr.ctx_raw, > > - curr_spec->lr.ctx_raw)) { > > + if (!len_str_eq(&spec_arr[jj].lr.ctx_raw, > > + &curr_spec->lr.ctx_raw)) { > > selinux_log > > (SELINUX_ERROR, > > "%s: Multiple different specifications for %s (%s and %s).\n", > > - path, curr_spec->property_key, > > - spec_arr[jj].lr.ctx_raw, > > - curr_spec->lr.ctx_raw); > > + path, curr_spec->property_key.str, > > + spec_arr[jj].lr.ctx_raw.str, > > + curr_spec->lr.ctx_raw.str); > > } else { > > selinux_log > > (SELINUX_ERROR, > > "%s: Multiple same specifications for %s.\n", > > - path, curr_spec->property_key); > > + path, curr_spec->property_key.str); > > } > > } > > } > > @@ -85,7 +85,7 @@ static int process_line(struct selabel_handle *rec, > > int pass, unsigned lineno) > > { > > int items; > > - char *prop = NULL, *context = NULL; > > + struct len_str *prop = { 0 }, *context = { 0 }; > > struct saved_data *data = (struct saved_data *)rec->data; > > spec_t *spec_arr = data->spec_arr; > > unsigned int nspec = data->nspec; > > @@ -118,14 +118,14 @@ static int process_line(struct selabel_handle *rec, > > free(context); > > } else if (pass == 1) { > > /* On the second pass, process and store the specification in spec. */ > > - spec_arr[nspec].property_key = prop; > > - spec_arr[nspec].lr.ctx_raw = context; > > + memcpy(&spec_arr[nspec].property_key, prop, sizeof(*prop)); > > + memcpy(&spec_arr[nspec].lr.ctx_raw, context, sizeof(*context)); > > > > if (rec->validating) { > > if (selabel_validate(rec, &spec_arr[nspec].lr) < 0) { > > selinux_log(SELINUX_ERROR, > > "%s: line %u has invalid context %s\n", > > - path, lineno, spec_arr[nspec].lr.ctx_raw); > > + path, lineno, spec_arr[nspec].lr.ctx_raw.str); > > errno = EINVAL; > > return -1; > > } > > @@ -233,8 +233,8 @@ static void closef(struct selabel_handle *rec) > > > > for (i = 0; i < data->nspec; i++) { > > spec = &data->spec_arr[i]; > > - free(spec->property_key); > > - free(spec->lr.ctx_raw); > > + free(spec->property_key.str); > > + free(spec->lr.ctx_raw.str); > > free(spec->lr.ctx_trans); > > } > > > > @@ -259,11 +259,11 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec, > > } > > > > for (i = 0; i < data->nspec; i++) { > > - if (strncmp(spec_arr[i].property_key, key, > > - strlen(spec_arr[i].property_key)) == 0) { > > + if (strncmp(spec_arr[i].property_key.str, key, > > + spec_arr[i].property_key.len) == 0) { > > break; > > } > > - if (strncmp(spec_arr[i].property_key, "*", 1) == 0) > > + if (strncmp(spec_arr[i].property_key.str, "*", 1) == 0) > > break; > > } > > > > diff --git a/libselinux/src/label_db.c b/libselinux/src/label_db.c > > index 1155bcc..c700aca 100644 > > --- a/libselinux/src/label_db.c > > +++ b/libselinux/src/label_db.c > > @@ -153,7 +153,8 @@ process_line(const char *path, char *line_buf, unsigned int line_num, > > > > free(type); > > spec->key = key; > > - spec->lr.ctx_raw = context; > > + spec->lr.ctx_raw.str = context; > > + spec->lr.ctx_raw.len = strlen(context); > > > > catalog->nspec++; > > > > @@ -181,7 +182,7 @@ db_close(struct selabel_handle *rec) > > for (i = 0; i < catalog->nspec; i++) { > > spec = &catalog->specs[i]; > > free(spec->key); > > - free(spec->lr.ctx_raw); > > + free(spec->lr.ctx_raw.str); > > free(spec->lr.ctx_trans); > > } > > free(catalog); > > @@ -333,7 +334,7 @@ out_error: > > spec_t *spec = &catalog->specs[i]; > > > > free(spec->key); > > - free(spec->lr.ctx_raw); > > + free(spec->lr.ctx_raw.str); > > free(spec->lr.ctx_trans); > > } > > free(catalog); > > diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c > > index 68c566b..ade07d8 100644 > > --- a/libselinux/src/label_file.c > > +++ b/libselinux/src/label_file.c > > @@ -71,25 +71,24 @@ static int nodups_specs(struct saved_data *data, const char *path) > > for (ii = 0; ii < data->nspec; ii++) { > > curr_spec = &spec_arr[ii]; > > for (jj = ii + 1; jj < data->nspec; jj++) { > > - if ((!strcmp(spec_arr[jj].regex_str, > > - curr_spec->regex_str)) > > + if (len_str_eq(&spec_arr[jj].regex_str, &curr_spec->regex_str) > > && (!spec_arr[jj].mode || !curr_spec->mode > > || spec_arr[jj].mode == curr_spec->mode)) { > > rc = -1; > > errno = EINVAL; > > - if (strcmp(spec_arr[jj].lr.ctx_raw, > > - curr_spec->lr.ctx_raw)) { > > + if (!len_str_eq(&spec_arr[jj].lr.ctx_raw, > > + &curr_spec->lr.ctx_raw)) { > > COMPAT_LOG > > (SELINUX_ERROR, > > "%s: Multiple different specifications for %s (%s and %s).\n", > > - path, curr_spec->regex_str, > > - spec_arr[jj].lr.ctx_raw, > > - curr_spec->lr.ctx_raw); > > + path, curr_spec->regex_str.str, > > + spec_arr[jj].lr.ctx_raw.str, > > + curr_spec->lr.ctx_raw.str); > > } else { > > COMPAT_LOG > > (SELINUX_ERROR, > > "%s: Multiple same specifications for %s.\n", > > - path, curr_spec->regex_str); > > + path, curr_spec->regex_str.str); > > } > > } > > } > > @@ -475,12 +474,13 @@ static int read_binary_file(struct selabel_handle *rec) > > goto out; > > } > > > > - spec->lr.ctx_raw = str_buf; > > + spec->lr.ctx_raw.str = str_buf; > > + spec->lr.ctx_raw.len = entry_len -1; > > > > - if (strcmp(spec->lr.ctx_raw, "<<none>>") && rec->validating) { > > + if (rec->validating && strcmp(spec->lr.ctx_raw.str, "<<none>>")) { > > if (selabel_validate(rec, &spec->lr) < 0) { > > selinux_log(SELINUX_ERROR, "%s: context %s is invalid\n", > > - data->path, spec->lr.ctx_raw); > > + data->path, spec->lr.ctx_raw.str); > > errno = EINVAL; > > free(str_buf); > > goto out; > > @@ -492,14 +492,16 @@ static int read_binary_file(struct selabel_handle *rec) > > if (err < 0 || !entry_len) > > goto out; > > > > - spec->regex_str = (char *) map_area->next_addr; > > + spec->regex_str.str = (char *) map_area->next_addr; > > err = next_entry(NULL, map_area, entry_len); > > if (err < 0) > > goto out; > > > > - if (spec->regex_str[entry_len - 1] != '\0') > > + if (spec->regex_str.str[entry_len - 1] != '\0') > > goto out; > > > > + spec->regex_str.len = entry_len - 1; > > + > > /* Process mode */ > > if (version >= SELINUX_COMPILED_FCONTEXT_MODE) > > err = next_entry(&mode, map_area, sizeof(mode)); > > @@ -715,11 +717,13 @@ static void closef(struct selabel_handle *rec) > > for (i = 0; i < data->nspec; i++) { > > spec = &data->spec_arr[i]; > > free(spec->lr.ctx_trans); > > - free(spec->lr.ctx_raw); > > + free(spec->lr.ctx_raw.str); > > if (spec->from_mmap) > > continue; > > - free(spec->regex_str); > > - free(spec->type_str); > > + > > + free(spec->regex_str.str); > > + free(spec->type_str.str); > > + > > if (spec->regcomp) { > > pcre_free(spec->regex); > > pcre_free_study(spec->sd); > > @@ -767,6 +771,11 @@ static struct spec *lookup_common(struct selabel_handle *rec, > > const char *prev_slash, *next_slash; > > unsigned int sofar = 0; > > > > + struct len_str none = { > > + .str = (char *)"<<none>>", > > + .len = 8 > > + }; > > + > > if (!data->nspec) { > > errno = ENOENT; > > goto finish; > > @@ -834,7 +843,7 @@ static struct spec *lookup_common(struct selabel_handle *rec, > > } > > } > > > > - if (i < 0 || strcmp(spec_arr[i].lr.ctx_raw, "<<none>>") == 0) { > > + if (i < 0 || len_str_eq(&spec_arr[i].lr.ctx_raw, &none)) { > > /* No matching specification. */ > > errno = ENOENT; > > goto finish; > > @@ -926,8 +935,8 @@ static enum selabel_cmp_result incomp(struct spec *spec1, struct spec *spec2, co > > selinux_log(SELINUX_INFO, > > "selabel_cmp: mismatched %s on entry %d: (%s, %x, %s) vs entry %d: (%s, %x, %s)\n", > > reason, > > - i, spec1->regex_str, spec1->mode, spec1->lr.ctx_raw, > > - j, spec2->regex_str, spec2->mode, spec2->lr.ctx_raw); > > + i, spec1->regex_str.str, spec1->mode, spec1->lr.ctx_raw.str, > > + j, spec2->regex_str.str, spec2->mode, spec2->lr.ctx_raw.str); > > return SELABEL_INCOMPARABLE; > > } > > > > @@ -976,7 +985,7 @@ static enum selabel_cmp_result cmp(struct selabel_handle *h1, > > memcmp(spec1->regex, spec2->regex, len1)) > > return incomp(spec1, spec2, "regex", i, j); > > } else { > > - if (strcmp(spec1->regex_str, spec2->regex_str)) > > + if (strcmp(spec1->regex_str.str, spec2->regex_str.str)) > > return incomp(spec1, spec2, "regex_str", i, j); > > } > > > > @@ -995,7 +1004,7 @@ static enum selabel_cmp_result cmp(struct selabel_handle *h1, > > return incomp(spec1, spec2, "stem", i, j); > > } > > > > - if (strcmp(spec1->lr.ctx_raw, spec2->lr.ctx_raw)) > > + if (!len_str_eq(&spec1->lr.ctx_raw, &spec2->lr.ctx_raw)) > > return incomp(spec1, spec2, "ctx_raw", i, j); > > > > i++; > > @@ -1020,17 +1029,17 @@ static void stats(struct selabel_handle *rec) > > > > for (i = 0; i < nspec; i++) { > > if (spec_arr[i].matches == 0) { > > - if (spec_arr[i].type_str) { > > + if (spec_arr[i].type_str.str) { > > COMPAT_LOG(SELINUX_WARNING, > > "Warning! No matches for (%s, %s, %s)\n", > > - spec_arr[i].regex_str, > > - spec_arr[i].type_str, > > - spec_arr[i].lr.ctx_raw); > > + spec_arr[i].regex_str.str, > > + spec_arr[i].type_str.str, > > + spec_arr[i].lr.ctx_raw.str); > > } else { > > COMPAT_LOG(SELINUX_WARNING, > > "Warning! No matches for (%s, %s)\n", > > - spec_arr[i].regex_str, > > - spec_arr[i].lr.ctx_raw); > > + spec_arr[i].regex_str.str, > > + spec_arr[i].lr.ctx_raw.str); > > } > > } > > } > > diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h > > index da06164..cd021f4 100644 > > --- a/libselinux/src/label_file.h > > +++ b/libselinux/src/label_file.h > > @@ -26,10 +26,10 @@ > > > > /* 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 */ > > - pcre *regex; /* compiled regular expression */ > > + struct selabel_lookup_rec lr; /* holds contexts for lookup result */ > > + struct len_str regex_str; /* regular expession string for diagnostics */ > > + struct len_str type_str; /* type string for diagnostic messages */ > > + pcre *regex; /* compiled regular expression */ > > union { > > pcre_extra *sd; /* pointer to extra compiled stuff */ > > pcre_extra lsd; /* used to hold the mmap'd version */ > > @@ -90,16 +90,19 @@ static inline pcre_extra *get_pcre_extra(struct spec *spec) > > return spec->sd; > > } > > > > -static inline mode_t string_to_mode(char *mode) > > +static inline mode_t string_to_mode(struct len_str *mode) > > { > > size_t len; > > > > if (!mode) > > return 0; > > - len = strlen(mode); > > - if (mode[0] != '-' || len != 2) > > + > > + len = mode->len; > > + > > + if (mode->str[0] != '-' || len != 2) > > return -1; > > - switch (mode[1]) { > > + > > + switch (mode->str[1]) { > > case 'b': > > return S_IFBLK; > > case 'c': > > @@ -153,8 +156,8 @@ static inline void spec_hasMetaChars(struct spec *spec) > > int len; > > char *end; > > > > - c = spec->regex_str; > > - len = strlen(spec->regex_str); > > + c = spec->regex_str.str; > > + len = spec->regex_str.len; > > end = c + len; > > > > spec->hasMetaChars = 0; > > @@ -175,7 +178,7 @@ static inline void spec_hasMetaChars(struct spec *spec) > > case '(': > > case '{': > > spec->hasMetaChars = 1; > > - spec->prefix_len = c - spec->regex_str; > > + spec->prefix_len = c - spec->regex_str.str; > > return; > > case '\\': /* skip the next character */ > > c++; > > @@ -327,13 +330,16 @@ static inline int compile_regex(struct saved_data *data, struct spec *spec, > > if (spec->regcomp) > > return 0; /* already done */ > > > > + len = spec->regex_str.len; > > + reg_buf = spec->regex_str.str; > > + > > /* Skip the fixed stem. */ > > - reg_buf = spec->regex_str; > > - if (spec->stem_id >= 0) > > + if (spec->stem_id >= 0) { > > reg_buf += stem_arr[spec->stem_id].len; > > + len -= stem_arr[spec->stem_id].len; > > + } > > > > /* Anchor the regular expression. */ > > - len = strlen(reg_buf); > > cp = anchored_regex = malloc(len + 3); > > if (!anchored_regex) > > return -1; > > @@ -375,7 +381,15 @@ static inline int process_line(struct selabel_handle *rec, > > char *line_buf, unsigned lineno) > > { > > int items, len, rc; > > - char *regex = NULL, *type = NULL, *context = NULL; > > + > > + struct len_str regex = { 0 } , type = { 0 }, context = { 0 }; > > + > > + /* XXX Export this as a const */ > > + struct len_str none = { > > + .str = (char *)"<<none>>", > > + .len = 8 > > + }; > > + > > struct saved_data *data = (struct saved_data *)rec->data; > > struct spec *spec_arr; > > unsigned int nspec = data->nspec; > > @@ -399,21 +413,21 @@ static inline int process_line(struct selabel_handle *rec, > > "%s: line %u is missing fields\n", path, > > lineno); > > if (items == 1) > > - free(regex); > > + free(regex.str); > > errno = EINVAL; > > return -1; > > } else if (items == 2) { > > /* The type field is optional. */ > > context = type; > > - type = 0; > > + memset(&type, 0, sizeof(type)); > > } > > > > - len = get_stem_from_spec(regex); > > - if (len && prefix && strncmp(prefix, regex, len)) { > > + len = get_stem_from_spec(regex.str); > > + if (len && prefix && strncmp(prefix, regex.str, len)) { > > /* Stem of regex does not match requested prefix, discard. */ > > - free(regex); > > - free(type); > > - free(context); > > + free(regex.str); > > + free(type.str); > > + free(context.str); > > return 0; > > } > > > > @@ -424,13 +438,13 @@ static inline int process_line(struct selabel_handle *rec, > > spec_arr = data->spec_arr; > > > > /* process and store the specification in spec. */ > > - spec_arr[nspec].stem_id = find_stem_from_spec(data, regex); > > - spec_arr[nspec].regex_str = regex; > > - > > - spec_arr[nspec].type_str = type; > > + spec_arr[nspec].stem_id = find_stem_from_spec(data, regex.str); > > + memcpy(&spec_arr[nspec].regex_str, ®ex, sizeof(regex)); > > + memcpy(&spec_arr[nspec].lr.ctx_raw, &context, sizeof(context)); > > spec_arr[nspec].mode = 0; > > > > - spec_arr[nspec].lr.ctx_raw = context; > > + if (type.str) > > + memcpy(&spec_arr[nspec].type_str, &type, sizeof(type)); > > > > /* > > * bump data->nspecs to cause closef() to cover it in its free > > @@ -442,19 +456,19 @@ static inline int process_line(struct selabel_handle *rec, > > compile_regex(data, &spec_arr[nspec], &errbuf)) { > > COMPAT_LOG(SELINUX_ERROR, > > "%s: line %u has invalid regex %s: %s\n", > > - path, lineno, regex, > > + path, lineno, regex.str, > > (errbuf ? errbuf : "out of memory")); > > errno = EINVAL; > > return -1; > > } > > > > - if (type) { > > - mode_t mode = string_to_mode(type); > > + if (type.str) { > > + mode_t mode = string_to_mode(&type); > > > > if (mode == (mode_t)-1) { > > COMPAT_LOG(SELINUX_ERROR, > > "%s: line %u has invalid file type %s\n", > > - path, lineno, type); > > + path, lineno, type.str); > > errno = EINVAL; > > return -1; > > } > > @@ -465,7 +479,7 @@ static inline int process_line(struct selabel_handle *rec, > > * any meta characters in the RE */ > > spec_hasMetaChars(&spec_arr[nspec]); > > > > - if (strcmp(context, "<<none>>") && rec->validating) > > + if (rec->validating && !len_str_eq(&context, &none)) > > compat_validate(rec, &spec_arr[nspec].lr, path, lineno); > > > > return 0; > > diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h > > index aa48fff..51aa33d 100644 > > --- a/libselinux/src/label_internal.h > > +++ b/libselinux/src/label_internal.h > > @@ -71,8 +71,28 @@ extern struct selabel_sub *selabel_subs_init(const char *path, > > struct selabel_sub *list, > > struct selabel_digest *digest); > > > > +/* > > + * A simple struct for tracking string lengths > > + * with strings. > > + */ > > +struct len_str { > > + size_t len; > > + char *str; > > +}; > > + > > +static inline bool len_str_eq(struct len_str *a, struct len_str *b) > > +{ > > + if (a->len != b->len) > > + return false; > > + > > + if (a->str == b->str) > > + return true; > > + > > + return !strcmp(a->str, b->str); > > +} > > + > > struct selabel_lookup_rec { > > - char * ctx_raw; > > + struct len_str ctx_raw; > > char * ctx_trans; > > int validated; > > }; > > diff --git a/libselinux/src/label_media.c b/libselinux/src/label_media.c > > index 622741b..e85e973 100644 > > --- a/libselinux/src/label_media.c > > +++ b/libselinux/src/label_media.c > > @@ -56,7 +56,8 @@ static int process_line(const char *path, char *line_buf, int pass, > > > > if (pass == 1) { > > data->spec_arr[data->nspec].key = key; > > - data->spec_arr[data->nspec].lr.ctx_raw = context; > > + data->spec_arr[data->nspec].lr.ctx_raw.str = context; > > + data->spec_arr[data->nspec].lr.ctx_raw.len = strlen(context); > > } > > > > data->nspec++; > > @@ -159,7 +160,7 @@ static void close(struct selabel_handle *rec) > > for (i = 0; i < data->nspec; i++) { > > spec = &spec_arr[i]; > > free(spec->key); > > - free(spec->lr.ctx_raw); > > + free(spec->lr.ctx_raw.str); > > free(spec->lr.ctx_trans); > > } > > > > diff --git a/libselinux/src/label_support.c b/libselinux/src/label_support.c > > index 26f9ef1..e9b842f 100644 > > --- a/libselinux/src/label_support.c > > +++ b/libselinux/src/label_support.c > > @@ -22,16 +22,17 @@ > > * errno will be set. > > * > > */ > > -static inline int read_spec_entry(char **entry, char **ptr, int *len, const char **errbuf) > > +static inline int read_spec_entry(struct len_str *entry, char **ptr, const char **errbuf) > > { > > - *entry = NULL; > > + size_t len = 0; > > char *tmp_buf = NULL; > > > > + memset(entry, 0, sizeof(*entry)); > > + > > while (isspace(**ptr) && **ptr != '\0') > > (*ptr)++; > > > > tmp_buf = *ptr; > > - *len = 0; > > > > while (!isspace(**ptr) && **ptr != '\0') { > > if (!isascii(**ptr)) { > > @@ -40,13 +41,15 @@ static inline int read_spec_entry(char **entry, char **ptr, int *len, const char > > return -1; > > } > > (*ptr)++; > > - (*len)++; > > + len++; > > } > > > > - if (*len) { > > - *entry = strndup(tmp_buf, *len); > > - if (!*entry) > > + if (len) { > > + entry->str = strndup(tmp_buf, len); > > + if (!entry->str) > > return -1; > > + > > + entry->len = len; > > } > > > > return 0; > > @@ -56,7 +59,7 @@ static inline int read_spec_entry(char **entry, char **ptr, int *len, const char > > * line_buf - Buffer containing the spec entries . > > * errbuf - Double pointer used for passing back specific error messages. > > * num_args - The number of spec parameter entries to process. > > - * ... - A 'char **spec_entry' for each parameter. > > + * ... - A 'struct len_str **spec_entry' for each parameter. > > * returns - The number of items processed. On error, it returns -1 with errno > > * set and may set errbuf to a specific error message. > > * > > @@ -65,8 +68,9 @@ static inline int read_spec_entry(char **entry, char **ptr, int *len, const char > > */ > > int hidden read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...) > > { > > - char **spec_entry, *buf_p; > > - int len, rc, items, entry_len = 0; > > + struct len_str *spec_entry; > > + char *buf_p; > > + int len, rc, items; > > va_list ap; > > > > *errbuf = NULL; > > @@ -93,20 +97,22 @@ int hidden read_spec_entries(char *line_buf, const char **errbuf, int num_args, > > > > items = 0; > > while (items < num_args) { > > - spec_entry = va_arg(ap, char **); > > + spec_entry = va_arg(ap, struct len_str *); > > > > if (len - 1 == buf_p - line_buf) { > > va_end(ap); > > return items; > > } > > > > - rc = read_spec_entry(spec_entry, &buf_p, &entry_len, errbuf); > > + rc = read_spec_entry(spec_entry, &buf_p, errbuf); > > if (rc < 0) { > > va_end(ap); > > return rc; > > } > > - if (entry_len) > > + > > + if (spec_entry->len) { > > items++; > > + } > > } > > va_end(ap); > > return items; > > diff --git a/libselinux/src/label_x.c b/libselinux/src/label_x.c > > index 700def1..cdbac8c 100644 > > --- a/libselinux/src/label_x.c > > +++ b/libselinux/src/label_x.c > > @@ -81,7 +81,8 @@ static int process_line(const char *path, char *line_buf, int pass, > > return 0; > > } > > data->spec_arr[data->nspec].key = key; > > - data->spec_arr[data->nspec].lr.ctx_raw = context; > > + data->spec_arr[data->nspec].lr.ctx_raw.str = context; > > + data->spec_arr[data->nspec].lr.ctx_raw.len = strlen(context); > > free(type); > > } > > > > @@ -186,7 +187,7 @@ static void close(struct selabel_handle *rec) > > for (i = 0; i < data->nspec; i++) { > > spec = &spec_arr[i]; > > free(spec->key); > > - free(spec->lr.ctx_raw); > > + free(spec->lr.ctx_raw.str); > > free(spec->lr.ctx_trans); > > } > > > > diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c > > index 4764ab7..96c39b4 100644 > > --- a/libselinux/src/matchpathcon.c > > +++ b/libselinux/src/matchpathcon.c > > @@ -541,7 +541,7 @@ int compat_validate(struct selabel_handle *rec, > > const char *path, unsigned lineno) > > { > > int rc; > > - char **ctx = &contexts->ctx_raw; > > + char **ctx = &contexts->ctx_raw.str; > > > > if (myinvalidcon) > > rc = myinvalidcon(path, lineno, *ctx); > > > > _______________________________________________ > Seandroid-list mailing list > [email protected] > To unsubscribe, send email to [email protected]. > To get help, send an email containing "help" to [email protected].
_______________________________________________ Seandroid-list mailing list [email protected] To unsubscribe, send email to [email protected]. To get help, send an email containing "help" to [email protected].
