PostgreSQL Source Code  git master
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

void _PG_init (void)
 
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 *rangeTabls, bool abort)
 
static void sepgsql_utility_command (PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, char *completionTag)
 

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
 
static bool sepgsql_debug_audit
 

Function Documentation

◆ _PG_init()

void _PG_init ( void  )

Definition at line 400 of file hooks.c.

References DefineCustomBoolVariable(), ereport, errcode(), errmsg(), ERROR, ExecutorCheckPerms_hook, GUC_NOT_IN_SAMPLE, IsUnderPostmaster, 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_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().

401 {
402  /*
403  * We allow to load the SE-PostgreSQL module on single-user-mode or
404  * shared_preload_libraries settings only.
405  */
406  if (IsUnderPostmaster)
407  ereport(ERROR,
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,
433  PGC_SIGHUP,
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,
451  PGC_USERSET,
453  NULL,
454  NULL,
455  NULL);
456 
457  /* Initialize userspace access vector cache */
459 
460  /* Initialize security label of the client and related stuff */
462 
463  /* Security label provider hook */
466 
467  /* Object access hook */
470 
471  /* DML permission check */
474 
475  /* ProcessUtility hook */
478 
479  /* init contextual info */
480  memset(&sepgsql_context_info, 0, sizeof(sepgsql_context_info));
481 }
static ExecutorCheckPerms_hook_type next_exec_check_perms_hook
Definition: hooks.c:39
void sepgsql_init_client_label(void)
Definition: label.c:405
ProcessUtility_hook_type ProcessUtility_hook
Definition: utility.c:75
int errcode(int sqlerrcode)
Definition: elog.c:608
#define SEPGSQL_MODE_DISABLED
Definition: sepgsql.h:31
static bool sepgsql_debug_audit
Definition: hooks.c:72
static void sepgsql_utility_command(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, char *completionTag)
Definition: hooks.c:314
static bool sepgsql_exec_check_perms(List *rangeTabls, bool abort)
Definition: hooks.c:291
void sepgsql_avc_init(void)
Definition: uavc.c:487
#define ERROR
Definition: elog.h:43
int sepgsql_set_mode(int new_mode)
Definition: selinux.c:634
static bool sepgsql_permissive
Definition: hooks.c:61
bool IsUnderPostmaster
Definition: globals.c:109
#define SEPGSQL_LABEL_TAG
Definition: sepgsql.h:23
#define GUC_NOT_IN_SAMPLE
Definition: guc.h:209
#define ereport(elevel, rest)
Definition: elog.h:141
static sepgsql_context_info_t sepgsql_context_info
Definition: hooks.c:56
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:76
Definition: guc.h:72
static object_access_hook_type next_object_access_hook
Definition: hooks.c:38
void register_label_provider(const char *provider_name, check_object_relabel_type hook)
Definition: seclabel.c:493
object_access_hook_type object_access_hook
Definition: objectaccess.c:22
static void sepgsql_object_access(ObjectAccessType access, Oid classId, Oid objectId, int subId, void *arg)
Definition: hooks.c:87
static ProcessUtility_hook_type next_ProcessUtility_hook
Definition: hooks.c:40
void sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
Definition: label.c:483
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:8636

◆ sepgsql_exec_check_perms()

static bool sepgsql_exec_check_perms ( List rangeTabls,
bool  abort 
)
static

Definition at line 291 of file hooks.c.

References next_exec_check_perms_hook, and sepgsql_dml_privileges().

Referenced by _PG_init().

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

◆ sepgsql_get_debug_audit()

bool sepgsql_get_debug_audit ( void  )

Definition at line 75 of file hooks.c.

References sepgsql_debug_audit.

Referenced by sepgsql_avc_check_perms_label(), and sepgsql_check_perms().

76 {
77  return sepgsql_debug_audit;
78 }
static bool sepgsql_debug_audit
Definition: hooks.c:72

◆ sepgsql_get_permissive()

bool sepgsql_get_permissive ( void  )

Definition at line 64 of file hooks.c.

References sepgsql_permissive.

Referenced by sepgsql_client_auth().

65 {
66  return sepgsql_permissive;
67 }
static bool sepgsql_permissive
Definition: hooks.c:61

