Re: [PATCH] [RFC] nodups_specs: speedup

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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, &regex, 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.

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux