Skip to content

Commit f4c4335

Browse files
committed
Add context info to OAT_POST_CREATE security hook
... and have sepgsql use it to determine whether to check permissions during certain operations. Indexes that are being created as a result of REINDEX, for instance, do not need to have their permissions checked; they were already checked when the index was created. Author: KaiGai Kohei, slightly revised by me
1 parent 4c9d090 commit f4c4335

File tree

16 files changed

+336
-116
lines changed

16 files changed

+336
-116
lines changed

contrib/sepgsql/expected/ddl.out

+53
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_
3434
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"
3535
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"
3636
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"
37+
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"
38+
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"
3739
ALTER TABLE regtest_table ADD COLUMN z int;
3840
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"
3941
CREATE TABLE regtest_table_2 (a int) WITH OIDS;
@@ -93,6 +95,55 @@ LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfine
9395
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)"
9496
RESET SESSION AUTHORIZATION;
9597
--
98+
-- ALTER and CREATE/DROP extra attribute permissions
99+
--
100+
CREATE TABLE regtest_table_4 (x int primary key, y int, z int);
101+
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"
102+
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"
103+
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"
104+
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"
105+
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"
106+
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"
107+
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"
108+
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"
109+
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"
110+
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"
111+
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"
112+
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"
113+
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"
114+
CREATE INDEX regtest_index_tbl4_y ON regtest_table_4(y);
115+
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"
116+
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"
117+
CREATE INDEX regtest_index_tbl4_z ON regtest_table_4(z);
118+
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"
119+
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"
120+
ALTER TABLE regtest_table_4 ALTER COLUMN y TYPE float;
121+
DROP INDEX regtest_index_tbl4_y;
122+
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"
123+
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"
124+
ALTER TABLE regtest_table_4
125+
ADD CONSTRAINT regtest_tbl4_con EXCLUDE USING btree (z WITH =);
126+
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"
127+
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"
128+
DROP TABLE regtest_table_4 CASCADE;
129+
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"
130+
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"
131+
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"
132+
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"
133+
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"
134+
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"
135+
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"
136+
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"
137+
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"
138+
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"
139+
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"
140+
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"
141+
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"
142+
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"
143+
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"
144+
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"
145+
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"
146+
--
96147
-- DROP Permission checks (with clean-up)
97148
--
98149
DROP FUNCTION regtest_func(text,int[]);
@@ -115,6 +166,8 @@ DROP TABLE regtest_table;
115166
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"
116167
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"
117168
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"
169+
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"
170+
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"
118171
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"
119172
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"
120173
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"

contrib/sepgsql/hooks.c

+41-84
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ void _PG_init(void);
3838
static object_access_hook_type next_object_access_hook = NULL;
3939
static ExecutorCheckPerms_hook_type next_exec_check_perms_hook = NULL;
4040
static ProcessUtility_hook_type next_ProcessUtility_hook = NULL;
41-
static ExecutorStart_hook_type next_ExecutorStart_hook = NULL;
4241

4342
/*
4443
* Contextual information on DDL commands
@@ -97,53 +96,55 @@ sepgsql_object_access(ObjectAccessType access,
9796
switch (access)
9897
{
9998
case OAT_POST_CREATE:
100-
switch (classId)
10199
{
102-
case DatabaseRelationId:
103-
sepgsql_database_post_create(objectId,
104-
sepgsql_context_info.createdb_dtemplate);
105-
break;
100+
ObjectAccessPostCreate *pc_arg = arg;
101+
bool is_internal;
106102

107-
case NamespaceRelationId:
108-
sepgsql_schema_post_create(objectId);
109-
break;
103+
is_internal = pc_arg ? pc_arg->is_internal : false;
110104

111-
case RelationRelationId:
112-
if (subId == 0)
113-
{
114-
/*
115-
* All cases we want to apply permission checks on
116-
* creation of a new relation are invocation of the
117-
* heap_create_with_catalog via DefineRelation or
118-
* OpenIntoRel. Elsewhere, we need neither assignment
119-
* of security label nor permission checks.
120-
*/
121-
switch (sepgsql_context_info.cmdtype)
105+
switch (classId)
106+
{
107+
case DatabaseRelationId:
108+
Assert(!is_internal);
109+
sepgsql_database_post_create(objectId,
110+
sepgsql_context_info.createdb_dtemplate);
111+
break;
112+
113+
case NamespaceRelationId:
114+
Assert(!is_internal);
115+
sepgsql_schema_post_create(objectId);
116+
break;
117+
118+
case RelationRelationId:
119+
if (subId == 0)
122120
{
123-
case T_CreateStmt:
124-
case T_ViewStmt:
125-
case T_CreateSeqStmt:
126-
case T_CompositeTypeStmt:
127-
case T_CreateForeignTableStmt:
128-
case T_SelectStmt:
129-
sepgsql_relation_post_create(objectId);
130-
break;
131-
default:
132-
/* via make_new_heap() */
121+
/*
122+
* The cases in which we want to apply permission
123+
* checks on creation of a new relation correspond
124+
* to direct user invocation. For internal uses,
125+
* that is creation of toast tables, index rebuild
126+
* or ALTER TABLE commands, we need neither
127+
* assignment of security labels nor permission
128+
* checks.
129+
*/
130+
if (is_internal)
133131
break;
132+
133+
sepgsql_relation_post_create(objectId);
134134
}
135-
}
136-
else
137-
sepgsql_attribute_post_create(objectId, subId);
138-
break;
135+
else
136+
sepgsql_attribute_post_create(objectId, subId);
137+
break;
139138

140-
case ProcedureRelationId:
141-
sepgsql_proc_post_create(objectId);
142-
break;
139+
case ProcedureRelationId:
140+
Assert(!is_internal);
141+
sepgsql_proc_post_create(objectId);
142+
break;
143143

144-
default:
145-
/* Ignore unsupported object classes */
146-
break;
144+
default:
145+
/* Ignore unsupported object classes */
146+
break;
147+
}
147148
}
148149
break;
149150

@@ -215,46 +216,6 @@ sepgsql_exec_check_perms(List *rangeTabls, bool abort)
215216
return true;
216217
}
217218

218-
/*
219-
* sepgsql_executor_start
220-
*
221-
* It saves contextual information during ExecutorStart to distinguish
222-
* a case with/without permission checks later.
223-
*/
224-
static void
225-
sepgsql_executor_start(QueryDesc *queryDesc, int eflags)
226-
{
227-
sepgsql_context_info_t saved_context_info = sepgsql_context_info;
228-
229-
PG_TRY();
230-
{
231-
if (queryDesc->operation == CMD_SELECT)
232-
sepgsql_context_info.cmdtype = T_SelectStmt;
233-
else if (queryDesc->operation == CMD_INSERT)
234-
sepgsql_context_info.cmdtype = T_InsertStmt;
235-
else if (queryDesc->operation == CMD_DELETE)
236-
sepgsql_context_info.cmdtype = T_DeleteStmt;
237-
else if (queryDesc->operation == CMD_UPDATE)
238-
sepgsql_context_info.cmdtype = T_UpdateStmt;
239-
240-
/*
241-
* XXX - If queryDesc->operation is not above four cases, an error
242-
* shall be raised on the following executor stage soon.
243-
*/
244-
if (next_ExecutorStart_hook)
245-
(*next_ExecutorStart_hook) (queryDesc, eflags);
246-
else
247-
standard_ExecutorStart(queryDesc, eflags);
248-
}
249-
PG_CATCH();
250-
{
251-
sepgsql_context_info = saved_context_info;
252-
PG_RE_THROW();
253-
}
254-
PG_END_TRY();
255-
sepgsql_context_info = saved_context_info;
256-
}
257-
258219
/*
259220
* sepgsql_utility_command
260221
*
@@ -425,10 +386,6 @@ _PG_init(void)
425386
next_ProcessUtility_hook = ProcessUtility_hook;
426387
ProcessUtility_hook = sepgsql_utility_command;
427388

428-
/* ExecutorStart hook */
429-
next_ExecutorStart_hook = ExecutorStart_hook;
430-
ExecutorStart_hook = sepgsql_executor_start;
431-
432389
/* init contextual info */
433390
memset(&sepgsql_context_info, 0, sizeof(sepgsql_context_info));
434391
}

0 commit comments

Comments
 (0)