All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions
@ 2012-08-31 17:49 Eric Paris
  2012-08-31 17:49 ` [PATCH 02/18] libselinux: label_file: remove all typedefs Eric Paris
                   ` (17 more replies)
  0 siblings, 18 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

The PCRE functions are about x10 faster than the glibc functions.  So
use the external library.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/Makefile     |  2 ++
 libselinux/src/label_file.c | 63 ++++++++++++++++++++++++---------------------
 2 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
index 74e53bb..ac019df 100644
--- a/libselinux/src/Makefile
+++ b/libselinux/src/Makefile
@@ -20,6 +20,8 @@ RUBYINC ?= $(shell pkg-config --cflags ruby-$(RUBYLIBVER))
 RUBYINSTALL ?= $(LIBDIR)/ruby/site_ruby/$(RUBYLIBVER)/$(RUBYPLATFORM)
 LIBBASE=$(shell basename $(LIBDIR))
 
+LDFLAGS ?= -lpcre
+
 VERSION = $(shell cat ../VERSION)
 LIBVERSION = 1
 
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 82a608c..5e7e712 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -16,7 +16,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <limits.h>
-#include <regex.h>
+#include <pcre.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -33,7 +33,8 @@ typedef struct spec {
 	struct selabel_lookup_rec lr;	/* holds contexts for lookup result */
 	char *regex_str;	/* regular expession string for diagnostics */
 	char *type_str;		/* type string for diagnostic messages */
-	regex_t regex;		/* compiled regular expression */
+	pcre *regex;		/* compiled regular expression */
+	pcre_extra *sd;		/* extra compiled stuff */
 	char regcomp;           /* regex_str has been compiled to regex */
 	mode_t mode;		/* mode format value */
 	int matches;		/* number of matching pathnames */
@@ -224,12 +225,13 @@ static void spec_hasMetaChars(struct spec *spec)
 	return;
 }
 
