diff --git a/libselinux/man/man3/matchpathcon.3 b/libselinux/man/man3/matchpathcon.3 index cdbb252..e2a4371 100644 --- a/libselinux/man/man3/matchpathcon.3 +++ b/libselinux/man/man3/matchpathcon.3 @@ -8,7 +8,7 @@ matchpathcon, matchpathcon_index \- get the default SELinux security context for .BI "int matchpathcon_init(const char *" path ");" -.BI "int matchpathcon_init_prefix(const char *" path ", const char *" subset ");" +.BI "int matchpathcon_init_prefix(const char *" path ", const char *" prefix ");" .BI "int matchpathcon_fini(void);" .sp @@ -48,7 +48,7 @@ is the same as but only loads entries with regular expressions that have stems prefixed by .I prefix. - +prefix can have multiple paths separated by ":", for example "/dev:/var/run:/tmp" .sp .B matchpathcon_fini frees the memory allocated by a prior call to diff --git a/libselinux/man/man3/selabel_open.3 b/libselinux/man/man3/selabel_open.3 index 8674e37..89bb4d3 100644 --- a/libselinux/man/man3/selabel_open.3 +++ b/libselinux/man/man3/selabel_open.3 @@ -66,6 +66,13 @@ A non-null value for this option enables context validation. By default, is used; a custom validation function can be provided via .BR selinux_set_callback (3). Note that an invalid context may not be treated as an error unless it is actually encountered during a lookup operation. +.TP +.B SELABEL_OPT_SUBSET +A ":" separates string of path prefixes that tell the system to only loads entries with regular expressions that could match this strings. For example "/dev:/var/run:/tmp". This option can cause the system to use less memory and work faster, but you should only use paths that begin with a prefix. +.TP +.B SELABEL_OPT_PATH +A string representing an alternate path the the regular expressions. +.sp .SH "BACKENDS" @@ -99,4 +106,3 @@ Eamon Walsh .BR selabel_stats (3), .BR selinux_set_callback (3), .BR selinux (8) - diff --git a/libselinux/src/callbacks.c b/libselinux/src/callbacks.c index b245364..7c47222 100644 --- a/libselinux/src/callbacks.c +++ b/libselinux/src/callbacks.c @@ -16,6 +16,7 @@ default_selinux_log(int type __attribute__((unused)), const char *fmt, ...) { int rc; va_list ap; + if (is_selinux_enabled() == 0) return 0; va_start(ap, fmt); rc = vfprintf(stderr, fmt, ap); va_end(ap); diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c index 3b8346d..02f3f98 100644 --- a/libselinux/src/label_file.c +++ b/libselinux/src/label_file.c @@ -27,6 +27,7 @@ * Internals, mostly moved over from matchpathcon.c */ +#define MAX_PREFIX 100 /* A file security context specification. */ typedef struct spec { struct selabel_lookup_rec lr; /* holds contexts for lookup result */ @@ -279,7 +280,7 @@ static int compile_regex(struct saved_data *data, spec_t *spec, char **errbuf) static int process_line(struct selabel_handle *rec, - const char *path, const char *prefix, + const char *path, const char **prefix_array, char *line_buf, int pass, unsigned lineno) { int items, len; @@ -313,12 +314,24 @@ static int process_line(struct selabel_handle *rec, } 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 (len && prefix_array[0]) { + int i = 0; + int found = 0; + while (i < MAX_PREFIX && prefix_array[i]) { + if (strncmp(prefix_array[i], regex, len) == 0) { + found = 1; + break; + } + i++; + } + + if (! found) { + /* Stem of regex does not match requested prefix, discard. */ + free(regex); + free(type); + free(context); + return 0; + } } if (pass == 1) { @@ -400,7 +413,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts, { struct saved_data *data = (struct saved_data *)rec->data; const char *path = NULL; - const char *prefix = NULL; + const char *prefix_array[MAX_PREFIX] = {NULL,}; FILE *fp; FILE *localfp = NULL; FILE *homedirfp = NULL; @@ -421,8 +434,19 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts, path = opts[n].value; break; case SELABEL_OPT_SUBSET: - prefix = opts[n].value; + { + char *ptr; + i = 0; + if (opts[n].value) { + prefix_array[i] = strtok_r((char *)opts[n].value, ":", &ptr); + while ((prefix_array[i] != NULL) && i < MAX_PREFIX - 1) { + i++; + prefix_array[i] = strtok_r(NULL, ":", &ptr); + } + } + break; + } case SELABEL_OPT_BASEONLY: baseonly = !!opts[n].value; break; @@ -481,7 +505,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts, data->ncomp = 0; while (getline(&line_buf, &line_len, fp) > 0 && data->nspec < maxnspec) { - if (process_line(rec, path, prefix, line_buf, + if (process_line(rec, path, prefix_array, line_buf, pass, ++lineno) != 0) goto finish; } @@ -495,7 +519,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts, while (getline(&line_buf, &line_len, homedirfp) > 0 && data->nspec < maxnspec) { if (process_line - (rec, homedir_path, prefix, + (rec, homedir_path, prefix_array, line_buf, pass, ++lineno) != 0) goto finish; } @@ -505,7 +529,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts, while (getline(&line_buf, &line_len, localfp) > 0 && data->nspec < maxnspec) { if (process_line - (rec, local_path, prefix, line_buf, + (rec, local_path, prefix_array, line_buf, pass, ++lineno) != 0) goto finish; } diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c index 868660f..7fa6383 100644 --- a/libselinux/src/load_policy.c +++ b/libselinux/src/load_policy.c @@ -380,7 +380,7 @@ int selinux_init_load_policy(int *enforce) } if (! mntpoint ) { - if (errno == ENODEV) { + if (errno == ENODEV || errno == ENOENT) { /* * SELinux was disabled in the kernel, either * omitted entirely or disabled at boot via selinux=0. diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c index 5914afa..df83b30 100644 --- a/libselinux/src/matchpathcon.c +++ b/libselinux/src/matchpathcon.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "selinux_internal.h" #include "label_internal.h" #include "callbacks.h" @@ -62,7 +63,7 @@ static void { va_list ap; va_start(ap, fmt); - vfprintf(stderr, fmt, ap); + vsyslog(LOG_ERR, fmt, ap); va_end(ap); }