> -----Original Message-----
> From: Stephen Smalley [mailto:s...@tycho.nsa.gov]
> Sent: Tuesday, September 20, 2016 6:18 AM
> To: Roberts, William C <william.c.robe...@intel.com>; seli...@tycho.nsa.gov;
> seandroid-list@tycho.nsa.gov; jda...@google.com
> Subject: Re: [RFC] mmap file_contexts and property_contexts:
> 
> On 09/19/2016 05:51 PM, Roberts, William C wrote:
> > FYI I only tested this with checkfc...
> 
> Evidently.  matchpathcon and sefcontext_compile both report calls to
> free() on invalid pointers and abort.

That doesn’t surprise me, I only tested the checkfc usages. Hence #4 in todo's

> 
> >
> >> -----Original Message-----
> >> From: Roberts, William C
> >> Sent: Monday, September 19, 2016 2:45 PM
> >> To: seli...@tycho.nsa.gov; seandroid-list@tycho.nsa.gov;
> >> s...@tycho.nsa.gov; jda...@google.com
> >> Cc: Roberts, William C <william.c.robe...@intel.com>
> >> Subject: [RFC] mmap file_contexts and property_contexts:
> >>
> >> From: William Roberts <william.c.robe...@intel.com>
> >>
> >> THIS IS WIP...
> >>
> >> Rather than using stdio and making copies, just mmap the files and
> >> use the pointers in place. The affect of this change, is that text
> >> file load time is now faster than binary load time by 4.7% when
> >> testing with a file_contexts file from the Android tree. Note that the 
> >> Android
> doesn't use monstrous regexs.
> >>
> >> Times are the average of 3 runs.
> >>
> >> BEFORE:
> >> Text file allocs: 114803
> >> Text file load time: 0.266101
> >> Bin file allocs: 93073
> >> Bin file load time: 0.248757667
> >>
> >> AFTER:
> >> Text file allocs: 103933
> >> Text file load time: 0.236192667
> >> Bin file allocs: 87645
> >> Bin file load time: .247607333
> >>
> >> THINGS TO DO:
> >> 1. What's arm performance like?
> >> 2. What interfaces to backends are busted by this (if any)?
> >> 3. Test Android Properties
> >> 4. Im pretty sure this breaks sefcontext_compile, fix.
> >> 5. Test with PCRE2 enabled.
> >> 6. Spell check this message!
> >> 7. Run checkpatch
> >>
> >> Signed-off-by: William Roberts <william.c.robe...@intel.com>
> >> ---
> >>  libselinux/src/label.c                  |   2 -
> >>  libselinux/src/label_android_property.c |  22 ++---
> >>  libselinux/src/label_file.c             | 140 
> >> +++++++++++++++++++-------------
> >>  libselinux/src/label_file.h             |  66 +++++++++------
> >>  libselinux/src/label_internal.h         |   3 +-
> >>  libselinux/src/label_support.c          |  79 ++++++++----------
> >>  6 files changed, 172 insertions(+), 140 deletions(-)
> >>
> >> diff --git a/libselinux/src/label.c b/libselinux/src/label.c index
> >> 963bfcb..d767b49
> >> 100644
> >> --- a/libselinux/src/label.c
> >> +++ b/libselinux/src/label.c
> >> @@ -15,8 +15,6 @@
> >>  #include "callbacks.h"
> >>  #include "label_internal.h"
> >>
> >> -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
> >> -
> >>  typedef int (*selabel_initfunc)(struct selabel_handle *rec,
> >>                            const struct selinux_opt *opts,
> >>                            unsigned nopts);
> >> diff --git a/libselinux/src/label_android_property.c
> >> b/libselinux/src/label_android_property.c
> >> index 290b438..2aac394 100644
> >> --- a/libselinux/src/label_android_property.c
> >> +++ b/libselinux/src/label_android_property.c
> >> @@ -85,13 +85,19 @@ static int process_line(struct selabel_handle *rec,
> >>                    int pass, unsigned lineno)
> >>  {
> >>    int items;
> >> -  char *prop = NULL, *context = NULL;
> >> +  union {
> >> +          struct {
> >> +                  char *prop;
> >> +                  char *context;
> >> +          };
> >> +          char *array[2];
> >> +  } found = { .array = { 0 } };
> >>    struct saved_data *data = (struct saved_data *)rec->data;
> >>    spec_t *spec_arr = data->spec_arr;
> >>    unsigned int nspec = data->nspec;
> >>    const char *errbuf = NULL;
> >>
> >> -  items = read_spec_entries(line_buf, &errbuf, 2, &prop, &context);
> >> +  items = read_spec_entries(line_buf, &errbuf,
> >> +ARRAY_SIZE(found.array), found.array);
> >>    if (items < 0) {
> >>            items = errno;
> >>            selinux_log(SELINUX_ERROR,
> >> @@ -108,18 +114,14 @@ static int process_line(struct selabel_handle *rec,
> >>            selinux_log(SELINUX_ERROR,
> >>                        "%s:  line %u is missing fields\n", path,
> >>                        lineno);
> >> -          free(prop);
> >>            errno = EINVAL;
> >>            return -1;
> >>    }
> >>
> >> -  if (pass == 0) {
> >> -          free(prop);
> >> -          free(context);
> >> -  } else if (pass == 1) {
> >> +  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;
> >> +          spec_arr[nspec].property_key = found.prop;
> >> +          spec_arr[nspec].lr.ctx_raw = found.context;
> >>
> >>            if (rec->validating) {
> >>                    if (selabel_validate(rec, &spec_arr[nspec].lr) < 0) { 
> >> @@ -
> >> 234,7 +236,7 @@ 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->lr.ctx_raw);
> >>            free(spec->lr.ctx_trans);
> >>    }
> >>
> >> diff --git a/libselinux/src/label_file.c
> >> b/libselinux/src/label_file.c index 7156825..4dc440e 100644
> >> --- a/libselinux/src/label_file.c
> >> +++ b/libselinux/src/label_file.c
> >> @@ -96,43 +96,64 @@ static int nodups_specs(struct saved_data *data,
> >> const char *path)
> >>    return rc;
> >>  }
> >>
> >> -static int process_text_file(FILE *fp, const char *prefix,
> >> -                       struct selabel_handle *rec, const char *path)
> >> +static inline struct saved_data *rec_to_data(struct selabel_handle
> >> +*rec) {
> >> +  return (struct saved_data *)rec->data; }
> >> +
> >> +static char *mmap_area_get_line(struct mmap_area *area) {
> >> +  size_t len = area->next_len;
> >> +  if (!len)
> >> +          return NULL;
> >> +
> >> +  char *start = area->next_addr;
> >> +  char *end = memchr(start, '\n', len);
> >> +
> >> +  /* the file may not end with a newline */
> >> +  if (!end)
> >> +          end = (char *)area->next_addr + len - 1;
> >> +
> >> +  *end = '\0';
> >> +  /* len includes null byte */
> >> +  len = end - start;
> >> +
> >> +  area->next_len -= len + 1;
> >> +  area->next_addr = ++end;
> >> +  return start;
> >> +}
> >> +
> >> +static int process_text_file(const char *path, const char *prefix,
> >> +          struct selabel_handle *rec)
> >>  {
> >>    int rc;
> >> -  size_t line_len;
> >>    unsigned int lineno = 0;
> >> -  char *line_buf = NULL;
> >> +  char *line_buf;
> >> +  struct mmap_area *areas = rec_to_data(rec)->mmap_areas;
> >> +
> >> +  /* mmap_area_get_line() and process_line() require mutable string
> >> pointers */
> >> +  rc = mprotect(areas->addr, areas->len, PROT_READ | PROT_WRITE);
> >> +  if (rc < 0)
> >> +          goto out;
> >>
> >> -  while (getline(&line_buf, &line_len, fp) > 0) {
> >> +  while ( (line_buf = mmap_area_get_line(areas)) ) {
> >>            rc = process_line(rec, path, prefix, line_buf, ++lineno);
> >>            if (rc)
> >>                    goto out;
> >>    }
> >>    rc = 0;
> >>  out:
> >> -  free(line_buf);
> >>    return rc;
> >>  }
> >>
> >> -static int load_mmap(FILE *fp, size_t len, struct selabel_handle *rec,
> >> -               const char *path)
> >> +static int mmap_file(FILE *fp, size_t len, struct saved_data *data)
> >>  {
> >> -  struct saved_data *data = (struct saved_data *)rec->data;
> >> -  int rc;
> >> -  char *addr, *str_buf;
> >> -  int *stem_map;
> >> -  struct mmap_area *mmap_area;
> >> -  uint32_t i, magic, version;
> >> -  uint32_t entry_len, stem_map_len, regex_array_len;
> >> -  const char *reg_version;
> >> -
> >> -  mmap_area = malloc(sizeof(*mmap_area));
> >> +  struct mmap_area *mmap_area = malloc(sizeof(*mmap_area));
> >>    if (!mmap_area) {
> >>            return -1;
> >>    }
> >>
> >> -  addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fileno(fp), 0);
> >> +  void *addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fileno(fp),
> >> +0);
> >>    if (addr == MAP_FAILED) {
> >>            free(mmap_area);
> >>            perror("mmap");
> >> @@ -145,17 +166,26 @@ static int load_mmap(FILE *fp, size_t len,
> >> struct selabel_handle *rec,
> >>    mmap_area->next = data->mmap_areas;
> >>    data->mmap_areas = mmap_area;
> >>
> >> -  /* check if this looks like an fcontext file */
> >> -  rc = next_entry(&magic, mmap_area, sizeof(uint32_t));
> >> -  if (rc < 0 || magic != SELINUX_MAGIC_COMPILED_FCONTEXT)
> >> -          return -1;
> >> +  return 0;
> >> +}
> >> +
> >> +static int process_binary_file(const char *path, struct
> >> +selabel_handle
> >> +*rec) {
> >> +  struct saved_data *data = (struct saved_data *)rec->data;
> >> +  int rc;
> >> +  char *str_buf;
> >> +  int *stem_map;
> >> +  struct mmap_area *mmap_area = data->mmap_areas;
> >> +  uint32_t i, version;
> >> +  uint32_t entry_len, stem_map_len, regex_array_len;
> >> +  size_t len;
> >>
> >>    /* check if this version is higher than we understand */
> >>    rc = next_entry(&version, mmap_area, sizeof(uint32_t));
> >>    if (rc < 0 || version > SELINUX_COMPILED_FCONTEXT_MAX_VERS)
> >>            return -1;
> >>
> >> -  reg_version = regex_version();
> >> +  const char *reg_version = regex_version();
> >>    if (!reg_version)
> >>            return -1;
> >>
> >> @@ -235,12 +265,11 @@ static int load_mmap(FILE *fp, size_t len,
> >> struct selabel_handle *rec,
> >>            /* store the mapping between old and new */
> >>            newid = find_stem(data, buf, stem_len);
> >>            if (newid < 0) {
> >> -                  newid = store_stem(data, buf, stem_len);
> >> +                  newid = store_stem(data, buf, stem_len, true);
> >>                    if (newid < 0) {
> >>                            rc = newid;
> >>                            goto out;
> >>                    }
> >> -                  data->stem_arr[newid].from_mmap = 1;
> >>            }
> >>            stem_map[i] = newid;
> >>    }
> >> @@ -262,7 +291,6 @@ static int load_mmap(FILE *fp, size_t len, struct
> >> selabel_handle *rec,
> >>                    goto out;
> >>
> >>            spec = &data->spec_arr[data->nspec];
> >> -          spec->from_mmap = 1;
> >>
> >>            /* Process context */
> >>            rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t)); @@ -
> >> 271,22 +299,10 @@ static int load_mmap(FILE *fp, size_t len, struct
> >> selabel_handle *rec,
> >>                    goto out;
> >>            }
> >>
> >> -          str_buf = malloc(entry_len);
> >> -          if (!str_buf) {
> >> -                  rc = -1;
> >> -                  goto out;
> >> -          }
> >> -          rc = next_entry(str_buf, mmap_area, entry_len);
> >> +          rc = next_pstr(&spec->lr.ctx_raw, mmap_area, entry_len);
> >>            if (rc < 0)
> >>                    goto out;
> >>
> >> -          if (str_buf[entry_len - 1] != '\0') {
> >> -                  free(str_buf);
> >> -                  rc = -1;
> >> -                  goto out;
> >> -          }
> >> -          spec->lr.ctx_raw = str_buf;
> >> -
> >>            if (strcmp(spec->lr.ctx_raw, "<<none>>") && rec->validating) {
> >>                    if (selabel_validate(rec, &spec->lr) < 0) {
> >>                            selinux_log(SELINUX_ERROR,
> >> @@ -401,17 +417,29 @@ static char *rolling_append(char *current,
> >> const char *suffix, size_t max)
> >>    return current;
> >>  }
> >>
> >> -static bool fcontext_is_binary(FILE *fp)
> >> +static inline int mmap_area_rewind(struct mmap_area *area, size_t
> >> +bytes) {
> >> +  if (area->next_len + bytes > area->len)
> >> +          return -1;
> >> +
> >> +  area->next_addr = (char *) area->next_addr - bytes;
> >> +  area->next_len += bytes;
> >> +  return 0;
> >> +}
> >> +
> >> +static bool fcontext_is_binary(struct mmap_area *area)
> >>  {
> >>    uint32_t magic;
> >> +  bool is_binary = false;
> >>
> >> -  size_t len = fread(&magic, sizeof(magic), 1, fp);
> >> -  rewind(fp);
> >> +  int rc = next_entry(&magic, area, sizeof(magic));
> >>
> >> -  return (len && (magic == SELINUX_MAGIC_COMPILED_FCONTEXT));
> >> -}
> >> +  is_binary = (!rc && (magic == SELINUX_MAGIC_COMPILED_FCONTEXT));
> >> +  if (!is_binary)
> >> +          mmap_area_rewind(area, sizeof(magic));
> >>
> >> -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
> >> +  return is_binary;
> >> +}
> >>
> >>  static FILE *open_file(const char *path, const char *suffix,
> >>           char *save_path, size_t len, struct stat *sb, bool
> >> open_oldest) @@ -
> >> 504,12 +532,17 @@ static int process_file(const char *path, const char 
> >> *suffix,
> >>            if (fp == NULL)
> >>                    return -1;
> >>
> >> -          rc = fcontext_is_binary(fp) ?
> >> -                          load_mmap(fp, sb.st_size, rec, found_path) :
> >> -                          process_text_file(fp, prefix, rec, found_path);
> >> +          rc = mmap_file(fp, sb.st_size, rec_to_data(rec));
> >> +          if (rc < 0) {
> >> +                  fclose(fp);
> >> +                  return -1;
> >> +          }
> >> +
> >> +          rc = fcontext_is_binary(rec_to_data(rec)->mmap_areas) ?
> >> +                          process_binary_file(found_path, rec) :
> >> +                          process_text_file(found_path, prefix, rec);
> >>            if (!rc)
> >> -                  rc = digest_add_specfile(digest, fp, NULL, sb.st_size,
> >> -                          found_path);
> >> +                  rc = digest_add_specfile(digest, fp, NULL, sb.st_size,
> >> found_path);
> >>
> >>            fclose(fp);
> >>
> >> @@ -613,12 +646,7 @@ 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);
> >>            regex_data_free(spec->regex);
> >> -          if (spec->from_mmap)
> >> -                  continue;
> >> -          free(spec->regex_str);
> >> -          free(spec->type_str);
> >>    }
> >>
> >>    for (i = 0; i < (unsigned int)data->num_stems; i++) { diff --git
> >> a/libselinux/src/label_file.h b/libselinux/src/label_file.h index
> >> 88f4294..2704906
> >> 100644
> >> --- a/libselinux/src/label_file.h
> >> +++ b/libselinux/src/label_file.h
> >> @@ -37,7 +37,6 @@ struct spec {
> >>    int matches;            /* number of matching pathnames */
> >>    int stem_id;            /* indicates which stem-compression item */
> >>    char hasMetaChars;      /* regular expression has meta-chars */
> >> -  char from_mmap;         /* this spec is from an mmap of the data
> >> */
> >>    size_t prefix_len;      /* length of fixed path prefix */
> >>  };
> >>
> >> @@ -255,7 +254,7 @@ static inline int find_stem(struct saved_data
> >> *data, const char *buf,  }
> >>
> >>  /* returns the index of the new stored object */ -static inline int
> >> store_stem(struct saved_data *data, char *buf, int stem_len)
> >> +static inline int store_stem(struct saved_data *data, char *buf, int
> >> +stem_len, bool from_mmap)
> >>  {
> >>    int num = data->num_stems;
> >>
> >> @@ -271,7 +270,7 @@ static inline int store_stem(struct saved_data
> >> *data, char *buf, int stem_len)
> >>    }
> >>    data->stem_arr[num].len = stem_len;
> >>    data->stem_arr[num].buf = buf;
> >> -  data->stem_arr[num].from_mmap = 0;
> >> +  data->stem_arr[num].from_mmap = from_mmap;
> >>    data->num_stems++;
> >>
> >>    return num;
> >> @@ -298,7 +297,7 @@ static inline int find_stem_from_spec(struct
> >> saved_data *data, const char *buf)
> >>    if (!stem)
> >>            return -1;
> >>
> >> -  return store_stem(data, stem, stem_len);
> >> +  return store_stem(data, stem, stem_len, false);
> >>  }
> >>
> >>  /* This will always check for buffer over-runs and either read the
> >> next entry @@
> >> -317,6 +316,22 @@ static inline int next_entry(void *buf, struct
> >> mmap_area *fp, size_t bytes)
> >>    return 0;
> >>  }
> >>
> >> +static inline int next_pstr(char **str, struct mmap_area *fp, size_t
> >> +len) {
> >> +  if (len > fp->next_len)
> >> +          return -1;
> >> +
> >> +  char *tmp = (char *)fp->next_addr;
> >> +  if (tmp[len-1] != '\0')
> >> +          return -1;
> >> +
> >> +  *str = tmp;
> >> +
> >> +  fp->next_addr = (char *)fp->next_addr + len;
> >> +  fp->next_len -= len;
> >> +  return 0;
> >> +}
> >> +
> >>  static inline int compile_regex(struct saved_data *data, struct spec 
> >> *spec,
> >>                                        const char **errbuf)
> >>  {
> >> @@ -375,13 +390,21 @@ 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;
> >> +  union {
> >> +          struct {
> >> +                  char *regex;
> >> +                  char *type;
> >> +                  char *context;
> >> +          };
> >> +          char *array[3];
> >> +  } found = { .array = { 0 } };
> >> +
> >>    struct saved_data *data = (struct saved_data *)rec->data;
> >>    struct spec *spec_arr;
> >>    unsigned int nspec = data->nspec;
> >>    const char *errbuf = NULL;
> >>
> >> -  items = read_spec_entries(line_buf, &errbuf, 3, &regex, &type,
> >> &context);
> >> +  items = read_spec_entries(line_buf, &errbuf,
> >> +ARRAY_SIZE(found.array), found.array);
> >>    if (items < 0) {
> >>            rc = errno;
> >>            selinux_log(SELINUX_ERROR,
> >> @@ -398,22 +421,17 @@ static inline int process_line(struct selabel_handle
> *rec,
> >>            COMPAT_LOG(SELINUX_ERROR,
> >>                        "%s:  line %u is missing fields\n", path,
> >>                        lineno);
> >> -          if (items == 1)
> >> -                  free(regex);
> >>            errno = EINVAL;
> >>            return -1;
> >>    } else if (items == 2) {
> >>            /* The type field is optional. */
> >> -          context = type;
> >> -          type = 0;
> >> +          found.context = found.type;
> >> +          found.type = NULL;
> >>    }
> >>
> >> -  len = get_stem_from_spec(regex);
> >> -  if (len && prefix && strncmp(prefix, regex, len)) {
> >> +  len = get_stem_from_spec(found.regex);
> >> +  if (len && prefix && strncmp(prefix, found.regex, len)) {
> >>            /* Stem of regex does not match requested prefix, discard. */
> >> -          free(regex);
> >> -          free(type);
> >> -          free(context);
> >>            return 0;
> >>    }
> >>
> >> @@ -424,13 +442,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].stem_id = find_stem_from_spec(data, found.regex);
> >> +  spec_arr[nspec].regex_str = found.regex;
> >>
> >> -  spec_arr[nspec].type_str = type;
> >> +  spec_arr[nspec].type_str = found.type;
> >>    spec_arr[nspec].mode = 0;
> >>
> >> -  spec_arr[nspec].lr.ctx_raw = context;
> >> +  spec_arr[nspec].lr.ctx_raw = found.context;
> >>
> >>    /*
> >>     * bump data->nspecs to cause closef() to cover it in its free @@
> >> -442,18
> >> +460,18 @@ 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, errbuf);
> >> +                     path, lineno, found.regex, errbuf);
> >>            errno = EINVAL;
> >>            return -1;
> >>    }
> >>
> >> -  if (type) {
> >> -          mode_t mode = string_to_mode(type);
> >> +  if (found.type) {
> >> +          mode_t mode = string_to_mode(found.type);
> >>
> >>            if (mode == (mode_t)-1) {
> >>                    COMPAT_LOG(SELINUX_ERROR,
> >>                               "%s:  line %u has invalid file type %s\n",
> >> -                             path, lineno, type);
> >> +                             path, lineno, found.type);
> >>                    errno = EINVAL;
> >>                    return -1;
> >>            }
> >> @@ -464,7 +482,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 (strcmp(found.context, "<<none>>") && rec->validating)
> >>            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..e40d68b 100644
> >> --- a/libselinux/src/label_internal.h
> >> +++ b/libselinux/src/label_internal.h
> >> @@ -136,10 +136,11 @@ compat_validate(struct selabel_handle *rec,
> >>            struct selabel_lookup_rec *contexts,
> >>            const char *path, unsigned lineno) hidden;
> >>
> >> +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
> >>  /*
> >>   * The read_spec_entries function may be used to
> >>   * replace sscanf to read entries from spec files.
> >>   */
> >> -extern int read_spec_entries(char *line_buf, const char **errbuf,
> >> int num_args, ...);
> >> +extern int hidden read_spec_entries(char *line_buf, const char
> >> +**errbuf, unsigned int num, char *found[]);
> >>
> >>  #endif                            /* _SELABEL_INTERNAL_H_ */
> >> diff --git a/libselinux/src/label_support.c
> >> b/libselinux/src/label_support.c index 26f9ef1..3f5728d 100644
> >> --- a/libselinux/src/label_support.c
> >> +++ b/libselinux/src/label_support.c
> >> @@ -17,39 +17,40 @@
> >>   * Read an entry from a spec file (e.g. file_contexts)
> >>   * entry - Buffer to allocate for the entry.
> >>   * ptr - current location of the line to be processed.
> >> - * returns  - 0 on success and *entry is set to be a null
> >> - *            terminated value. On Error it returns -1 and
> >> - *            errno will be set.
> >> + * returns  - a pointer to the begining of the string.
> >> + *            that is the
> >>   *
> >>   */
> >> -static inline int read_spec_entry(char **entry, char **ptr, int
> >> *len, const char
> >> **errbuf)
> >> +static inline char *read_spec_entry(char **current, const char
> >> +**errbuf)
> >>  {
> >> -  *entry = NULL;
> >> -  char *tmp_buf = NULL;
> >> -
> >> -  while (isspace(**ptr) && **ptr != '\0')
> >> -          (*ptr)++;
> >> +  if(!**current) {
> >> +          (*current)++;
> >> +          return NULL;
> >> +  }
> >>
> >> -  tmp_buf = *ptr;
> >> -  *len = 0;
> >> +  while (isspace(**current) && **current != '\0')
> >> +          (*current)++;
> >>
> >> -  while (!isspace(**ptr) && **ptr != '\0') {
> >> -          if (!isascii(**ptr)) {
> >> +  char *start = *current;
> >> +  while (!isspace(**current) && **current != '\0') {
> >> +          if (!isascii(**current)) {
> >>                    errno = EINVAL;
> >>                    *errbuf = "Non-ASCII characters found";
> >> -                  return -1;
> >> +                  return NULL;
> >>            }
> >> -          (*ptr)++;
> >> -          (*len)++;
> >> +          (*current)++;
> >>    }
> >>
> >> -  if (*len) {
> >> -          *entry = strndup(tmp_buf, *len);
> >> -          if (!*entry)
> >> -                  return -1;
> >> -  }
> >> +  char *end = *current;
> >>
> >> -  return 0;
> >> +  if (start == end)
> >> +          return NULL;
> >> +
> >> +  if (*end != '\0') {
> >> +          *end = '\0';
> >> +          (*current)++;
> >> +  }
> >> +  return start;
> >>  }
> >>
> >>  /*
> >> @@ -63,15 +64,13 @@ static inline int read_spec_entry(char **entry,
> >> char **ptr, int *len, const char
> >>   * This function calls read_spec_entry() to do the actual string 
> >> processing.
> >>   * As such, can return anything from that function as well.
> >>   */
> >> -int hidden read_spec_entries(char *line_buf, const char **errbuf,
> >> int num_args,
> >> ...)
> >> +int hidden read_spec_entries(char *line_buf, const char **errbuf,
> >> +unsigned int num, char *found[])
> >>  {
> >> -  char **spec_entry, *buf_p;
> >> -  int len, rc, items, entry_len = 0;
> >> -  va_list ap;
> >> -
> >> +  char*buf_p;
> >> +  unsigned int items = 0;
> >>    *errbuf = NULL;
> >>
> >> -  len = strlen(line_buf);
> >> +  size_t len = strlen(line_buf);
> >>    if (line_buf[len - 1] == '\n')
> >>            line_buf[len - 1] = '\0';
> >>    else
> >> @@ -89,26 +88,12 @@ int hidden read_spec_entries(char *line_buf,
> >> const char **errbuf, int num_args,
> >>            return 0;
> >>
> >>    /* Process the spec file entries */
> >> -  va_start(ap, num_args);
> >> -
> >> -  items = 0;
> >> -  while (items < num_args) {
> >> -          spec_entry = va_arg(ap, char **);
> >> -
> >> -          if (len - 1 == buf_p - line_buf) {
> >> -                  va_end(ap);
> >> -                  return items;
> >> -          }
> >> -
> >> -          rc = read_spec_entry(spec_entry, &buf_p, &entry_len, errbuf);
> >> -          if (rc < 0) {
> >> -                  va_end(ap);
> >> -                  return rc;
> >> -          }
> >> -          if (entry_len)
> >> -                  items++;
> >> +  while (items < num) {
> >> +          found[items] = read_spec_entry(&buf_p, errbuf);
> >> +          if (!found[items])
> >> +                  break;
> >> +          items++;
> >>    }
> >> -  va_end(ap);
> >>    return items;
> >>  }
> >>
> >> --
> >> 1.9.1
> >
> >


_______________________________________________
Seandroid-list mailing list
Seandroid-list@tycho.nsa.gov
To unsubscribe, send email to seandroid-list-le...@tycho.nsa.gov.
To get help, send an email containing "help" to 
seandroid-list-requ...@tycho.nsa.gov.

Reply via email to