static int process_line(struct selabel_handle *rec, const char *path, const char *prefix, char *line_buf, int pass, unsigned lineno) { int items, len; char *buf_p, *regex, *type, *context; struct saved_data *data = (struct saved_data *)rec->data; spec_t *spec_arr = data->spec_arr; unsigned int nspec = data->nspec; len = strlen(line_buf); if (line_buf[len - 1] == '\n') line_buf[len - 1] = 0; buf_p = line_buf; while (isspace(*buf_p)) buf_p++; /* Skip comment lines and empty lines. */ if (*buf_p == '#' || *buf_p == 0) return 0; items = sscanf(line_buf, "%as %as %as", ®ex, &type, &context); if (items < 2) { COMPAT_LOG(SELINUX_WARNING, "%s: line %d is missing fields, skipping\n", path, lineno); if (items == 1) free(regex); return 0; } else if (items == 2) { /* The type field is optional. */ free(context); context = type; type = 0; } len = get_stem_from_spec(regex); if (len && prefix && strncmp(prefix, regex, len)) { /* Stem of regex does not match requested prefix, discard. */ free(regex); free(type); free(context); return 0; } if (pass == 1) { /* On the second pass, process and store the specification in spec. */ char *errbuf = NULL; spec_arr[nspec].stem_id = find_stem_from_spec(data, regex); spec_arr[nspec].regex_str = regex; if (rec->validating && compile_regex(data, &spec_arr[nspec], &errbuf)) { COMPAT_LOG(SELINUX_WARNING, "%s: line %d has invalid regex %s: %s\n", path, lineno, regex, (errbuf ? errbuf : "out of memory")); } /* Convert the type string to a mode format */ spec_arr[nspec].type_str = type; spec_arr[nspec].mode = 0; if (!type) goto skip_type; len = strlen(type); if (type[0] != '-' || len != 2) { COMPAT_LOG(SELINUX_WARNING, "%s: line %d has invalid file type %s\n", path, lineno, type); return 0; } switch (type[1]) { case 'b': spec_arr[nspec].mode = S_IFBLK; break; case 'c': spec_arr[nspec].mode = S_IFCHR; break; case 'd': spec_arr[nspec].mode = S_IFDIR; break; case 'p': spec_arr[nspec].mode = S_IFIFO; break; case 'l': spec_arr[nspec].mode = S_IFLNK; break; case 's': spec_arr[nspec].mode = S_IFSOCK; break; case '-': spec_arr[nspec].mode = S_IFREG; break; default: COMPAT_LOG(SELINUX_WARNING, "%s: line %d has invalid file type %s\n", path, lineno, type); return 0; } skip_type: spec_arr[nspec].lr.ctx_raw = context; /* Determine if specification has * any meta characters in the RE */ spec_hasMetaChars(&spec_arr[nspec]); if (strcmp(context, "<<none>>") && rec->validating) compat_validate(rec, &spec_arr[nspec].lr, path, lineno); } data->nspec = ++nspec; if (pass == 0) { free(regex); if (type) free(type); free(context); } return 0; }
static int process_file(struct saved_data *data, const char *filename) { struct spec *spec; unsigned int line_num; char *line_buf = NULL; size_t line_len; ssize_t len; FILE *context_file; context_file = fopen(filename, "r"); if (!context_file) { fprintf(stderr, "Error opening %s: %s\n", filename, strerror(errno)); return -1; } line_num = 0; while ((len = getline(&line_buf, &line_len, context_file)) != -1) { char *context; char *mode; char *regex; char *cp, *anchored_regex; char *buf_p; pcre *re; pcre_extra *sd; const char *err; int items, erroff, rc; size_t regex_len; int32_t stem_id; len = strlen(line_buf); if (line_buf[len - 1] == '\n') line_buf[len - 1] = 0; buf_p = line_buf; while (isspace(*buf_p)) buf_p++; /* Skip comment lines and empty lines. */ if (*buf_p == '#' || *buf_p == 0) continue; items = sscanf(line_buf, "%ms %ms %ms", ®ex, &mode, &context); if (items < 2 || items > 3) { fprintf(stderr, "invalid entry, skipping:%s", line_buf); continue; } if (items == 2) { context = mode; mode = NULL; } rc = grow_specs(data); if (rc) { fprintf(stderr, "grow_specs failed: %s\n", strerror(errno)); return rc; } spec = &data->spec_arr[data->nspec]; spec->lr.ctx_raw = context; spec->mode = string_to_mode(mode); if (spec->mode == -1) { fprintf(stderr, "%s: line %d has invalid file type %s\n", regex, line_num + 1, mode); spec->mode = 0; } free(mode); spec->regex_str = regex; stem_id = find_stem_from_spec(data, regex); spec->stem_id = stem_id; /* skip past the fixed stem part */ if (stem_id != -1) regex += data->stem_arr[stem_id].len; regex_len = strlen(regex); cp = anchored_regex = malloc(regex_len + 3); if (!cp) { fprintf(stderr, "Malloc Failed: %s\n", strerror(errno)); return -1; } *cp++ = '^'; memcpy(cp, regex, regex_len); cp += regex_len; *cp++ = '$'; *cp = '\0'; spec_hasMetaChars(spec); re = pcre_compile(anchored_regex, 0, &err, &erroff, NULL); if (!re) { fprintf(stderr, "PCRE compilation failed for %s at offset %d: %s\n", anchored_regex, erroff, err); return -1; } spec->regex = re; sd = pcre_study(re, 0, &err); if (!sd) { fprintf(stderr, "PCRE study failed for %s: %s\n", anchored_regex, err); return -1; } free(anchored_regex); spec->sd = sd; line_num++; data->nspec++; } free(line_buf); fclose(context_file); return 0; }