[PATCH] libselinux: add support for /contexts/postgresql_contexts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

The attached patch enables to obtain the default security context of newly
created database, defined at /etc/selinux/*/contexts/postgresql_contexts .

The format is as follows:
--------
#
# Config file for SE-PostgreSQL
#
# <domain of client>  <type of newly created database>
unconfined_t    sepgsql_db_t
*               sepgsql_db_t
--------

'*' means default security context, if given key is not matched for any entry.

This API requires the security context of client as a key, and it returns
a security context to be attached for a newly created database.
It has a type field defined in the right-hand of config file, and inherits
user and lower-range field of given security context as a key.

e.g)
selabel_lookup(sehandle, &context, "user_u:user_r:user_t:s0", 0);
returns "user_u:object_r:sepgsql_db_t:s0".

This patch is implemented based on the previous discussion at:
  http://marc.info/?l=selinux&m=120999566809541&w=2

Thanks,

Signed-off-by: KaiGai Kohei <kaigai@xxxxxxxxxxxxx>
--
 include/selinux/label.h   |    2
 include/selinux/selinux.h |    1
 src/file_path_suffixes.h  |    1
 src/label.c               |   20 +++-
 src/label_internal.h      |    4
 src/label_pgsql.c         |  209 ++++++++++++++++++++++++++++++++++++++++++++++
 src/selinux_config.c      |    9 +
 src/selinux_internal.h    |    1
 8 files changed, 243 insertions(+), 4 deletions(-)
-- 
OSS Platform Development Division, NEC
KaiGai Kohei <kaigai@xxxxxxxxxxxxx>
Index: libselinux/include/selinux/label.h
===================================================================
--- libselinux/include/selinux/label.h	(revision 2883)
+++ libselinux/include/selinux/label.h	(working copy)
@@ -29,6 +29,8 @@
 #define SELABEL_CTX_MEDIA	1
 /* x contexts */
 #define SELABEL_CTX_X		2
