All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Cashman <dcashman@android.com>
To: selinux@tycho.nsa.gov
Cc: jeffv@google.com, jwcart2@tycho.nsa.gov, dcashman@google.com,
	dcashman@android.com
Subject: [PATCH] selinux: libselinux: Enable multiple input files to selabel_open.
Date: Mon, 11 Sep 2017 11:04:39 -0700	[thread overview]
Message-ID: <20170911180439.26437-1-dcashman@android.com> (raw)

From: Dan Cashman <dcashman@google.com>

The file_contexts labeling backend, specified in label_file.c, currently assumes
that only one path will be specified as an option to selabel_open().  The split
of platform and non-platform policy on device, however, will necessitate the
loading of two disparate policy files.  Rather than combining the files and then
calling the existing API on a newly-formed file, just add the ability to specify
multiple files to use.  Order of opt specification to selabel_open matters.

This corresponds to AOSP commit 50400d38203e4db08314168e60c281cc61a717a8, which
lead to a fork with upstream, which we'd like to correct.

Signed-off-by: Dan Cashman <dcashman@android.com>
---
 libselinux/src/label.c          |  21 +++++---
 libselinux/src/label_file.c     | 104 +++++++++++++++++++++++++++++-----------
 libselinux/src/label_internal.h |   5 +-
 3 files changed, 94 insertions(+), 36 deletions(-)