-static int compile_regex(struct saved_data *data, spec_t *spec, char **errbuf)
+static int compile_regex(struct saved_data *data, spec_t *spec, const char **errbuf)
 {
+	const char *tmperrbuf;
 	char *reg_buf, *anchored_regex, *cp;
 	stem_t *stem_arr = data->stem_arr;
 	size_t len;
-	int regerr;
+	int erroff;
 
 	if (spec->regcomp)
 		return 0; /* already done */
@@ -246,6 +248,7 @@ static int compile_regex(struct saved_data *data, spec_t *spec, char **errbuf)
 	cp = anchored_regex = malloc(len + 3);
 	if (!anchored_regex)
 		return -1;
+
 	/* Create ^...$ regexp.  */
 	*cp++ = '^';
 	cp = mempcpy(cp, reg_buf, len);
@@ -253,21 +256,20 @@ static int compile_regex(struct saved_data *data, spec_t *spec, char **errbuf)
 	*cp = '\0';
 
 	/* Compile the regular expression. */
-	regerr = regcomp(&spec->regex, anchored_regex, 
-			 REG_EXTENDED | REG_NOSUB);
-	if (regerr != 0) {
-		size_t errsz = 0;
-		errsz = regerror(regerr, &spec->regex, NULL, 0);
-		if (errsz && errbuf)
-			*errbuf = malloc(errsz);
-		if (errbuf && *errbuf)
-			(void)regerror(regerr, &spec->regex,
-				       *errbuf, errsz);
-
-		free(anchored_regex);
+	spec->regex = pcre_compile(anchored_regex, 0, &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) {
+		if (errbuf)
+			*errbuf=tmperrbuf;
 		return -1;
 	}
-	free(anchored_regex);
 
 	/* Done. */
 	spec->regcomp = 1;
@@ -333,7 +335,7 @@ static int process_line(struct selabel_handle *rec,
 
 	if (pass == 1) {
 		/* On the second pass, process and store the specification in spec. */
-		char *errbuf = NULL;
+		const 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)) {
@@ -592,7 +594,10 @@ static void closef(struct selabel_handle *rec)
 		free(spec->type_str);
 		free(spec->lr.ctx_raw);
 		free(spec->lr.ctx_trans);
-		regfree(&spec->regex);
+		if (spec->regcomp) {
+			pcre_free(spec->regex);
+			pcre_free_study(spec->sd);
+		}
 	}
 
 	for (i = 0; i < (unsigned int)data->num_stems; i++) {
@@ -651,26 +656,24 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
 	 * the last matching specification is used.
 	 */
 	for (i = data->nspec - 1; i >= 0; i--) {
+		spec_t *spec = &spec_arr[i];
 		/* if the spec in question matches no stem or has the same
 		 * stem as the file AND if the spec in question has no mode
 		 * specified or if the mode matches the file mode then we do
 		 * a regex check        */
-		if ((spec_arr[i].stem_id == -1
-		     || spec_arr[i].stem_id == file_stem)
-		    && (!mode || !spec_arr[i].mode
-			|| mode == spec_arr[i].mode)) {
-			if (compile_regex(data, &spec_arr[i], NULL) < 0)
+		if ((spec->stem_id == -1 || spec->stem_id == file_stem) &&
+		    (!mode || !spec->mode || mode == spec->mode)) {
+			if (compile_regex(data, spec, NULL) < 0)
 				goto finish;
-			if (spec_arr[i].stem_id == -1)
-				rc = regexec(&spec_arr[i].regex, key, 0, 0, 0);
+			if (spec->stem_id == -1)
+				rc = pcre_exec(spec->regex, spec->sd, key, strlen(key), 0, 0, NULL, 0);
 			else
-				rc = regexec(&spec_arr[i].regex, buf, 0, 0, 0);
+				rc = pcre_exec(spec->regex, spec->sd, buf, strlen(buf), 0, 0, NULL, 0);
 
 			if (rc == 0) {
-				spec_arr[i].matches++;
+				spec->matches++;
 				break;
-			}
-			if (rc == REG_NOMATCH)
+			} else if (rc == PCRE_ERROR_NOMATCH)
 				continue;
 			/* else it's an error */
 			goto finish;
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 02/18] libselinux: label_file: remove all typedefs
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 03/18] libselinux: label_file: move definitions to include file Eric Paris
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

I hate them.  They just indirectly you needlessly.  Just use the struct
definitions.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.c | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 5e7e712..f0e3d2a 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -29,7 +29,7 @@
 
 #define MAX_PREFIX 100
 /* A file security context specification. */
-typedef struct spec {
+struct spec {
 	struct selabel_lookup_rec lr;	/* holds contexts for lookup result */
 	char *regex_str;	/* regular expession string for diagnostics */
 	char *type_str;		/* type string for diagnostic messages */
@@ -40,13 +40,13 @@ typedef struct spec {
 	int matches;		/* number of matching pathnames */
 	int hasMetaChars;	/* regular expression has meta-chars */
 	int stem_id;		/* indicates which stem-compression item */
-} spec_t;
+};
 
 /* A regular expression stem */
-typedef struct stem {
+struct stem {
 	char *buf;
 	int len;
-} stem_t;
+};
 
 /* Our stored configuration */
 struct saved_data {
@@ -54,14 +54,14 @@ struct saved_data {
 	 * The array of specifications, initially in the same order as in 
 	 * the specification file. Sorting occurs based on hasMetaChars.
 	 */
-	spec_t *spec_arr;
+	struct spec *spec_arr;
 	unsigned int nspec;
 	unsigned int ncomp;
 
 	/*
 	 * The array of regular expression stems.
 	 */
-	stem_t *stem_arr;
+	struct stem *stem_arr;
 	int num_stems;
 	int alloc_stems;
 };
@@ -109,10 +109,10 @@ static int find_stem_from_spec(struct saved_data *data, const char *buf)
 			return i;
 	}
 	if (data->alloc_stems == num) {
-		stem_t *tmp_arr;
+		struct stem *tmp_arr;
 		data->alloc_stems = data->alloc_stems * 2 + 16;
 		tmp_arr = realloc(data->stem_arr,
-				  sizeof(stem_t) * data->alloc_stems);
+				  sizeof(*tmp_arr) * data->alloc_stems);
 		if (!tmp_arr)
 			return -1;
 		data->stem_arr = tmp_arr;
@@ -225,11 +225,11 @@ static void spec_hasMetaChars(struct spec *spec)
 	return;
 }
 
-static int compile_regex(struct saved_data *data, spec_t *spec, const char **errbuf)
+static int compile_regex(struct saved_data *data, struct spec *spec, const char **errbuf)
 {
 	const char *tmperrbuf;
 	char *reg_buf, *anchored_regex, *cp;
-	stem_t *stem_arr = data->stem_arr;
+	struct stem *stem_arr = data->stem_arr;
 	size_t len;
 	int erroff;
 
@@ -285,7 +285,7 @@ static int process_line(struct selabel_handle *rec,
 	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;
+	struct spec *spec_arr = data->spec_arr;
 	unsigned int nspec = data->nspec;
 
 	len = strlen(line_buf);
@@ -423,7 +423,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 	char *line_buf = NULL;
 	size_t line_len = 0;
 	unsigned int lineno, pass, i, j, maxnspec;
-	spec_t *spec_copy = NULL;
+	struct spec *spec_copy = NULL;
 	int status = -1, baseonly = 0;
 	struct stat sb;
 
@@ -491,7 +491,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 	 * The second pass performs detailed validation of the input
 	 * and fills in the spec array.
 	 */
-	maxnspec = UINT_MAX / sizeof(spec_t);
+	maxnspec = UINT_MAX / sizeof(struct spec);
 	for (pass = 0; pass < 2; pass++) {
 		data->nspec = 0;
 		data->ncomp = 0;
@@ -536,7 +536,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 				status = 0;
 				goto finish;
 			}
-			data->spec_arr = calloc(data->nspec, sizeof(spec_t));
+			data->spec_arr = calloc(data->nspec, sizeof(*data->spec_arr));
 			if (!data->spec_arr)
 				goto finish;
 
@@ -551,18 +551,18 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 	free(line_buf);
 
 	/* Move exact pathname specifications to the end. */
-	spec_copy = malloc(sizeof(spec_t) * data->nspec);
+	spec_copy = malloc(sizeof(*spec_copy) * data->nspec);
 	if (!spec_copy)
 		goto finish;
 	j = 0;
 	for (i = 0; i < data->nspec; i++)
 		if (data->spec_arr[i].hasMetaChars)
 			memcpy(&spec_copy[j++],
-			       &data->spec_arr[i], sizeof(spec_t));
+			       &data->spec_arr[i], sizeof(spec_copy[j]));
 	for (i = 0; i < data->nspec; i++)
 		if (!data->spec_arr[i].hasMetaChars)
 			memcpy(&spec_copy[j++],
-			       &data->spec_arr[i], sizeof(spec_t));
+			       &data->spec_arr[i], sizeof(spec_copy[j]));
 	free(data->spec_arr);
 	data->spec_arr = spec_copy;
 
@@ -617,7 +617,7 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
 					 const char *key, int type)
 {
 	struct saved_data *data = (struct saved_data *)rec->data;
-	spec_t *spec_arr = data->spec_arr;
+	struct spec *spec_arr = data->spec_arr;
 	int i, rc, file_stem;
 	mode_t mode = (mode_t)type;
 	const char *buf;
@@ -656,7 +656,7 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
 	 * the last matching specification is used.
 	 */
 	for (i = data->nspec - 1; i >= 0; i--) {
-		spec_t *spec = &spec_arr[i];
+		struct spec *spec = &spec_arr[i];
 		/* if the spec in question matches no stem or has the same
 		 * stem as the file AND if the spec in question has no mode
 		 * specified or if the mode matches the file mode then we do
@@ -697,7 +697,7 @@ static void stats(struct selabel_handle *rec)
 {
 	struct saved_data *data = (struct saved_data *)rec->data;
 	unsigned int i, nspec = data->nspec;
-	spec_t *spec_arr = data->spec_arr;
+	struct spec *spec_arr = data->spec_arr;
 
 	for (i = 0; i < nspec; i++) {
 		if (spec_arr[i].matches == 0) {
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 03/18] libselinux: label_file: move definitions to include file
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
  2012-08-31 17:49 ` [PATCH 02/18] libselinux: label_file: remove all typedefs Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 04/18] libselinux: label_file: do string to mode_t conversion in a helper function Eric Paris
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

We want to use some label_file internals in a utility to compile
fcontext files into binary data for fast use.  So start pushing
structures and such into a header file.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.c | 38 +-------------------------------------
 libselinux/src/label_file.h | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 37 deletions(-)
 create mode 100644 libselinux/src/label_file.h

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index f0e3d2a..a3ea934 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -22,49 +22,13 @@
 #include <unistd.h>
 #include "callbacks.h"
 #include "label_internal.h"
+#include "label_file.h"
 
 /*
  * Internals, mostly moved over from matchpathcon.c
  */
 
 #define MAX_PREFIX 100
-/* A file security context specification. */
-struct spec {
-	struct selabel_lookup_rec lr;	/* holds contexts for lookup result */
-	char *regex_str;	/* regular expession string for diagnostics */
-	char *type_str;		/* type string for diagnostic messages */
-	pcre *regex;		/* compiled regular expression */
-	pcre_extra *sd;		/* extra compiled stuff */
-	char regcomp;           /* regex_str has been compiled to regex */
-	mode_t mode;		/* mode format value */
-	int matches;		/* number of matching pathnames */
-	int hasMetaChars;	/* regular expression has meta-chars */
-	int stem_id;		/* indicates which stem-compression item */
-};
-
-/* A regular expression stem */
-struct stem {
-	char *buf;
-	int len;
-};
-
-/* Our stored configuration */
-struct saved_data {
-	/*
-	 * The array of specifications, initially in the same order as in 
-	 * the specification file. Sorting occurs based on hasMetaChars.
-	 */
-	struct spec *spec_arr;
-	unsigned int nspec;
-	unsigned int ncomp;
-
-	/*
-	 * The array of regular expression stems.
-	 */
-	struct stem *stem_arr;
-	int num_stems;
-	int alloc_stems;
-};
 
 /* Return the length of the text that can be considered the stem, returns 0
  * if there is no identifiable stem */
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
new file mode 100644
index 0000000..da2e350
--- /dev/null
+++ b/libselinux/src/label_file.h
@@ -0,0 +1,43 @@
+#ifndef _SELABEL_FILE_H_
+#define _SELABEL_FILE_H_
+
+#include "label_internal.h"
+
+/* A file security context specification. */
+struct spec {
+	struct selabel_lookup_rec lr;	/* holds contexts for lookup result */
+	char *regex_str;	/* regular expession string for diagnostics */
+	char *type_str;		/* type string for diagnostic messages */
+	pcre *regex;		/* compiled regular expression */
+	pcre_extra *sd;		/* extra compiled stuff */
+	char regcomp;		/* regex_str has been compiled to regex */
+	mode_t mode;		/* mode format value */
+	int matches;		/* number of matching pathnames */
+	int hasMetaChars;	/* regular expression has meta-chars */
+	int stem_id;		/* indicates which stem-compression item */
+};
+
+/* A regular expression stem */
+struct stem {
+	char *buf;
+	int len;
+};
+
+/* Our stored configuration */
+struct saved_data {
+	/*
+	 * The array of specifications, initially in the same order as in 
+	 * the specification file. Sorting occurs based on hasMetaChars.
+	 */
+	struct spec *spec_arr;
+	unsigned int nspec;
+	unsigned int ncomp;
+
+	/*
+	 * The array of regular expression stems.
+	 */
+	struct stem *stem_arr;
+	int num_stems;
+	int alloc_stems;
+};
+#endif /* _SELABEL_FILE_H_ */
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 04/18] libselinux: label_file: do string to mode_t conversion in a helper function
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
  2012-08-31 17:49 ` [PATCH 02/18] libselinux: label_file: remove all typedefs Eric Paris
  2012-08-31 17:49 ` [PATCH 03/18] libselinux: label_file: move definitions to include file Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 05/18] libselinux: label_file: move error reporting back into caller Eric Paris
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

So the string to mode_t conversion in a helper function so it can be
used later by a regex compilation program.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.c | 41 ++---------------------------------------
 libselinux/src/label_file.h | 39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 39 deletions(-)

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index a3ea934..3ae9985 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -241,7 +241,6 @@ static int compile_regex(struct saved_data *data, struct spec *spec, const char
 	return 0;
 }
 
-
 static int process_line(struct selabel_handle *rec,
 			const char *path, const char **prefix_array,
 			char *line_buf, int pass, unsigned lineno)
@@ -312,45 +311,9 @@ static int process_line(struct selabel_handle *rec,
 		/* 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;
-		}
+		if (type)
+			spec_arr[nspec].mode = string_to_mode(type, path, lineno);
 
-	skip_type:
 		spec_arr[nspec].lr.ctx_raw = context;
 
 		/* Determine if specification has 
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index da2e350..297ea25 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -1,6 +1,8 @@
 #ifndef _SELABEL_FILE_H_
 #define _SELABEL_FILE_H_
 
+#include <sys/stat.h>
+
 #include "label_internal.h"
 
 /* A file security context specification. */
@@ -40,4 +42,41 @@ struct saved_data {
 	int num_stems;
 	int alloc_stems;
 };
+
+static inline mode_t string_to_mode(char *mode, const char *path, unsigned lineno)
+{
+	size_t len;
+
+	len = strlen(mode);
+	if (mode[0] != '-' || len != 2) {
+		COMPAT_LOG(SELINUX_WARNING,
+			    "%s:  line %d has invalid file type %s\n",
+			    path, lineno, mode);
+		return 0;
+	}
+	switch (mode[1]) {
+	case 'b':
+		return S_IFBLK;
+	case 'c':
+		return S_IFCHR;
+	case 'd':
+		return S_IFDIR;
+	case 'p':
+		return S_IFIFO;
+	case 'l':
+		return S_IFLNK;
+	case 's':
+		return S_IFSOCK;
+	case '-':
+		return S_IFREG;
+	default:
+		COMPAT_LOG(SELINUX_WARNING,
+			    "%s:  line %d has invalid file type %s\n",
+			    path, lineno, mode);
+		return 0;
+	}
+	/* impossible to get here */
+	return 0;
+}
+
 #endif /* _SELABEL_FILE_H_ */
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 05/18] libselinux: label_file: move error reporting back into caller
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (2 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 04/18] libselinux: label_file: do string to mode_t conversion in a helper function Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 06/18] libselinux: label_file: move stem/spec handling to header Eric Paris
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

If we want to use these functions in utilities we shouldn't call such
libselinux internal functions.  Move the error reporting up to the
caller.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.c | 12 ++++++++++--
 libselinux/src/label_file.h | 17 ++++++-----------
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 3ae9985..d4ec878 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -311,8 +311,16 @@ static int process_line(struct selabel_handle *rec,
 		/* Convert the type string to a mode format */
 		spec_arr[nspec].type_str = type;
 		spec_arr[nspec].mode = 0;
-		if (type)
-			spec_arr[nspec].mode = string_to_mode(type, path, lineno);
+		if (type) {
+			mode_t mode = string_to_mode(type);
+			if (mode == -1) {
+				COMPAT_LOG(SELINUX_WARNING,
+					"%s:  line %d has invalid file type %s\n",
+					path, lineno, type);
+				mode = 0;
+			}
+			spec_arr[nspec].mode = mode;
+		}
 
 		spec_arr[nspec].lr.ctx_raw = context;
 
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index 297ea25..9d31c18 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -43,17 +43,15 @@ struct saved_data {
 	int alloc_stems;
 };
 
-static inline mode_t string_to_mode(char *mode, const char *path, unsigned lineno)
+static inline mode_t string_to_mode(char *mode)
 {
 	size_t len;
 
-	len = strlen(mode);
-	if (mode[0] != '-' || len != 2) {
-		COMPAT_LOG(SELINUX_WARNING,
-			    "%s:  line %d has invalid file type %s\n",
-			    path, lineno, mode);
+	if (!mode)
 		return 0;
-	}
+	len = strlen(mode);
+	if (mode[0] != '-' || len != 2)
+		return -1;
 	switch (mode[1]) {
 	case 'b':
 		return S_IFBLK;
@@ -70,10 +68,7 @@ static inline mode_t string_to_mode(char *mode, const char *path, unsigned linen
 	case '-':
 		return S_IFREG;
 	default:
-		COMPAT_LOG(SELINUX_WARNING,
-			    "%s:  line %d has invalid file type %s\n",
-			    path, lineno, mode);
-		return 0;
+		return -1;
 	}
 	/* impossible to get here */
 	return 0;
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 06/18] libselinux: label_file: move stem/spec handling to header
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (3 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 05/18] libselinux: label_file: move error reporting back into caller Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 07/18] libselinux: label_file: drop useless ncomp field from label_file data Eric Paris
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

We want to be able to find the stem and the spec from our new utility.
So move those functions to the header file.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.c | 52 ---------------------------------------------
 libselinux/src/label_file.h | 52 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 52 deletions(-)

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index d4ec878..9c0bfa0 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -30,23 +30,6 @@
 
 #define MAX_PREFIX 100
 
-/* Return the length of the text that can be considered the stem, returns 0
- * if there is no identifiable stem */
-static int get_stem_from_spec(const char *const buf)
-{
-	const char *tmp = strchr(buf + 1, '/');
-	const char *ind;
-
-	if (!tmp)
-		return 0;
-
-	for (ind = buf; ind < tmp; ind++) {
-		if (strchr(".^$?*+|[({", (int)*ind))
-			return 0;
-	}
-	return tmp - buf;
-}
-
 /* return the length of the text that is the stem of a file name */
 static int get_stem_from_file_name(const char *const buf)
 {
@@ -57,41 +40,6 @@ static int get_stem_from_file_name(const char *const buf)
 	return tmp - buf;
 }
 
-/* find the stem of a file spec, returns the index into stem_arr for a new
- * or existing stem, (or -1 if there is no possible stem - IE for a file in
- * the root directory or a regex that is too complex for us). */
-static int find_stem_from_spec(struct saved_data *data, const char *buf)
-{
-	int i, num = data->num_stems;
-	int stem_len = get_stem_from_spec(buf);
-
-	if (!stem_len)
-		return -1;
-	for (i = 0; i < num; i++) {
-		if (stem_len == data->stem_arr[i].len
-		    && !strncmp(buf, data->stem_arr[i].buf, stem_len))
-			return i;
-	}
-	if (data->alloc_stems == num) {
-		struct stem *tmp_arr;
-		data->alloc_stems = data->alloc_stems * 2 + 16;
-		tmp_arr = realloc(data->stem_arr,
-				  sizeof(*tmp_arr) * data->alloc_stems);
-		if (!tmp_arr)
-			return -1;
-		data->stem_arr = tmp_arr;
-	}
-	data->stem_arr[num].len = stem_len;
-	data->stem_arr[num].buf = malloc(stem_len + 1);
-	if (!data->stem_arr[num].buf)
-		return -1;
-	memcpy(data->stem_arr[num].buf, buf, stem_len);
-	data->stem_arr[num].buf[stem_len] = '\0';
-	data->num_stems++;
-	buf += stem_len;
-	return num;
-}
-
 /* find the stem of a file name, returns the index into stem_arr (or -1 if
  * there is no match - IE for a file in the root directory or a regex that is
  * too complex for us).  Makes buf point to the text AFTER the stem. */
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index 9d31c18..de58d1e 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -74,4 +74,56 @@ static inline mode_t string_to_mode(char *mode)
 	return 0;
 }
 
+/* Return the length of the text that can be considered the stem, returns 0
+ * if there is no identifiable stem */
+static inline int get_stem_from_spec(const char *const buf)
+{
+	const char *tmp = strchr(buf + 1, '/');
+	const char *ind;
+
+	if (!tmp)
+		return 0;
+
+	for (ind = buf; ind < tmp; ind++) {
+		if (strchr(".^$?*+|[({", (int)*ind))
+			return 0;
+	}
+	return tmp - buf;
+}
+
+/* find the stem of a file spec, returns the index into stem_arr for a new
+ * or existing stem, (or -1 if there is no possible stem - IE for a file in
+ * the root directory or a regex that is too complex for us). */
+static inline int find_stem_from_spec(struct saved_data *data, const char *buf)
+{
+	int i, num = data->num_stems;
+	int stem_len = get_stem_from_spec(buf);
+
+	if (!stem_len)
+		return -1;
+	for (i = 0; i < num; i++) {
+		if (stem_len == data->stem_arr[i].len
+		    && !strncmp(buf, data->stem_arr[i].buf, stem_len))
+			return i;
+	}
+	if (data->alloc_stems == num) {
+		struct stem *tmp_arr;
+		data->alloc_stems = data->alloc_stems * 2 + 16;
+		tmp_arr = realloc(data->stem_arr,
+				  sizeof(*tmp_arr) * data->alloc_stems);
+		if (!tmp_arr)
+			return -1;
+		data->stem_arr = tmp_arr;
+	}
+	data->stem_arr[num].len = stem_len;
+	data->stem_arr[num].buf = malloc(stem_len + 1);
+	if (!data->stem_arr[num].buf)
+		return -1;
+	memcpy(data->stem_arr[num].buf, buf, stem_len);
+	data->stem_arr[num].buf[stem_len] = '\0';
+	data->num_stems++;
+	buf += stem_len;
+	return num;
+}
+
 #endif /* _SELABEL_FILE_H_ */
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 07/18] libselinux: label_file: drop useless ncomp field from label_file data
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (4 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 06/18] libselinux: label_file: move stem/spec handling to header Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 08/18] libselinux: label_file: move spec_hasMetaChars to header Eric Paris
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

