PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 "tcop/utility.h"
#include "utils/guc.h"
#include "utils/queryenvironment.h"
#include "sepgsql.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

void _PG_init ( void  )

Definition at line 389 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().

390 {
391  /*
392  * We allow to load the SE-PostgreSQL module on single-user-mode or
393  * shared_preload_libraries settings only.
394  */
395  if (IsUnderPostmaster)
396  ereport(ERROR,
397  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
398  errmsg("sepgsql must be loaded via shared_preload_libraries")));
399 
400  /*
401  * Check availability of SELinux on the platform. If disabled, we cannot
402  * activate any SE-PostgreSQL features, and we have to skip rest of
403  * initialization.
404  */
405  if (is_selinux_enabled() < 1)
406  {
408  return;
409  }
410 
411  /*
412  * sepgsql.permissive = (on|off)
413  *
414  * This variable controls performing mode of SE-PostgreSQL on user's
415  * session.
416  */
417  DefineCustomBoolVariable("sepgsql.permissive",
418  "Turn on/off permissive mode in SE-PostgreSQL",
419  NULL,
421  false,
422  PGC_SIGHUP,
424  NULL,
425  NULL,
426  NULL);
427 
428  /*
429  * sepgsql.debug_audit = (on|off)
430  *
431  * This variable allows users to turn on/off audit logs on access control
432  * decisions, independent from auditallow/auditdeny setting in the
433  * security policy. We intend to use this option for debugging purpose.
434  */
435  DefineCustomBoolVariable("sepgsql.debug_audit",
436  "Turn on/off debug audit messages",
437  NULL,
439  false,
440  PGC_USERSET,
442  NULL,
443  NULL,
444  NULL);
445 
446  /* Initialize userspace access vector cache */
448 
449  /* Initialize security label of the client and related stuff */
451 
452  /* Security label provider hook */
455 
456  /* Object access hook */
459 
460  /* DML permission check */
463 
464  /* ProcessUtility hook */
467 
468  /* init contextual info */
469  memset(&sepgsql_context_info, 0, sizeof(sepgsql_context_info));
470 }
static ExecutorCheckPerms_hook_type next_exec_check_perms_hook
Definition: hooks.c:40
void sepgsql_init_client_label(void)
Definition: label.c:422
ProcessUtility_hook_type ProcessUtility_hook
Definition: utility.c:73
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SEPGSQL_MODE_DISABLED
Definition: sepgsql.h:31
static bool sepgsql_debug_audit
Definition: hooks.c:73
static void sepgsql_utility_command(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, char *completionTag)
Definition: hooks.c:301
static bool sepgsql_exec_check_perms(List *rangeTabls, bool abort)
Definition: hooks.c:278
void sepgsql_avc_init(void)
Definition: uavc.c:496
#define ERROR
Definition: elog.h:43
int sepgsql_set_mode(int new_mode)
Definition: selinux.c:631
static bool sepgsql_permissive
Definition: hooks.c:62
bool IsUnderPostmaster
Definition: globals.c:101
#define SEPGSQL_LABEL_TAG
Definition: sepgsql.h:23
#define GUC_NOT_IN_SAMPLE
Definition: guc.h:209
#define ereport(elevel, rest)
Definition: elog.h:122
static sepgsql_context_info_t sepgsql_context_info
Definition: hooks.c:57
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:39
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:21
static void sepgsql_object_access(ObjectAccessType access, Oid classId, Oid objectId, int subId, void *arg)
Definition: hooks.c:88
static ProcessUtility_hook_type next_ProcessUtility_hook
Definition: hooks.c:41
void sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
Definition: label.c:503
int errmsg(const char *fmt,...)
Definition: elog.c:797
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:7738
static bool sepgsql_exec_check_perms ( List rangeTabls,
bool  abort 
)
static

Definition at line 278 of file hooks.c.

References next_exec_check_perms_hook, and sepgsql_dml_privileges().

Referenced by _PG_init().

279 {
280  /*
281  * If security provider is stacking and one of them replied 'false' at
282  * least, we don't need to check any more.
283  */
285  !(*next_exec_check_perms_hook) (rangeTabls, abort))
286  return false;
287 
288  if (!sepgsql_dml_privileges(rangeTabls, abort))
289  return false;
290 
291  return true;
292 }
static ExecutorCheckPerms_hook_type next_exec_check_perms_hook
Definition: hooks.c:40
bool sepgsql_dml_privileges(List *rangeTabls, bool abort_on_violation)
Definition: dml.c:287
bool sepgsql_get_debug_audit ( void  )

Definition at line 76 of file hooks.c.

References sepgsql_debug_audit.

Referenced by sepgsql_avc_check_perms_label(), and sepgsql_check_perms().

77 {
78  return sepgsql_debug_audit;
79 }
static bool sepgsql_debug_audit
Definition: hooks.c:73
bool sepgsql_get_permissive ( void  )

Definition at line 65 of file hooks.c.

References sepgsql_permissive.

Referenced by sepgsql_client_auth().

