PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
hooks.c File Reference
#include "postgres.h"
#include "catalog/dependency.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_class.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "commands/seclabel.h"
#include "executor/executor.h"
#include "fmgr.h"
#include "miscadmin.h"
#include "sepgsql.h"
#include "tcop/utility.h"
#include "utils/guc.h"
#include "utils/queryenvironment.h"
Include dependency graph for hooks.c:

Go to the source code of this file.

Data Structures

struct  sepgsql_context_info_t
 

Functions

bool sepgsql_get_permissive (void)
 
bool sepgsql_get_debug_audit (void)
 
static void sepgsql_object_access (ObjectAccessType access, Oid classId, Oid objectId, int subId, void *arg)
 
static bool sepgsql_exec_check_perms (List *rangeTbls, List *rteperminfos, bool abort)
 
static void sepgsql_utility_command (PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
 
void _PG_init (void)
 

Variables

 PG_MODULE_MAGIC
 
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 sepgsql_context_info_t sepgsql_context_info
 
static bool sepgsql_permissive = false
 
static bool sepgsql_debug_audit = false
 

Function Documentation

◆ _PG_init()

void _PG_init ( void  )

Definition at line 400 of file hooks.c.

401{
402 /*
403 * We allow to load the SE-PostgreSQL module on single-user-mode or
404 * shared_preload_libraries settings only.
405 */
408 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
409 errmsg("sepgsql must be loaded via \"shared_preload_libraries\"")));
410
411 /*
412 * Check availability of SELinux on the platform. If disabled, we cannot
413 * activate any SE-PostgreSQL features, and we have to skip rest of
414 * initialization.
415 */
416 if (is_selinux_enabled() < 1)
417 {
419 return;
420 }
421
422 /*
423 * sepgsql.permissive = (on|off)
424 *
425 * This variable controls performing mode of SE-PostgreSQL on user's
426 * session.
427 */
428 DefineCustomBoolVariable("sepgsql.permissive",
429 "Turn on/off permissive mode in SE-PostgreSQL",
430 NULL,
432 false,
435 NULL,
436 NULL,
437 NULL);
438
439 /*
440 * sepgsql.debug_audit = (on|off)
441 *
442 * This variable allows users to turn on/off audit logs on access control
443 * decisions, independent from auditallow/auditdeny setting in the
444 * security policy. We intend to use this option for debugging purpose.
445 */
446 DefineCustomBoolVariable("sepgsql.debug_audit",
447 "Turn on/off debug audit messages",
448 NULL,
450 false,
453 NULL,
454 NULL,
455 NULL);
456
457 MarkGUCPrefixReserved("sepgsql");
458
459 /* Initialize userspace access vector cache */
461
462 /* Initialize security label of the client and related stuff */
464
465 /* Security label provider hook */
468
469 /* Object access hook */
472
473 /* DML permission check */
476
477 /* ProcessUtility hook */
480
481 /* init contextual info */
482 memset(&sepgsql_context_info, 0, sizeof(sepgsql_context_info));
483}
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:73
bool IsUnderPostmaster
Definition: globals.c:119
void DefineCustomBoolVariable(const char *name, const char *short_desc, const char *long_desc, bool *valueAddr, bool bootValue, GucContext context, int flags, GucBoolCheckHook check_hook, GucBoolAssignHook assign_hook, GucShowHook show_hook)
Definition: guc.c:5132
void MarkGUCPrefixReserved(const char *className)
Definition: guc.c:5279
@ PGC_USERSET
Definition: guc.h:75
@ PGC_SIGHUP
Definition: guc.h:71
#define GUC_NOT_IN_SAMPLE
Definition: guc.h:217
static sepgsql_context_info_t sepgsql_context_info
Definition: hooks.c:55
static ExecutorCheckPerms_hook_type next_exec_check_perms_hook
Definition: hooks.c:38
static ProcessUtility_hook_type next_ProcessUtility_hook
Definition: hooks.c:39
static void sepgsql_object_access(ObjectAccessType access, Oid classId, Oid objectId, int subId, void *arg)
Definition: hooks.c:86
static bool sepgsql_debug_audit
Definition: hooks.c:71
static bool sepgsql_permissive
Definition: hooks.c:60
static bool sepgsql_exec_check_perms(List *rangeTbls, List *rteperminfos, bool abort)
Definition: hooks.c:290
static object_access_hook_type next_object_access_hook
Definition: hooks.c:37
static void sepgsql_utility_command(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition: hooks.c:313
void sepgsql_init_client_label(void)
Definition: label.c:404
void sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
Definition: label.c:482
object_access_hook_type object_access_hook
Definition: objectaccess.c:22
void register_label_provider(const char *provider_name, check_object_relabel_type hook)
Definition: seclabel.c:570
int sepgsql_set_mode(int new_mode)
Definition: selinux.c:634
#define SEPGSQL_LABEL_TAG
Definition: sepgsql.h:23
#define SEPGSQL_MODE_DISABLED
Definition: sepgsql.h:31
void sepgsql_avc_init(void)
Definition: uavc.c:488
ProcessUtility_hook_type ProcessUtility_hook
Definition: utility.c:70

References DefineCustomBoolVariable(), ereport, errcode(), errmsg(), ERROR, ExecutorCheckPerms_hook, GUC_NOT_IN_SAMPLE, IsUnderPostmaster, MarkGUCPrefixReserved(), next_exec_check_perms_hook, next_object_access_hook, next_ProcessUtility_hook, object_access_hook, PGC_SIGHUP, PGC_USERSET, ProcessUtility_hook, register_label_provider(), sepgsql_avc_init(), sepgsql_context_info, sepgsql_debug_audit, sepgsql_exec_check_perms(), sepgsql_init_client_label(), SEPGSQL_LABEL_TAG, SEPGSQL_MODE_DISABLED, sepgsql_object_access(), sepgsql_object_relabel(), sepgsql_permissive, sepgsql_set_mode(), and sepgsql_utility_command().

◆ sepgsql_exec_check_perms()

static bool sepgsql_exec_check_perms ( List rangeTbls,
List rteperminfos,
bool  abort 
)
static

Definition at line 290 of file hooks.c.

291{
292 /*
293 * If security provider is stacking and one of them replied 'false' at
294 * least, we don't need to check any more.
295 */
297 !(*next_exec_check_perms_hook) (rangeTbls, rteperminfos, abort))
298 return false;
299
300 if (!sepgsql_dml_privileges(rangeTbls, rteperminfos, abort))
301 return false;
302
303 return true;
304}
bool sepgsql_dml_privileges(List *rangeTbls, List *rteperminfos, bool abort_on_violation)
Definition: dml.c:282

References next_exec_check_perms_hook, and sepgsql_dml_privileges().

Referenced by _PG_init().

◆ sepgsql_get_debug_audit()

bool sepgsql_get_debug_audit ( void  )

Definition at line 74 of file hooks.c.

75{
77}

References sepgsql_debug_audit.

Referenced by sepgsql_avc_check_perms_label().

◆ sepgsql_get_permissive()

bool sepgsql_get_permissive ( void  )

Definition at line 63 of file hooks.c.

64{
65 return sepgsql_permissive;
66}

References sepgsql_permissive.

Referenced by sepgsql_client_auth().

◆ sepgsql_object_access()

static void sepgsql_object_access ( ObjectAccessType  access,
Oid  classId,
Oid  objectId,
int  subId,
void *  arg 
)
static

Definition at line 86 of file hooks.c.

91{
93 (*next_object_access_hook) (access, classId, objectId, subId, arg);
94
95 switch (access)
96 {
97 case OAT_POST_CREATE:
98 {
100 bool is_internal;
101
102 is_internal = pc_arg ? pc_arg->is_internal : false;
103
104 switch (classId)
105 {
106 case DatabaseRelationId:
107 Assert(!is_internal);
110 break;
111
112 case NamespaceRelationId:
113 Assert(!is_internal);
115 break;
116
117 case RelationRelationId:
118 if (subId == 0)
119 {
120 /*
121 * The cases in which we want to apply permission
122 * checks on creation of a new relation correspond
123 * to direct user invocation. For internal uses,
124 * that is creation of toast tables, index rebuild
125 * or ALTER TABLE commands, we need neither
126 * assignment of security labels nor permission
127 * checks.
128 */
129 if (is_internal)
130 break;
131
133 }
134 else
135 sepgsql_attribute_post_create(objectId, subId);
136 break;
137
138 case ProcedureRelationId:
139 Assert(!is_internal);
140 sepgsql_proc_post_create(objectId);
141 break;
142
143 default:
144 /* Ignore unsupported object classes */
145 break;
146 }
147 }
148 break;
149
150 case OAT_DROP:
151 {
152 ObjectAccessDrop *drop_arg = (ObjectAccessDrop *) arg;
153
154 /*
155 * No need to apply permission checks on object deletion due
156 * to internal cleanups; such as removal of temporary database
157 * object on session closed.
158 */
159 if ((drop_arg->dropflags & PERFORM_DELETION_INTERNAL) != 0)
160 break;
161
162 switch (classId)
163 {
164 case DatabaseRelationId:
165 sepgsql_database_drop(objectId);
166 break;
167
168 case NamespaceRelationId:
169 sepgsql_schema_drop(objectId);
170 break;
171
172 case RelationRelationId:
173 if (subId == 0)
174 sepgsql_relation_drop(objectId);
175 else
176 sepgsql_attribute_drop(objectId, subId);
177 break;
178
179 case ProcedureRelationId:
180 sepgsql_proc_drop(objectId);
181 break;
182
183 default:
184 /* Ignore unsupported object classes */
185 break;
186 }
187 }
188 break;
189
190 case OAT_TRUNCATE:
191 {
192 switch (classId)
193 {
194 case RelationRelationId:
196 break;
197 default:
198 /* Ignore unsupported object classes */
199 break;
200 }
201 }
202 break;
203
204 case OAT_POST_ALTER:
205 {
206 ObjectAccessPostAlter *pa_arg = arg;
207 bool is_internal = pa_arg->is_internal;
208
209 switch (classId)
210 {
211 case DatabaseRelationId:
212 Assert(!is_internal);
213 sepgsql_database_setattr(objectId);
214 break;
215
216 case NamespaceRelationId:
217 Assert(!is_internal);
218 sepgsql_schema_setattr(objectId);
219 break;
220
221 case RelationRelationId:
222 if (subId == 0)
223 {
224 /*
225 * A case when we don't want to apply permission
226 * check is that relation is internally altered
227 * without user's intention. E.g, no need to check
228 * on toast table/index to be renamed at end of
229 * the table rewrites.
230 */
231 if (is_internal)
232 break;
233
234 sepgsql_relation_setattr(objectId);
235 }
236 else
237 sepgsql_attribute_setattr(objectId, subId);
238 break;
239
240 case ProcedureRelationId:
241 Assert(!is_internal);
242 sepgsql_proc_setattr(objectId);
243 break;
244
245 default:
246 /* Ignore unsupported object classes */
247 break;
248 }
249 }
250 break;
251
253 {
255
256 /*
257 * If stacked extension already decided not to allow users to
258 * search this schema, we just stick with that decision.
259 */
260 if (!ns_arg->result)
261 break;
262
263 Assert(classId == NamespaceRelationId);
264 Assert(ns_arg->result);
265 ns_arg->result
266 = sepgsql_schema_search(objectId,
267 ns_arg->ereport_on_violation);
268 }
269 break;
270
272 {
273 Assert(classId == ProcedureRelationId);
274 sepgsql_proc_execute(objectId);
275 }
276 break;
277
278 default:
279 elog(ERROR, "unexpected object access type: %d", (int) access);
280 break;
281 }
282}
#define Assert(condition)
Definition: c.h:812
void sepgsql_proc_post_create(Oid functionId)
Definition: proc.c:37
void sepgsql_proc_setattr(Oid functionId)
Definition: proc.c:235
void sepgsql_proc_drop(Oid functionId)
Definition: proc.c:155
void sepgsql_proc_execute(Oid functionId)
Definition: proc.c:315
void sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum)
Definition: relation.c:209
void sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
Definition: relation.c:43
void sepgsql_relation_post_create(Oid relOid)
Definition: relation.c:240
void sepgsql_relation_truncate(Oid relOid)
Definition: relation.c:524
void sepgsql_relation_setattr(Oid relOid)
Definition: relation.c:615
void sepgsql_relation_drop(Oid relOid)
Definition: relation.c:416
void sepgsql_attribute_drop(Oid relOid, AttrNumber attnum)
Definition: relation.c:133
void sepgsql_database_post_create(Oid databaseId, const char *dtemplate)
Definition: database.c:33
void sepgsql_database_drop(Oid databaseId)
Definition: database.c:133
void sepgsql_database_setattr(Oid databaseId)
Definition: database.c:160
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:92
#define elog(elevel,...)
Definition: elog.h:225
@ OAT_NAMESPACE_SEARCH
Definition: objectaccess.h:53
@ OAT_FUNCTION_EXECUTE
Definition: objectaccess.h:54
@ OAT_DROP
Definition: objectaccess.h:51
@ OAT_TRUNCATE
Definition: objectaccess.h:55
@ OAT_POST_ALTER
Definition: objectaccess.h:52
@ OAT_POST_CREATE
Definition: objectaccess.h:50
void * arg
short access
Definition: preproc-type.c:36
void sepgsql_schema_post_create(Oid namespaceId)
Definition: schema.c:36
void sepgsql_schema_setattr(Oid namespaceId)
Definition: schema.c:202
bool sepgsql_schema_search(Oid namespaceId, bool abort_on_violation)
Definition: schema.c:209
void sepgsql_schema_drop(Oid namespaceId)
Definition: schema.c:114
const char * createdb_dtemplate
Definition: hooks.c:52

References arg, Assert, sepgsql_context_info_t::createdb_dtemplate, ObjectAccessDrop::dropflags, elog, ObjectAccessNamespaceSearch::ereport_on_violation, ERROR, ObjectAccessPostCreate::is_internal, ObjectAccessPostAlter::is_internal, next_object_access_hook, OAT_DROP, OAT_FUNCTION_EXECUTE, OAT_NAMESPACE_SEARCH, OAT_POST_ALTER, OAT_POST_CREATE, OAT_TRUNCATE, PERFORM_DELETION_INTERNAL, ObjectAccessNamespaceSearch::result, sepgsql_attribute_drop(), sepgsql_attribute_post_create(), sepgsql_attribute_setattr(), sepgsql_context_info, sepgsql_database_drop(), sepgsql_database_post_create(), sepgsql_database_setattr(), sepgsql_proc_drop(), sepgsql_proc_execute(), sepgsql_proc_post_create(), sepgsql_proc_setattr(), sepgsql_relation_drop(), sepgsql_relation_post_create(), sepgsql_relation_setattr(), sepgsql_relation_truncate(), sepgsql_schema_drop(), sepgsql_schema_post_create(), sepgsql_schema_search(), and sepgsql_schema_setattr().

Referenced by _PG_init().

◆ sepgsql_utility_command()

static void sepgsql_utility_command ( PlannedStmt pstmt,
const char *  queryString,
bool  readOnlyTree,
ProcessUtilityContext  context,
ParamListInfo  params,
QueryEnvironment queryEnv,
DestReceiver dest,
QueryCompletion qc 
)
static

Definition at line 313 of file hooks.c.

321{
322 Node *parsetree = pstmt->utilityStmt;
323 sepgsql_context_info_t saved_context_info = sepgsql_context_info;
324 ListCell *cell;
325
326 PG_TRY();
327 {
328 /*
329 * Check command tag to avoid nefarious operations, and save the
330 * current contextual information to determine whether we should apply
331 * permission checks here, or not.
332 */
334
335 switch (nodeTag(parsetree))
336 {
337 case T_CreatedbStmt:
338
339 /*
340 * We hope to reference name of the source database, but it
341 * does not appear in system catalog. So, we save it here.
342 */
343 foreach(cell, ((CreatedbStmt *) parsetree)->options)
344 {
345 DefElem *defel = (DefElem *) lfirst(cell);
346
347 if (strcmp(defel->defname, "template") == 0)
348 {
350 = strVal(defel->arg);
351 break;
352 }
353 }
354 break;
355
356 case T_LoadStmt:
357
358 /*
359 * We reject LOAD command across the board on enforcing mode,
360 * because a binary module can arbitrarily override hooks.
361 */
362 if (sepgsql_getenforce())
363 {
365 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
366 errmsg("SELinux: LOAD is not permitted")));
367 }
368 break;
369 default:
370
371 /*
372 * Right now we don't check any other utility commands,
373 * because it needs more detailed information to make access
374 * control decision here, but we don't want to have two parse
375 * and analyze routines individually.
376 */
377 break;
378 }
379
381 (*next_ProcessUtility_hook) (pstmt, queryString, readOnlyTree,
382 context, params, queryEnv,
383 dest, qc);
384 else
385 standard_ProcessUtility(pstmt, queryString, readOnlyTree,
386 context, params, queryEnv,
387 dest, qc);
388 }
389 PG_FINALLY();
390 {
391 sepgsql_context_info = saved_context_info;
392 }
393 PG_END_TRY();
394}
#define PG_TRY(...)
Definition: elog.h:371
#define PG_END_TRY(...)
Definition: elog.h:396
#define PG_FINALLY(...)
Definition: elog.h:388
#define nodeTag(nodeptr)
Definition: nodes.h:133
#define lfirst(lc)
Definition: pg_list.h:172
bool sepgsql_getenforce(void)
Definition: selinux.c:651
char * defname
Definition: parsenodes.h:817
Node * arg
Definition: parsenodes.h:818
Definition: nodes.h:129
Node * utilityStmt
Definition: plannodes.h:95
void standard_ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition: utility.c:543
#define strVal(v)
Definition: value.h:82