The libselinux label_file backend counted the number of regexes which
had been compiled.  We didn't use it and it wasn't useful information.
Stop doing it.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.c | 3 ---
 libselinux/src/label_file.h | 1 -
 2 files changed, 4 deletions(-)

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 9c0bfa0..0dc0332 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -148,8 +148,6 @@ static int compile_regex(struct saved_data *data, struct spec *spec, const char
 	if (spec->regcomp)
 		return 0; /* already done */
 
-	data->ncomp++; /* how many compiled regexes required */
-
 	/* Skip the fixed stem. */
 	reg_buf = spec->regex_str;
 	if (spec->stem_id >= 0)
@@ -377,7 +375,6 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 	maxnspec = UINT_MAX / sizeof(struct spec);
 	for (pass = 0; pass < 2; pass++) {
 		data->nspec = 0;
-		data->ncomp = 0;
 
 		lineno = 0;
 		while (getline(&line_buf, &line_len, fp) > 0) {
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index de58d1e..560035d 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -33,7 +33,6 @@ struct saved_data {
 	 */
 	struct spec *spec_arr;
 	unsigned int nspec;
-	unsigned int ncomp;
 
 	/*
 	 * The array of regular expression stems.
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 08/18] libselinux: label_file: move spec_hasMetaChars to header
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (5 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 07/18] libselinux: label_file: drop useless ncomp field from label_file data Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 09/18] libselinux: label_file: fix potential read past buffer in spec_hasMetaChars Eric Paris
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

So we can use it in the new compile utility, move the
spec_hasMetaChars() function, which looks for things like .*?+^$ in
regular expressions into the internal header file.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.c | 41 -----------------------------------------
 libselinux/src/label_file.h | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 0dc0332..8216840 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -96,47 +96,6 @@ static int nodups_specs(struct saved_data *data, const char *path)
 	return rc;
 }
 
-/* Determine if the regular expression specification has any meta characters. */
-static void spec_hasMetaChars(struct spec *spec)
-{
-	char *c;
-	int len;
-	char *end;
-
-	c = spec->regex_str;
-	len = strlen(spec->regex_str);
-	end = c + len;
-
-	spec->hasMetaChars = 0;
-
-	/* Look at each character in the RE specification string for a 
-	 * meta character. Return when any meta character reached. */
-	while (c != end) {
-		switch (*c) {
-		case '.':
-		case '^':
-		case '$':
-		case '?':
-		case '*':
-		case '+':
-		case '|':
-		case '[':
-		case '(':
-		case '{':
-			spec->hasMetaChars = 1;
-			return;
-		case '\\':	/* skip the next character */
-			c++;
-			break;
-		default:
-			break;
-
-		}
-		c++;
-	}
-	return;
-}
-
 static int compile_regex(struct saved_data *data, struct spec *spec, const char **errbuf)
 {
 	const char *tmperrbuf;
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index 560035d..b839a23 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -73,6 +73,47 @@ static inline mode_t string_to_mode(char *mode)
 	return 0;
 }
 
+/* Determine if the regular expression specification has any meta characters. */
+static inline void spec_hasMetaChars(struct spec *spec)
+{
+	char *c;
+	int len;
+	char *end;
+
+	c = spec->regex_str;
+	len = strlen(spec->regex_str);
+	end = c + len;
+
+	spec->hasMetaChars = 0;
+
+	/* Look at each character in the RE specification string for a 
+	 * meta character. Return when any meta character reached. */
+	while (c != end) {
+		switch (*c) {
+		case '.':
+		case '^':
+		case '$':
+		case '?':
+		case '*':
+		case '+':
+		case '|':
+		case '[':
+		case '(':
+		case '{':
+			spec->hasMetaChars = 1;
+			return;
+		case '\\':	/* skip the next character */
+			c++;
+			break;
+		default:
+			break;
+
+		}
+		c++;
+	}
+	return;
+}
+
 /* Return the length of the text that can be considered the stem, returns 0
  * if there is no identifiable stem */
 static inline int get_stem_from_spec(const char *const buf)
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 09/18] libselinux: label_file: fix potential read past buffer in spec_hasMetaChars
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (6 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 08/18] libselinux: label_file: move spec_hasMetaChars to header Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 10/18] libselinux: label_file: move regex sorting to the header Eric Paris
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

An illegal regex may end with a single \ followed by nul.  This could
cause us to search past the end of the character array.  The loop
formation looks like so:

        c = regex_str;
        len = strlen(c);
        end = c + len;

        while (c != end) {
		switch (*c) {
		...
                case '\\':      /* skip the next character */
                        c++;
                        break;
		...
                }
                c++;
	}

If the \ is the last character then we will increment c and break from
the switch.  The while loop will then increment c.  So now c == end+1.
This means we will keep running into infinity and beyond!  Easy fix.
Make the loop check (c < end).  Thus even if we jump past end, we still
exit the loop.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index b839a23..e520acc 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -88,7 +88,7 @@ static inline void spec_hasMetaChars(struct spec *spec)
 
 	/* Look at each character in the RE specification string for a 
 	 * meta character. Return when any meta character reached. */
-	while (c != end) {
+	while (c < end) {
 		switch (*c) {
 		case '.':
 		case '^':
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 10/18] libselinux: label_file: move regex sorting to the header
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (7 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 09/18] libselinux: label_file: fix potential read past buffer in spec_hasMetaChars Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 11/18] libselinux: label_file: add accessors for the pcre extra data Eric Paris
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

We want to do the same thing in the compiler and as we do in in the code
which reads regexes in from the text file.  Move that sorting into the header.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.c | 21 +++------------------
 libselinux/src/label_file.h | 22 ++++++++++++++++++++++
 2 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 8216840..0fba6aa 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -262,8 +262,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 	char subs_file[PATH_MAX + 1];
 	char *line_buf = NULL;
 	size_t line_len = 0;
-	unsigned int lineno, pass, i, j, maxnspec;
-	struct spec *spec_copy = NULL;
+	unsigned int lineno, pass, maxnspec;
 	int status = -1, baseonly = 0;
 	struct stat sb;
 
@@ -389,26 +388,12 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 	}
 	free(line_buf);
 
-	/* Move exact pathname specifications to the end. */
-	spec_copy = malloc(sizeof(*spec_copy) * data->nspec);
-	if (!spec_copy)
-		goto finish;
-	j = 0;
-	for (i = 0; i < data->nspec; i++)
-		if (data->spec_arr[i].hasMetaChars)
-			memcpy(&spec_copy[j++],
-			       &data->spec_arr[i], sizeof(spec_copy[j]));
-	for (i = 0; i < data->nspec; i++)
-		if (!data->spec_arr[i].hasMetaChars)
-			memcpy(&spec_copy[j++],
-			       &data->spec_arr[i], sizeof(spec_copy[j]));
-	free(data->spec_arr);
-	data->spec_arr = spec_copy;
+	status = sort_specs(data);
 
 	status = 0;
 finish:
 	fclose(fp);
-	if (data->spec_arr != spec_copy)
+	if (status)
 		free(data->spec_arr);
 	if (homedirfp)
 		fclose(homedirfp);
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index e520acc..c6c8ad3 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -114,6 +114,28 @@ static inline void spec_hasMetaChars(struct spec *spec)
 	return;
 }
 
+/* Move exact pathname specifications to the end. */
+static inline int sort_specs(struct saved_data *data)
+{
+	struct spec *spec_copy;
+	int i, j;
+
+	spec_copy = malloc(sizeof(*spec_copy) * data->nspec);
+	if (!spec_copy)
+		return -1;
+	j = 0;
+	for (i = 0; i < data->nspec; i++)
+		if (data->spec_arr[i].hasMetaChars)
+			memcpy(&spec_copy[j++], &data->spec_arr[i], sizeof(spec_copy[j]));
+	for (i = 0; i < data->nspec; i++)
+		if (!data->spec_arr[i].hasMetaChars)
+			memcpy(&spec_copy[j++], &data->spec_arr[i], sizeof(spec_copy[j]));
+	free(data->spec_arr);
+	data->spec_arr = spec_copy;
+
+	return 0;
+}
+
 /* Return the length of the text that can be considered the stem, returns 0
  * if there is no identifiable stem */
 static inline int get_stem_from_spec(const char *const buf)
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 11/18] libselinux: label_file: add accessors for the pcre extra data
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (8 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 10/18] libselinux: label_file: move regex sorting to the header Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 12/18] libselinux: label_file: only run regex files one time Eric Paris
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