66 {
67  return sepgsql_permissive;
68 }
static bool sepgsql_permissive
Definition: hooks.c:62
static void sepgsql_object_access ( ObjectAccessType  access,
Oid  classId,
Oid  objectId,
int  subId,
void *  arg 
)
static

Definition at line 88 of file hooks.c.

References arg, Assert, sepgsql_context_info_t::createdb_dtemplate, DatabaseRelationId, ObjectAccessDrop::dropflags, elog, ObjectAccessNamespaceSearch::ereport_on_violation, ERROR, ObjectAccessPostCreate::is_internal, ObjectAccessPostAlter::is_internal, NamespaceRelationId, next_object_access_hook, OAT_DROP, OAT_FUNCTION_EXECUTE, OAT_NAMESPACE_SEARCH, OAT_POST_ALTER, OAT_POST_CREATE, PERFORM_DELETION_INTERNAL, ProcedureRelationId, RelationRelationId, 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_schema_drop(), sepgsql_schema_post_create(), sepgsql_schema_search(), and sepgsql_schema_setattr().

Referenced by _PG_init().

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

Definition at line 301 of file hooks.c.

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

Referenced by _PG_init().

308 {
309  Node *parsetree = pstmt->utilityStmt;
310  sepgsql_context_info_t saved_context_info = sepgsql_context_info;
311  ListCell *cell;
312 
313  PG_TRY();
314  {
315  /*
316  * Check command tag to avoid nefarious operations, and save the
317  * current contextual information to determine whether we should apply
318  * permission checks here, or not.
319  */
320  sepgsql_context_info.cmdtype = nodeTag(parsetree);
321 
322  switch (nodeTag(parsetree))
323  {
324  case T_CreatedbStmt:
325 
326  /*
327  * We hope to reference name of the source database, but it
328  * does not appear in system catalog. So, we save it here.
329  */
330  foreach(cell, ((CreatedbStmt *) parsetree)->options)
331  {
332  DefElem *defel = (DefElem *) lfirst(cell);
333 
334  if (strcmp(defel->defname, "template") == 0)
335  {
337  = strVal(defel->arg);
338  break;
339  }
340  }
341  break;
342 
343  case T_LoadStmt:
344 
345  /*
346  * We reject LOAD command across the board on enforcing mode,
347  * because a binary module can arbitrarily override hooks.
348  */
349  if (sepgsql_getenforce())
350  {
351  ereport(ERROR,
352  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
353  errmsg("SELinux: LOAD is not permitted")));
354  }
355  break;
356  default:
357 
358  /*
359  * Right now we don't check any other utility commands,
360  * because it needs more detailed information to make access
361  * control decision here, but we don't want to have two parse
362  * and analyze routines individually.
363  */
364  break;
365  }
366 
368  (*next_ProcessUtility_hook) (pstmt, queryString,
369  context, params, queryEnv,
370  dest, completionTag);
371  else
372  standard_ProcessUtility(pstmt, queryString,
373  context, params, queryEnv,
374  dest, completionTag);
375  }
376  PG_CATCH();
377  {
378  sepgsql_context_info = saved_context_info;
379  PG_RE_THROW();
380  }
381  PG_END_TRY();
382  sepgsql_context_info = saved_context_info;
383 }
const char * createdb_dtemplate
Definition: hooks.c:54
Definition: nodes.h:509
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
bool sepgsql_getenforce(void)
Definition: selinux.c:648
void standard_ProcessUtility(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, char *completionTag)
Definition: utility.c:374
#define ERROR
Definition: elog.h:43
Node * utilityStmt
Definition: plannodes.h:94
#define ereport(elevel, rest)
Definition: elog.h:122
static sepgsql_context_info_t sepgsql_context_info
Definition: hooks.c:57
Node * arg
Definition: parsenodes.h:720
#define PG_CATCH()
Definition: elog.h:293
#define lfirst(lc)
Definition: pg_list.h:106
#define PG_RE_THROW()
Definition: elog.h:314
#define nodeTag(nodeptr)
Definition: nodes.h:514
static ProcessUtility_hook_type next_ProcessUtility_hook
Definition: hooks.c:41
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:719
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300

Variable Documentation

ExecutorCheckPerms_hook_type next_exec_check_perms_hook = NULL
static

Definition at line 40 of file hooks.c.

Referenced by _PG_init(), and sepgsql_exec_check_perms().

object_access_hook_type next_object_access_hook = NULL
static

Definition at line 39 of file hooks.c.

Referenced by _PG_init(), and sepgsql_object_access().

ProcessUtility_hook_type next_ProcessUtility_hook = NULL
static

Definition at line 41 of file hooks.c.

Referenced by _PG_init(), and sepgsql_utility_command().

PG_MODULE_MAGIC

Definition at line 29 of file hooks.c.

sepgsql_context_info_t sepgsql_context_info
static

Definition at line 57 of file hooks.c.

Referenced by sepgsql_utility_command().

bool sepgsql_debug_audit
static

Definition at line 73 of file hooks.c.

Referenced by _PG_init(), and sepgsql_get_debug_audit().

bool sepgsql_permissive
static

Definition at line 62 of file hooks.c.

Referenced by _PG_init(), and sepgsql_get_permissive().