 contrib/sepgsql/Makefile   |    2 +-
 contrib/sepgsql/database.c |   88 ++++++++++++++++++++++++++++++++++++++++++++
 contrib/sepgsql/hooks.c    |    5 ++
 contrib/sepgsql/label.c    |   26 +++++++++++--
 contrib/sepgsql/schema.c   |   13 ++----
 contrib/sepgsql/sepgsql.h  |    6 +++
 6 files changed, 127 insertions(+), 13 deletions(-)

diff --git a/contrib/sepgsql/Makefile b/contrib/sepgsql/Makefile
index c83b2e3..033c41a 100644
--- a/contrib/sepgsql/Makefile
+++ b/contrib/sepgsql/Makefile
@@ -2,7 +2,7 @@
 
 MODULE_big = sepgsql
 OBJS = hooks.o selinux.o uavc.o label.o dml.o \
-	schema.o relation.o proc.o
+	database.o schema.o relation.o proc.o
 DATA_built = sepgsql.sql
 
 REGRESS = label dml misc
diff --git a/contrib/sepgsql/database.c b/contrib/sepgsql/database.c
new file mode 100644
index 0000000..7f15d9c
--- /dev/null
+++ b/contrib/sepgsql/database.c
@@ -0,0 +1,88 @@
+/* -------------------------------------------------------------------------
+ *
+ * contrib/sepgsql/database.c
+ *
+ * Routines corresponding to database objects
+ *
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "catalog/dependency.h"
+#include "catalog/pg_database.h"
+#include "commands/seclabel.h"
+#include "sepgsql.h"
+
+void
+sepgsql_database_post_create(Oid databaseId)
+{
+	char   *scontext = sepgsql_get_client_label();
+	char   *tcontext;
+	char   *ncontext;
+	ObjectAddress	object;
+
+	/*
+	 * Compute a default security label of the newly created database
+	 * based on a pair of security label of client and source database.
+	 *
+	 * XXX - Right now, this logic uses "template1" as its source, because
+	 * here is no way to know the Oid of source database.
+	 */
+	object.classId = DatabaseRelationId;
+	object.objectId = TemplateDbOid;
+	object.objectSubId = 0;
+	tcontext = GetSecurityLabel(&object, SEPGSQL_LABEL_TAG);
+
+	ncontext = sepgsql_compute_create(scontext, tcontext,
+									  SEPG_CLASS_DB_DATABASE);
+
+	/*
+	 * Assign the default security label on the new database
+	 */
+	object.classId = DatabaseRelationId;
+	object.objectId = databaseId;
+	object.objectSubId = 0;
+
+	SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
+
+	pfree(ncontext);
+	pfree(tcontext);
+}
+
+/*
+ * sepgsql_database_relabel
+ *
+ * It checks privileges to relabel the supplied database with the `seclabel'
+ */
+void
+sepgsql_database_relabel(Oid databaseId, const char *seclabel)
+{
+	ObjectAddress	object;
+	char		   *audit_name;
+
+	object.classId = DatabaseRelationId;
+	object.objectId = databaseId;
+	object.objectSubId = 0;
+	audit_name = getObjectDescription(&object);
+
+	/*
+	 * check db_database:{setattr relabelfrom} permission
+	 */
+	sepgsql_avc_check_perms(&object,
+							SEPG_CLASS_DB_DATABASE,
+							SEPG_DB_DATABASE__SETATTR |
+							SEPG_DB_DATABASE__RELABELFROM,
+							audit_name,
+							true);
+	/*
+	 * check db_database:{relabelto} permission
+	 */
+	sepgsql_avc_check_perms_label(seclabel,
+								  SEPG_CLASS_DB_DATABASE,
+								  SEPG_DB_DATABASE__RELABELTO,
+								  audit_name,
+								  true);
+	pfree(audit_name);
+}
diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c
index ca6ce99..331bbd7 100644
--- a/contrib/sepgsql/hooks.c
+++ b/contrib/sepgsql/hooks.c
@@ -12,6 +12,7 @@
 
 #include "catalog/objectaccess.h"
 #include "catalog/pg_class.h"
+#include "catalog/pg_database.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_proc.h"
 #include "commands/seclabel.h"