+/* pgsql database contexts */
+#define SELABEL_CTX_PGSQL	3
 
 /*
  * Available options
Index: libselinux/include/selinux/selinux.h
===================================================================
--- libselinux/include/selinux/selinux.h	(revision 2883)
+++ libselinux/include/selinux/selinux.h	(working copy)
@@ -460,6 +460,7 @@
 extern const char *selinux_homedir_context_path(void);
 extern const char *selinux_media_context_path(void);
 extern const char *selinux_x_context_path(void);
+extern const char *selinux_pgsql_context_path(void);
 extern const char *selinux_contexts_path(void);
 extern const char *selinux_securetty_types_path(void);
 extern const char *selinux_booleans_path(void);
Index: libselinux/src/file_path_suffixes.h
===================================================================
--- libselinux/src/file_path_suffixes.h	(revision 2883)
+++ libselinux/src/file_path_suffixes.h	(working copy)
@@ -19,3 +19,4 @@
     S_(FILE_CONTEXTS_HOMEDIR, "/contexts/files/file_contexts.homedirs")
     S_(FILE_CONTEXTS_LOCAL, "/contexts/files/file_contexts.local")
     S_(X_CONTEXTS, "/contexts/x_contexts")
+    S_(PGSQL_CONTEXTS, "/contexts/postgresql_contexts")
Index: libselinux/src/label_pgsql.c
===================================================================
--- libselinux/src/label_pgsql.c	(revision 0)
+++ libselinux/src/label_pgsql.c	(revision 0)
@@ -0,0 +1,209 @@
+/*
+ * Media contexts backend for SE-PostgreSQL database contexts
+ *
+ * Author: KaiGai Kohei <kaigai@xxxxxxxxxxxxx>
+ */
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "callbacks.h"
+#include "label_internal.h"
+
+typedef struct pgsql_entry {
+	struct pgsql_entry *next;
+	char *key, *type;
+} pgsql_entry;
+
+static void pgsql_close(struct selabel_handle *h)
+{
+	pgsql_entry *entry, *next_entry;
+
+	for (entry = h->data; entry != NULL; entry = next_entry) {
+		next_entry = entry->next;
+
+		if (entry->key)
+			free(entry->key);
+		free(entry->type);
+		free(entry);
+	}
+	h->data = NULL;
+}
+
+static struct selabel_lookup_rec *pgsql_lookup(struct selabel_handle *h,
+					       const char *key, int type)
+{
+	struct selabel_lookup_rec *lr;
+	pgsql_entry *head = h->data;
+	pgsql_entry *entry, *default_entry = NULL;
+	security_context_t context;
+	char *user, *role, *domain, *range;
+
+	if (type != 0) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	/* pick up user's domain */
+	if (selinux_trans_to_raw_context((security_context_t)key, &context) < 0)
+		return NULL;
+
+	user = strtok(context, ":");
+	role = strtok(NULL, ":");
+	domain = strtok(NULL, ":");
+	range = strtok(NULL, "-");
+
+	for (entry = head; entry != NULL; entry = entry->next) {
+		if (!entry->key) {
+			default_entry = entry;
+			continue;
+		}
+		if (!strcmp(domain, entry->key))
+			goto found;
+	}
+	/* not found */
+	if (!default_entry) {
+		errno = ENOENT;
+		goto error0;
+	}
+	entry = default_entry;
+
+found:
+	lr = malloc(sizeof(struct selabel_lookup_rec));
+	if (!lr)
+		goto error0;
+
+	lr->ctx_raw = malloc(strlen(user) + sizeof("object_r") + strlen(entry->type) + 4
+			     + (!range ? 0 : strlen(range)));
+	if (!lr->ctx_raw)
+		goto error1;
+
+	if (!range) {
+		sprintf(lr->ctx_raw, "%s:object_r:%s", user, entry->type);
+	} else {
+		sprintf(lr->ctx_raw, "%s:object_r:%s:%s", user, entry->type, range);
+	}
+
+	if (security_check_context_raw(lr->ctx_raw) < 0)
+		goto error2;
+
+	freecon(context);
+
+	return lr;
+
+error2:
+	free(lr->ctx_raw);
+error1:
+	free(lr);
+error0:
+	freecon(context);
+	return NULL;
+}
+
+static void pgsql_lookup_post(struct selabel_handle *h,
+			      struct selabel_lookup_rec *lr)
+{
+	h = h;	/* to kill compiler warnings */
+
+	free(lr->ctx_raw);
+	if (lr->ctx_trans)
+		free(lr->ctx_trans);
+	free(lr);
+}
+
+static void pgsql_stats(struct selabel_handle *h)
+{
+	pgsql_entry *entry, *head = h->data;
+	unsigned int count;
+	int has_default = 0;
+
+	for (count=0, entry = head; entry != NULL; count++, entry = entry->next) {
+		if (!entry->key)
+			has_default = 1;
+	}
+
+	selinux_log(SELINUX_INFO, "%u entries%s\n",
+		    count,
+		    has_default ? " has default type," : "");
+}
+
+pgsql_entry *read_a_line(FILE *filp)
+{
+	pgsql_entry *entry;
+	char buffer[4096];
+	char *ptr, *key, *type;
+	int items;
+
+retry:
+	ptr = fgets(buffer, sizeof(buffer), filp);
+	if (!ptr)
+		return NULL;
+
+	/* skip comment line */
+	while (isspace(*ptr))
+		ptr++;
+	if (*ptr == '#' || *ptr == '\0')
+		goto retry;
+
+	items = sscanf(ptr, "%as %as", &key, &type);
+	if (items < 2) {
+		if (items > 0)
+			free(key);
+		goto retry;
+	}
+
+	/* make a pgsql_entry */
+	entry = malloc(sizeof(pgsql_entry));
+	if (!entry) {
+		free(key);
+		free(type);
+		return NULL;
+	}
+	memset(entry, 0, sizeof(pgsql_entry));
+
+	if (!strcmp(key, "*")) {
+		free(key);
+		key = NULL;	/* default */
+	}
+
+	entry->key = key;
+	entry->type = type;
+
+	return entry;
+}
+
+int selabel_pgsql_init(struct selabel_handle *rec,
+		       struct selinux_opt *opts,
+		       unsigned int nopts)
+{
+	FILE *filp;
+	const char *path = NULL;
+	pgsql_entry *entry, *head = NULL;
+
+	/* parse options */
+	while (nopts--) {
+		if (opts[nopts].type == SELABEL_OPT_PATH)
+			path = opts[nopts].value;
+	}
+
+	/* open the specified file */
+	if (!path)
+		path = selinux_pgsql_context_path();
+	filp = fopen(path, "rb");
+	if (!filp)
+		return -1;
+
+	while ((entry = read_a_line(filp)) != NULL) {
+		entry->next = head;
+		head = entry;
+	}
+	fclose(filp);
+
+	rec->data = head;
+	rec->func_close	      = pgsql_close;
+	rec->func_lookup      = pgsql_lookup;
+	rec->func_lookup_post = pgsql_lookup_post;
+	rec->func_stats       = pgsql_stats;
+
+	return 0;
+}
Index: libselinux/src/selinux_internal.h
===================================================================
--- libselinux/src/selinux_internal.h	(revision 2883)
+++ libselinux/src/selinux_internal.h	(working copy)
@@ -66,6 +66,7 @@
     hidden_proto(selinux_customizable_types_path)
     hidden_proto(selinux_media_context_path)
     hidden_proto(selinux_x_context_path)
