pgsql-v9.2-drop-permissions.v5.patch
application/octet-stream
Filename: pgsql-v9.2-drop-permissions.v5.patch
Type: application/octet-stream
Part: 0
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/database.c | 27 | 0 |
| contrib/sepgsql/expected/create.out | 0 | 80 |
| contrib/sepgsql/expected/ddl.out | 164 | 0 |
| contrib/sepgsql/hooks.c | 44 | 2 |
| contrib/sepgsql/proc.c | 42 | 0 |
| contrib/sepgsql/relation.c | 119 | 0 |
| contrib/sepgsql/schema.c | 27 | 0 |
| contrib/sepgsql/sepgsql.h | 5 | 0 |
| contrib/sepgsql/sql/create.sql | 0 | 46 |
| contrib/sepgsql/sql/ddl.sql | 81 | 0 |
| contrib/sepgsql/test_sepgsql | 1 | 1 |
| doc/src/sgml/sepgsql.sgml | 14 | 0 |
| src/backend/catalog/dependency.c | 10 | 0 |
| src/backend/catalog/heap.c | 2 | 1 |
| src/backend/catalog/pg_collation.c | 1 | 1 |
| src/backend/catalog/pg_constraint.c | 2 | 1 |
| src/backend/catalog/pg_conversion.c | 2 | 2 |
| src/backend/catalog/pg_namespace.c | 2 | 1 |
| src/backend/catalog/pg_operator.c | 2 | 2 |
| src/backend/catalog/pg_proc.c | 2 | 1 |
| src/backend/catalog/pg_type.c | 4 | 2 |
| src/backend/commands/dbcommands.c | 11 | 1 |
| src/backend/commands/extension.c | 1 | 1 |
| src/backend/commands/foreigncmds.c | 5 | 3 |
| src/backend/commands/functioncmds.c | 2 | 1 |
| src/backend/commands/opclasscmds.c | 2 | 2 |
| src/backend/commands/proclang.c | 1 | 1 |
| src/backend/commands/tablecmds.c | 1 | 1 |
| src/backend/commands/tablespace.c | 10 | 1 |
| src/backend/commands/trigger.c | 1 | 1 |
| src/backend/commands/tsearchcmds.c | 7 | 4 |
| src/backend/commands/user.c | 11 | 1 |
| src/backend/rewrite/rewriteDefine.c | 1 | 1 |
| src/backend/storage/large_object/inv_api.c | 1 | 1 |
| src/include/catalog/objectaccess.h | 23 | 6 |
contrib/sepgsql/database.c | 27 +++++
contrib/sepgsql/expected/create.out | 80 --------------
contrib/sepgsql/expected/ddl.out | 164 ++++++++++++++++++++++++++++
contrib/sepgsql/hooks.c | 46 ++++++++-
contrib/sepgsql/proc.c | 42 +++++++
contrib/sepgsql/relation.c | 119 ++++++++++++++++++++
contrib/sepgsql/schema.c | 27 +++++
contrib/sepgsql/sepgsql.h | 5 +
contrib/sepgsql/sql/create.sql | 46 --------
contrib/sepgsql/sql/ddl.sql | 81 ++++++++++++++
contrib/sepgsql/test_sepgsql | 2 +-
doc/src/sgml/sepgsql.sgml | 14 +++
src/backend/catalog/dependency.c | 10 ++
src/backend/catalog/heap.c | 3 +-
src/backend/catalog/pg_collation.c | 2 +-
src/backend/catalog/pg_constraint.c | 3 +-
src/backend/catalog/pg_conversion.c | 4 +-
src/backend/catalog/pg_namespace.c | 3 +-
src/backend/catalog/pg_operator.c | 4 +-
src/backend/catalog/pg_proc.c | 3 +-
src/backend/catalog/pg_type.c | 6 +-
src/backend/commands/dbcommands.c | 12 ++-
src/backend/commands/extension.c | 2 +-
src/backend/commands/foreigncmds.c | 8 +-
src/backend/commands/functioncmds.c | 3 +-
src/backend/commands/opclasscmds.c | 4 +-
src/backend/commands/proclang.c | 2 +-
src/backend/commands/tablecmds.c | 2 +-
src/backend/commands/tablespace.c | 11 ++-
src/backend/commands/trigger.c | 2 +-
src/backend/commands/tsearchcmds.c | 11 +-
src/backend/commands/user.c | 12 ++-
src/backend/rewrite/rewriteDefine.c | 2 +-
src/backend/storage/large_object/inv_api.c | 2 +-
src/include/catalog/objectaccess.h | 29 ++++-
35 files changed, 628 insertions(+), 165 deletions(-)
diff --git a/contrib/sepgsql/database.c b/contrib/sepgsql/database.c
index be3a7be..0c395c4 100644
--- a/contrib/sepgsql/database.c
+++ b/contrib/sepgsql/database.c
@@ -119,6 +119,33 @@ sepgsql_database_post_create(Oid databaseId, const char *dtemplate)
}
/*
+ * sepgsql_database_drop
+ *
+ * It checks privileges to drop the supplied database
+ */
+void
+sepgsql_database_drop(Oid databaseId)
+{
+ ObjectAddress object;
+ char *audit_name;
+
+ /*
+ * check db_database:{drop} permission
+ */
+ object.classId = DatabaseRelationId;
+ object.objectId = databaseId;
+ object.objectSubId = 0;
+ audit_name = getObjectDescription(&object);
+
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_DATABASE,
+ SEPG_DB_DATABASE__DROP,
+ audit_name,
+ true);
+ pfree(audit_name);
+}
+
+/*
* sepgsql_database_relabel
*
* It checks privileges to relabel the supplied database with the `seclabel'
diff --git a/contrib/sepgsql/expected/create.out b/contrib/sepgsql/expected/create.out
deleted file mode 100644
index 0f04a3e..0000000
--- a/contrib/sepgsql/expected/create.out
+++ /dev/null
@@ -1,80 +0,0 @@
---
--- Regression Test for Creation of Object Permission Checks
---
--- confirm required permissions using audit messages
-SELECT sepgsql_getcon(); -- confirm client privilege
- sepgsql_getcon
--------------------------------------------
- unconfined_u:unconfined_r:unconfined_t:s0
-(1 row)
-
-SET sepgsql.debug_audit = true;
-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;
-CREATE TABLE regtest_table (x serial primary key, y text);
-NOTICE: CREATE TABLE will create implicit sequence "regtest_table_x_seq" for serial column "regtest_table.x"
-LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_table_x_seq"
-LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column tableoid"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column cmax"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column xmax"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column cmin"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column xmin"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column ctid"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column x"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column y"
-NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "regtest_table_pkey" for table "regtest_table"
-ALTER TABLE regtest_table ADD COLUMN z int;
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column z"
-CREATE TABLE regtest_table_2 (a int) WITH OIDS;
-LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_2"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column tableoid"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column cmax"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column xmax"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column cmin"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column xmin"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column oid"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column ctid"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column a"
--- corresponding toast table should not have label and permission checks
-ALTER TABLE regtest_table_2 ADD COLUMN b text;
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column b"
--- VACUUM FULL internally create a new table and swap them later.
-VACUUM FULL regtest_table;
-CREATE VIEW regtest_view AS SELECT * FROM regtest_table WHERE x < 100;
-LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view"
-CREATE SEQUENCE regtest_seq;
-LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_seq"
-CREATE TYPE regtest_comptype AS (a int, b text);
-CREATE FUNCTION regtest_func(text,int[]) RETURNS bool LANGUAGE plpgsql
- AS 'BEGIN RAISE NOTICE ''regtest_func => %'', $1; RETURN true; END';
-LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func(text,integer[])"
-CREATE AGGREGATE regtest_agg (
- sfunc1 = int4pl, basetype = int4, stype1 = int4, initcond1 = '0'
-);
-LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
-LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_agg(integer)"
---
--- clean-up
---
-DROP DATABASE IF EXISTS regtest_sepgsql_test_database;
-DROP SCHEMA IF EXISTS regtest_schema CASCADE;
-NOTICE: drop cascades to 7 other objects
-DETAIL: drop cascades to table regtest_table
-drop cascades to table regtest_table_2
-drop cascades to view regtest_view
-drop cascades to sequence regtest_seq
-drop cascades to type regtest_comptype
-drop cascades to function regtest_func(text,integer[])
-drop cascades to function regtest_agg(integer)
diff --git a/contrib/sepgsql/expected/ddl.out b/contrib/sepgsql/expected/ddl.out
new file mode 100644
index 0000000..1c7bcc5
--- /dev/null
+++ b/contrib/sepgsql/expected/ddl.out
@@ -0,0 +1,164 @@
+--
+-- Regression Test for DDL of Object Permission Checks
+--
+-- confirm required permissions using audit messages
+SELECT sepgsql_getcon(); -- confirm client privilege
+ sepgsql_getcon
+-------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0
+(1 row)
+
+SET sepgsql.debug_audit = true;
+SET client_min_messages = LOG;
+--
+-- CREATE Permission checks
+--
+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 USER regtest_sepgsql_test_user;
+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"
+GRANT ALL ON SCHEMA regtest_schema TO regtest_sepgsql_test_user;
+SET search_path = regtest_schema, public;
+CREATE TABLE regtest_table (x serial primary key, y text);
+NOTICE: CREATE TABLE will create implicit sequence "regtest_table_x_seq" for serial column "regtest_table.x"
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_table_x_seq"
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column tableoid"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column cmax"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column xmax"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column cmin"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column xmin"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column ctid"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column x"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column y"
+NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "regtest_table_pkey" for table "regtest_table"
+ALTER TABLE regtest_table ADD COLUMN z int;
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column z"
+CREATE TABLE regtest_table_2 (a int) WITH OIDS;
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_2"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column tableoid"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column cmax"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column xmax"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column cmin"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column xmin"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column oid"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column ctid"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column a"
+-- corresponding toast table should not have label and permission checks
+ALTER TABLE regtest_table_2 ADD COLUMN b text;
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column b"
+-- VACUUM FULL internally create a new table and swap them later.
+VACUUM FULL regtest_table;
+CREATE VIEW regtest_view AS SELECT * FROM regtest_table WHERE x < 100;
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view"
+CREATE SEQUENCE regtest_seq;
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_seq"
+CREATE TYPE regtest_comptype AS (a int, b text);
+CREATE FUNCTION regtest_func(text,int[]) RETURNS bool LANGUAGE plpgsql
+ AS 'BEGIN RAISE NOTICE ''regtest_func => %'', $1; RETURN true; END';
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func(text,integer[])"
+CREATE AGGREGATE regtest_agg (
+ sfunc1 = int4pl, basetype = int4, stype1 = int4, initcond1 = '0'
+);
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_agg(integer)"
+-- CREATE objects owned by others
+SET SESSION AUTHORIZATION regtest_sepgsql_test_user;
+SET search_path = regtest_schema, public;
+CREATE TABLE regtest_table_3 (x int, y serial);
+NOTICE: CREATE TABLE will create implicit sequence "regtest_table_3_y_seq" for serial column "regtest_table_3.y"
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_table_3_y_seq"
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_3"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column tableoid"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column cmax"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column xmax"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column cmin"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column xmin"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column ctid"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column x"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column y"
+CREATE VIEW regtest_view_2 AS SELECT * FROM regtest_table_3 WHERE x < y;
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_2"
+CREATE FUNCTION regtest_func_2(int) RETURNS bool LANGUAGE plpgsql
+ AS 'BEGIN RETURN $1 * $1 < 100; END';
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func_2(integer)"
+RESET SESSION AUTHORIZATION;
+--
+-- DROP Permission checks (with clean-up)
+--
+DROP FUNCTION regtest_func(text,int[]);
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func(text,integer[])"
+DROP AGGREGATE regtest_agg(int);
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_agg(integer)"
+DROP SEQUENCE regtest_seq;
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_seq"
+DROP VIEW regtest_view;
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view"
+ALTER TABLE regtest_table DROP COLUMN y;
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column y"
+ALTER TABLE regtest_table_2 SET WITHOUT OIDS;
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column oid"
+DROP TABLE regtest_table;
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_table_x_seq"
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column tableoid"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column cmax"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column xmax"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column cmin"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column xmin"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column ctid"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column x"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column z"
+DROP OWNED BY regtest_sepgsql_test_user;
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func_2(integer)"
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_2"
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_table_3_y_seq"
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_3"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column tableoid"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column cmax"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column xmax"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column cmin"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column xmin"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column ctid"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column x"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column y"
+DROP DATABASE regtest_sepgsql_test_database;
+LOG: SELinux: allowed { drop } 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"
+DROP USER regtest_sepgsql_test_user;
+DROP SCHEMA IF EXISTS regtest_schema CASCADE;
+NOTICE: drop cascades to 2 other objects
+DETAIL: drop cascades to table regtest_table_2
+drop cascades to type regtest_comptype
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_2"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column tableoid"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column cmax"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column xmax"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column cmin"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column xmin"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column ctid"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column a"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column b"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c
index 47437ba..9823d46 100644
--- a/contrib/sepgsql/hooks.c
+++ b/contrib/sepgsql/hooks.c
@@ -10,6 +10,7 @@
*/
#include "postgres.h"
+#include "catalog/dependency.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_class.h"
#include "catalog/pg_database.h"
@@ -133,10 +134,11 @@ static void
sepgsql_object_access(ObjectAccessType access,
Oid classId,
Oid objectId,
- int subId)
+ int subId,
+ void *arg)
{
if (next_object_access_hook)
- (*next_object_access_hook) (access, classId, objectId, subId);
+ (*next_object_access_hook) (access, classId, objectId, subId, arg);
switch (access)
{
@@ -192,6 +194,46 @@ sepgsql_object_access(ObjectAccessType access,
}
break;
+ case OAT_DROP:
+ {
+ ObjectAccessDrop *drop_arg = (ObjectAccessDrop *)arg;
+
+ /*
+ * No need to apply permission checks on object deletion
+ * due to internal cleanups; such as removal of temporary
+ * database object on session closed.
+ */
+ if ((drop_arg->dropflags & PERFORM_DELETION_INTERNAL) != 0)
+ break;
+
+ switch (classId)
+ {
+ case DatabaseRelationId:
+ sepgsql_database_drop(objectId);
+ break;
+
+ case NamespaceRelationId:
+ sepgsql_schema_drop(objectId);
+ break;
+
+ case RelationRelationId:
+ if (subId == 0)
+ sepgsql_relation_drop(objectId);
+ else
+ sepgsql_attribute_drop(objectId, subId);
+ break;
+
+ case ProcedureRelationId:
+ sepgsql_proc_drop(objectId);
+ break;
+
+ default:
+ /* Ignore unsupported object classes */
+ break;
+ }
+ }
+ break;
+
default:
elog(ERROR, "unexpected object access type: %d", (int) access);
break;
diff --git a/contrib/sepgsql/proc.c b/contrib/sepgsql/proc.c
index b902797..1efbc90 100644
--- a/contrib/sepgsql/proc.c
+++ b/contrib/sepgsql/proc.c
@@ -131,6 +131,48 @@ sepgsql_proc_post_create(Oid functionId)
}
/*
+ * sepgsql_proc_drop
+ *
+ * It checks privileges to drop the supplied function.
+ */
+void
+sepgsql_proc_drop(Oid functionId)
+{
+ ObjectAddress object;
+ char *audit_name;
+
+ /*
+ * check db_schema:{remove_name} permission
+ */
+ object.classId = NamespaceRelationId;
+ object.objectId = get_func_namespace(functionId);
+ object.objectSubId = 0;
+ audit_name = getObjectDescription(&object);
+
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_SCHEMA,
+ SEPG_DB_SCHEMA__REMOVE_NAME,
+ audit_name,
+ true);
+ pfree(audit_name);
+
+ /*
+ * check db_procedure:{drop} permission
+ */
+ object.classId = ProcedureRelationId;
+ object.objectId = functionId;
+ object.objectSubId = 0;
+ audit_name = getObjectDescription(&object);
+
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_PROCEDURE,
+ SEPG_DB_PROCEDURE__DROP,
+ audit_name,
+ true);
+ pfree(audit_name);
+}
+
+/*
* sepgsql_proc_relabel
*
* It checks privileges to relabel the supplied function
diff --git a/contrib/sepgsql/relation.c b/contrib/sepgsql/relation.c
index efce914..259be49 100644
--- a/contrib/sepgsql/relation.c
+++ b/contrib/sepgsql/relation.c
@@ -21,6 +21,7 @@
#include "commands/seclabel.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
+#include "utils/syscache.h"
#include "utils/tqual.h"
#include "sepgsql.h"
@@ -110,6 +111,36 @@ sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
}
/*
+ * sepgsql_attribute_drop
+ *
+ * It checks privileges to drop the supplied column.
+ */
+void
+sepgsql_attribute_drop(Oid relOid, AttrNumber attnum)
+{
+ ObjectAddress object;
+ char *audit_name;
+
+ if (get_rel_relkind(relOid) != RELKIND_RELATION)
+ return;
+
+ /*
+ * check db_column:{drop} permission
+ */
+ object.classId = RelationRelationId;
+ object.objectId = relOid;
+ object.objectSubId = attnum;
+ audit_name = getObjectDescription(&object);
+
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_COLUMN,
+ SEPG_DB_COLUMN__DROP,
+ audit_name,
+ true);
+ pfree(audit_name);
+}
+
+/*
* sepgsql_attribute_relabel
*
* It checks privileges to relabel the supplied column
@@ -310,6 +341,94 @@ out:
}
/*
+ * sepgsql_relation_drop
+ *
+ * It checks privileges to drop the supplied relation.
+ */
+void
+sepgsql_relation_drop(Oid relOid)
+{
+ ObjectAddress object;
+ char *audit_name;
+ uint16_t tclass = 0;
+ char relkind;
+
+ relkind = get_rel_relkind(relOid);
+ if (relkind == RELKIND_RELATION)
+ tclass = SEPG_CLASS_DB_TABLE;
+ else if (relkind == RELKIND_SEQUENCE)
+ tclass = SEPG_CLASS_DB_SEQUENCE;
+ else if (relkind == RELKIND_VIEW)
+ tclass = SEPG_CLASS_DB_VIEW;
+ else
+ return;
+
+ /*
+ * check db_schema:{remove_name} permission
+ */
+ object.classId = NamespaceRelationId;
+ object.objectId = get_rel_namespace(relOid);
+ object.objectSubId = 0;
+ audit_name = getObjectDescription(&object);
+
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_SCHEMA,
+ SEPG_DB_SCHEMA__REMOVE_NAME,
+ audit_name,
+ true);
+ pfree(audit_name);
+
+ /*
+ * check db_table/sequence/view:{drop} permission
+ */
+ object.classId = RelationRelationId;
+ object.objectId = relOid;
+ object.objectSubId = 0;
+ audit_name = getObjectDescription(&object);
+
+ sepgsql_avc_check_perms(&object,
+ tclass,
+ SEPG_DB_TABLE__DROP,
+ audit_name,
+ true);
+ pfree(audit_name);
+
+ /*
+ * check db_column:{drop} permission
+ */
+ if (relkind == RELKIND_RELATION)
+ {
+ Form_pg_attribute attForm;
+ CatCList *attrList;
+ HeapTuple atttup;
+ int i;
+
+ attrList = SearchSysCacheList1(ATTNUM, ObjectIdGetDatum(relOid));
+ for (i=0; i < attrList->n_members; i++)
+ {
+ atttup = &attrList->members[i]->tuple;
+ attForm = (Form_pg_attribute) GETSTRUCT(atttup);
+
+ if (attForm->attisdropped)
+ continue;
+
+ object.classId = RelationRelationId;
+ object.objectId = relOid;
+ object.objectSubId = attForm->attnum;
+ audit_name = getObjectDescription(&object);
+
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_COLUMN,
+ SEPG_DB_COLUMN__DROP,
+ audit_name,
+ true);
+ pfree(audit_name);
+ }
+ ReleaseCatCacheList(attrList);
+ }
+}
+
+/*
* sepgsql_relation_relabel
*
* It checks privileges to relabel the supplied relation by the `seclabel'.
diff --git a/contrib/sepgsql/schema.c b/contrib/sepgsql/schema.c
index 90dca1d..31d60ef 100644
--- a/contrib/sepgsql/schema.c
+++ b/contrib/sepgsql/schema.c
@@ -97,6 +97,33 @@ sepgsql_schema_post_create(Oid namespaceId)
}
/*
+ * sepgsql_schema_drop
+ *
+ * It checks privileges to drop the supplied schema object.
+ */
+void
+sepgsql_schema_drop(Oid namespaceId)
+{
+ ObjectAddress object;
+ char *audit_name;
+
+ /*
+ * check db_schema:{drop} permission
+ */
+ object.classId = NamespaceRelationId;
+ object.objectId = namespaceId;
+ object.objectSubId = 0;
+ audit_name = getObjectDescription(&object);
+
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_SCHEMA,
+ SEPG_DB_SCHEMA__DROP,
+ audit_name,
+ true);
+ pfree(audit_name);
+}
+
+/*
* sepgsql_schema_relabel
*
* It checks privileges to relabel the supplied schema
diff --git a/contrib/sepgsql/sepgsql.h b/contrib/sepgsql/sepgsql.h
index c93da7a..a7a4532 100644
--- a/contrib/sepgsql/sepgsql.h
+++ b/contrib/sepgsql/sepgsql.h
@@ -288,27 +288,32 @@ extern bool sepgsql_dml_privileges(List *rangeTabls, bool abort);
*/
extern void sepgsql_database_post_create(Oid databaseId,
const char *dtemplate);
+extern void sepgsql_database_drop(Oid databaseId);
extern void sepgsql_database_relabel(Oid databaseId, const char *seclabel);
/*
* schema.c
*/
extern void sepgsql_schema_post_create(Oid namespaceId);
+extern void sepgsql_schema_drop(Oid namespaceId);
extern void sepgsql_schema_relabel(Oid namespaceId, const char *seclabel);
/*
* relation.c
*/
extern void sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum);
+extern void sepgsql_attribute_drop(Oid relOid, AttrNumber attnum);
extern void sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
const char *seclabel);
extern void sepgsql_relation_post_create(Oid relOid);
+extern void sepgsql_relation_drop(Oid relOid);
extern void sepgsql_relation_relabel(Oid relOid, const char *seclabel);
/*
* proc.c
*/
extern void sepgsql_proc_post_create(Oid functionId);
+extern void sepgsql_proc_drop(Oid functionId);
extern void sepgsql_proc_relabel(Oid functionId, const char *seclabel);
#endif /* SEPGSQL_H */
diff --git a/contrib/sepgsql/sql/create.sql b/contrib/sepgsql/sql/create.sql
deleted file mode 100644
index b0695b4..0000000
--- a/contrib/sepgsql/sql/create.sql
+++ /dev/null
@@ -1,46 +0,0 @@
---
--- Regression Test for Creation of Object Permission Checks
---
-
--- confirm required permissions using audit messages
--- @SECURITY-CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0
-SET sepgsql.debug_audit = true;
-SET client_min_messages = LOG;
-
-CREATE DATABASE regtest_sepgsql_test_database;
-
-CREATE SCHEMA regtest_schema;
-
-SET search_path = regtest_schema, public;
-
-CREATE TABLE regtest_table (x serial primary key, y text);
-
-ALTER TABLE regtest_table ADD COLUMN z int;
-
-CREATE TABLE regtest_table_2 (a int) WITH OIDS;
-
--- corresponding toast table should not have label and permission checks
-ALTER TABLE regtest_table_2 ADD COLUMN b text;
-
--- VACUUM FULL internally create a new table and swap them later.
-VACUUM FULL regtest_table;
-
-CREATE VIEW regtest_view AS SELECT * FROM regtest_table WHERE x < 100;
-
-CREATE SEQUENCE regtest_seq;
-
-CREATE TYPE regtest_comptype AS (a int, b text);
-
-CREATE FUNCTION regtest_func(text,int[]) RETURNS bool LANGUAGE plpgsql
- AS 'BEGIN RAISE NOTICE ''regtest_func => %'', $1; RETURN true; END';
-
-CREATE AGGREGATE regtest_agg (
- sfunc1 = int4pl, basetype = int4, stype1 = int4, initcond1 = '0'
-);
-
---
--- clean-up
---
-DROP DATABASE IF EXISTS regtest_sepgsql_test_database;
-
-DROP SCHEMA IF EXISTS regtest_schema CASCADE;
diff --git a/contrib/sepgsql/sql/ddl.sql b/contrib/sepgsql/sql/ddl.sql
new file mode 100644
index 0000000..8dd57e0
--- /dev/null
+++ b/contrib/sepgsql/sql/ddl.sql
@@ -0,0 +1,81 @@
+--
+-- Regression Test for DDL of Object Permission Checks
+--
+
+-- confirm required permissions using audit messages
+-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0
+SET sepgsql.debug_audit = true;
+SET client_min_messages = LOG;
+
+--
+-- CREATE Permission checks
+--
+CREATE DATABASE regtest_sepgsql_test_database;
+
+CREATE USER regtest_sepgsql_test_user;
+
+CREATE SCHEMA regtest_schema;
+
+GRANT ALL ON SCHEMA regtest_schema TO regtest_sepgsql_test_user;
+
+SET search_path = regtest_schema, public;
+
+CREATE TABLE regtest_table (x serial primary key, y text);
+
+ALTER TABLE regtest_table ADD COLUMN z int;
+
+CREATE TABLE regtest_table_2 (a int) WITH OIDS;
+
+-- corresponding toast table should not have label and permission checks
+ALTER TABLE regtest_table_2 ADD COLUMN b text;
+
+-- VACUUM FULL internally create a new table and swap them later.
+VACUUM FULL regtest_table;
+
+CREATE VIEW regtest_view AS SELECT * FROM regtest_table WHERE x < 100;
+
+CREATE SEQUENCE regtest_seq;
+
+CREATE TYPE regtest_comptype AS (a int, b text);
+
+CREATE FUNCTION regtest_func(text,int[]) RETURNS bool LANGUAGE plpgsql
+ AS 'BEGIN RAISE NOTICE ''regtest_func => %'', $1; RETURN true; END';
+
+CREATE AGGREGATE regtest_agg (
+ sfunc1 = int4pl, basetype = int4, stype1 = int4, initcond1 = '0'
+);
+
+-- CREATE objects owned by others
+SET SESSION AUTHORIZATION regtest_sepgsql_test_user;
+
+SET search_path = regtest_schema, public;
+
+CREATE TABLE regtest_table_3 (x int, y serial);
+
+CREATE VIEW regtest_view_2 AS SELECT * FROM regtest_table_3 WHERE x < y;
+
+CREATE FUNCTION regtest_func_2(int) RETURNS bool LANGUAGE plpgsql
+ AS 'BEGIN RETURN $1 * $1 < 100; END';
+
+RESET SESSION AUTHORIZATION;
+
+--
+-- DROP Permission checks (with clean-up)
+--
+
+DROP FUNCTION regtest_func(text,int[]);
+DROP AGGREGATE regtest_agg(int);
+
+DROP SEQUENCE regtest_seq;
+DROP VIEW regtest_view;
+
+ALTER TABLE regtest_table DROP COLUMN y;
+ALTER TABLE regtest_table_2 SET WITHOUT OIDS;
+
+DROP TABLE regtest_table;
+
+DROP OWNED BY regtest_sepgsql_test_user;
+
+DROP DATABASE regtest_sepgsql_test_database;
+DROP USER regtest_sepgsql_test_user;
+DROP SCHEMA IF EXISTS regtest_schema CASCADE;
diff --git a/contrib/sepgsql/test_sepgsql b/contrib/sepgsql/test_sepgsql
index 52237e6..473004f 100755
--- a/contrib/sepgsql/test_sepgsql
+++ b/contrib/sepgsql/test_sepgsql
@@ -259,6 +259,6 @@ echo "found ${NUM}"
echo
echo "============== running sepgsql regression tests =============="
-make REGRESS="label dml create misc" REGRESS_OPTS="--launcher ./launcher" installcheck
+make REGRESS="label dml ddl misc" REGRESS_OPTS="--launcher ./launcher" installcheck
# exit with the exit code provided by "make"
diff --git a/doc/src/sgml/sepgsql.sgml b/doc/src/sgml/sepgsql.sgml
index e45c258..d9b1fed 100644
--- a/doc/src/sgml/sepgsql.sgml
+++ b/doc/src/sgml/sepgsql.sgml
@@ -448,6 +448,20 @@ UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
</para>
<para>
+ When <literal>DROP</> command is executed, <literal>drop</> will be
+ checked on the object being removed for each object types.
+ Please note that it shall not be checked on the objects removed by
+ cascaded deletion according to the standard manner in SQL.
+ </para>
+ <para>
+ A few additional checks are applied depending on object types.
+ On deletion of objects underlying a particula schema (tables, views,
+ sequences and procedures), <literal>remove_name</> shall be also checked
+ on the schema, not only <literal>drop</> on the object being removed
+ itself.
+ </para>
+
+ <para>
When <xref linkend="sql-security-label"> is executed, <literal>setattr</>
and <literal>relabelfrom</> will be checked on the object being relabeled
with its old security label, then <literal>relabelto</> with the supplied
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index db86262..aa6de11 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -20,6 +20,7 @@
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h"
#include "catalog/pg_attrdef.h"
@@ -972,6 +973,15 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
SysScanDesc scan;
HeapTuple tup;
+ /* DROP hook of the objects being removed */
+ if (object_access_hook)
+ {
+ ObjectAccessDrop drop_arg;
+ drop_arg.dropflags = flags;
+ InvokeObjectAccessHook(OAT_DROP, object->classId, object->objectId,
+ object->objectSubId, &drop_arg);
+ }
+
/*
* First remove any pg_depend records that link from this object to
* others. (Any records linking to this object should be gone already.)
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index aef410a..4e6459c 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -1279,7 +1279,8 @@ heap_create_with_catalog(const char *relname,
}
/* Post creation hook for new relation */
- InvokeObjectAccessHook(OAT_POST_CREATE, RelationRelationId, relid, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ RelationRelationId, relid, 0, NULL);
/*
* Store any supplied constraints and defaults.
diff --git a/src/backend/catalog/pg_collation.c b/src/backend/catalog/pg_collation.c
index 511d70c..18c7acf 100644
--- a/src/backend/catalog/pg_collation.c
+++ b/src/backend/catalog/pg_collation.c
@@ -136,7 +136,7 @@ CollationCreate(const char *collname, Oid collnamespace,
/* Post creation hook for new collation */
InvokeObjectAccessHook(OAT_POST_CREATE,
- CollationRelationId, oid, 0);
+ CollationRelationId, oid, 0, NULL);
heap_freetuple(tup);
heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 0bad4d9..342cf75 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -366,7 +366,8 @@ CreateConstraintEntry(const char *constraintName,
}
/* Post creation hook for new constraint */
- InvokeObjectAccessHook(OAT_POST_CREATE, ConstraintRelationId, conOid, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ ConstraintRelationId, conOid, 0, NULL);
return conOid;
}
diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c
index 8194cd6..f86c84f 100644
--- a/src/backend/catalog/pg_conversion.c
+++ b/src/backend/catalog/pg_conversion.c
@@ -134,8 +134,8 @@ ConversionCreate(const char *conname, Oid connamespace,
recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new conversion */
- InvokeObjectAccessHook(OAT_POST_CREATE,
- ConversionRelationId, HeapTupleGetOid(tup), 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE, ConversionRelationId,
+ HeapTupleGetOid(tup), 0, NULL);
heap_freetuple(tup);
heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c
index d5ab48a..da5fe5d 100644
--- a/src/backend/catalog/pg_namespace.c
+++ b/src/backend/catalog/pg_namespace.c
@@ -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);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ NamespaceRelationId, nspoid, 0, NULL);
return nspoid;
}
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 3b72722..4fd55ae 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -275,7 +275,7 @@ OperatorShellMake(const char *operatorName,
/* Post creation hook for new shell operator */
InvokeObjectAccessHook(OAT_POST_CREATE,
- OperatorRelationId, operatorObjectId, 0);
+ OperatorRelationId, operatorObjectId, 0, NULL);
/*
* Make sure the tuple is visible for subsequent lookups/updates.
@@ -544,7 +544,7 @@ OperatorCreate(const char *operatorName,
/* Post creation hook for new operator */
InvokeObjectAccessHook(OAT_POST_CREATE,
- OperatorRelationId, operatorObjectId, 0);
+ OperatorRelationId, operatorObjectId, 0, NULL);
heap_close(pg_operator_desc, RowExclusiveLock);
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 8c0d5f9..b7575a6 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -653,7 +653,8 @@ ProcedureCreate(const char *procedureName,
heap_freetuple(tup);
/* Post creation hook for new function */
- InvokeObjectAccessHook(OAT_POST_CREATE, ProcedureRelationId, retval, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ ProcedureRelationId, retval, 0, NULL);
heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 2c2e3b3..5b2ad6b 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -162,7 +162,8 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
false);
/* Post creation hook for new shell type */
- InvokeObjectAccessHook(OAT_POST_CREATE, TypeRelationId, typoid, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ TypeRelationId, typoid, 0, NULL);
/*
* clean up and return the type-oid
@@ -474,7 +475,8 @@ TypeCreate(Oid newTypeOid,
rebuildDeps);
/* Post creation hook for new type */
- InvokeObjectAccessHook(OAT_POST_CREATE, TypeRelationId, typeObjectId, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ TypeRelationId, typeObjectId, 0, NULL);
/*
* finish up
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 42a8b31..91d7481 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -515,7 +515,8 @@ createdb(const CreatedbStmt *stmt)
copyTemplateDependencies(src_dboid, dboid);
/* Post creation hook for new database */
- InvokeObjectAccessHook(OAT_POST_CREATE, DatabaseRelationId, dboid, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ DatabaseRelationId, dboid, 0, NULL);
/*
* Force a checkpoint before starting the copy. This will force dirty
@@ -777,6 +778,15 @@ dropdb(const char *dbname, bool missing_ok)
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
dbname);
+ /* DROP hook for the database being removed */
+ if (object_access_hook)
+ {
+ ObjectAccessDrop drop_arg;
+ memset(&drop_arg, 0, sizeof(ObjectAccessDrop));
+ InvokeObjectAccessHook(OAT_DROP,
+ DatabaseRelationId, db_id, 0, &drop_arg);
+ }
+
/*
* Disallow dropping a DB that is marked istemplate. This is just to
* prevent people from accidentally dropping template0 or template1; they
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 6ecbbc7..64fca87 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1558,7 +1558,7 @@ InsertExtensionTuple(const char *extName, Oid extOwner,
}
/* Post creation hook for new extension */
InvokeObjectAccessHook(OAT_POST_CREATE,
- ExtensionRelationId, extensionOid, 0);
+ ExtensionRelationId, extensionOid, 0, NULL);
return extensionOid;
}
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index 4135e26..61e9b6c 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -594,7 +594,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
/* Post creation hook for new foreign data wrapper */
InvokeObjectAccessHook(OAT_POST_CREATE,
- ForeignDataWrapperRelationId, fdwId, 0);
+ ForeignDataWrapperRelationId, fdwId, 0, NULL);
heap_close(rel, RowExclusiveLock);
}
@@ -890,7 +890,8 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new foreign server */
- InvokeObjectAccessHook(OAT_POST_CREATE, ForeignServerRelationId, srvId, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ ForeignServerRelationId, srvId, 0, NULL);
heap_close(rel, RowExclusiveLock);
}
@@ -1130,7 +1131,8 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new user mapping */
- InvokeObjectAccessHook(OAT_POST_CREATE, UserMappingRelationId, umId, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ UserMappingRelationId, umId, 0, NULL);
heap_close(rel, RowExclusiveLock);
}
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index c692a65..4c40a73 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -1723,7 +1723,8 @@ CreateCast(CreateCastStmt *stmt)
recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new cast */
- InvokeObjectAccessHook(OAT_POST_CREATE, CastRelationId, castid, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ CastRelationId, castid, 0, NULL);
heap_freetuple(tuple);
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index 5dc131a..87c8896 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -314,7 +314,7 @@ CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid)
/* Post creation hook for new operator family */
InvokeObjectAccessHook(OAT_POST_CREATE,
- OperatorFamilyRelationId, opfamilyoid, 0);
+ OperatorFamilyRelationId, opfamilyoid, 0, NULL);
heap_close(rel, RowExclusiveLock);
@@ -717,7 +717,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
/* Post creation hook for new operator class */
InvokeObjectAccessHook(OAT_POST_CREATE,
- OperatorClassRelationId, opclassoid, 0);
+ OperatorClassRelationId, opclassoid, 0, NULL);
heap_close(rel, RowExclusiveLock);
}
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index a3a111d..87cf2b3 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -425,7 +425,7 @@ create_proc_lang(const char *languageName, bool replace,
/* Post creation hook for new procedural language */
InvokeObjectAccessHook(OAT_POST_CREATE,
- LanguageRelationId, myself.objectId, 0);
+ LanguageRelationId, myself.objectId, 0, NULL);
heap_close(rel, RowExclusiveLock);
}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 07dc326..10bb48b 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4379,7 +4379,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
/* Post creation hook for new attribute */
InvokeObjectAccessHook(OAT_POST_CREATE,
- RelationRelationId, myrelid, newattnum);
+ RelationRelationId, myrelid, newattnum, NULL);
heap_close(pgclass, RowExclusiveLock);
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index 8ed6d06..8cd836d 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -330,7 +330,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
/* Post creation hook for new tablespace */
InvokeObjectAccessHook(OAT_POST_CREATE,
- TableSpaceRelationId, tablespaceoid, 0);
+ TableSpaceRelationId, tablespaceoid, 0, NULL);
create_tablespace_directories(location, tablespaceoid);
@@ -434,6 +434,15 @@ DropTableSpace(DropTableSpaceStmt *stmt)
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE,
tablespacename);
+ /* DROP hook for the tablespace being removed */
+ if (object_access_hook)
+ {
+ ObjectAccessDrop drop_arg;
+ memset(&drop_arg, 0, sizeof(ObjectAccessDrop));
+ InvokeObjectAccessHook(OAT_DROP, TableSpaceRelationId,
+ tablespaceoid, 0, &drop_arg);
+ }
+
/*
* Remove the pg_tablespace tuple (this will roll back if we fail below)
*/
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 2838b66..4dc5732 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -749,7 +749,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
/* Post creation hook for new trigger */
InvokeObjectAccessHook(OAT_POST_CREATE,
- TriggerRelationId, trigoid, 0);
+ TriggerRelationId, trigoid, 0, NULL);
/* Keep lock on target rel until end of xact */
heap_close(rel, NoLock);
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index fe500a6..86cb870 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -271,7 +271,8 @@ DefineTSParser(List *names, List *parameters)
makeParserDependencies(tup);
/* Post creation hook for new text search parser */
- InvokeObjectAccessHook(OAT_POST_CREATE, TSParserRelationId, prsOid, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ TSParserRelationId, prsOid, 0, NULL);
heap_freetuple(tup);
@@ -565,7 +566,7 @@ DefineTSDictionary(List *names, List *parameters)
/* Post creation hook for new text search dictionary */
InvokeObjectAccessHook(OAT_POST_CREATE,
- TSDictionaryRelationId, dictOid, 0);
+ TSDictionaryRelationId, dictOid, 0, NULL);
heap_freetuple(tup);
@@ -1036,7 +1037,8 @@ DefineTSTemplate(List *names, List *parameters)
makeTSTemplateDependencies(tup);
/* Post creation hook for new text search template */
- InvokeObjectAccessHook(OAT_POST_CREATE, TSTemplateRelationId, dictOid, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ TSTemplateRelationId, dictOid, 0, NULL);
heap_freetuple(tup);
@@ -1419,7 +1421,8 @@ DefineTSConfiguration(List *names, List *parameters)
makeConfigurationDependencies(tup, false, mapRel);
/* Post creation hook for new text search configuration */
- InvokeObjectAccessHook(OAT_POST_CREATE, TSConfigRelationId, cfgOid, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ TSConfigRelationId, cfgOid, 0, NULL);
heap_freetuple(tup);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 9a88c90..2edbabe 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -425,7 +425,8 @@ CreateRole(CreateRoleStmt *stmt)
GetUserId(), false);
/* Post creation hook for new role */
- InvokeObjectAccessHook(OAT_POST_CREATE, AuthIdRelationId, roleid, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ AuthIdRelationId, roleid, 0, NULL);
/*
* Close pg_authid, but keep lock till commit.
@@ -932,6 +933,15 @@ DropRole(DropRoleStmt *stmt)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to drop superusers")));
+ /* DROP hook for the role being removed */
+ if (object_access_hook)
+ {
+ ObjectAccessDrop drop_arg;
+ memset(&drop_arg, 0, sizeof(ObjectAccessDrop));
+ InvokeObjectAccessHook(OAT_DROP,
+ AuthIdRelationId, roleid, 0, &drop_arg);
+ }
+
/*
* Lock the role, so nobody can add dependencies to her while we drop
* her. We keep the lock until the end of transaction.
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 8c87ac5..645182d 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -178,7 +178,7 @@ InsertRule(char *rulname,
/* Post creation hook for new rule */
InvokeObjectAccessHook(OAT_POST_CREATE,
- RewriteRelationId, rewriteObjectId, 0);
+ RewriteRelationId, rewriteObjectId, 0, NULL);
heap_close(pg_rewrite_desc, RowExclusiveLock);
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index a14ce44..3adfb15 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -217,7 +217,7 @@ inv_create(Oid lobjId)
/* Post creation hook for new large object */
InvokeObjectAccessHook(OAT_POST_CREATE,
- LargeObjectRelationId, lobjId_new, 0);
+ LargeObjectRelationId, lobjId_new, 0, NULL);
/*
* Advance command counter to make new tuple visible to later operations.
diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h
index 5c7a40a..9763280 100644
--- a/src/include/catalog/objectaccess.h
+++ b/src/include/catalog/objectaccess.h
@@ -19,28 +19,45 @@
* Typically, this is done after inserting the primary catalog records and
* associated dependencies.
*
+ * OAT_DROP should be invoked just before deletion of objects; typically
+ * deleteOneObject(). Its arguments are packed within ObjectAccessDrop.
+ *
* Other types may be added in the future.
*/
typedef enum ObjectAccessType
{
OAT_POST_CREATE,
+ OAT_DROP,
} ObjectAccessType;
/*
- * Hook, and a macro to invoke it.
+ * Arguments of OAT_DROP event
*/
+typedef struct
+{
+ /*
+ * Flags to inform extensions the context of this deletion.
+ * Also see PERFORM_DELETION_* in dependency.h
+ */
+ int dropflags;
+} ObjectAccessDrop;
+/*
+ * Hook, and a macro to invoke it.
+ */
typedef void (*object_access_hook_type) (ObjectAccessType access,
Oid classId,
Oid objectId,
- int subId);
+ int subId,
+ void *arg);
extern PGDLLIMPORT object_access_hook_type object_access_hook;
-#define InvokeObjectAccessHook(access,classId,objectId,subId) \
- do { \
- if (object_access_hook) \
- (*object_access_hook)((access),(classId),(objectId),(subId)); \
+#define InvokeObjectAccessHook(access,classId,objectId,subId,arg) \
+ do { \
+ if (object_access_hook) \
+ (*object_access_hook)((access),(classId), \
+ (objectId),(subId),(arg)); \
} while(0)
#endif /* OBJECTACCESS_H */