On 09/09/2016 01:44 PM, [email protected] wrote:
> From: William Roberts <[email protected]>
> 
> The current process_file() code will open the file
> twice on the case of a binary file, correct this.
> 
> The general flow through process_file() was a bit
> difficult to read, streamline the routine to be
> more readable.
> 
> Detailed statistics of before and after:
> 
> Source lines of code reported by cloc on modified files:
> before: 735
> after: 742
> 
> Object size difference:
> before: 195530 bytes
> after:  195485 bytes
> 
> Signed-off-by: William Roberts <[email protected]>

Thanks, applied, with some whitespace and other fixes on top
(scripts/checkpatch.pl from the kernel tree would have noted them).

> ---
>  libselinux/src/label_file.c | 310 
> ++++++++++++++++++++++++--------------------
>  1 file changed, 166 insertions(+), 144 deletions(-)
> 
> diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
> index c89bb35..94b7627 100644
> --- a/libselinux/src/label_file.c
> +++ b/libselinux/src/label_file.c
> @@ -97,62 +97,40 @@ static int nodups_specs(struct saved_data *data, const 
> char *path)
>       return rc;
>  }
>  
> -static int load_mmap(struct selabel_handle *rec, const char *path,
> -                                 struct stat *sb, bool isbinary,
> -                                 struct selabel_digest *digest)
> +static int process_text_file(FILE *fp, const char *prefix, struct 
> selabel_handle *rec, const char *path)
> +{
> +     int rc;
> +     size_t line_len;
> +     unsigned lineno = 0;
> +     char *line_buf = NULL;
> +
> +     while (getline(&line_buf, &line_len, fp) > 0) {
> +             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)
>  {
>       struct saved_data *data = (struct saved_data *)rec->data;
> -     char mmap_path[PATH_MAX + 1];
> -     int mmapfd;
>       int rc;
> -     struct stat mmap_stat;
>       char *addr, *str_buf;
> -     size_t len;
>       int *stem_map;
>       struct mmap_area *mmap_area;
>       uint32_t i, magic, version;
>       uint32_t entry_len, stem_map_len, regex_array_len;
>  
> -     if (isbinary) {
> -             len = strlen(path);
> -             if (len >= sizeof(mmap_path))
> -                     return -1;
> -             strcpy(mmap_path, path);
> -     } else {
> -             rc = snprintf(mmap_path, sizeof(mmap_path), "%s.bin", path);
> -             if (rc >= (int)sizeof(mmap_path))
> -                     return -1;
> -     }
> -
> -     mmapfd = open(mmap_path, O_RDONLY | O_CLOEXEC);
> -     if (mmapfd < 0)
> -             return -1;
> -
> -     rc = fstat(mmapfd, &mmap_stat);
> -     if (rc < 0) {
> -             close(mmapfd);
> -             return -1;
> -     }
> -
> -     /* if mmap is old, ignore it */
> -     if (mmap_stat.st_mtime < sb->st_mtime) {
> -             close(mmapfd);
> -             return -1;
> -     }
> -
> -     /* ok, read it in... */
> -     len = mmap_stat.st_size;
> -     len += (sysconf(_SC_PAGE_SIZE) - 1);
> -     len &= ~(sysconf(_SC_PAGE_SIZE) - 1);
> -
>       mmap_area = malloc(sizeof(*mmap_area));
>       if (!mmap_area) {
> -             close(mmapfd);
>               return -1;
>       }
>  
> -     addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, mmapfd, 0);
> -     close(mmapfd);
> +     addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fileno(fp), 0);
>       if (addr == MAP_FAILED) {
>               free(mmap_area);
>               perror("mmap");
> @@ -227,7 +205,7 @@ static int load_mmap(struct selabel_handle *rec, const 
> char *path,
>               rc = next_entry(&stem_len, mmap_area, sizeof(uint32_t));
>               if (rc < 0 || !stem_len) {
>                       rc = -1;
> -                     goto err;
> +                     goto out;
>               }
>  
>               /* Check for stem_len wrap around. */
> @@ -236,15 +214,15 @@ static int load_mmap(struct selabel_handle *rec, const 
> char *path,
>                       /* Check if over-run before null check. */
>                       rc = next_entry(NULL, mmap_area, (stem_len + 1));
>                       if (rc < 0)
> -                             goto err;
> +                             goto out;
>  
>                       if (buf[stem_len] != '\0') {
>                               rc = -1;
> -                             goto err;
> +                             goto out;
>                       }
>               } else {
>                       rc = -1;
> -                     goto err;
> +                     goto out;
>               }
>  
>               /* store the mapping between old and new */
> @@ -253,7 +231,7 @@ static int load_mmap(struct selabel_handle *rec, const 
> char *path,
>                       newid = store_stem(data, buf, stem_len);
>                       if (newid < 0) {
>                               rc = newid;
> -                             goto err;
> +                             goto out;
>                       }
>                       data->stem_arr[newid].from_mmap = 1;
>               }
> @@ -264,7 +242,7 @@ static int load_mmap(struct selabel_handle *rec, const 
> char *path,
>       rc = next_entry(&regex_array_len, mmap_area, sizeof(uint32_t));
>       if (rc < 0 || !regex_array_len) {
>               rc = -1;
> -             goto err;
> +             goto out;
>       }
>  
>       for (i = 0; i < regex_array_len; i++) {
> @@ -274,7 +252,7 @@ static int load_mmap(struct selabel_handle *rec, const 
> char *path,
>  
>               rc = grow_specs(data);
>               if (rc < 0)
> -                     goto err;
> +                     goto out;
>  
>               spec = &data->spec_arr[data->nspec];
>               spec->from_mmap = 1;
> @@ -284,30 +262,30 @@ static int load_mmap(struct selabel_handle *rec, const 
> char *path,
>               rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t));
>               if (rc < 0 || !entry_len) {
>                       rc = -1;
> -                     goto err;
> +                     goto out;
>               }
>  
>               str_buf = malloc(entry_len);
>               if (!str_buf) {
>                       rc = -1;
> -                     goto err;
> +                     goto out;
>               }
>               rc = next_entry(str_buf, mmap_area, entry_len);
>               if (rc < 0)
> -                     goto err;
> +                     goto out;
>  
>               if (str_buf[entry_len - 1] != '\0') {
>                       free(str_buf);
>                       rc = -1;
> -                     goto err;
> +                     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,
> -                                         "%s: context %s is invalid\n", 
> mmap_path, spec->lr.ctx_raw);
> -                             goto err;
> +                                         "%s: context %s is invalid\n", 
> path, spec->lr.ctx_raw);
> +                             goto out;
>                       }
>               }
>  
> @@ -315,17 +293,17 @@ static int load_mmap(struct selabel_handle *rec, const 
> char *path,
>               rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t));
>               if (rc < 0 || !entry_len) {
>                       rc = -1;
> -                     goto err;
> +                     goto out;
>               }
>  
>               spec->regex_str = (char *)mmap_area->next_addr;
>               rc = next_entry(NULL, mmap_area, entry_len);
>               if (rc < 0)
> -                     goto err;
> +                     goto out;
>  
>               if (spec->regex_str[entry_len - 1] != '\0') {
>                       rc = -1;
> -                     goto err;
> +                     goto out;
>               }
>  
>               /* Process mode */
> @@ -334,14 +312,14 @@ static int load_mmap(struct selabel_handle *rec, const 
> char *path,
>               else
>                       rc = next_entry(&mode, mmap_area, sizeof(mode_t));
>               if (rc < 0)
> -                     goto err;
> +                     goto out;
>  
>               spec->mode = mode;
>  
>               /* map the stem id from the mmap file to the data->stem_arr */
>               rc = next_entry(&stem_id, mmap_area, sizeof(int32_t));
>               if (rc < 0)
> -                     goto err;
> +                     goto out;
>  
>               if (stem_id < 0 || stem_id >= (int32_t)stem_map_len)
>                       spec->stem_id = -1;
> @@ -351,7 +329,7 @@ static int load_mmap(struct selabel_handle *rec, const 
> char *path,
>               /* retrieve the hasMetaChars bit */
>               rc = next_entry(&meta_chars, mmap_area, sizeof(uint32_t));
>               if (rc < 0)
> -                     goto err;
> +                     goto out;
>  
>               spec->hasMetaChars = meta_chars;
>               /* and prefix length for use by selabel_lookup_best_match */
> @@ -359,7 +337,7 @@ static int load_mmap(struct selabel_handle *rec, const 
> char *path,
>                       rc = next_entry(&prefix_len, mmap_area,
>                                           sizeof(uint32_t));
>                       if (rc < 0)
> -                             goto err;
> +                             goto out;
>  
>                       spec->prefix_len = prefix_len;
>               }
> @@ -368,25 +346,25 @@ static int load_mmap(struct selabel_handle *rec, const 
> char *path,
>               rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t));
>               if (rc < 0 || !entry_len) {
>                       rc = -1;
> -                     goto err;
> +                     goto out;
>               }
>               spec->regex = (pcre *)mmap_area->next_addr;
>               rc = next_entry(NULL, mmap_area, entry_len);
>               if (rc < 0)
> -                     goto err;
> +                     goto out;
>  
>               /* Check that regex lengths match. pcre_fullinfo()
>                * also validates its magic number. */
>               rc = pcre_fullinfo(spec->regex, NULL, PCRE_INFO_SIZE, &len);
>               if (rc < 0 || len != entry_len) {
>                       rc = -1;
> -                     goto err;
> +                     goto out;
>               }
>  
>               rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t));
>               if (rc < 0 || !entry_len) {
>                       rc = -1;
> -                     goto err;
> +                     goto out;
>               }
>  
>               if (entry_len) {
> @@ -394,119 +372,163 @@ static int load_mmap(struct selabel_handle *rec, 
> const char *path,
>                       spec->lsd.flags |= PCRE_EXTRA_STUDY_DATA;
>                       rc = next_entry(NULL, mmap_area, entry_len);
>                       if (rc < 0)
> -                             goto err;
> +                             goto out;
>  
>                       /* Check that study data lengths match. */
>                       rc = pcre_fullinfo(spec->regex, &spec->lsd,
>                                          PCRE_INFO_STUDYSIZE, &len);
>                       if (rc < 0 || len != entry_len) {
>                               rc = -1;
> -                             goto err;
> +                             goto out;
>                       }
>               }
>  
>               data->nspec++;
>       }
>  
> -     rc = digest_add_specfile(digest, NULL, addr, mmap_stat.st_size,
> -                                                                 mmap_path);
> -     if (rc)
> -             goto err;
> -
> -err:
> +     rc = 0;
> +out:
>       free(stem_map);
>  
>       return rc;
>  }
>  
> -static int process_file(const char *path, const char *suffix,
> -                       struct selabel_handle *rec,
> -                       const char *prefix, struct selabel_digest *digest)
> -{
> -     FILE *fp;
> +struct file_details {
> +     const char *suffix;
>       struct stat sb;
> -     unsigned int lineno;
> -     size_t line_len = 0;
> -     char *line_buf = NULL;
> -     int rc;
> -     char stack_path[PATH_MAX + 1];
> -     bool isbinary = false;
> +};
> +
> +static char *rolling_append(char *current, const char *suffix, size_t max)
> +{
> +     size_t size;
> +     size_t suffix_size;
> +     size_t current_size;
> +
> +     if (!suffix)
> +             return current;
> +
> +     current_size = strlen(current);
> +     suffix_size = strlen(suffix);
> +
> +     size = current_size + suffix_size;
> +     if (size < current_size || size < suffix_size)
> +             return NULL;
> +
> +     /* ensure space for the '.' and the '\0' characters. */
> +     if (size >= (SIZE_MAX - 2))
> +             return NULL;
> +
> +     size += 2;
> +
> +     if (size > max)
> +             return NULL;
> +
> +     /* Append any given suffix */
> +     char *to = current + current_size;
> +     *to++ = '.';
> +     strcpy(to, suffix);
> +
> +     return current;
> +}
> +
> +static bool fcontext_is_binary(FILE *fp)
> +{
>       uint32_t magic;
>  
> -     /* append the path suffix if we have one */
> -     if (suffix) {
> -             rc = snprintf(stack_path, sizeof(stack_path),
> -                                         "%s.%s", path, suffix);
> -             if (rc >= (int)sizeof(stack_path)) {
> -                     errno = ENAMETOOLONG;
> -                     return -1;
> -             }
> -             path = stack_path;
> +     size_t len = fread(&magic, sizeof(magic), 1, fp);
> +     rewind(fp);
> +
> +     return (len && (magic == SELINUX_MAGIC_COMPILED_FCONTEXT));
> +}
> +
> +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
> +
> +static FILE *open_file(const char *path, const char *suffix,
> +        char *save_path, size_t len, struct stat *sb)
> +{
> +     unsigned i;
> +     int rc;
> +     char stack_path[len];
> +     struct file_details *found = NULL;
> +
> +     /*
> +      * Rolling append of suffix. Try to open with path.suffix then the
> +      * next as path.suffix.suffix and so forth.
> +      */
> +     struct file_details fdetails[2] = {
> +                     { .suffix = suffix },
> +                     { .suffix = "bin" }
> +     };
> +
> +     rc = snprintf(stack_path, sizeof(stack_path), "%s", path);
> +     if (rc >= (int) sizeof(stack_path)) {
> +             errno = ENAMETOOLONG;
> +             return NULL;
>       }
>  
> -     /* Open the specification file. */
> -     fp = fopen(path, "r");
> -     if (fp) {
> -             __fsetlocking(fp, FSETLOCKING_BYCALLER);
> +     for (i = 0; i < ARRAY_SIZE(fdetails); i++) {
>  
> -             if (fstat(fileno(fp), &sb) < 0)
> -                     return -1;
> -             if (!S_ISREG(sb.st_mode)) {
> -                     errno = EINVAL;
> -                     return -1;
> -             }
> +             /* This handles the case if suffix is null */
> +             path = rolling_append(stack_path, fdetails[i].suffix,
> +                     sizeof(stack_path));
> +             if (!path)
> +                     return NULL;
>  
> -             magic = 0;
> -             if (fread(&magic, sizeof magic, 1, fp) != 1) {
> -                     if (ferror(fp)) {
> -                             errno = EINVAL;
> -                             fclose(fp);
> -                             return -1;
> -                     }
> -                     clearerr(fp);
> -             }
> +             rc = stat(path, &fdetails[i].sb);
> +             if (rc)
> +                     continue;
>  
> -             if (magic == SELINUX_MAGIC_COMPILED_FCONTEXT) {
> -                     /* file_contexts.bin format */
> -                     fclose(fp);
> -                     fp = NULL;
> -                     isbinary = true;
> -             } else {
> -                     rewind(fp);
> +             /* first file thing found, just take it */
> +             if (!found) {
> +                     strcpy(save_path, path);
> +                     found = &fdetails[i];
> +                     continue;
>               }
> -     } else {
> +
>               /*
> -              * Text file does not exist, so clear the timestamp
> -              * so that we will always pass the timestamp comparison
> -              * with the bin file in load_mmap().
> +              * Keep picking the newest file found. Where "newest"
> +              * includes equality. This provides a precedence on
> +              * secondary suffixes even when the timestamp is the
> +              * same. Ie choose file_contexts.bin over file_contexts
> +              * even if the time stamp is the same.
>                */
> -             sb.st_mtime = 0;
> +             if (fdetails[i].sb.st_mtime >= found->sb.st_mtime) {
> +                     found = &fdetails[i];
> +                     strcpy(save_path, path);
> +             }
>       }
>  
> -     rc = load_mmap(rec, path, &sb, isbinary, digest);
> -     if (rc == 0)
> -             goto out;
> +     if (!found) {
> +             errno = ENOENT;
> +             return NULL;
> +     }
>  
> -     if (!fp)
> -             return -1; /* no text or bin file */
> +     memcpy(sb, &found->sb, sizeof(*sb));
> +     return fopen(save_path, "r");
> +}
>  
> -     /*
> -      * Then do detailed validation of the input and fill the spec array
> -      */
> -     lineno = 0;
> -     rc = 0;
> -     while (getline(&line_buf, &line_len, fp) > 0) {
> -             rc = process_line(rec, path, prefix, line_buf, ++lineno);
> -             if (rc)
> -                     goto out;
> -     }
> +static int process_file(const char *path, const char *suffix,
> +                       struct selabel_handle *rec,
> +                       const char *prefix, struct selabel_digest *digest)
> +{
> +     int rc;
> +     struct stat sb;
> +     FILE *fp = NULL;
> +     char found_path[PATH_MAX];
>  
> -     rc = digest_add_specfile(digest, fp, NULL, sb.st_size, path);
> +     fp = open_file(path, suffix, found_path, sizeof(found_path), &sb);
> +     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);
> +     if (rc < 0)
> +             goto out;
> +
> +     rc = digest_add_specfile(digest, fp, NULL, sb.st_size, found_path);
>  out:
> -     free(line_buf);
> -     if (fp)
> -             fclose(fp);
> +     fclose(fp);
>       return rc;
>  }
>  
> 

_______________________________________________
Seandroid-list mailing list
[email protected]
To unsubscribe, send email to [email protected].
To get help, send an email containing "help" to 
[email protected].

Reply via email to