On Sep 6, 2016 11:58, "Stephen Smalley" <sds@xxxxxxxxxxxxx> wrote:
>
> On 08/29/2016 12:22 PM, william.c.roberts@xxxxxxxxx wrote:
> > From: William Roberts <william.c.roberts@xxxxxxxxx>
> >
> > 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 <william.c.roberts@xxxxxxxxx>
> > ---
> > 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 = "" 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 = "" 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
> Seandroid-list@xxxxxxxxxxxxx
> To unsubscribe, send email to Seandroid-list-leave@xxxxxxxxxxxxx.
> To get help, send an email containing "help" to Seandroid-list-request@xxxxxxxxxxxxx.
_______________________________________________ Selinux mailing list Selinux@xxxxxxxxxxxxx To unsubscribe, send email to Selinux-leave@xxxxxxxxxxxxx. To get help, send an email containing "help" to Selinux-request@xxxxxxxxxxxxx.