+    hidden_proto(selinux_pgsql_context_path)
     hidden_proto(selinux_path)
     hidden_proto(selinux_check_passwd_access)
     hidden_proto(selinux_check_securetty_context)
Index: libselinux/src/selinux_config.c
===================================================================
--- libselinux/src/selinux_config.c	(revision 2883)
+++ libselinux/src/selinux_config.c	(working copy)
@@ -39,7 +39,8 @@
 #define FILE_CONTEXTS_LOCAL 17
 #define SECURETTY_TYPES   18
 #define X_CONTEXTS        19
-#define NEL               20
+#define PGSQL_CONTEXTS    20
+#define NEL               21
 
 /* New layout is relative to SELINUXDIR/policytype. */
 static char *file_paths[NEL];
@@ -383,3 +384,9 @@
 }
 
 hidden_def(selinux_x_context_path)
+
+const char *selinux_pgsql_context_path()
+{
+	return get_path(PGSQL_CONTEXTS);
+}
+hidden_def(selinux_pgsql_context_path);
Index: libselinux/src/label.c
===================================================================
--- libselinux/src/label.c	(revision 2883)
+++ libselinux/src/label.c	(working copy)
@@ -20,7 +20,8 @@
 static selabel_initfunc initfuncs[] = {
 	&selabel_file_init,
 	&selabel_media_init,
-	&selabel_x_init
+	&selabel_x_init,
+	&selabel_pgsql_init,
 };
 
 /*
@@ -84,6 +85,13 @@
 	return rec;
 }
 
+static void selabel_lookup_post_common(struct selabel_handle *rec,
+				       struct selabel_lookup_rec *lr)
+{
+	if (rec->func_lookup_post)
+		rec->func_lookup_post(rec, lr);
+}
+
 static struct selabel_lookup_rec *
 selabel_lookup_common(struct selabel_handle *rec, int translating,
 		      const char *key, int type)
@@ -92,12 +100,16 @@
 	if (!lr)
 		return NULL;
 
-	if (compat_validate(rec, lr, "file_contexts", 0))
+	if (compat_validate(rec, lr, "file_contexts", 0)) {
+		selabel_lookup_post_common(rec, lr);
 		return NULL;
+	}
 
 	if (translating && !lr->ctx_trans &&
-	    selinux_raw_to_trans_context(lr->ctx_raw, &lr->ctx_trans))
+	    selinux_raw_to_trans_context(lr->ctx_raw, &lr->ctx_trans)) {
+		selabel_lookup_post_common(rec, lr);
 		return NULL;
+	}
 
 	return lr;
 }
@@ -112,6 +124,7 @@
 		return -1;
 
 	*con = strdup(lr->ctx_trans);
+	selabel_lookup_post_common(rec, lr);
 	return *con ? 0 : -1;
 }
 
@@ -125,6 +138,7 @@
 		return -1;
 
 	*con = strdup(lr->ctx_raw);
+	selabel_lookup_post_common(rec, lr);
 	return *con ? 0 : -1;
 }
 
Index: libselinux/src/label_internal.h
===================================================================
--- libselinux/src/label_internal.h	(revision 2883)
+++ libselinux/src/label_internal.h	(working copy)
@@ -23,6 +23,8 @@
 		      unsigned nopts) hidden;
 int selabel_x_init(struct selabel_handle *rec, struct selinux_opt *opts,
 		   unsigned nopts) hidden;
+int selabel_pgsql_init(struct selabel_handle *rec, struct selinux_opt *opts,
+		       unsigned nopts) hidden;
 
 /*
  * Labeling internal structures
@@ -41,6 +43,8 @@
 	/* labeling operations */
 	struct selabel_lookup_rec *(*func_lookup) (struct selabel_handle *h,
 						   const char *key, int type);
+	void (*func_lookup_post) (struct selabel_handle *h,
+				  struct selabel_lookup_rec *lr);
 	void (*func_close) (struct selabel_handle *h);
 	void (*func_stats) (struct selabel_handle *h);
 

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux