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"
+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 { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="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 { 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;
--
+-- ALTER and CREATE/DROP extra attribute permissions
+--
+CREATE TABLE regtest_table_4 (x int primary key, y int, z int);
+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_4"
+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_4 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_4 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_4 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_4 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_4 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_4 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_4 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_4 column y"
+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_4 column z"
+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 { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4"
+CREATE INDEX regtest_index_tbl4_y ON regtest_table_4(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 { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4"
+CREATE INDEX regtest_index_tbl4_z ON regtest_table_4(z);
+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 { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4"
+ALTER TABLE regtest_table_4 ALTER COLUMN y TYPE float;
+DROP INDEX regtest_index_tbl4_y;
+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 { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4"
+ALTER TABLE regtest_table_4
+ ADD CONSTRAINT regtest_tbl4_con EXCLUDE USING btree (z WITH =);
+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 { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4"
+DROP TABLE regtest_table_4 CASCADE;
+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 { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4"
+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 { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4"
+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 { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4"
+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_4"
+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_4 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_4 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_4 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_4 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_4 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_4 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_4 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_4 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_4 column z"
+--
-- 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_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 { setattr } 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 { 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"
static object_access_hook_type next_object_access_hook = NULL;
static ExecutorCheckPerms_hook_type next_exec_check_perms_hook = NULL;
static ProcessUtility_hook_type next_ProcessUtility_hook = NULL;
-static ExecutorStart_hook_type next_ExecutorStart_hook = NULL;
/*
* Contextual information on DDL commands
switch (access)
{
case OAT_POST_CREATE:
- switch (classId)
{
- case DatabaseRelationId:
- sepgsql_database_post_create(objectId,
- sepgsql_context_info.createdb_dtemplate);
- break;
+ ObjectAccessPostCreate *pc_arg = arg;
+ bool is_internal;
- case NamespaceRelationId:
- sepgsql_schema_post_create(objectId);
- break;
+ is_internal = pc_arg ? pc_arg->is_internal : false;
- case RelationRelationId:
- if (subId == 0)
- {
- /*
- * All cases we want to apply permission checks on
- * creation of a new relation are invocation of the
- * heap_create_with_catalog via DefineRelation or
- * OpenIntoRel. Elsewhere, we need neither assignment
- * of security label nor permission checks.
- */
- switch (sepgsql_context_info.cmdtype)
+ switch (classId)
+ {
+ case DatabaseRelationId:
+ Assert(!is_internal);
+ sepgsql_database_post_create(objectId,
+ sepgsql_context_info.createdb_dtemplate);
+ break;
+
+ case NamespaceRelationId:
+ Assert(!is_internal);
+ sepgsql_schema_post_create(objectId);
+ break;
+
+ case RelationRelationId:
+ if (subId == 0)
{
- case T_CreateStmt:
- case T_ViewStmt:
- case T_CreateSeqStmt:
- case T_CompositeTypeStmt:
- case T_CreateForeignTableStmt:
- case T_SelectStmt:
- sepgsql_relation_post_create(objectId);
- break;
- default:
- /* via make_new_heap() */
+ /*
+ * The cases in which we want to apply permission
+ * checks on creation of a new relation correspond
+ * to direct user invocation. For internal uses,
+ * that is creation of toast tables, index rebuild
+ * or ALTER TABLE commands, we need neither
+ * assignment of security labels nor permission
+ * checks.
+ */
+ if (is_internal)
break;
+
+ sepgsql_relation_post_create(objectId);
}
- }
- else
- sepgsql_attribute_post_create(objectId, subId);
- break;
+ else
+ sepgsql_attribute_post_create(objectId, subId);
+ break;
- case ProcedureRelationId:
- sepgsql_proc_post_create(objectId);
- break;
+ case ProcedureRelationId:
+ Assert(!is_internal);
+ sepgsql_proc_post_create(objectId);
+ break;
- default:
- /* Ignore unsupported object classes */
- break;
+ default:
+ /* Ignore unsupported object classes */
+ break;
+ }
}
break;
return true;
}
-/*
- * sepgsql_executor_start
- *
- * It saves contextual information during ExecutorStart to distinguish
- * a case with/without permission checks later.
- */
-static void
-sepgsql_executor_start(QueryDesc *queryDesc, int eflags)
-{
- sepgsql_context_info_t saved_context_info = sepgsql_context_info;
-
- PG_TRY();
- {
- if (queryDesc->operation == CMD_SELECT)
- sepgsql_context_info.cmdtype = T_SelectStmt;
- else if (queryDesc->operation == CMD_INSERT)
- sepgsql_context_info.cmdtype = T_InsertStmt;
- else if (queryDesc->operation == CMD_DELETE)
- sepgsql_context_info.cmdtype = T_DeleteStmt;
- else if (queryDesc->operation == CMD_UPDATE)
- sepgsql_context_info.cmdtype = T_UpdateStmt;
-
- /*
- * XXX - If queryDesc->operation is not above four cases, an error
- * shall be raised on the following executor stage soon.
- */
- if (next_ExecutorStart_hook)
- (*next_ExecutorStart_hook) (queryDesc, eflags);
- else
- standard_ExecutorStart(queryDesc, eflags);
- }
- PG_CATCH();
- {
- sepgsql_context_info = saved_context_info;
- PG_RE_THROW();
- }
- PG_END_TRY();
- sepgsql_context_info = saved_context_info;
-}
-
/*
* sepgsql_utility_command
*
next_ProcessUtility_hook = ProcessUtility_hook;
ProcessUtility_hook = sepgsql_utility_command;
- /* ExecutorStart hook */
- next_ExecutorStart_hook = ExecutorStart_hook;
- ExecutorStart_hook = sepgsql_executor_start;
-
/* init contextual info */
memset(&sepgsql_context_info, 0, sizeof(sepgsql_context_info));
}
#include "utils/fmgroids.h"
#include "utils/catcache.h"
#include "utils/lsyscache.h"
+#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
#include "sepgsql.h"
+static void sepgsql_index_modify(Oid indexOid);
+
/*
* sepgsql_attribute_post_create
*
classForm = (Form_pg_class) GETSTRUCT(tuple);
+ /* ignore indexes on toast tables */
+ if (classForm->relkind == RELKIND_INDEX &&
+ classForm->relnamespace == PG_TOAST_NAMESPACE)
+ goto out;
+
+ /*
+ * check db_schema:{add_name} permission of the namespace
+ */
+ object.classId = NamespaceRelationId;
+ object.objectId = classForm->relnamespace;
+ object.objectSubId = 0;
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_SCHEMA,
+ SEPG_DB_SCHEMA__ADD_NAME,
+ getObjectDescription(&object),
+ true);
+
switch (classForm->relkind)
{
case RELKIND_RELATION:
tclass = SEPG_CLASS_DB_VIEW;
tclass_text = "view";
break;
+ case RELKIND_INDEX:
+ /* deal with indexes specially; no need for tclass */
+ sepgsql_index_modify(relOid);
+ goto out;
default:
+ /* ignore other relkinds */
goto out;
}
- /*
- * check db_schema:{add_name} permission of the namespace
- */
- object.classId = NamespaceRelationId;
- object.objectId = classForm->relnamespace;
- object.objectSubId = 0;
- sepgsql_avc_check_perms(&object,
- SEPG_CLASS_DB_SCHEMA,
- SEPG_DB_SCHEMA__ADD_NAME,
- getObjectDescription(&object),
- true);
-
/*
* Compute a default security label when we create a new relation object
* under the specified namespace.
heap_close(arel, AccessShareLock);
}
pfree(rcontext);
+
out:
systable_endscan(sscan);
heap_close(rel, AccessShareLock);
{
ObjectAddress object;
char *audit_name;
- uint16_t tclass = 0;
+ uint16_t tclass;
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;
+ switch (relkind)
+ {
+ case RELKIND_RELATION:
+ tclass = SEPG_CLASS_DB_TABLE;
+ break;
+ case RELKIND_SEQUENCE:
+ tclass = SEPG_CLASS_DB_SEQUENCE;
+ break;
+ case RELKIND_VIEW:
+ tclass = SEPG_CLASS_DB_VIEW;
+ break;
+ case RELKIND_INDEX:
+ /* ignore indexes on toast tables */
+ if (get_rel_namespace(relOid) == PG_TOAST_NAMESPACE)
+ return;
+ /* other indexes are handled specially below; no need for tclass */
+ break;
+ default:
+ /* ignore other relkinds */
+ return;
+ }
/*
* check db_schema:{remove_name} permission
true);
pfree(audit_name);
+ /* deal with indexes specially */
+ if (relkind == RELKIND_INDEX)
+ {
+ sepgsql_index_modify(relOid);
+ return;
+ }
+
/*
* check db_table/sequence/view:{drop} permission
*/
true);
pfree(audit_name);
}
+
+/*
+ * sepgsql_relation_setattr
+ *
+ * It checks privileges to set attribute of the supplied relation
+ */
+void
+sepgsql_relation_setattr(Oid relOid)
+{
+ ObjectAddress object;
+ char *audit_name;
+ uint16_t tclass;
+
+ switch (get_rel_relkind(relOid))
+ {
+ case RELKIND_RELATION:
+ tclass = SEPG_CLASS_DB_TABLE;
+ break;
+ case RELKIND_SEQUENCE:
+ tclass = SEPG_CLASS_DB_SEQUENCE;
+ break;
+ case RELKIND_VIEW:
+ tclass = SEPG_CLASS_DB_VIEW;
+ break;
+ case RELKIND_INDEX:
+ /* deal with indexes specially */
+ sepgsql_index_modify(relOid);
+ return;
+ default:
+ /* other relkinds don't need additional work */
+ return;
+ }
+
+ object.classId = RelationRelationId;
+ object.objectId = relOid;
+ object.objectSubId = 0;
+ audit_name = getObjectDescription(&object);
+
+ /*
+ * XXX - we should add checks related to namespace stuff, when
+ * object_access_hook get support for ALTER statement. Right now, there is
+ * no invocation path on ALTER ... RENAME TO / SET SCHEMA.
+ */
+
+ /*
+ * check db_xxx:{setattr} permission
+ */
+ sepgsql_avc_check_perms(&object,
+ tclass,
+ SEPG_DB_TABLE__SETATTR,
+ audit_name,
+ true);
+ pfree(audit_name);
+}
+
+/*
+ * sepgsql_relation_setattr_extra
+ *
+ * It checks permission of the relation being referenced by extra attributes,
+ * such as pg_index entries. Like core PostgreSQL, sepgsql also does not deal
+ * with such entries as individual "objects", thus, modification of these
+ * entries shall be considered as setting an attribute of the underlying
+ * relation.
+ */
+static void
+sepgsql_relation_setattr_extra(Relation catalog,
+ Oid catindex_id,
+ Oid extra_oid,
+ AttrNumber anum_relation_id,
+ AttrNumber anum_extra_id)
+{
+ ScanKeyData skey;
+ SysScanDesc sscan;
+ HeapTuple tuple;
+ Datum datum;
+ bool isnull;
+
+ ScanKeyInit(&skey, anum_extra_id,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(extra_oid));
+
+ sscan = systable_beginscan(catalog, catindex_id, true,
+ SnapshotSelf, 1, &skey);
+ tuple = systable_getnext(sscan);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "catalog lookup failed for object %u in catalog \"%s\"",
+ extra_oid, RelationGetRelationName(catalog));
+
+ datum = heap_getattr(tuple, anum_relation_id,
+ RelationGetDescr(catalog), &isnull);
+ Assert(!isnull);
+
+ sepgsql_relation_setattr(DatumGetObjectId(datum));
+
+ systable_endscan(sscan);
+}
+
+/*
+ * sepgsql_index_modify
+ * Handle index create, update, drop
+ *
+ * Unlike other relation kinds, indexes do not have their own security labels,
+ * so instead of doing checks directly, treat them as extra attributes of their
+ * owning tables; so check 'setattr' permissions on the table.
+ */
+static void
+sepgsql_index_modify(Oid indexOid)
+{
+ Relation catalog = heap_open(IndexRelationId, AccessShareLock);
+
+ /* check db_table:{setattr} permission of the table being indexed */
+ sepgsql_relation_setattr_extra(catalog,
+ IndexRelidIndexId,
+ indexOid,
+ Anum_pg_index_indrelid,
+ Anum_pg_index_indexrelid);
+ heap_close(catalog, AccessShareLock);
+}
#define SEPG_DB_TABLE__INSERT (1<<8)
#define SEPG_DB_TABLE__DELETE (1<<9)
#define SEPG_DB_TABLE__LOCK (1<<10)
-#define SEPG_DB_TABLE__INDEXON (1<<11)
#define SEPG_DB_SEQUENCE__CREATE (SEPG_DB_DATABASE__CREATE)
#define SEPG_DB_SEQUENCE__DROP (SEPG_DB_DATABASE__DROP)
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);
+extern void sepgsql_relation_setattr(Oid relOid);
/*
* proc.c
RESET SESSION AUTHORIZATION;
+--
+-- ALTER and CREATE/DROP extra attribute permissions
+--
+CREATE TABLE regtest_table_4 (x int primary key, y int, z int);
+CREATE INDEX regtest_index_tbl4_y ON regtest_table_4(y);
+CREATE INDEX regtest_index_tbl4_z ON regtest_table_4(z);
+ALTER TABLE regtest_table_4 ALTER COLUMN y TYPE float;
+DROP INDEX regtest_index_tbl4_y;
+ALTER TABLE regtest_table_4
+ ADD CONSTRAINT regtest_tbl4_con EXCLUDE USING btree (z WITH =);
+DROP TABLE regtest_table_4 CASCADE;
+
--
-- DROP Permission checks (with clean-up)
--
<literal>remove_name</> on the schema.
</para>
+ <para>
+ When objects that are subsidiary of other objects (such as a table's indexes
+ or triggers) are created or dropped, <literal>setattr</> permission will be
+ checked on the main object, instead of the subsidiary object itself.
+ </para>
+
<para>
When <xref linkend="sql-security-label"> is executed, <literal>setattr</>
and <literal>relabelfrom</> will be checked on the object being relabeled
ONCOMMIT_NOOP,
(Datum) 0,
false,
- true);
+ true,
+ false);
elog(DEBUG4, "relation created with OID %u", id);
}
do_end();
OnCommitAction oncommit,
Datum reloptions,
bool use_user_acl,
- bool allow_system_table_mods)
+ bool allow_system_table_mods,
+ bool is_internal)
{
Relation pg_class_desc;
Relation new_rel_desc;
}
/* Post creation hook for new relation */
- InvokeObjectAccessHook(OAT_POST_CREATE,
- RelationRelationId, relid, 0, NULL);
+ if (object_access_hook)
+ {
+ ObjectAccessPostCreate post_create_args;
+
+ memset(&post_create_args, 0, sizeof(ObjectAccessPostCreate));
+ post_create_args.is_internal = is_internal;
+ (*object_access_hook)(OAT_POST_CREATE, RelationRelationId,
+ relid, 0, &post_create_args);
+ }
/*
* Store any supplied constraints and defaults.
#include "catalog/dependency.h"
#include "catalog/heap.h"
#include "catalog/index.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_operator.h"
bool initdeferred,
bool allow_system_table_mods,
bool skip_build,
- bool concurrent)
+ bool concurrent,
+ bool is_internal)
{
Oid heapRelationId = RelationGetRelid(heapRelation);
Relation pg_class;
Assert(!initdeferred);
}
+ /* Post creation hook for new index */
+ if (object_access_hook)
+ {
+ ObjectAccessPostCreate post_create_args;
+
+ memset(&post_create_args, 0, sizeof(ObjectAccessPostCreate));
+ post_create_args.is_internal = is_internal;
+ (*object_access_hook)(OAT_POST_CREATE, RelationRelationId,
+ indexRelationId, 0, &post_create_args);
+ }
+
/*
* Advance the command counter so that we can see the newly-entered
* catalog tuples for the index.
ONCOMMIT_NOOP,
reloptions,
false,
+ true,
true);
Assert(toast_relid != InvalidOid);
rel->rd_rel->reltablespace,
collationObjectId, classObjectId, coloptions, (Datum) 0,
true, false, false, false,
- true, false, false);
+ true, false, false, true);
heap_close(toast_rel, NoLock);
ONCOMMIT_NOOP,
reloptions,
false,
+ true,
true);
Assert(OIDNewHeap != InvalidOid);
stmt->isconstraint, stmt->deferrable, stmt->initdeferred,
allowSystemTableMods,
skip_build || stmt->concurrent,
- stmt->concurrent);
+ stmt->concurrent, !check_rights);
/* Add any requested comment */
if (stmt->idxcomment != NULL)
stmt->oncommit,
reloptions,
true,
- allowSystemTableMods);
+ allowSystemTableMods,
+ false);
/* Store inheritance information for new rel. */
StoreCatalogInheritance(relationId, inheritOids);
OnCommitAction oncommit,
Datum reloptions,
bool use_user_acl,
- bool allow_system_table_mods);
+ bool allow_system_table_mods,
+ bool is_internal);
extern void heap_create_init_fork(Relation rel);
bool initdeferred,
bool allow_system_table_mods,
bool skip_build,
- bool concurrent);
+ bool concurrent,
+ bool is_internal);
extern void index_constraint_create(Relation heapRelation,
Oid indexRelationId,
OAT_DROP,
} ObjectAccessType;
+/*
+ * Arguments of OAT_POST_CREATE event
+ */
+typedef struct
+{
+ /*
+ * This flag informs extensions whether the context of this creation
+ * is invoked by user's operations, or not. E.g, it shall be dealt
+ * as internal stuff on toast tables or indexes due to type changes.
+ */
+ bool is_internal;
+} ObjectAccessPostCreate;
+
/*
* Arguments of OAT_DROP event
*/