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

 PG_MODULE_MAGIC_EXT (.name="sepgsql",.version=PG_VERSION)
 
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

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 403 of file hooks.c.

404{
405 /*
406 * We allow to load the SE-PostgreSQL module on single-user-mode or
407 * shared_preload_libraries settings only.
408 */
411 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
412 errmsg("sepgsql must be loaded via \"shared_preload_libraries\"")));
413
414 /*
415 * Check availability of SELinux on the platform. If disabled, we cannot
416 * activate any SE-PostgreSQL features, and we have to skip rest of
417 * initialization.
418 */
419 if (is_selinux_enabled() < 1)
420 {
422 return;
423 }
424
425 /*
426 * sepgsql.permissive = (on|off)
427 *
428 * This variable controls performing mode of SE-PostgreSQL on user's
429 * session.
430 */
431 DefineCustomBoolVariable("sepgsql.permissive",
432 "Turn on/off permissive mode in SE-PostgreSQL",
433 NULL,
435 false,
438 NULL,
439 NULL,
440 NULL);
441
442 /*
443 * sepgsql.debug_audit = (on|off)
444 *
445 * This variable allows users to turn on/off audit logs on access control
446 * decisions, independent from auditallow/auditdeny setting in the
447 * security policy. We intend to use this option for debugging purpose.
448 */
449 DefineCustomBoolVariable("sepgsql.debug_audit",
450 "Turn on/off debug audit messages",
451 NULL,
453 false,
456 NULL,
457 NULL,
458 NULL);
459
460 MarkGUCPrefixReserved("sepgsql");
461
462 /* Initialize userspace access vector cache */
464
465 /* Initialize security label of the client and related stuff */
467
468 /* Security label provider hook */
471
472 /* Object access hook */
475
476 /* DML permission check */
479
480 /* ProcessUtility hook */
483
484 /* init contextual info */
485 memset(&sepgsql_context_info, 0, sizeof(sepgsql_context_info));
486}
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:76
bool IsUnderPostmaster
Definition: globals.c:121
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:5133
void MarkGUCPrefixReserved(const char *className)
Definition: guc.c:5280
@ PGC_USERSET
Definition: guc.h:79
@ PGC_SIGHUP
Definition: guc.h:75
#define GUC_NOT_IN_SAMPLE
Definition: guc.h:221
static sepgsql_context_info_t sepgsql_context_info
Definition: hooks.c:58
static ExecutorCheckPerms_hook_type next_exec_check_perms_hook
Definition: hooks.c:41
static ProcessUtility_hook_type next_ProcessUtility_hook
Definition: hooks.c:42
static void sepgsql_object_access(ObjectAccessType access, Oid classId, Oid objectId, int subId, void *arg)
Definition: hooks.c:89
static bool sepgsql_debug_audit
Definition: hooks.c:74
static bool sepgsql_permissive
Definition: hooks.c:63
static bool sepgsql_exec_check_perms(List *rangeTbls, List *rteperminfos, bool abort)
Definition: hooks.c:293
static object_access_hook_type next_object_access_hook
Definition: hooks.c:40
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:316
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().

◆ PG_MODULE_MAGIC_EXT()

PG_MODULE_MAGIC_EXT ( name = "sepgsql",
version = PG_VERSION 
)

◆ sepgsql_exec_check_perms()

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

Definition at line 293 of file hooks.c.

294{
295 /*
296 * If security provider is stacking and one of them replied 'false' at
297 * least, we don't need to check any more.
298 */
300 !(*next_exec_check_perms_hook) (rangeTbls, rteperminfos, abort))
301 return false;
302
303 if (!sepgsql_dml_privileges(rangeTbls, rteperminfos, abort))
304 return false;
305
306 return true;
307}
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 77 of file hooks.c.

78{
80}

References sepgsql_debug_audit.

Referenced by sepgsql_avc_check_perms_label().

◆ sepgsql_get_permissive()

bool sepgsql_get_permissive ( void  )

Definition at line 66 of file hooks.c.

67{
68 return sepgsql_permissive;
69}

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 89 of file hooks.c.

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

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 316 of file hooks.c.

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

Referenced by _PG_init(), and sepgsql_utility_command().

◆ sepgsql_context_info

sepgsql_context_info_t sepgsql_context_info
static

Definition at line 58 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 74 of file hooks.c.

Referenced by _PG_init(), and sepgsql_get_debug_audit().

◆ sepgsql_permissive

bool sepgsql_permissive = false
static

Definition at line 63 of file hooks.c.

Referenced by _PG_init(), and sepgsql_get_permissive().