diff --git a/libselinux/man/man3/matchpathcon.3 b/libselinux/man/man3/matchpathcon.3 index cdbb252..0cc2268 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..23df23b 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..0d89dcb 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,17 @@ 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; + 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 +503,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 +517,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 +527,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/matchpathcon.c b/libselinux/src/matchpathcon.c index 9717b14..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); } @@ -353,7 +354,7 @@ static int symlink_realpath(const char *name, char *resolved_path) tmp_path = strdup(name); if (!tmp_path) { - fprintf(stderr, "symlink_realpath(%s) strdup() failed: %s\n", + myprintf("symlink_realpath(%s) strdup() failed: %s\n", name, strerror(errno)); rc = -1; goto out; @@ -374,21 +375,24 @@ static int symlink_realpath(const char *name, char *resolved_path) } if (!p) { - fprintf(stderr, "symlink_realpath(%s) realpath() failed: %s\n", + myprintf("symlink_realpath(%s) realpath() failed: %s\n", name, strerror(errno)); rc = -1; goto out; } len = strlen(p); - if (len + strlen(last_component) + 1 > PATH_MAX) { - fprintf(stderr, "symlink_realpath(%s) failed: Filename too long \n", + if (len + strlen(last_component) + 2 > PATH_MAX) { + myprintf("symlink_realpath(%s) failed: Filename too long \n", name); + errno=ENAMETOOLONG; rc = -1; goto out; } resolved_path += len; + strcpy(resolved_path, "/"); + resolved_path += 1; strcpy(resolved_path, last_component); out: free(tmp_path); diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c index 2fa21bc..5f0a4c2 100644 --- a/libselinux/utils/matchpathcon.c +++ b/libselinux/utils/matchpathcon.c @@ -45,7 +45,7 @@ int printmatchpathcon(char *path, int header, int mode) int main(int argc, char **argv) { - int i, init = 0, rc = 0; + int i, init = 0; int header = 1, opt; int verify = 0; int notrans = 0;