aboutsummaryrefslogtreecommitdiffstats
path: root/libselinux/src/label_file.c
diff options
context:
space:
mode:
authorRichard Haines <richard_c_haines@btinternet.com>2015-06-16 14:49:19 +0100
committerStephen Smalley <sds@tycho.nsa.gov>2015-06-16 12:30:08 -0400
commit3cb6078ae5e9a811b1b40faee7bb5108d5f7fbe8 (patch)
tree01f96eeb27ca550eb14abf1cd2a20f6554b00c9a /libselinux/src/label_file.c
parente88914849490c3fc17b0e5ed67387e47f2701d3c (diff)
downloadandroid_external_selinux-3cb6078ae5e9a811b1b40faee7bb5108d5f7fbe8.tar.gz
android_external_selinux-3cb6078ae5e9a811b1b40faee7bb5108d5f7fbe8.tar.bz2
android_external_selinux-3cb6078ae5e9a811b1b40faee7bb5108d5f7fbe8.zip
libselinux: Enhance file context support
Update file contexts generation and loading to use common code. Remove "status = 0; after "status = sort_specs(data);" otherwise the function will never indicate a failure. The file labeling code also has minor formatting, white space removal etc. changes. label_file.c - Move process_line function to label_file.h sefcontext_compile.c - Update to use common process_line code. Now frees all malloc'ed memory, checked by valgrind. Also added optional -o output file parameter - updated man page to reflect this change. V2 - Revert to using compat_validate instead of selabel_validate. V3 - Revert to using callback for validation now the problem has been fixed by commit e88914849490c3fc17b0e5ed67387e47f2701d3c ("libselinux: build sefcontext_compile with static libselinux") Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
Diffstat (limited to 'libselinux/src/label_file.c')
-rw-r--r--libselinux/src/label_file.c171
1 files changed, 19 insertions, 152 deletions
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 60aae669..1d6c36e1 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -15,13 +15,11 @@
#include <limits.h>
#include <stdint.h>
#include <pcre.h>
-
-#include <linux/limits.h>
-
+#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <unistd.h>
+
#include "callbacks.h"
#include "label_internal.h"
#include "label_file.h"
@@ -72,12 +70,14 @@ 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 ((!strcmp(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 (strcmp(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",
@@ -96,136 +96,8 @@ static int nodups_specs(struct saved_data *data, const char *path)
return rc;
}
-static int compile_regex(struct saved_data *data, struct spec *spec, const char **errbuf)
-{
- const char *tmperrbuf;
- char *reg_buf, *anchored_regex, *cp;
- struct stem *stem_arr = data->stem_arr;
- size_t len;
- int erroff;
-
- if (spec->regcomp)
- return 0; /* already done */
-
- /* Skip the fixed stem. */
- reg_buf = spec->regex_str;
- if (spec->stem_id >= 0)
- reg_buf += 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;
-
- /* Create ^...$ regexp. */
- *cp++ = '^';
- cp = mempcpy(cp, reg_buf, len);
- *cp++ = '$';
- *cp = '\0';
-
- /* Compile the regular expression. */
- spec->regex = pcre_compile(anchored_regex, PCRE_DOTALL, &tmperrbuf, &erroff, NULL);
- free(anchored_regex);
- if (!spec->regex) {
- if (errbuf)
- *errbuf=tmperrbuf;
- return -1;
- }
-
- spec->sd = pcre_study(spec->regex, 0, &tmperrbuf);
- if (!spec->sd && tmperrbuf) {
- if (errbuf)
- *errbuf=tmperrbuf;
- return -1;
- }
-
- /* Done. */
- spec->regcomp = 1;
-
- return 0;
-}
-
-static int process_line(struct selabel_handle *rec,
- const char *path, const char *prefix,
- char *line_buf, unsigned lineno)
-{
- int items, len, rc;
- char *regex = NULL, *type = NULL, *context = NULL;
- 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, 3, &regex, &type, &context);
- if (items <= 0)
- return items;
-
- if (items < 2) {
- COMPAT_LOG(SELINUX_WARNING,
- "%s: line %u 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;
- }
-
- rc = grow_specs(data);
- if (rc)
- return rc;
-
- 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;
- if (rec->validating && compile_regex(data, &spec_arr[nspec], &errbuf)) {
- COMPAT_LOG(SELINUX_WARNING, "%s: line %u 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) {
- mode_t mode = string_to_mode(type);
- if (mode == (mode_t)-1) {
- COMPAT_LOG(SELINUX_WARNING, "%s: line %u has invalid file type %s\n",
- path, lineno, type);
- mode = 0;
- }
- spec_arr[nspec].mode = mode;
- }
-
- 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;
-
- return 0;
-}
-
-static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *sb)
+static int load_mmap(struct selabel_handle *rec, const char *path,
+ struct stat *sb)
{
struct saved_data *data = (struct saved_data *)rec->data;
char mmap_path[PATH_MAX + 1];
@@ -259,12 +131,6 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
return -1;
}
- if (mmap_stat.st_mtime == sb->st_mtime &&
- mmap_stat.st_mtim.tv_nsec < sb->st_mtim.tv_nsec) {
- close(mmapfd);
- return -1;
- }
-
/* ok, read it in... */
len = mmap_stat.st_size;
len += (sysconf(_SC_PAGE_SIZE) - 1);
@@ -460,7 +326,7 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
if (rc < 0)
goto err;
- if (stem_id < 0 || stem_id >= stem_map_len)
+ if (stem_id < 0 || stem_id >= (int32_t)stem_map_len)
spec->stem_id = -1;
else
spec->stem_id = stem_map[stem_id];
@@ -520,19 +386,21 @@ err:
return rc;
}
-static int process_file(const char *path, const char *suffix, struct selabel_handle *rec, const char *prefix)
+static int process_file(const char *path, const char *suffix,
+ struct selabel_handle *rec, const char *prefix)
{
FILE *fp;
struct stat sb;
unsigned int lineno;
- size_t line_len;
+ size_t line_len = 0;
char *line_buf = NULL;
int rc;
char stack_path[PATH_MAX + 1];
/* append the path suffix if we have one */
if (suffix) {
- rc = snprintf(stack_path, sizeof(stack_path), "%s.%s", path, suffix);
+ rc = snprintf(stack_path, sizeof(stack_path),
+ "%s.%s", path, suffix);
if (rc >= (int)sizeof(stack_path)) {
errno = ENAMETOOLONG;
return -1;
@@ -563,13 +431,13 @@ static int process_file(const char *path, const char *suffix, struct selabel_han
while (getline(&line_buf, &line_len, fp) > 0) {
rc = process_line(rec, path, prefix, line_buf, ++lineno);
if (rc)
- return rc;
+ goto out;
}
+
out:
free(line_buf);
fclose(fp);
-
- return 0;
+ return rc;
}
static int init(struct selabel_handle *rec, struct selinux_opt *opts,
@@ -609,7 +477,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
rec->spec_file = strdup(path);
- /*
+ /*
* The do detailed validation of the input and fill the spec array
*/
status = process_file(path, NULL, rec, prefix);
@@ -634,7 +502,6 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
status = sort_specs(data);
- status = 0;
finish:
if (status)
free(data->spec_arr);
@@ -731,7 +598,7 @@ static struct spec *lookup_common(struct selabel_handle *rec,
if (partial)
pcre_options |= PCRE_PARTIAL_SOFT;
- /*
+ /*
* Check for matching specifications in reverse order, so that
* the last matching specification is used.
*/