pgsql-v9.2-prep-creation-hook-part-2.v1.patch
application/octet-stream
Filename: pgsql-v9.2-prep-creation-hook-part-2.v1.patch
Type: application/octet-stream
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v9
| File | + | − |
|---|---|---|
| contrib/sepgsql/expected/create.out | 4 | 0 |
| contrib/sepgsql/hooks.c | 6 | 1 |
| contrib/sepgsql/schema.c | 36 | 13 |
| contrib/sepgsql/sepgsql.h | 2 | 1 |
| contrib/sepgsql/sql/create.sql | 6 | 0 |
| src/backend/catalog/namespace.c | 13 | 4 |
| src/backend/catalog/pg_namespace.c | 4 | 3 |
| src/backend/commands/schemacmds.c | 6 | 1 |
| src/include/catalog/objectaccess.h | 19 | 0 |
| src/include/catalog/pg_namespace.h | 2 | 1 |
contrib/sepgsql/expected/create.out | 4 +++
contrib/sepgsql/hooks.c | 7 ++++-
contrib/sepgsql/schema.c | 49 +++++++++++++++++++++++++---------
contrib/sepgsql/sepgsql.h | 3 +-
contrib/sepgsql/sql/create.sql | 6 ++++
src/backend/catalog/namespace.c | 17 +++++++++---
src/backend/catalog/pg_namespace.c | 7 +++--
src/backend/commands/schemacmds.c | 7 ++++-
src/include/catalog/objectaccess.h | 19 +++++++++++++
src/include/catalog/pg_namespace.h | 3 +-
10 files changed, 98 insertions(+), 24 deletions(-)
diff --git a/contrib/sepgsql/expected/create.out b/contrib/sepgsql/expected/create.out
index 95fc4f1..3293a73 100644
--- a/contrib/sepgsql/expected/create.out
+++ b/contrib/sepgsql/expected/create.out
@@ -13,7 +13,11 @@ SET client_min_messages = LOG;
CREATE DATABASE regtest_sepgsql_test_database;
LOG: SELinux: allowed { getattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=system_u:object_r:sepgsql_db_t:s0 tclass=db_database name="database template1"
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_db_t:s0 tclass=db_database name="database: regtest_sepgsql_test_database"
+CREATE SCHEMA regtest_schema;
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+SET search_path = regtest_schema, public;
--
-- clean-up
--
DROP DATABASE IF EXISTS regtest_sepgsql_test_database;
+DROP SCHEMA IF EXISTS regtest_schema CASCADE;
diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c
index 886f1fa..2b62a75 100644
--- a/contrib/sepgsql/hooks.c
+++ b/contrib/sepgsql/hooks.c
@@ -141,6 +141,11 @@ sepgsql_object_prep_create(Oid classId, Oid objectId, int subId,
args->pg_database.tablespaceId);
break;
+ case NamespaceRelationId:
+ cinfo->ncontext =
+ sepgsql_schema_prep_create(args->pg_namespace.nspname);
+ break;
+
default:
/* Ignore unsupported object classes */
break;
@@ -171,7 +176,7 @@ sepgsql_object_post_create(Oid classId, Oid objectId, int subId,
break;
case NamespaceRelationId:
- sepgsql_schema_post_create(objectId);
+ sepgsql_schema_post_create(objectId, cinfo->ncontext);
break;
case RelationRelationId:
diff --git a/contrib/sepgsql/schema.c b/contrib/sepgsql/schema.c
index a167be1..07dbf80 100644
--- a/contrib/sepgsql/schema.c
+++ b/contrib/sepgsql/schema.c
@@ -20,38 +20,61 @@
#include "sepgsql.h"
/*
- * sepgsql_schema_post_create
+ * sepgsql_schema_prep_create
*
- * This routine assigns a default security label on a newly defined
- * schema.
+ * It computes a default security label of schema object, and checks
+ * permission to create a new schema object.
*/
-void
-sepgsql_schema_post_create(Oid namespaceId)
+const char *
+sepgsql_schema_prep_create(const char *nspname)
{
- char *scontext;
+ char *scontext = sepgsql_get_client_label();
char *tcontext;
char *ncontext;
- ObjectAddress object;
+ char audit_name[NAMEDATALEN + 16];
/*
* 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);
/*
- * Assign the default security label on a new procedure
+ * Check db_schema:{create} permission
*/
+ if (strncmp(nspname, "pg_temp_", 8) == 0)
+ snprintf(audit_name, sizeof(audit_name), "schema pg_temp");
+ else
+ snprintf(audit_name, sizeof(audit_name), "schema %s", nspname);
+
+ sepgsql_avc_check_perms_label(ncontext,
+ SEPG_CLASS_DB_SCHEMA,
+ SEPG_DB_SCHEMA__CREATE,
+ audit_name,
+ true);
+
+ pfree(tcontext);
+
+ return ncontext;
+}
+
+
+/*
+ * sepgsql_schema_post_create
+ *
+ * This routine assigns a default security label on a newly defined schema.
+ */
+void
+sepgsql_schema_post_create(Oid namespaceId, const char *seclabel)
+{
+ ObjectAddress object;
+
object.classId = NamespaceRelationId;
object.objectId = namespaceId;
object.objectSubId = 0;
- SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
-
- pfree(ncontext);
- pfree(tcontext);
+ SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, seclabel);
}
/*
diff --git a/contrib/sepgsql/sepgsql.h b/contrib/sepgsql/sepgsql.h
index 0d0eead..b4a3e4d 100644
--- a/contrib/sepgsql/sepgsql.h
+++ b/contrib/sepgsql/sepgsql.h
@@ -313,7 +313,8 @@ extern void sepgsql_database_relabel(Oid databaseId, const char *seclabel);
/*
* schema.c
*/
-extern void sepgsql_schema_post_create(Oid namespaceId);
+extern const char *sepgsql_schema_prep_create(const char *nspname);
+extern void sepgsql_schema_post_create(Oid namespaceId, const char *seclabel);
extern void sepgsql_schema_relabel(Oid namespaceId, const char *seclabel);
/*
diff --git a/contrib/sepgsql/sql/create.sql b/contrib/sepgsql/sql/create.sql
index e75d57b..9ce1db9 100644
--- a/contrib/sepgsql/sql/create.sql
+++ b/contrib/sepgsql/sql/create.sql
@@ -9,7 +9,13 @@ SET client_min_messages = LOG;
CREATE DATABASE regtest_sepgsql_test_database;
+CREATE SCHEMA regtest_schema;
+
+SET search_path = regtest_schema, public;
+
--
-- clean-up
--
DROP DATABASE IF EXISTS regtest_sepgsql_test_database;
+
+DROP SCHEMA IF EXISTS regtest_schema CASCADE;
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index fcc90fe..3a0238f 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -21,6 +21,7 @@
#include "access/xact.h"
#include "catalog/dependency.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
@@ -3384,9 +3385,12 @@ InitTempTableNamespace(void)
char namespaceName[NAMEDATALEN];
Oid namespaceId;
Oid toastspaceId;
+ Datum hook_private = 0;
Assert(!OidIsValid(myTempNamespace));
+ snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
+
/*
* First, do permission check to see if we are authorized to make temp
* tables. We use a nonstandard error message here since "databasename:
@@ -3404,6 +3408,9 @@ InitTempTableNamespace(void)
errmsg("permission denied to create temporary tables in database \"%s\"",
get_database_name(MyDatabaseId))));
+ /* Prep-creation hook for new temp-schema */
+ InvokePrepCreateSchemaHook(&hook_private, namespaceName);
+
/*
* Do not allow a Hot Standby slave session to make temp tables. Aside
* from problems with modifying the system catalogs, there is a naming
@@ -3419,8 +3426,6 @@ InitTempTableNamespace(void)
(errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
errmsg("cannot create temporary tables during recovery")));
- snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
-
namespaceId = get_namespace_oid(namespaceName, true);
if (!OidIsValid(namespaceId))
{
@@ -3432,7 +3437,9 @@ InitTempTableNamespace(void)
* temp tables. This works because the places that access the temp
* namespace for my own backend skip permissions checks on it.
*/
- namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
+ namespaceId = NamespaceCreate(namespaceName,
+ BOOTSTRAP_SUPERUSERID,
+ hook_private);
/* Advance command counter to make namespace visible */
CommandCounterIncrement();
}
@@ -3456,7 +3463,9 @@ InitTempTableNamespace(void)
toastspaceId = get_namespace_oid(namespaceName, true);
if (!OidIsValid(toastspaceId))
{
- toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
+ toastspaceId = NamespaceCreate(namespaceName,
+ BOOTSTRAP_SUPERUSERID,
+ hook_private);
/* Advance command counter to make namespace visible */
CommandCounterIncrement();
}
diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c
index ceebac2..48b9fc9 100644
--- a/src/backend/catalog/pg_namespace.c
+++ b/src/backend/catalog/pg_namespace.c
@@ -29,7 +29,7 @@
* ---------------
*/
Oid
-NamespaceCreate(const char *nspName, Oid ownerId)
+NamespaceCreate(const char *nspName, Oid ownerId, Datum hook_private)
{
Relation nspdesc;
HeapTuple tup;
@@ -86,7 +86,8 @@ NamespaceCreate(const char *nspName, Oid ownerId)
recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new schema */
- InvokeObjectAccessHook(OAT_POST_CREATE, NamespaceRelationId, nspoid, 0);
-
+ InvokeObjectAccessHookArg(OAT_POST_CREATE,
+ NamespaceRelationId, nspoid, 0,
+ hook_private);
return nspoid;
}
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 8daa9d0..d6f1927 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -19,6 +19,7 @@
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_namespace.h"
#include "commands/dbcommands.h"
#include "commands/schemacmds.h"
@@ -48,6 +49,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
Oid owner_uid;
Oid saved_uid;
int save_sec_context;
+ Datum hook_private = 0;
AclResult aclresult;
GetUserIdAndSecContext(&saved_uid, &save_sec_context);
@@ -74,6 +76,9 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
check_is_member_of_role(saved_uid, owner_uid);
+ /* Prep-creation hook for new schema */
+ InvokePrepCreateSchemaHook(&hook_private, schemaName);
+
/* Additional check to protect reserved schema names */
if (!allowSystemTableMods && IsReservedName(schemaName))
ereport(ERROR,
@@ -94,7 +99,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
/* Create the schema's namespace */
- namespaceId = NamespaceCreate(schemaName, owner_uid);
+ namespaceId = NamespaceCreate(schemaName, owner_uid, hook_private);
/* Advance cmd counter to make the namespace visible */
CommandCounterIncrement();
diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h
index 0531327..cb5c396 100644
--- a/src/include/catalog/objectaccess.h
+++ b/src/include/catalog/objectaccess.h
@@ -51,6 +51,10 @@ typedef union
Oid datsourceId; /* oid of source database */
Oid tablespaceId; /* oid of default tablespace */
} pg_database;
+ struct {
+ Datum *private; /* common */
+ const char *nspname; /* name of new schema */
+ } pg_namespace;
} ObjectAccessCreateObjectArgs;
/*
@@ -102,4 +106,19 @@ extern PGDLLIMPORT object_access_hook_type object_access_hook;
} \
} while(0)
+#define InvokePrepCreateSchemaHook(_private,_nspname) \
+ do { \
+ if (object_access_hook) \
+ { \
+ ObjectAccessCreateObjectArgs __args; \
+ \
+ __args.pg_namespace.private = (_private); \
+ __args.pg_namespace.nspname = (_nspname); \
+ \
+ (*object_access_hook)(OAT_PREP_CREATE, \
+ NamespaceRelationId, InvalidOid, 0, \
+ PointerGetDatum(&__args)); \
+ } \
+ } while(0)
+
#endif /* OBJECTACCESS_H */
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index 680802d7..eedcf1b 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -77,6 +77,7 @@ DESCR("standard public schema");
/*
* prototypes for functions in pg_namespace.c
*/
-extern Oid NamespaceCreate(const char *nspName, Oid ownerId);
+extern Oid NamespaceCreate(const char *nspName, Oid ownerId,
+ Datum hook_private);
#endif /* PG_NAMESPACE_H */