When we use an mmap backed version of data we need to declare the pcre
extra data since we are only given a point to the data->buffer.  Since
sometimes the spec will hold a pointer to the extra data and sometimes
we want to declare it on the stack I introduce and use an accessor for
the extra data instead of using it directly.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.c | 4 ++--
 libselinux/src/label_file.h | 5 +++++
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 0fba6aa..0f4f9a5 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -490,9 +490,9 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
 			if (compile_regex(data, spec, NULL) < 0)
 				goto finish;
 			if (spec->stem_id == -1)
-				rc = pcre_exec(spec->regex, spec->sd, key, strlen(key), 0, 0, NULL, 0);
+				rc = pcre_exec(spec->regex, get_pcre_extra(spec), key, strlen(key), 0, 0, NULL, 0);
 			else
-				rc = pcre_exec(spec->regex, spec->sd, buf, strlen(buf), 0, 0, NULL, 0);
+				rc = pcre_exec(spec->regex, get_pcre_extra(spec), buf, strlen(buf), 0, 0, NULL, 0);
 
 			if (rc == 0) {
 				spec->matches++;
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index c6c8ad3..8c213d2 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -42,6 +42,11 @@ struct saved_data {
 	int alloc_stems;
 };
 
+static inline pcre_extra *get_pcre_extra(struct spec *spec)
+{
+	return spec->sd;
+}
+
 static inline mode_t string_to_mode(char *mode)
 {
 	size_t len;
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 12/18] libselinux: label_file: only run regex files one time
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (9 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 11/18] libselinux: label_file: add accessors for the pcre extra data Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 13/18] libselinux: label_file: new process_file function Eric Paris
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

We currectly run all of the regex files 2 times.  The first time counts
the lines and does the simple validatation.  We then allocate an array
of exactly the right size to hold the entries and run them a second time
doing stronger validation, regex compile, etc.

This is dumb.  Just run them one time and use realloc to grow the size
of the array as needed.  At the end the array will get sized perfectly
to fit by the sorting function, so even if we accidentally allocated
entra memory we'll get it back.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.c | 152 +++++++++++++++++---------------------------
 libselinux/src/label_file.h |  26 ++++++++
 2 files changed, 85 insertions(+), 93 deletions(-)

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 0f4f9a5..d53bc21 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -148,13 +148,14 @@ static int compile_regex(struct saved_data *data, struct spec *spec, const char
 
 static int process_line(struct selabel_handle *rec,
 			const char *path, const char **prefix_array,
-			char *line_buf, int pass, unsigned lineno)
+			char *line_buf, unsigned lineno)
 {
-	int items, len;
+	int items, len, rc;
 	char *buf_p, *regex, *type, *context;
 	struct saved_data *data = (struct saved_data *)rec->data;
-	struct spec *spec_arr = data->spec_arr;
+	struct spec *spec_arr;
 	unsigned int nspec = data->nspec;
+	const char *errbuf = NULL;
 
 	len = strlen(line_buf);
 	if (line_buf[len - 1] == '\n')
@@ -201,49 +202,44 @@ static int process_line(struct selabel_handle *rec,
 		}
 	}
 
-	if (pass == 1) {
-		/* On the second pass, process and store the specification in spec. */
-		const 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"));
-		}
+	rc = grow_specs(data);
+	if (rc)
+		return rc;
 
-		/* 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 == -1) {
-				COMPAT_LOG(SELINUX_WARNING,
-					"%s:  line %d has invalid file type %s\n",
-					path, lineno, type);
-				mode = 0;
-			}
-			spec_arr[nspec].mode = mode;
+	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 %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) {
+		mode_t mode = string_to_mode(type);
+		if (mode == -1) {
+			COMPAT_LOG(SELINUX_WARNING, "%s:  line %d has invalid file type %s\n",
+				   path, lineno, type);
+			mode = 0;
 		}
+		spec_arr[nspec].mode = mode;
+	}
 
-		spec_arr[nspec].lr.ctx_raw = context;
+	spec_arr[nspec].lr.ctx_raw = context;
 
-		/* Determine if specification has 
-		 * any meta characters in the RE */
-		spec_hasMetaChars(&spec_arr[nspec]);
+	/* 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);
-	}
+	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;
 }
 
@@ -262,7 +258,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 	char subs_file[PATH_MAX + 1];
 	char *line_buf = NULL;
 	size_t line_len = 0;
-	unsigned int lineno, pass, maxnspec;
+	unsigned int lineno;
 	int status = -1, baseonly = 0;
 	struct stat sb;
 
@@ -323,69 +319,39 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 	rec->spec_file = strdup(path);
 
 	/* 
-	 * Perform two passes over the specification file.
-	 * The first pass counts the number of specifications and
-	 * performs simple validation of the input.  At the end
-	 * of the first pass, the spec array is allocated.
-	 * The second pass performs detailed validation of the input
-	 * and fills in the spec array.
+	 * The do detailed validation of the input and fill the spec array
 	 */
-	maxnspec = UINT_MAX / sizeof(struct spec);
-	for (pass = 0; pass < 2; pass++) {
-		data->nspec = 0;
+	data->nspec = 0;
 
-		lineno = 0;
-		while (getline(&line_buf, &line_len, fp) > 0) {
-			if (data->nspec >= maxnspec)
-				break;
-			status = process_line(rec, path, prefix_array, line_buf, pass, ++lineno);
+	lineno = 0;
+	while (getline(&line_buf, &line_len, fp) > 0) {
+		status = process_line(rec, path, prefix_array, line_buf, ++lineno);
+		if (status)
+			goto finish;
+	}
+
+	if (rec->validating) {
+		status = nodups_specs(data, path);
+		if (status)
+			goto finish;
+	}
+
+	lineno = 0;
+	if (homedirfp)
+		while (getline(&line_buf, &line_len, homedirfp) > 0) {
+			status = process_line(rec, homedir_path, prefix_array, line_buf, ++lineno);
 			if (status)
 				goto finish;
 		}
 
-		if (pass == 1 && rec->validating) {
-			status = nodups_specs(data, path);
+	lineno = 0;
+	if (localfp)
+		while (getline(&line_buf, &line_len, localfp) > 0) {
+			status = process_line(rec, local_path, prefix_array, line_buf, ++lineno);
 			if (status)
 				goto finish;
 		}
 
-		lineno = 0;
-		if (homedirfp)
-			while (getline(&line_buf, &line_len, homedirfp) > 0) {
-				if (data->nspec >= maxnspec)
-					break;
-				status = process_line(rec, homedir_path, prefix_array, line_buf, pass, ++lineno);
-				if (status)
-					goto finish;
-			}
-
-		lineno = 0;
-		if (localfp)
-			while (getline(&line_buf, &line_len, localfp) > 0) {
-				if (data->nspec >= maxnspec)
-					break;
-				status = process_line(rec, local_path, prefix_array, line_buf, pass, ++lineno);
-				if (status)
-					goto finish;
-			}
-
-		if (pass == 0) {
-			if (data->nspec == 0) {
-				status = 0;
-				goto finish;
-			}
-			data->spec_arr = calloc(data->nspec, sizeof(*data->spec_arr));
-			if (!data->spec_arr)
-				goto finish;
-
-			maxnspec = data->nspec;
-			rewind(fp);
-			if (homedirfp)
-				rewind(homedirfp);
-			if (localfp)
-				rewind(localfp);
-		}
-	}
 	free(line_buf);
 
 	status = sort_specs(data);
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index 8c213d2..ddb7fbd 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -33,6 +33,7 @@ struct saved_data {
 	 */
 	struct spec *spec_arr;
 	unsigned int nspec;
+	unsigned int alloc_specs;
 
 	/*
 	 * The array of regular expression stems.
@@ -78,6 +79,31 @@ static inline mode_t string_to_mode(char *mode)
 	return 0;
 }
 
+static inline int grow_specs(struct saved_data *data)
+{
+	struct spec *specs;
+	size_t new_specs, total_specs;
+
+	if (data->nspec < data->alloc_specs)
+		return 0;
+
+	new_specs = data->nspec + 16;
+	total_specs = data->nspec + new_specs;
+	
+	specs = realloc(data->spec_arr, total_specs * sizeof(*specs));
+	if (!specs) {
+		perror("realloc");
+		return -1;
+	}
+
+	/* blank the new entries */
+	memset(&specs[data->nspec], 0, new_specs * sizeof(*specs));
+
+	data->spec_arr = specs;
+	data->alloc_specs = total_specs;
+	return 0;
+}
+
 /* Determine if the regular expression specification has any meta characters. */
 static inline void spec_hasMetaChars(struct spec *spec)
 {
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 13/18] libselinux: label_file: new process_file function
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (10 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 12/18] libselinux: label_file: only run regex files one time Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 14/18] libselinux: label_file: break up find_stem_from_spec Eric Paris
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

We currently duplicate code 3 times for the main file, the homedirs, and
the local file.  Just put that stuff in its own function so we don't
have to deal with it multiple times.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.c | 123 +++++++++++++++++++++-----------------------
 1 file changed, 59 insertions(+), 64 deletions(-)

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index d53bc21..0815d12 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -243,6 +243,53 @@ static int process_line(struct selabel_handle *rec,
 	return 0;
 }
 
+static int process_file(const char *path, const char *suffix, struct selabel_handle *rec, const char **prefix_array)
+{
+	FILE *fp;
+	struct stat sb;
+	unsigned int lineno;
+	size_t line_len;
+	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);
+		if (rc >= sizeof(stack_path)) {
+			errno = ENAMETOOLONG;
+			return -1;
+		}
+		path = stack_path;
+	}
+
+	/* Open the specification file. */
+	if ((fp = fopen(path, "r")) == NULL)
+		return -1;
+	__fsetlocking(fp, FSETLOCKING_BYCALLER);
+
+	if (fstat(fileno(fp), &sb) < 0)
+		return -1;
+	if (!S_ISREG(sb.st_mode)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* 
+	 * The do detailed validation of the input and fill the spec array
+	 */
+	lineno = 0;
+	while (getline(&line_buf, &line_len, fp) > 0) {
+		rc = process_line(rec, path, prefix_array, line_buf, ++lineno);
+		if (rc)
+			return rc;
+	}
+	free(line_buf);
+	fclose(fp);
+
+	return 0;
+}
+
 static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 		unsigned n)
 {
@@ -250,17 +297,8 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 	const char *path = NULL;
 	const char *static_prefix_array[2] = {NULL, };
 	const char **prefix_array = static_prefix_array;
-	FILE *fp;
-	FILE *localfp = NULL;
-	FILE *homedirfp = NULL;
-	char local_path[PATH_MAX + 1];
-	char homedir_path[PATH_MAX + 1];
 	char subs_file[PATH_MAX + 1];
-	char *line_buf = NULL;
-	size_t line_len = 0;
-	unsigned int lineno;
 	int status = -1, baseonly = 0;
-	struct stat sb;
 
 	/* Process arguments */
 	while (n--)
@@ -283,6 +321,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 	if (!path) {
 		rec->subs = selabel_subs_init(selinux_file_context_subs_dist_path(), rec->subs);
 		rec->subs = selabel_subs_init(selinux_file_context_subs_path(), rec->subs);
+		path = selinux_file_context_path();
 	} else {
 		snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", path);
 		rec->subs = selabel_subs_init(subs_file, rec->subs);
@@ -290,45 +329,14 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 		rec->subs = selabel_subs_init(subs_file, rec->subs);
 	}
 
-	/* Open the specification file. */
-	if (!path)
-		path = selinux_file_context_path();
-	if ((fp = fopen(path, "r")) == NULL)
-		return -1;
-	__fsetlocking(fp, FSETLOCKING_BYCALLER);
-
-	if (fstat(fileno(fp), &sb) < 0)
-		return -1;
-	if (!S_ISREG(sb.st_mode)) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	if (!baseonly) {
-		snprintf(homedir_path, sizeof(homedir_path), "%s.homedirs",
-			 path);
-		homedirfp = fopen(homedir_path, "r");
-		if (homedirfp != NULL)
-			__fsetlocking(homedirfp, FSETLOCKING_BYCALLER);
-
-		snprintf(local_path, sizeof(local_path), "%s.local", path);
-		localfp = fopen(local_path, "r");
-		if (localfp != NULL)
-			__fsetlocking(localfp, FSETLOCKING_BYCALLER);
-	}
 	rec->spec_file = strdup(path);
 
 	/* 
 	 * The do detailed validation of the input and fill the spec array
 	 */
-	data->nspec = 0;
-
-	lineno = 0;
-	while (getline(&line_buf, &line_len, fp) > 0) {
-		status = process_line(rec, path, prefix_array, line_buf, ++lineno);
-		if (status)
-			goto finish;
-	}
+	status = process_file(path, NULL, rec, prefix_array);
+	if (status)
+		goto finish;
 
 	if (rec->validating) {
 		status = nodups_specs(data, path);
@@ -336,35 +344,22 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 			goto finish;
 	}
 
-	lineno = 0;
-	if (homedirfp)
-		while (getline(&line_buf, &line_len, homedirfp) > 0) {
-			status = process_line(rec, homedir_path, prefix_array, line_buf, ++lineno);
-			if (status)
-				goto finish;
-		}
-
-	lineno = 0;
-	if (localfp)
-		while (getline(&line_buf, &line_len, localfp) > 0) {
-			status = process_line(rec, local_path, prefix_array, line_buf, ++lineno);
-			if (status)
-				goto finish;
-		}
+	if (!baseonly) {
+		status = process_file(path, "homedirs", rec, prefix_array);
+		if (status && errno != ENOENT)
+			goto finish;
 
-	free(line_buf);
+		status = process_file(path, "local", rec, prefix_array);
+		if (status && errno != ENOENT)
+			goto finish;
+	}
 
 	status = sort_specs(data);
 
 	status = 0;
 finish:
-	fclose(fp);
 	if (status)
 		free(data->spec_arr);
-	if (homedirfp)
-		fclose(homedirfp);
-	if (localfp)
-		fclose(localfp);
 	return status;
 }
 
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 14/18] libselinux: label_file: break up find_stem_from_spec
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (11 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 13/18] libselinux: label_file: new process_file function Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 15/18] libselinux: label_file: struct reorg Eric Paris
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

Right now find_stem_from_spec does a number of things:
- calculate the length of th stem
- look for that stem
- duplicate the stem
- add the stem to the array

break those things up a bit because the mmap version isn't going to need
to do some of those things.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.h | 61 ++++++++++++++++++++++++++++++++-------------
 1 file changed, 44 insertions(+), 17 deletions(-)

diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index ddb7fbd..1208d8b 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -184,23 +184,30 @@ static inline int get_stem_from_spec(const char *const buf)
 	return tmp - buf;
 }
 
-/* find the stem of a file spec, returns the index into stem_arr for a new
- * or existing stem, (or -1 if there is no possible stem - IE for a file in
- * the root directory or a regex that is too complex for us). */
-static inline int find_stem_from_spec(struct saved_data *data, const char *buf)
+/*
+ * return the stemid given a string and a length
+ */
+static inline int find_stem(struct saved_data *data, const char *buf, int stem_len)
 {
-	int i, num = data->num_stems;
-	int stem_len = get_stem_from_spec(buf);
+	int i;
 
-	if (!stem_len)
-		return -1;
-	for (i = 0; i < num; i++) {
-		if (stem_len == data->stem_arr[i].len
-		    && !strncmp(buf, data->stem_arr[i].buf, stem_len))
+	for (i = 0; i < data->num_stems; i++) {
+		if (stem_len == data->stem_arr[i].len &&
+		    !strncmp(buf, data->stem_arr[i].buf, stem_len))
 			return i;
 	}
+
+	return -1;
+}
+
+/* returns the index of the new stored object */
+static inline int store_stem(struct saved_data *data, char *buf, int stem_len)
+{
+	int num = data->num_stems;
+
 	if (data->alloc_stems == num) {
 		struct stem *tmp_arr;
+
 		data->alloc_stems = data->alloc_stems * 2 + 16;
 		tmp_arr = realloc(data->stem_arr,
 				  sizeof(*tmp_arr) * data->alloc_stems);
@@ -209,14 +216,34 @@ static inline int find_stem_from_spec(struct saved_data *data, const char *buf)
 		data->stem_arr = tmp_arr;
 	}
 	data->stem_arr[num].len = stem_len;
-	data->stem_arr[num].buf = malloc(stem_len + 1);
-	if (!data->stem_arr[num].buf)
-		return -1;
-	memcpy(data->stem_arr[num].buf, buf, stem_len);
-	data->stem_arr[num].buf[stem_len] = '\0';
+	data->stem_arr[num].buf = buf;
 	data->num_stems++;
-	buf += stem_len;
+
 	return num;
 }
 
+/* find the stem of a file spec, returns the index into stem_arr for a new
+ * or existing stem, (or -1 if there is no possible stem - IE for a file in
+ * the root directory or a regex that is too complex for us). */
+static inline int find_stem_from_spec(struct saved_data *data, const char *buf)
+{
+	int stem_len = get_stem_from_spec(buf);
+	int stemid;
+	char *stem;
+
+	if (!stem_len)
+		return -1;
+
+	stemid = find_stem(data, buf, stem_len);
+	if (stemid >= 0)
+		return stemid;
+
+	/* not found, allocate a new one */
+	stem = strndup(buf, stem_len);
+	if (!stem)
+		return -1;
+
+	return store_stem(data, stem, stem_len);
+}
+
 #endif /* _SELABEL_FILE_H_ */
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 15/18] libselinux: label_file: struct reorg
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (12 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 14/18] libselinux: label_file: break up find_stem_from_spec Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 16/18] libselinux: label_file: only run array once when sorting Eric Paris
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

Use char instead of int, reorder to put the chars together.  Just litle
things.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index 1208d8b..ef97213 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -12,11 +12,11 @@ struct spec {
 	char *type_str;		/* type string for diagnostic messages */
 	pcre *regex;		/* compiled regular expression */
 	pcre_extra *sd;		/* extra compiled stuff */
-	char regcomp;		/* regex_str has been compiled to regex */
 	mode_t mode;		/* mode format value */
 	int matches;		/* number of matching pathnames */
-	int hasMetaChars;	/* regular expression has meta-chars */
 	int stem_id;		/* indicates which stem-compression item */
+	char hasMetaChars;	/* regular expression has meta-chars */
+	char regcomp;		/* regex_str has been compiled to regex */
 };
 
 /* A regular expression stem */
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 16/18] libselinux: label_file: only run array once when sorting
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (13 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 15/18] libselinux: label_file: struct reorg Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 17/18] libselinux: utils: new file context regex compiler Eric Paris
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

Instead of running the array two times, sorting the 'hasMeta' the first
time and the !hasMeta the second, run the array once putting hasMeta in
the front and !hasMeta in the back.  Then ONLY run the !hasMeta section
a second time reversing its order so its sorted as it should be.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.h | 40 ++++++++++++++++++++++++++++++++--------
 1 file changed, 32 insertions(+), 8 deletions(-)

diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index ef97213..8e6f550 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -149,18 +149,42 @@ static inline void spec_hasMetaChars(struct spec *spec)
 static inline int sort_specs(struct saved_data *data)
 {
 	struct spec *spec_copy;
-	int i, j;
+	struct spec spec;
+	int i;
+	int front, back;
+	size_t len = sizeof(*spec_copy);
 
-	spec_copy = malloc(sizeof(*spec_copy) * data->nspec);
+	spec_copy = malloc(len * data->nspec);
 	if (!spec_copy)
 		return -1;
-	j = 0;
-	for (i = 0; i < data->nspec; i++)
+
+	/* first move the exact pathnames to the back */
+	front = 0;
+	back = data->nspec - 1;
+	for (i = 0; i < data->nspec; i++) {
 		if (data->spec_arr[i].hasMetaChars)
-			memcpy(&spec_copy[j++], &data->spec_arr[i], sizeof(spec_copy[j]));
-	for (i = 0; i < data->nspec; i++)
-		if (!data->spec_arr[i].hasMetaChars)
-			memcpy(&spec_copy[j++], &data->spec_arr[i], sizeof(spec_copy[j]));
+			memcpy(&spec_copy[front++], &data->spec_arr[i], len);
+		else
+			memcpy(&spec_copy[back--], &data->spec_arr[i], len);
+	}
+
+	/*
+	 * now the exact pathnames are at the end, but they are in the reverse order.
+	 * since 'front' is now the first of the 'exact' we can run that part of the
+	 * array switching the front and back element.
+	 */
+	back = data->nspec - 1;
+	while (front < back) {
+		/* save the front */
+		memcpy(&spec, &spec_copy[front], len);
+		/* move the back to the front */
+		memcpy(&spec_copy[front], &spec_copy[back], len);
+		/* put the old front in the back */
+		memcpy(&spec_copy[back], &spec, len);
+		front++;
+		back--;
+	}
+
 	free(data->spec_arr);
 	data->spec_arr = spec_copy;
 
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 17/18] libselinux: utils: new file context regex compiler
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (14 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 16/18] libselinux: label_file: only run array once when sorting Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 17:49 ` [PATCH 18/18] libselinux: label_file: use precompiled filecontext when possible Eric Paris
  2012-08-31 18:36 ` [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Stephen Smalley
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

This is a new 'compiler' which tranforms the file context database into
a binary format.  This binary format may be mmap'd in later removing the
need to compile the regular expression at run time.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/utils/.gitignore           |   1 +
 libselinux/utils/Makefile             |   1 +
 libselinux/utils/sefcontext_compile.c | 338 ++++++++++++++++++++++++++++++++++
 3 files changed, 340 insertions(+)
 create mode 100644 libselinux/utils/sefcontext_compile.c

diff --git a/libselinux/utils/.gitignore b/libselinux/utils/.gitignore
index 8b9294d..060eaab 100644
--- a/libselinux/utils/.gitignore
+++ b/libselinux/utils/.gitignore
@@ -13,6 +13,7 @@ getsebool
 getseuser
 matchpathcon
 policyvers
+sefcontext_compile
 selinux_check_securetty_context
 selinuxenabled
 selinuxexeccon
diff --git a/libselinux/utils/Makefile b/libselinux/utils/Makefile
index 5f3e047..f469924 100644
--- a/libselinux/utils/Makefile
+++ b/libselinux/utils/Makefile
@@ -28,6 +28,7 @@ LDLIBS += -L../src -lselinux -L$(LIBDIR)
 
 TARGETS=$(patsubst %.c,%,$(wildcard *.c))
 
+sefcontext_compile: LDLIBS += -lpcre
 
 ifeq ($(DISABLE_AVC),y)
 	UNUSED_TARGETS+=compute_av compute_create compute_member compute_relabel
diff --git a/libselinux/utils/sefcontext_compile.c b/libselinux/utils/sefcontext_compile.c
new file mode 100644
index 0000000..2393763
--- /dev/null
+++ b/libselinux/utils/sefcontext_compile.c
@@ -0,0 +1,338 @@
+#include <ctype.h>
+#include <errno.h>
+#include <pcre.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <linux/limits.h>
+
+#include "../src/label_file.h"
+
+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)
+		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", &regex, &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)
+			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)
+			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;
+}
+
+/*
+ * File Format
+ *
+ * u32 - magic number
+ * u32 - number of stems
+ * ** Stems
+ * 	u32  - length of stem EXCLUDING nul
+ * 	char - stem char array INCLUDING nul
+ * u32 - number of regexs
+ * ** Regexes
+ * 	u32  - length of upcoming context INCLUDING nul
+ * 	char - char array of the raw context
+ *	u32  - length of the upcoming regex_str
+ *	char - char array of the original regex string including the stem.
+ *	mode_t - mode bits
+ *	s32  - stemid associated with the regex
+ *	u32  - spec has meta characters
+ *	u32  - data length of the pcre regex
+ *	char - a bufer holding the raw pcre regex info
+ *	u32  - data length of the pcre regex study daya
+ *	char - a buffer holding the raw pcre regex study data
+ */
+static int write_binary_file(struct saved_data *data, char *filename)
+{
+	struct spec *specs = data->spec_arr;
+	FILE *bin_file;
+	size_t len;
+	uint32_t magic = 0xdeadbeef;
+	uint32_t section_len;
+	uint32_t i;
+
+	bin_file = fopen(filename, "w");
+	if (!bin_file) {
+		perror("fopen output_file");
+		exit(EXIT_FAILURE);
+	}
+
+	/* write some magic number or version or soemthing FIXME "*/
+	len = fwrite(&magic, sizeof(uint32_t), 1, bin_file);
+	if (len != 1)
+		return -1;
+
+	/* write the number of stems coming */
+	section_len = data->num_stems;
+	len = fwrite(&section_len, sizeof(uint32_t), 1, bin_file);
+	if (len != 1)
+		return -1;
+
+	for (i = 0; i < section_len; i++) {
+		char *stem = data->stem_arr[i].buf;
+		uint32_t stem_len = data->stem_arr[i].len;
+		
+		/* write the strlen (aka no nul) */
+		len = fwrite(&stem_len, sizeof(uint32_t), 1, bin_file);
+		if (len != 1)
+			return -1;
+
+		/* include the nul in the file */
+		stem_len += 1;
+		len = fwrite(stem, sizeof(char), stem_len, bin_file);
+		if (len != stem_len)
+			return -1;
+	}
+
+	/* write the number of regexes coming */
+	section_len = data->nspec;
+	len = fwrite(&section_len, sizeof(uint32_t), 1, bin_file);
+	if (len != 1)
+		return -1;
+
+	for (i = 0; i < section_len; i++) {
+		char *context = specs[i].lr.ctx_raw;
+		char *regex_str = specs[i].regex_str;
+		mode_t mode = specs[i].mode;
+		int32_t stem_id = specs[i].stem_id;
+		pcre *re = specs[i].regex;
+		pcre_extra *sd = get_pcre_extra(&specs[i]);
+		uint32_t to_write;
+		size_t size;
+		int rc;
+
+		/* length of the context string (including nul) */
+		to_write = strlen(context) + 1;
+		len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file);
+		if (len != 1)
+			return -1;
+
+		/* original context strin (including nul) */
+		len = fwrite(context, sizeof(char), to_write, bin_file);
+		if (len != to_write)
+			return -1;
+
+		/* length of the original regex string (including nul) */
+		to_write = strlen(regex_str) + 1;
+		len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file);
+		if (len != 1)
+			return -1;
+
+		/* original regex string */
+		len = fwrite(regex_str, sizeof(char), to_write, bin_file);
+		if (len != to_write)
+			return -1;
+
+		/* binary F_MODE bits */
+		len = fwrite(&mode, sizeof(mode), 1, bin_file);
+		if (len != 1)
+			return -1;
+
+		/* stem for this regex (could be -1) */
+		len = fwrite(&stem_id, sizeof(stem_id), 1, bin_file);
+		if (len != 1)
+			return -1;
+
+		/* does this spec have a metaChar? */
+		to_write = specs[i].hasMetaChars;
+		len = fwrite(&to_write, sizeof(to_write), 1, bin_file);
+		if (len != 1)
+			return -1;
+
+		/* determine the size of the pcre data in bytes */
+		rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size);
+		if (rc < 0)
+			return -1;
+
+		/* write the number of bytes in the pcre data */
+		to_write = size;
+		len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file);
+		if (len != 1)
+			return -1;
+
+		/* write the actual pcre data as a char array */
+		len = fwrite(re, 1, to_write, bin_file);
+		if (len != to_write)
+			return -1;
+
+		/* determine the size of the pcre study info */
+		rc = pcre_fullinfo(re, sd, PCRE_INFO_STUDYSIZE, &size);
+		if (rc < 0)
+			return -1;
+
+		/* write the number of bytes in the pcre study data */
+		to_write = size;
+		len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file);
+		if (len != 1)
+			return -1;
+
+		/* write the actual pcre study data as a char array */
+		len = fwrite(sd->study_data, 1, to_write, bin_file);
+		if (len != to_write)
+			return -1;
+	}
+
+	fclose(bin_file);
+
+	return 0;
+}
+
+static int free_specs(struct saved_data *data)
+{
+	struct spec *specs = data->spec_arr;
+	unsigned int num_entries = data->nspec;
+	unsigned int i;
+
+	for (i = 0; i < num_entries; i++) {
+		free(specs[i].lr.ctx_raw);
+		free(specs[i].lr.ctx_trans);
+		free(specs[i].regex_str);
+		pcre_free(specs[i].regex);
+		pcre_free_study(specs[i].sd);
+	}
+	free(specs);
+
+	num_entries = data->num_stems;
+	for (i = 0; i < num_entries; i++) {
+		free(data->stem_arr[i].buf);
+	}
+	free(data->stem_arr);
+
+	memset(data, 0, sizeof(*data));
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	struct saved_data data;
+	const char *path;
+	char stack_path[PATH_MAX + 1];
+	int rc;
+
+	if (argc != 2) {
+		fprintf(stderr, "usage: %s input_file\n", argv[0]);
+		exit(EXIT_FAILURE);
+	}
+
+	memset(&data, 0, sizeof(data));
+
+	path = argv[1];
+
+	rc = process_file(&data, path);
+	if (rc < 0)
+		return rc;
+
+	rc = sort_specs(&data);
+	if (rc)
+		return rc;
+
+	rc = snprintf(stack_path, sizeof(stack_path), "%s.bin", path);
+	if (rc < 0 || rc >= sizeof(stack_path))
+		return rc;
+	rc = write_binary_file(&data, stack_path);
+	if (rc < 0)
+		return rc;
+
+	rc = free_specs(&data);
+	if (rc < 0)
+		return rc;
+
+	return 0;
+}
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 18/18] libselinux: label_file: use precompiled filecontext when possible
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (15 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 17/18] libselinux: utils: new file context regex compiler Eric Paris
@ 2012-08-31 17:49 ` Eric Paris
  2012-08-31 18:36 ` [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Stephen Smalley
  17 siblings, 0 replies; 20+ messages in thread
From: Eric Paris @ 2012-08-31 17:49 UTC (permalink / raw)
  To: sds; +Cc: selinux, Eric Paris

When loading the filecontext database, check to see if there is a newer
binary version.  If so, mmap that file, is used to populate the regex db
instead of reading from the text representation and compiling regex's as
needed.  If the text file is newer it will use the text version and
ignore the binary version.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
 libselinux/src/label_file.c | 169 ++++++++++++++++++++++++++++++++++++++++++++
 libselinux/src/label_file.h |  12 +++-
 2 files changed, 179 insertions(+), 2 deletions(-)

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 0815d12..2421186 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -8,6 +8,7 @@
  * developed by Secure Computing Corporation.
  */
 
+#include <assert.h>
 #include <fcntl.h>
 #include <stdarg.h>
 #include <string.h>
@@ -16,7 +17,12 @@
 #include <ctype.h>
 #include <errno.h>
 #include <limits.h>
+#include <stdint.h>
 #include <pcre.h>
+
+#include <linux/limits.h>
+
+#include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -243,6 +249,160 @@ static int process_line(struct selabel_handle *rec,
 	return 0;
 }
 
