#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().
1.7.1