diff --git a/libselinux/src/label.c b/libselinux/src/label.c
index 48f4d2d6..0dfa054c 100644
--- a/libselinux/src/label.c
+++ b/libselinux/src/label.c
@@ -143,7 +143,11 @@ static int selabel_fini(struct selabel_handle *rec,
 			    struct selabel_lookup_rec *lr,
 			    int translating)
 {
-	if (compat_validate(rec, lr, rec->spec_file, 0))
+	char *path = NULL;
+
+	if (rec->spec_files)
+		path = rec->spec_files[0];
+	if (compat_validate(rec, lr, path, 0))
 		return -1;
 
 	if (translating && !lr->ctx_trans &&
@@ -226,11 +230,9 @@ struct selabel_handle *selabel_open(unsigned int backend,
 	rec->digest = selabel_is_digest_set(opts, nopts, rec->digest);
 
 	if ((*initfuncs[backend])(rec, opts, nopts)) {
-		free(rec->spec_file);
-		free(rec);
+		selabel_close(rec);
 		rec = NULL;
 	}
-
 out:
 	return rec;
 }
@@ -337,10 +339,17 @@ int selabel_digest(struct selabel_handle *rec,
 
 void selabel_close(struct selabel_handle *rec)
 {
+	size_t i;
+
+	if (rec->spec_files) {
+		for (i = 0; i < rec->spec_files_len; i++)
+			free(rec->spec_files[i]);
+		free(rec->spec_files);
+	}
 	if (rec->digest)
 		selabel_digest_fini(rec->digest);
-	rec->func_close(rec);
-	free(rec->spec_file);
+	if (rec->func_close)
+		rec->func_close(rec);
 	free(rec);
 }
 
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 560d8c3d..b3b36bc2 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -709,28 +709,61 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
 		unsigned n)
 {
 	struct saved_data *data = (struct saved_data *)rec->data;
-	const char *path = NULL;
+	size_t num_paths = 0;
+	char **path = NULL;
 	const char *prefix = NULL;
-	int status = -1, baseonly = 0;
+	int status = -1;
+	size_t i;
+	bool baseonly = false;
+	bool path_provided;
 
 	/* Process arguments */
-	while (n--)
-		switch(opts[n].type) {
+	i = n;
+	while (i--)
+		switch(opts[i].type) {
 		case SELABEL_OPT_PATH:
-			path = opts[n].value;
+			num_paths++;
 			break;
 		case SELABEL_OPT_SUBSET:
-			prefix = opts[n].value;
+			prefix = opts[i].value;
 			break;
 		case SELABEL_OPT_BASEONLY:
-			baseonly = !!opts[n].value;
+			baseonly = !!opts[i].value;
 			break;
 		}
 
+	if (!num_paths) {
+		num_paths = 1;
+		path_provided = false;
+	} else {
+		path_provided = true;
+	}
+
+	path = calloc(num_paths, sizeof(*path));
+	if (path == NULL) {
+		goto finish;
+	}
+	rec->spec_files = path;
+	rec->spec_files_len = num_paths;
+
+	if (path_provided) {
+		for (i = 0; i < n; i++) {
+			switch(opts[i].type) {
+			case SELABEL_OPT_PATH:
+				*path = strdup(opts[i].value);
+				if (*path == NULL)
+					goto finish;
+				path++;
+				break;
+			default:
+				break;
+			}
+		}
+	}
 #if !defined(BUILD_HOST) && !defined(ANDROID)
 	char subs_file[PATH_MAX + 1];
 	/* Process local and distribution substitution files */
-	if (!path) {
+	if (!path_provided) {
 		status = selabel_subs_init(
 			selinux_file_context_subs_dist_path(),
 			rec->digest, &data->dist_subs);
@@ -740,43 +773,52 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
 			rec->digest, &data->subs);
 		if (status)
 			goto finish;
-		path = selinux_file_context_path();
+		rec->spec_files[0] = strdup(selinux_file_context_path());
+		if (rec->spec_files[0] == NULL)
+			goto finish;
 	} else {
-		snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", path);
-		status = selabel_subs_init(subs_file, rec->digest,
+		for (i = 0; i < num_paths; i++) {
+			snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", rec->spec_files[i]);
+			status = selabel_subs_init(subs_file, rec->digest,
 					   &data->dist_subs);
-		if (status)
-			goto finish;
-		snprintf(subs_file, sizeof(subs_file), "%s.subs", path);
-		status = selabel_subs_init(subs_file, rec->digest,
+			if (status)
+				goto finish;
+			snprintf(subs_file, sizeof(subs_file), "%s.subs", rec->spec_files[i]);
+			status = selabel_subs_init(subs_file, rec->digest,
 					   &data->subs);
-		if (status)
-			goto finish;
+			if (status)
+				goto finish;
+		}
+	}
+#else
+	if (!path_provided) {
+		selinux_log(SELINUX_ERROR, "No path given to file labeling backend\n");
+		goto finish;
 	}
-
 #endif
-	rec->spec_file = strdup(path);
 
 	/*
-	 * The do detailed validation of the input and fill the spec array
+	 * Do detailed validation of the input and fill the spec array
 	 */
-	status = process_file(path, NULL, rec, prefix, rec->digest);
-	if (status)
-		goto finish;
-
-	if (rec->validating) {
-		status = nodups_specs(data, path);
+	for (i = 0; i < num_paths; i++) {
+		status = process_file(rec->spec_files[i], NULL, rec, prefix, rec->digest);
 		if (status)
 			goto finish;
+
+		if (rec->validating) {
+			status = nodups_specs(data, rec->spec_files[i]);
+			if (status)
+				goto finish;
+		}
 	}
 
 	if (!baseonly) {
-		status = process_file(path, "homedirs", rec, prefix,
+		status = process_file(rec->spec_files[0], "homedirs", rec, prefix,
 							    rec->digest);
 		if (status && errno != ENOENT)
 			goto finish;
 
-		status = process_file(path, "local", rec, prefix,
+		status = process_file(rec->spec_files[0], "local", rec, prefix,
 							    rec->digest);
 		if (status && errno != ENOENT)
 			goto finish;
@@ -804,6 +846,12 @@ static void closef(struct selabel_handle *rec)
 	struct stem *stem;
 	unsigned int i;
 
+	if (!data)
+		return;
+
+	/* make sure successive ->func_close() calls are harmless */
+	rec->data = NULL;
+
 	selabel_subs_fini(data->subs);
 	selabel_subs_fini(data->dist_subs);
 
diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h
index c55efb75..43b63513 100644
--- a/libselinux/src/label_internal.h
+++ b/libselinux/src/label_internal.h
@@ -98,10 +98,11 @@ struct selabel_handle {
 	void *data;
 
 	/*
-	 * The main spec file used. Note for file contexts the local and/or
+	 * The main spec file(s) used. Note for file contexts the local and/or
 	 * homedirs could also have been used to resolve a context.
 	 */
-	char *spec_file;
+	size_t spec_files_len;
+	char **spec_files;
 
 	/* ptr to SHA1 hash information if SELABEL_OPT_DIGEST set */
 	struct selabel_digest *digest;
-- 
2.14.1.581.gf28d330327-goog

             reply	other threads:[~2017-09-11 18:05 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-11 18:04 Daniel Cashman [this message]
2017-09-11 21:51 ` [PATCH] selinux: libselinux: Enable multiple input files to selabel_open William Roberts
2017-09-20 20:28 ` Stephen Smalley
2017-10-10 21:12   ` Daniel Cashman
2017-10-10 21:19     ` Dan Cashman
2017-10-13 19:23     ` Stephen Smalley
2017-10-17 16:38       ` Dan Cashman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170911180439.26437-1-dcashman@android.com \
    --to=dcashman@android.com \
    --cc=dcashman@google.com \
    --cc=jeffv@google.com \
    --cc=jwcart2@tycho.nsa.gov \
    --cc=selinux@tycho.nsa.gov \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.