+static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *stat)
+{
+	struct saved_data *data = (struct saved_data *)rec->data;
+	char mmap_path[PATH_MAX + 1];
+	int mmapfd;
+	int rc, i;
+	struct stat mmap_stat;
+	char *addr;
+	size_t len;
+	int stem_map_len, *stem_map;
+
+	uint32_t *magic;
+	uint32_t *section_len;
+	uint32_t *plen;
+
+	rc = snprintf(mmap_path, sizeof(mmap_path), "%s.bin", path);
+	if (rc >= sizeof(mmap_path))
+		return -1;
+
+	mmapfd = open(mmap_path, O_RDONLY);
+	if (!mmapfd)
+		return -1;
+
+	rc = fstat(mmapfd, &mmap_stat);
+	if (rc < 0)
+		return -1;
+
+	/* if mmap is old, ignore it */
+	if (mmap_stat.st_mtime < stat->st_mtime)
+		return -1;
+
+	if (mmap_stat.st_mtime == stat->st_mtime &&
+	    mmap_stat.st_mtim.tv_nsec < stat->st_mtim.tv_nsec)
+		return -1;
+	
+	/* ok, read it in... */
+	len = mmap_stat.st_size;
+	len += (sysconf(_SC_PAGE_SIZE) - 1);
+	len &= ~(sysconf(_SC_PAGE_SIZE) - 1);
+
+	addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, mmapfd, 0);
+	close(mmapfd);
+	if (addr == MAP_FAILED) {
+		perror("mmap");
+		return -1;
+	}
+
+	magic = (uint32_t *)addr;
+	if (*magic != 0xdeadbeef)
+		return -1;
+	addr += sizeof(uint32_t);
+
+	/* allocate the stems_data array */
+	section_len = (uint32_t *)addr;
+	addr += sizeof(uint32_t);
+
+	/*
+	 * map indexed by the stem # in the mmap file and contains the stem
+	 * number in the data stem_arr
+	 */
+	stem_map_len = *section_len;
+	stem_map = calloc(stem_map_len, sizeof(*stem_map));
+	if (!stem_map)
+		return -1;
+
+	for (i = 0; i < *section_len; i++) {
+		char *buf;
+		uint32_t stem_len;
+		int newid;
+
+		/* the length does not inlude the nul */
+		plen = (uint32_t *)addr;
+		addr += sizeof(uint32_t);
+
+		stem_len = *plen;
+		buf = (char *)addr;
+		addr += (stem_len + 1); // +1 is the nul
+
+		/* store the mapping between old and new */
+		newid = find_stem(data, buf, stem_len);
+		if (newid < 0) {
+			newid = store_stem(data, buf, stem_len);
+			if (newid < 0)
+				return newid;
+			data->stem_arr[newid].from_mmap = 1;
+		}
+		stem_map[i] = newid;
+	}
+
+	/* allocate the regex array */
+	section_len = (uint32_t *)addr;
+	addr += sizeof(*section_len);
+
+	for (i = 0; i < *section_len; i++) {
+		struct spec *spec;
+		int32_t stem_id;
+
+		rc = grow_specs(data);
+		if (rc < 0)
+			return rc;
+
+		spec = &data->spec_arr[data->nspec];
+		spec->from_mmap = 1;
+		spec->regcomp = 1;
+
+		plen = (uint32_t *)addr;
+		addr += sizeof(uint32_t);
+		spec->lr.ctx_raw = strdup((char *)addr);
+		if (!spec->lr.ctx_raw)
+			return -1;
+		addr += *plen;
+
+		plen = (uint32_t *)addr;
+		addr += sizeof(uint32_t);
+		spec->regex_str = (char *)addr;
+		addr += *plen;
+
+		spec->mode = *(mode_t *)addr;
+		addr += sizeof(mode_t);
+
+		/* map the stem id from the mmap file to the data->stem_arr */
+		stem_id = *(int32_t *)addr;
+		if (stem_id == -1) {
+			spec->stem_id = -1;
+		} else {
+			assert(stem_id <= stem_map_len);
+			spec->stem_id = stem_map[stem_id];
+		}
+		addr += sizeof(int32_t);
+
+		/* retrieve the hasMetaChars bit */
+		spec->hasMetaChars = *(uint32_t *)addr;
+		addr += sizeof(uint32_t);
+
+		plen = (uint32_t *)addr;
+		addr += sizeof(uint32_t);
+		spec->regex = (pcre *)addr;
+		addr += *plen;
+
+		plen = (uint32_t *)addr;
+		addr += sizeof(uint32_t);
+		spec->lsd.study_data = (void *)addr;
+		spec->lsd.flags |= PCRE_EXTRA_STUDY_DATA;
+		addr += *plen;
+
+		data->nspec++;
+	}
+
+	free(stem_map);
+
+	/* win */
+	return 0;
+}
+
 static int process_file(const char *path, const char *suffix, struct selabel_handle *rec, const char **prefix_array)
 {
 	FILE *fp;
@@ -275,6 +435,10 @@ static int process_file(const char *path, const char *suffix, struct selabel_han
 		return -1;
 	}
 
+	rc = load_mmap(rec, path, &sb);
+	if (rc == 0)
+		goto out;
+
 	/* 
 	 * The do detailed validation of the input and fill the spec array
 	 */
@@ -284,6 +448,7 @@ static int process_file(const char *path, const char *suffix, struct selabel_han
 		if (rc)
 			return rc;
 	}
+out:
 	free(line_buf);
 	fclose(fp);
 
@@ -375,6 +540,8 @@ static void closef(struct selabel_handle *rec)
 
 	for (i = 0; i < data->nspec; i++) {
 		spec = &data->spec_arr[i];
+		if (spec->from_mmap)
+			continue;
 		free(spec->regex_str);
 		free(spec->type_str);
 		free(spec->lr.ctx_raw);
@@ -387,6 +554,8 @@ static void closef(struct selabel_handle *rec)
 
 	for (i = 0; i < (unsigned int)data->num_stems; i++) {
 		stem = &data->stem_arr[i];
+		if (stem->from_mmap)
+			continue;
 		free(stem->buf);
 	}
 
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index 8e6f550..5765fd4 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -11,18 +11,23 @@ struct spec {
 	char *regex_str;	/* regular expession string for diagnostics */
 	char *type_str;		/* type string for diagnostic messages */
 	pcre *regex;		/* compiled regular expression */
-	pcre_extra *sd;		/* extra compiled stuff */
+	union {
+		pcre_extra *sd;	/* pointer to extra compiled stuff */
+		pcre_extra lsd;	/* used to hold the mmap'd version */
+	};
 	mode_t mode;		/* mode format value */
 	int matches;		/* number of matching pathnames */
 	int stem_id;		/* indicates which stem-compression item */
 	char hasMetaChars;	/* regular expression has meta-chars */
 	char regcomp;		/* regex_str has been compiled to regex */
+	char from_mmap;		/* this spec is from an mmap of the data */
 };
 
 /* A regular expression stem */
 struct stem {
 	char *buf;
 	int len;
+	char from_mmap;
 };
 
 /* Our stored configuration */
@@ -45,7 +50,10 @@ struct saved_data {
 
 static inline pcre_extra *get_pcre_extra(struct spec *spec)
 {
-	return spec->sd;
+	if (spec->from_mmap)
+		return &spec->lsd;
+	else
+		return spec->sd;
 }
 
 static inline mode_t string_to_mode(char *mode)
-- 
1.7.11.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions
  2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
                   ` (16 preceding siblings ...)
  2012-08-31 17:49 ` [PATCH 18/18] libselinux: label_file: use precompiled filecontext when possible Eric Paris
@ 2012-08-31 18:36 ` Stephen Smalley
  2012-09-02 22:51   ` Guido Trentalancia
  17 siblings, 1 reply; 20+ messages in thread
From: Stephen Smalley @ 2012-08-31 18:36 UTC (permalink / raw)
  To: Eric Paris; +Cc: sds, selinux

On Fri, Aug 31, 2012 at 1:49 PM, Eric Paris <eparis@redhat.com> wrote:
> The PCRE functions are about x10 faster than the glibc functions.  So
> use the external library.
>
> Signed-off-by: Eric Paris <eparis@redhat.com>
> ---
>  libselinux/src/Makefile     |  2 ++
>  libselinux/src/label_file.c | 63 ++++++++++++++++++++++++---------------------
>  2 files changed, 35 insertions(+), 30 deletions(-)
>
> diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
> index 74e53bb..ac019df 100644
> --- a/libselinux/src/Makefile
> +++ b/libselinux/src/Makefile
> @@ -20,6 +20,8 @@ RUBYINC ?= $(shell pkg-config --cflags ruby-$(RUBYLIBVER))
>  RUBYINSTALL ?= $(LIBDIR)/ruby/site_ruby/$(RUBYLIBVER)/$(RUBYPLATFORM)
>  LIBBASE=$(shell basename $(LIBDIR))
>
> +LDFLAGS ?= -lpcre
> +
>  VERSION = $(shell cat ../VERSION)
>  LIBVERSION = 1

Minor nit: I think normally it would be added to LDLIBS rather than
LDFLAGS, so maybe add a LDLIBS += -lselinux -lpcre to the Makefile and
then replace all instances of -lselinux with $(LDLIBS).

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions
  2012-08-31 18:36 ` [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Stephen Smalley
@ 2012-09-02 22:51   ` Guido Trentalancia
  0 siblings, 0 replies; 20+ messages in thread
From: Guido Trentalancia @ 2012-09-02 22:51 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Eric Paris, sds, selinux

On 31/08/2012 20:36, Stephen Smalley wrote:
> On Fri, Aug 31, 2012 at 1:49 PM, Eric Paris <eparis@redhat.com> wrote:
>> The PCRE functions are about x10 faster than the glibc functions.  So
>> use the external library.
>>
>> Signed-off-by: Eric Paris <eparis@redhat.com>
>> ---
>>   libselinux/src/Makefile     |  2 ++
>>   libselinux/src/label_file.c | 63 ++++++++++++++++++++++++---------------------
>>   2 files changed, 35 insertions(+), 30 deletions(-)
>>
>> diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
>> index 74e53bb..ac019df 100644
>> --- a/libselinux/src/Makefile
>> +++ b/libselinux/src/Makefile
>> @@ -20,6 +20,8 @@ RUBYINC ?= $(shell pkg-config --cflags ruby-$(RUBYLIBVER))
>>   RUBYINSTALL ?= $(LIBDIR)/ruby/site_ruby/$(RUBYLIBVER)/$(RUBYPLATFORM)
>>   LIBBASE=$(shell basename $(LIBDIR))
>>
>> +LDFLAGS ?= -lpcre
>> +
>>   VERSION = $(shell cat ../VERSION)
>>   LIBVERSION = 1
>
> Minor nit: I think normally it would be added to LDLIBS rather than
> LDFLAGS, so maybe add a LDLIBS += -lselinux -lpcre to the Makefile and
> then replace all instances of -lselinux with $(LDLIBS).

Only a few days ago, we realized the (rather high) cost of external 
dependencies with the incompatibility generated in SELinux userspace by 
more recent swig versions (>2.0.4 or something similar).

If the regex functions' speed in glibc is a general issue perhaps it 
would be more profitable to import a fix from pcre into glibc ?

If not, perhaps it would at least be possible to add the changes with 
conditional selection so that we can keep the existing glibc code as a 
fallback option ?

Regards,

Guido

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2012-09-02 22:51 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-31 17:49 [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Eric Paris
2012-08-31 17:49 ` [PATCH 02/18] libselinux: label_file: remove all typedefs Eric Paris
2012-08-31 17:49 ` [PATCH 03/18] libselinux: label_file: move definitions to include file Eric Paris
2012-08-31 17:49 ` [PATCH 04/18] libselinux: label_file: do string to mode_t conversion in a helper function Eric Paris
2012-08-31 17:49 ` [PATCH 05/18] libselinux: label_file: move error reporting back into caller Eric Paris
2012-08-31 17:49 ` [PATCH 06/18] libselinux: label_file: move stem/spec handling to header Eric Paris
2012-08-31 17:49 ` [PATCH 07/18] libselinux: label_file: drop useless ncomp field from label_file data Eric Paris
2012-08-31 17:49 ` [PATCH 08/18] libselinux: label_file: move spec_hasMetaChars to header Eric Paris
2012-08-31 17:49 ` [PATCH 09/18] libselinux: label_file: fix potential read past buffer in spec_hasMetaChars Eric Paris
2012-08-31 17:49 ` [PATCH 10/18] libselinux: label_file: move regex sorting to the header Eric Paris
2012-08-31 17:49 ` [PATCH 11/18] libselinux: label_file: add accessors for the pcre extra data Eric Paris
2012-08-31 17:49 ` [PATCH 12/18] libselinux: label_file: only run regex files one time Eric Paris
2012-08-31 17:49 ` [PATCH 13/18] libselinux: label_file: new process_file function Eric Paris
2012-08-31 17:49 ` [PATCH 14/18] libselinux: label_file: break up find_stem_from_spec Eric Paris
2012-08-31 17:49 ` [PATCH 15/18] libselinux: label_file: struct reorg Eric Paris
2012-08-31 17:49 ` [PATCH 16/18] libselinux: label_file: only run array once when sorting Eric Paris
2012-08-31 17:49 ` [PATCH 17/18] libselinux: utils: new file context regex compiler Eric Paris
2012-08-31 17:49 ` [PATCH 18/18] libselinux: label_file: use precompiled filecontext when possible Eric Paris
2012-08-31 18:36 ` [PATCH 01/18] libselinux: label_file: use PCRE instead of glibc regex functions Stephen Smalley
2012-09-02 22:51   ` Guido Trentalancia

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.