◆ sepgsql_object_access()

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

Definition at line 87 of file hooks.c.

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_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().

92 {
94  (*next_object_access_hook) (access, classId, objectId, subId, arg);
95 
96  switch (access)
97  {
98  case OAT_POST_CREATE:
99  {
100  ObjectAccessPostCreate *pc_arg = arg;
101  bool is_internal;
102 
103  is_internal = pc_arg ? pc_arg->is_internal : false;
104 
105  switch (classId)
106  {
107  case DatabaseRelationId:
108  Assert(!is_internal);
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)
120  {
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)
131  break;
132 
134  }
135  else
136  sepgsql_attribute_post_create(objectId, subId);
137  break;
138 
139  case ProcedureRelationId:
140  Assert(!is_internal);
141  sepgsql_proc_post_create(objectId);
142  break;
143 
144  default:
145  /* Ignore unsupported object classes */
146  break;
147  }
148  }
149  break;
150 
151  case OAT_DROP:
152  {
153  ObjectAccessDrop *drop_arg = (ObjectAccessDrop *) arg;
154 
155  /*
156  * No need to apply permission checks on object deletion due
157  * to internal cleanups; such as removal of temporary database
158  * object on session closed.
159  */
160  if ((drop_arg->dropflags & PERFORM_DELETION_INTERNAL) != 0)
161  break;
162 
163  switch (classId)
164  {
165  case DatabaseRelationId:
166  sepgsql_database_drop(objectId);
167  break;
168 
169  case NamespaceRelationId:
170  sepgsql_schema_drop(objectId);
171  break;
172 
173  case RelationRelationId:
174  if (subId == 0)
175  sepgsql_relation_drop(objectId);
176  else
177  sepgsql_attribute_drop(objectId, subId);
178  break;
179 
180  case ProcedureRelationId:
181  sepgsql_proc_drop(objectId);
182  break;
183 
184  default:
185  /* Ignore unsupported object classes */
186  break;
187  }
188  }
189  break;
190 
191  case OAT_TRUNCATE:
192  {
193  switch (classId)
194  {
195  case RelationRelationId:
196  sepgsql_relation_truncate(objectId);
197  break;
198  default:
199  /* Ignore unsupported object classes */
200  break;
201  }
202  }
203  break;
204 
205  case OAT_POST_ALTER:
206  {
207  ObjectAccessPostAlter *pa_arg = arg;
208  bool is_internal = pa_arg->is_internal;
209 
210  switch (classId)
211  {
212  case DatabaseRelationId:
213  Assert(!is_internal);
214  sepgsql_database_setattr(objectId);
215  break;
216 
217  case NamespaceRelationId:
218  Assert(!is_internal);
219  sepgsql_schema_setattr(objectId);
220  break;
221 
222  case RelationRelationId:
223  if (subId == 0)
224  {
225  /*
226  * A case when we don't want to apply permission
227  * check is that relation is internally altered
228  * without user's intention. E.g, no need to check
229  * on toast table/index to be renamed at end of
230  * the table rewrites.
231  */
232  if (is_internal)
233  break;
234 
235  sepgsql_relation_setattr(objectId);
236  }
237  else
238  sepgsql_attribute_setattr(objectId, subId);
239  break;
240 
241  case ProcedureRelationId:
242  Assert(!is_internal);
243  sepgsql_proc_setattr(objectId);
244  break;
245 
246  default:
247  /* Ignore unsupported object classes */
248  break;
249  }
250  }
251  break;
252 
254  {
256 
257  /*
258  * If stacked extension already decided not to allow users to
259  * search this schema, we just stick with that decision.
260  */
261  if (!ns_arg->result)
262  break;
263 
264  Assert(classId == NamespaceRelationId);
265  Assert(ns_arg->result);
266  ns_arg->result
267  = sepgsql_schema_search(objectId,
268  ns_arg->ereport_on_violation);
269  }
270  break;
271 
273  {
274  Assert(classId == ProcedureRelationId);
275  sepgsql_proc_execute(objectId);
276  }
277  break;
278 
279  default:
280  elog(ERROR, "unexpected object access type: %d", (int) access);
281  break;
282  }
283 }
void sepgsql_attribute_drop(Oid relOid, AttrNumber attnum)
Definition: relation.c:134
void sepgsql_schema_setattr(Oid namespaceId)
Definition: schema.c:203
void sepgsql_schema_drop(Oid namespaceId)
Definition: schema.c:115
void sepgsql_relation_truncate(Oid relOid)
Definition: relation.c:525
void sepgsql_database_drop(Oid databaseId)
Definition: database.c:134
const char * createdb_dtemplate
Definition: hooks.c:53
void sepgsql_proc_setattr(Oid functionId)
Definition: proc.c:236
void sepgsql_proc_execute(Oid functionId)
Definition: proc.c:316
void sepgsql_schema_post_create(Oid namespaceId)
Definition: schema.c:37
void sepgsql_proc_drop(Oid functionId)
Definition: proc.c:156
void sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum)
Definition: relation.c:210
#define ERROR
Definition: elog.h:43
void sepgsql_relation_post_create(Oid relOid)
Definition: relation.c:241
static sepgsql_context_info_t sepgsql_context_info
Definition: hooks.c:56
void sepgsql_database_post_create(Oid databaseId, const char *dtemplate)
Definition: database.c:34
void sepgsql_proc_post_create(Oid functionId)
Definition: proc.c:38
static object_access_hook_type next_object_access_hook
Definition: hooks.c:38
bool sepgsql_schema_search(Oid namespaceId, bool abort_on_violation)
Definition: schema.c:210
#define Assert(condition)
Definition: c.h:739
void sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
Definition: relation.c:44
#define elog(elevel,...)
Definition: elog.h:228
void * arg
void sepgsql_database_setattr(Oid databaseId)
Definition: database.c:161
void sepgsql_relation_setattr(Oid relOid)
Definition: relation.c:616
void sepgsql_relation_drop(Oid relOid)
Definition: relation.c:417
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:134