@@ -125,6 +126,10 @@ sepgsql_object_access(ObjectAccessType access,
 		case OAT_POST_CREATE:
 			switch (classId)
 			{
+				case DatabaseRelationId:
+					sepgsql_database_post_create(objectId);
+					break;
+
 				case NamespaceRelationId:
 					sepgsql_schema_post_create(objectId);
 					break;
diff --git a/contrib/sepgsql/label.c b/contrib/sepgsql/label.c
index 669ee35..a2bf571 100644
--- a/contrib/sepgsql/label.c
+++ b/contrib/sepgsql/label.c
@@ -17,6 +17,7 @@
 #include "catalog/indexing.h"
 #include "catalog/pg_attribute.h"
 #include "catalog/pg_class.h"
+#include "catalog/pg_database.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_proc.h"
 #include "commands/dbcommands.h"
@@ -121,9 +122,14 @@ sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
 	 */
 	switch (object->classId)
 	{
+		case DatabaseRelationId:
+			sepgsql_database_relabel(object->objectId, seclabel);
+			break;
+
 		case NamespaceRelationId:
 			sepgsql_schema_relabel(object->objectId, seclabel);
 			break;
+
 		case RelationRelationId:
 			if (object->objectSubId == 0)
 				sepgsql_relation_relabel(object->objectId,
@@ -133,6 +139,7 @@ sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
 										  object->objectSubId,
 										  seclabel);
 			break;
+
 		case ProcedureRelationId:
 			sepgsql_proc_relabel(object->objectId, seclabel);
 			break;
@@ -315,6 +322,7 @@ exec_object_restorecon(struct selabel_handle * sehnd, Oid catalogId)
 							   SnapshotNow, 0, NULL);
 	while (HeapTupleIsValid(tuple = systable_getnext(sscan)))
 	{
+		Form_pg_database datForm;
 		Form_pg_namespace nspForm;
 		Form_pg_class relForm;
 		Form_pg_attribute attForm;
@@ -330,6 +338,19 @@ exec_object_restorecon(struct selabel_handle * sehnd, Oid catalogId)
 		 */
 		switch (catalogId)
 		{
+			case DatabaseRelationId:
+				datForm = (Form_pg_database) GETSTRUCT(tuple);
+
+				objtype = SELABEL_DB_DATABASE;
+
+				objname = quote_object_name(NameStr(datForm->datname),
+											NULL, NULL, NULL);
+
+				object.classId = DatabaseRelationId;
+				object.objectId = HeapTupleGetOid(tuple);
+				object.objectSubId = 0;
+				break;
+
 			case NamespaceRelationId:
 				nspForm = (Form_pg_namespace) GETSTRUCT(tuple);
 
@@ -506,10 +527,7 @@ sepgsql_restorecon(PG_FUNCTION_ARGS)
 			   errmsg("SELinux: failed to initialize labeling handle: %m")));
 	PG_TRY();
 	{
-		/*
-		 * Right now, we have no support labeling on the shared database
-		 * objects, such as database, role, or tablespace.
-		 */
+		exec_object_restorecon(sehnd, DatabaseRelationId);
 		exec_object_restorecon(sehnd, NamespaceRelationId);
 		exec_object_restorecon(sehnd, RelationRelationId);
 		exec_object_restorecon(sehnd, AttributeRelationId);
diff --git a/contrib/sepgsql/schema.c b/contrib/sepgsql/schema.c
index aae68ef..cb30aaa 100644
--- a/contrib/sepgsql/schema.c
+++ b/contrib/sepgsql/schema.c
@@ -13,6 +13,7 @@
 #include "catalog/dependency.h"
 #include "catalog/pg_namespace.h"
 #include "commands/seclabel.h"
+#include "miscadmin.h"
 #include "utils/lsyscache.h"
 
 #include "sepgsql.h"
@@ -26,22 +27,17 @@
 void
 sepgsql_schema_post_create(Oid namespaceId)
 {
-	char	   *scontext = sepgsql_get_client_label();
+	char	   *scontext;
 	char	   *tcontext;
 	char	   *ncontext;
 	ObjectAddress object;
 
 	/*
-	 * FIXME: Right now, we assume pg_database object has a fixed security
-	 * label, because pg_seclabel does not support to store label of shared
-	 * database objects.
-	 */
-	tcontext = "system_u:object_r:sepgsql_db_t:s0";
-
-	/*
 	 * Compute a default security label when we create a new schema object
 	 * under the working database.
 	 */
+	scontext = sepgsql_get_client_label();
+	tcontext = sepgsql_get_label(DatabaseRelationId, MyDatabaseId, 0);
 	ncontext = sepgsql_compute_create(scontext, tcontext,
 									  SEPG_CLASS_DB_SCHEMA);
 
@@ -54,6 +50,7 @@ sepgsql_schema_post_create(Oid namespaceId)
 	SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
 
 	pfree(ncontext);
+	pfree(tcontext);
 }
 
 /*
diff --git a/contrib/sepgsql/sepgsql.h b/contrib/sepgsql/sepgsql.h
index 35b500c..b4c1dfd 100644
--- a/contrib/sepgsql/sepgsql.h
+++ b/contrib/sepgsql/sepgsql.h
@@ -284,6 +284,12 @@ extern Datum sepgsql_restorecon(PG_FUNCTION_ARGS);
 extern bool sepgsql_dml_privileges(List *rangeTabls, bool abort);
 
 /*
+ * database.c
+ */
+extern void sepgsql_database_post_create(Oid databaseId);
+extern void sepgsql_database_relabel(Oid databaseId, const char *seclabel);
+
+/*
  * schema.c
  */
 extern void sepgsql_schema_post_create(Oid namespaceId);