References DefElem::arg, sepgsql_context_info_t::cmdtype, sepgsql_context_info_t::createdb_dtemplate, DefElem::defname, generate_unaccent_rules::dest, ereport, errcode(), errmsg(), ERROR, lfirst, next_ProcessUtility_hook, nodeTag, PG_END_TRY, PG_FINALLY, PG_TRY, sepgsql_context_info, sepgsql_getenforce(), standard_ProcessUtility(), strVal, and PlannedStmt::utilityStmt.

Referenced by _PG_init().

Variable Documentation

◆ next_exec_check_perms_hook

ExecutorCheckPerms_hook_type next_exec_check_perms_hook = NULL
static

Definition at line 38 of file hooks.c.

Referenced by _PG_init(), and sepgsql_exec_check_perms().

◆ next_object_access_hook

object_access_hook_type next_object_access_hook = NULL
static

Definition at line 37 of file hooks.c.

Referenced by _PG_init(), and sepgsql_object_access().

◆ next_ProcessUtility_hook

ProcessUtility_hook_type next_ProcessUtility_hook = NULL
static

Definition at line 39 of file hooks.c.

Referenced by _PG_init(), and sepgsql_utility_command().

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 28 of file hooks.c.

◆ sepgsql_context_info

sepgsql_context_info_t sepgsql_context_info
static

Definition at line 55 of file hooks.c.

Referenced by _PG_init(), sepgsql_object_access(), and sepgsql_utility_command().

◆ sepgsql_debug_audit

bool sepgsql_debug_audit = false
static

Definition at line 71 of file hooks.c.

Referenced by _PG_init(), and sepgsql_get_debug_audit().

◆ sepgsql_permissive

bool sepgsql_permissive = false
static

Definition at line 60 of file hooks.c.

Referenced by _PG_init(), and sepgsql_get_permissive().