◆ sepgsql_utility_command()

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

Definition at line 314 of file hooks.c.

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, T_CreatedbStmt, T_LoadStmt, and PlannedStmt::utilityStmt.

Referenced by _PG_init().

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  */
333  sepgsql_context_info.cmdtype = nodeTag(parsetree);
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  {
364  ereport(ERROR,
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,
382  context, params, queryEnv,
383  dest, completionTag);
384  else
385  standard_ProcessUtility(pstmt, queryString,
386  context, params, queryEnv,
387  dest, completionTag);
388  }
389  PG_FINALLY();
390  {
391  sepgsql_context_info = saved_context_info;
392  }
393  PG_END_TRY();
394 }
const char * createdb_dtemplate
Definition: hooks.c:53
Definition: nodes.h:525
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:608
bool sepgsql_getenforce(void)
Definition: selinux.c:651
void standard_ProcessUtility(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, char *completionTag)
Definition: utility.c:376
#define ERROR
Definition: elog.h:43
Node * utilityStmt
Definition: plannodes.h:92
#define ereport(elevel, rest)
Definition: elog.h:141
static sepgsql_context_info_t sepgsql_context_info
Definition: hooks.c:56
Node * arg
Definition: parsenodes.h:731
#define PG_FINALLY()
Definition: elog.h:339
#define lfirst(lc)
Definition: pg_list.h:190
#define nodeTag(nodeptr)
Definition: nodes.h:530
static ProcessUtility_hook_type next_ProcessUtility_hook
Definition: hooks.c:40
int errmsg(const char *fmt,...)
Definition: elog.c:822
char * defname
Definition: parsenodes.h:730
#define PG_TRY()
Definition: elog.h:322
#define PG_END_TRY()
Definition: elog.h:347

Variable Documentation

◆ next_exec_check_perms_hook

ExecutorCheckPerms_hook_type next_exec_check_perms_hook = NULL
static

Definition at line 39 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 38 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 40 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 56 of file hooks.c.

Referenced by sepgsql_utility_command().

◆ sepgsql_debug_audit

bool sepgsql_debug_audit
static

Definition at line 72 of file hooks.c.

Referenced by _PG_init(), and sepgsql_get_debug_audit().

◆ sepgsql_permissive

bool sepgsql_permissive
static

Definition at line 61 of file hooks.c.

Referenced by _PG_init(), and sepgsql_get_permissive().