#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 "sepgsql.h"
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 (Node *parsetree, const char *queryString, ProcessUtilityContext context, ParamListInfo params, 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 |
void _PG_init | ( | void | ) |
Definition at line 386 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, NULL, object_access_hook, PGC_SIGHUP, PGC_USERSET, ProcessUtility_hook, register_label_provider(), sepgsql_avc_init(), sepgsql_debug_audit, sepgsql_init_client_label(), SEPGSQL_LABEL_TAG, SEPGSQL_MODE_DISABLED, sepgsql_object_relabel(), sepgsql_permissive, and sepgsql_set_mode().
{ /* * We allow to load the SE-PostgreSQL module on single-user-mode or * shared_preload_libraries settings only. */ if (IsUnderPostmaster) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("sepgsql must be loaded via shared_preload_libraries"))); /* * Check availability of SELinux on the platform. If disabled, we cannot * activate any SE-PostgreSQL features, and we have to skip rest of * initialization. */ if (is_selinux_enabled() < 1) { sepgsql_set_mode(SEPGSQL_MODE_DISABLED); return; } /* * sepgsql.permissive = (on|off) * * This variable controls performing mode of SE-PostgreSQL on user's * session. */ DefineCustomBoolVariable("sepgsql.permissive", "Turn on/off permissive mode in SE-PostgreSQL", NULL, &sepgsql_permissive, false, PGC_SIGHUP, GUC_NOT_IN_SAMPLE, NULL, NULL, NULL); /* * sepgsql.debug_audit = (on|off) * * This variable allows users to turn on/off audit logs on access control * decisions, independent from auditallow/auditdeny setting in the * security policy. We intend to use this option for debugging purpose. */ DefineCustomBoolVariable("sepgsql.debug_audit", "Turn on/off debug audit messages", NULL, &sepgsql_debug_audit, false, PGC_USERSET, GUC_NOT_IN_SAMPLE, NULL, NULL, NULL); /* Initialize userspace access vector cache */ sepgsql_avc_init(); /* Initialize security label of the client and related stuff */ sepgsql_init_client_label(); /* Security label provider hook */ register_label_provider(SEPGSQL_LABEL_TAG, sepgsql_object_relabel); /* Object access hook */ next_object_access_hook = object_access_hook; object_access_hook = sepgsql_object_access; /* DML permission check */ next_exec_check_perms_hook = ExecutorCheckPerms_hook; ExecutorCheckPerms_hook = sepgsql_exec_check_perms; /* ProcessUtility hook */ next_ProcessUtility_hook = ProcessUtility_hook; ProcessUtility_hook = sepgsql_utility_command; /* init contextual info */ memset(&sepgsql_context_info, 0, sizeof(sepgsql_context_info)); }
Definition at line 277 of file hooks.c.
References next_exec_check_perms_hook, and sepgsql_dml_privileges().
{ /* * If security provider is stacking and one of them replied 'false' at * least, we don't need to check any more. */ if (next_exec_check_perms_hook && !(*next_exec_check_perms_hook) (rangeTabls, abort)) return false; if (!sepgsql_dml_privileges(rangeTabls, abort)) return false; return true; }
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().
{ return sepgsql_debug_audit; }
bool sepgsql_get_permissive | ( | void | ) |
Definition at line 64 of file hooks.c.
References sepgsql_permissive.
Referenced by sepgsql_client_auth().
{ return sepgsql_permissive; }
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 Assert, sepgsql_context_info_t::createdb_dtemplate, DatabaseRelationId, ObjectAccessDrop::dropflags, elog, ObjectAccessNamespaceSearch::ereport_on_violation, ERROR, ObjectAccessPostAlter::is_internal, ObjectAccessPostCreate::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().
{ if (next_object_access_hook) (*next_object_access_hook) (access, classId, objectId, subId, arg); switch (access) { case OAT_POST_CREATE: { ObjectAccessPostCreate *pc_arg = arg; bool is_internal; is_internal = pc_arg ? pc_arg->is_internal : false; switch (classId) { case DatabaseRelationId: Assert(!is_internal); sepgsql_database_post_create(objectId, sepgsql_context_info.createdb_dtemplate); break; case NamespaceRelationId: Assert(!is_internal); sepgsql_schema_post_create(objectId); break; case RelationRelationId: if (subId == 0) { /* * The cases in which we want to apply permission * checks on creation of a new relation correspond * to direct user invocation. For internal uses, * that is creation of toast tables, index rebuild * or ALTER TABLE commands, we need neither * assignment of security labels nor permission * checks. */ if (is_internal) break; sepgsql_relation_post_create(objectId); } else sepgsql_attribute_post_create(objectId, subId); break; case ProcedureRelationId: Assert(!is_internal); sepgsql_proc_post_create(objectId); break; default: /* Ignore unsupported object classes */ break; } } break; case OAT_DROP: { ObjectAccessDrop *drop_arg = (ObjectAccessDrop *) arg; /* * No need to apply permission checks on object deletion due * to internal cleanups; such as removal of temporary database * object on session closed. */ if ((drop_arg->dropflags & PERFORM_DELETION_INTERNAL) != 0) break; switch (classId) { case DatabaseRelationId: sepgsql_database_drop(objectId); break; case NamespaceRelationId: sepgsql_schema_drop(objectId); break; case RelationRelationId: if (subId == 0) sepgsql_relation_drop(objectId); else sepgsql_attribute_drop(objectId, subId); break; case ProcedureRelationId: sepgsql_proc_drop(objectId); break; default: /* Ignore unsupported object classes */ break; } } break; case OAT_POST_ALTER: { ObjectAccessPostAlter *pa_arg = arg; bool is_internal = pa_arg->is_internal; switch (classId) { case DatabaseRelationId: Assert(!is_internal); sepgsql_database_setattr(objectId); break; case NamespaceRelationId: Assert(!is_internal); sepgsql_schema_setattr(objectId); break; case RelationRelationId: if (subId == 0) { /* * A case when we don't want to apply permission * check is that relation is internally altered * without user's intention. E.g, no need to * check on toast table/index to be renamed at * end of the table rewrites. */ if (is_internal) break; sepgsql_relation_setattr(objectId); } else sepgsql_attribute_setattr(objectId, subId); break; case ProcedureRelationId: Assert(!is_internal); sepgsql_proc_setattr(objectId); break; default: /* Ignore unsupported object classes */ break; } } break; case OAT_NAMESPACE_SEARCH: { ObjectAccessNamespaceSearch *ns_arg = arg; /* * If stacked extension already decided not to allow users * to search this schema, we just stick with that decision. */ if (!ns_arg->result) break; Assert(classId == NamespaceRelationId); Assert(ns_arg->result); ns_arg->result = sepgsql_schema_search(objectId, ns_arg->ereport_on_violation); } break; case OAT_FUNCTION_EXECUTE: { Assert(classId == ProcedureRelationId); sepgsql_proc_execute(objectId); } break; default: elog(ERROR, "unexpected object access type: %d", (int) access); break; } }
static void sepgsql_utility_command | ( | Node * | parsetree, | |
const char * | queryString, | |||
ProcessUtilityContext | context, | |||
ParamListInfo | params, | |||
DestReceiver * | dest, | |||
char * | completionTag | |||
) | [static] |
Definition at line 300 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_getenforce(), standard_ProcessUtility(), strVal, T_CreatedbStmt, and T_LoadStmt.
{ sepgsql_context_info_t saved_context_info = sepgsql_context_info; ListCell *cell; PG_TRY(); { /* * Check command tag to avoid nefarious operations, and save the * current contextual information to determine whether we should apply * permission checks here, or not. */ sepgsql_context_info.cmdtype = nodeTag(parsetree); switch (nodeTag(parsetree)) { case T_CreatedbStmt: /* * We hope to reference name of the source database, but it * does not appear in system catalog. So, we save it here. */ foreach(cell, ((CreatedbStmt *) parsetree)->options) { DefElem *defel = (DefElem *) lfirst(cell); if (strcmp(defel->defname, "template") == 0) { sepgsql_context_info.createdb_dtemplate = strVal(defel->arg); break; } } break; case T_LoadStmt: /* * We reject LOAD command across the board on enforcing mode, * because a binary module can arbitrarily override hooks. */ if (sepgsql_getenforce()) { ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("SELinux: LOAD is not permitted"))); } break; default: /* * Right now we don't check any other utility commands, * because it needs more detailed information to make access * control decision here, but we don't want to have two parse * and analyze routines individually. */ break; } if (next_ProcessUtility_hook) (*next_ProcessUtility_hook) (parsetree, queryString, context, params, dest, completionTag); else standard_ProcessUtility(parsetree, queryString, context, params, dest, completionTag); } PG_CATCH(); { sepgsql_context_info = saved_context_info; PG_RE_THROW(); } PG_END_TRY(); sepgsql_context_info = saved_context_info; }
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().
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().
ProcessUtility_hook_type next_ProcessUtility_hook = NULL [static] |
Definition at line 40 of file hooks.c.
Referenced by _PG_init(), and sepgsql_utility_command().
bool sepgsql_debug_audit [static] |
Definition at line 72 of file hooks.c.
Referenced by _PG_init(), and sepgsql_get_debug_audit().
bool sepgsql_permissive [static] |
Definition at line 61 of file hooks.c.
Referenced by _PG_init(), and sepgsql_get_permissive().