PostgreSQL Source Code  git master
label.c File Reference
#include "postgres.h"
#include <selinux/label.h>
#include "access/htup_details.h"
#include "access/genam.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_attribute.h"
#include "catalog/pg_class.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "commands/dbcommands.h"
#include "commands/seclabel.h"
#include "libpq/auth.h"
#include "libpq/libpq-be.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "sepgsql.h"
Include dependency graph for label.c:

Go to the source code of this file.

Data Structures

struct  pending_label
 

Functions

char * sepgsql_get_client_label (void)
 
static void sepgsql_set_client_label (const char *new_label)
 
static void sepgsql_xact_callback (XactEvent event, void *arg)
 
static void sepgsql_subxact_callback (SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
 
static void sepgsql_client_auth (Port *port, int status)
 
static bool sepgsql_needs_fmgr_hook (Oid functionId)
 
static void sepgsql_fmgr_hook (FmgrHookEventType event, FmgrInfo *flinfo, Datum *private)
 
void sepgsql_init_client_label (void)
 
char * sepgsql_get_label (Oid classId, Oid objectId, int32 subId)
 
void sepgsql_object_relabel (const ObjectAddress *object, const char *seclabel)
 
 PG_FUNCTION_INFO_V1 (sepgsql_getcon)
 
Datum sepgsql_getcon (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (sepgsql_setcon)
 
Datum sepgsql_setcon (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (sepgsql_mcstrans_in)
 
Datum sepgsql_mcstrans_in (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (sepgsql_mcstrans_out)
 
Datum sepgsql_mcstrans_out (PG_FUNCTION_ARGS)
 
static char * quote_object_name (const char *src1, const char *src2, const char *src3, const char *src4)
 
static void exec_object_restorecon (struct selabel_handle *sehnd, Oid catalogId)
 
 PG_FUNCTION_INFO_V1 (sepgsql_restorecon)
 
Datum sepgsql_restorecon (PG_FUNCTION_ARGS)
 

Variables

static ClientAuthentication_hook_type next_client_auth_hook = NULL
 
static needs_fmgr_hook_type next_needs_fmgr_hook = NULL
 
static fmgr_hook_type next_fmgr_hook = NULL
 
static char * client_label_peer = NULL
 
static Listclient_label_pending = NIL
 
static char * client_label_committed = NULL
 
static char * client_label_func = NULL
 

Function Documentation

◆ exec_object_restorecon()

static void exec_object_restorecon ( struct selabel_handle *  sehnd,
Oid  catalogId 
)
static

Definition at line 708 of file label.c.

References AccessShareLock, elog, ereport, errcode(), errmsg(), ERROR, get_database_name(), get_namespace_name(), get_rel_name(), get_rel_namespace(), get_rel_relkind(), GETSTRUCT, HeapTupleIsValid, InvalidOid, MyDatabaseId, NameStr, NoLock, pfree(), PG_CATCH, PG_END_TRY, PG_FUNCTION_INFO_V1(), PG_RE_THROW, PG_TRY, quote_object_name(), SEPGSQL_LABEL_TAG, sepgsql_object_relabel(), sepgsql_restorecon(), SetSecurityLabel(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and WARNING.

Referenced by sepgsql_restorecon().

709 {
710  Relation rel;
711  SysScanDesc sscan;
712  HeapTuple tuple;
713  char *database_name = get_database_name(MyDatabaseId);
714  char *namespace_name;
715  Oid namespace_id;
716  char *relation_name;
717 
718  /*
719  * Open the target catalog. We don't want to allow writable accesses by
720  * other session during initial labeling.
721  */
722  rel = table_open(catalogId, AccessShareLock);
723 
724  sscan = systable_beginscan(rel, InvalidOid, false,
725  NULL, 0, NULL);
726  while (HeapTupleIsValid(tuple = systable_getnext(sscan)))
727  {
728  Form_pg_database datForm;
729  Form_pg_namespace nspForm;
730  Form_pg_class relForm;
731  Form_pg_attribute attForm;
732  Form_pg_proc proForm;
733  char *objname;
734  int objtype = 1234;
735  ObjectAddress object;
736  security_context_t context;
737 
738  /*
739  * The way to determine object name depends on object classes. So, any
740  * branches set up `objtype', `objname' and `object' here.
741  */
742  switch (catalogId)
743  {
744  case DatabaseRelationId:
745  datForm = (Form_pg_database) GETSTRUCT(tuple);
746 
747  objtype = SELABEL_DB_DATABASE;
748 
749  objname = quote_object_name(NameStr(datForm->datname),
750  NULL, NULL, NULL);
751 
752  object.classId = DatabaseRelationId;
753  object.objectId = datForm->oid;
754  object.objectSubId = 0;
755  break;
756 
757  case NamespaceRelationId:
758  nspForm = (Form_pg_namespace) GETSTRUCT(tuple);
759 
760  objtype = SELABEL_DB_SCHEMA;
761 
762  objname = quote_object_name(database_name,
763  NameStr(nspForm->nspname),
764  NULL, NULL);
765 
766  object.classId = NamespaceRelationId;
767  object.objectId = nspForm->oid;
768  object.objectSubId = 0;
769  break;
770 
771  case RelationRelationId:
772  relForm = (Form_pg_class) GETSTRUCT(tuple);
773 
774  if (relForm->relkind == RELKIND_RELATION ||
775  relForm->relkind == RELKIND_PARTITIONED_TABLE)
776  objtype = SELABEL_DB_TABLE;
777  else if (relForm->relkind == RELKIND_SEQUENCE)
778  objtype = SELABEL_DB_SEQUENCE;
779  else if (relForm->relkind == RELKIND_VIEW)
780  objtype = SELABEL_DB_VIEW;
781  else
782  continue; /* no need to assign security label */
783 
784  namespace_name = get_namespace_name(relForm->relnamespace);
785  objname = quote_object_name(database_name,
786  namespace_name,
787  NameStr(relForm->relname),
788  NULL);
789  pfree(namespace_name);
790 
791  object.classId = RelationRelationId;
792  object.objectId = relForm->oid;
793  object.objectSubId = 0;
794  break;
795 
796  case AttributeRelationId:
797  attForm = (Form_pg_attribute) GETSTRUCT(tuple);
798 
799  if (get_rel_relkind(attForm->attrelid) != RELKIND_RELATION &&
800  get_rel_relkind(attForm->attrelid) != RELKIND_PARTITIONED_TABLE)
801  continue; /* no need to assign security label */
802 
803  objtype = SELABEL_DB_COLUMN;
804 
805  namespace_id = get_rel_namespace(attForm->attrelid);
806  namespace_name = get_namespace_name(namespace_id);
807  relation_name = get_rel_name(attForm->attrelid);
808  objname = quote_object_name(database_name,
809  namespace_name,
810  relation_name,
811  NameStr(attForm->attname));
812  pfree(namespace_name);
813  pfree(relation_name);
814 
815  object.classId = RelationRelationId;
816  object.objectId = attForm->attrelid;
817  object.objectSubId = attForm->attnum;
818  break;
819 
820  case ProcedureRelationId:
821  proForm = (Form_pg_proc) GETSTRUCT(tuple);
822 
823  objtype = SELABEL_DB_PROCEDURE;
824 
825  namespace_name = get_namespace_name(proForm->pronamespace);
826  objname = quote_object_name(database_name,
827  namespace_name,
828  NameStr(proForm->proname),
829  NULL);
830  pfree(namespace_name);
831 
832  object.classId = ProcedureRelationId;
833  object.objectId = proForm->oid;
834  object.objectSubId = 0;
835  break;
836 
837  default:
838  elog(ERROR, "unexpected catalog id: %u", catalogId);
839  objname = NULL; /* for compiler quiet */
840  break;
841  }
842 
843  if (selabel_lookup_raw(sehnd, &context, objname, objtype) == 0)
844  {
845  PG_TRY();
846  {
847  /*
848  * Check SELinux permission to relabel the fetched object,
849  * then do the actual relabeling.
850  */
851  sepgsql_object_relabel(&object, context);
852 
853  SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, context);
854  }
855  PG_CATCH();
856  {
857  freecon(context);
858  PG_RE_THROW();
859  }
860  PG_END_TRY();
861  freecon(context);
862  }
863  else if (errno == ENOENT)
865  (errmsg("SELinux: no initial label assigned for %s (type=%d), skipping",
866  objname, objtype)));
867  else
868  ereport(ERROR,
869  (errcode(ERRCODE_INTERNAL_ERROR),
870  errmsg("SELinux: could not determine initial security label for %s (type=%d): %m", objname, objtype)));
871 
872  pfree(objname);
873  }
874  systable_endscan(sscan);
875 
876  table_close(rel, NoLock);
877 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:51
void SetSecurityLabel(const ObjectAddress *object, const char *provider, const char *label)
Definition: seclabel.c:327
FormData_pg_database * Form_pg_database
Definition: pg_database.h:81
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1805
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1754
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:570
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
static char * quote_object_name(const char *src1, const char *src2, const char *src3, const char *src4)
Definition: label.c:661
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2100
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
#define NoLock
Definition: lockdefs.h:34
#define SEPGSQL_LABEL_TAG
Definition: sepgsql.h:23
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
#define ereport(elevel, rest)
Definition: elog.h:141
#define WARNING
Definition: elog.h:40
Oid MyDatabaseId
Definition: globals.c:85
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:134
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_CATCH()
Definition: elog.h:310
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define PG_RE_THROW()
Definition: elog.h:331
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
void sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
Definition: label.c:487
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
#define PG_TRY()
Definition: elog.h:301
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1730
#define PG_END_TRY()
Definition: elog.h:317

◆ PG_FUNCTION_INFO_V1() [1/5]

◆ PG_FUNCTION_INFO_V1() [2/5]

PG_FUNCTION_INFO_V1 ( sepgsql_setcon  )

◆ PG_FUNCTION_INFO_V1() [3/5]

PG_FUNCTION_INFO_V1 ( sepgsql_mcstrans_in  )

◆ PG_FUNCTION_INFO_V1() [4/5]

PG_FUNCTION_INFO_V1 ( sepgsql_mcstrans_out  )

◆ PG_FUNCTION_INFO_V1() [5/5]

PG_FUNCTION_INFO_V1 ( sepgsql_restorecon  )

◆ quote_object_name()

static char* quote_object_name ( const char *  src1,
const char *  src2,
const char *  src3,
const char *  src4 
)
static

Definition at line 661 of file label.c.

References appendStringInfo(), appendStringInfoString(), StringInfoData::data, initStringInfo(), pfree(), and quote_identifier().

Referenced by exec_object_restorecon().

663 {
664  StringInfoData result;
665  const char *temp;
666 
667  initStringInfo(&result);
668 
669  if (src1)
670  {
671  temp = quote_identifier(src1);
672  appendStringInfoString(&result, temp);
673  if (src1 != temp)
674  pfree((void *) temp);
675  }
676  if (src2)
677  {
678  temp = quote_identifier(src2);
679  appendStringInfo(&result, ".%s", temp);
680  if (src2 != temp)
681  pfree((void *) temp);
682  }
683  if (src3)
684  {
685  temp = quote_identifier(src3);
686  appendStringInfo(&result, ".%s", temp);
687  if (src3 != temp)
688  pfree((void *) temp);
689  }
690  if (src4)
691  {
692  temp = quote_identifier(src4);
693  appendStringInfo(&result, ".%s", temp);
694  if (src4 != temp)
695  pfree((void *) temp);
696  }
697  return result.data;
698 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
void pfree(void *pointer)
Definition: mcxt.c:1056
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46

◆ sepgsql_client_auth()

static void sepgsql_client_auth ( Port port,
int  status 
)
static

Definition at line 232 of file label.c.

References client_label_peer, ereport, errcode(), errmsg(), FATAL, next_client_auth_hook, port, sepgsql_get_permissive(), SEPGSQL_MODE_DEFAULT, SEPGSQL_MODE_PERMISSIVE, sepgsql_set_mode(), status(), and STATUS_OK.

Referenced by sepgsql_init_client_label().

233 {
235  (*next_client_auth_hook) (port, status);
236 
237  /*
238  * In the case when authentication failed, the supplied socket shall be
239  * closed soon, so we don't need to do anything here.
240  */
241  if (status != STATUS_OK)
242  return;
243 
244  /*
245  * Getting security label of the peer process using API of libselinux.
246  */
247  if (getpeercon_raw(port->sock, &client_label_peer) < 0)
248  ereport(FATAL,
249  (errcode(ERRCODE_INTERNAL_ERROR),
250  errmsg("SELinux: unable to get peer label: %m")));
251 
252  /*
253  * Switch the current performing mode from INTERNAL to either DEFAULT or
254  * PERMISSIVE.
255  */
258  else
260 }
int errcode(int sqlerrcode)
Definition: elog.c:570
static ClientAuthentication_hook_type next_client_auth_hook
Definition: label.c:44
#define FATAL
Definition: elog.h:52
int sepgsql_set_mode(int new_mode)
Definition: selinux.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
#define STATUS_OK
Definition: c.h:1089
static int port
Definition: pg_regress.c:92
#define SEPGSQL_MODE_DEFAULT
Definition: sepgsql.h:28
#define SEPGSQL_MODE_PERMISSIVE
Definition: sepgsql.h:29
static char * client_label_peer
Definition: label.c:61
bool sepgsql_get_permissive(void)
Definition: hooks.c:65
int errmsg(const char *fmt,...)
Definition: elog.c:784
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227

◆ sepgsql_fmgr_hook()

static void sepgsql_fmgr_hook ( FmgrHookEventType  event,
FmgrInfo flinfo,
Datum private 
)
static

Definition at line 313 of file label.c.

References Assert, ObjectAddress::classId, client_label_func, DatumGetPointer, elog, ERROR, FHET_ABORT, FHET_END, FHET_START, FmgrInfo::fn_mcxt, FmgrInfo::fn_oid, getObjectDescription(), MemoryContextSwitchTo(), next_fmgr_hook, palloc(), PointerGetDatum, SEPG_CLASS_DB_PROCEDURE, SEPG_CLASS_PROCESS, SEPG_DB_PROCEDURE__ENTRYPOINT, SEPG_PROCESS__TRANSITION, sepgsql_avc_check_perms(), sepgsql_avc_check_perms_label(), and sepgsql_avc_trusted_proc().

Referenced by sepgsql_init_client_label().

315 {
316  struct
317  {
318  char *old_label;
319  char *new_label;
320  Datum next_private;
321  } *stack;
322 
323  switch (event)
324  {
325  case FHET_START:
326  stack = (void *) DatumGetPointer(*private);
327  if (!stack)
328  {
329  MemoryContext oldcxt;
330 
331  oldcxt = MemoryContextSwitchTo(flinfo->fn_mcxt);
332  stack = palloc(sizeof(*stack));
333  stack->old_label = NULL;
334  stack->new_label = sepgsql_avc_trusted_proc(flinfo->fn_oid);
335  stack->next_private = 0;
336 
337  MemoryContextSwitchTo(oldcxt);
338 
339  /*
340  * process:transition permission between old and new label,
341  * when user tries to switch security label of the client on
342  * execution of trusted procedure.
343  *
344  * Also, db_procedure:entrypoint permission should be checked
345  * whether this procedure can perform as an entrypoint of the
346  * trusted procedure, or not. Note that db_procedure:execute
347  * permission shall be checked individually.
348  */
349  if (stack->new_label)
350  {
351  ObjectAddress object;
352 
353  object.classId = ProcedureRelationId;
354  object.objectId = flinfo->fn_oid;
355  object.objectSubId = 0;
356  sepgsql_avc_check_perms(&object,
359  getObjectDescription(&object),
360  true);
361 
362  sepgsql_avc_check_perms_label(stack->new_label,
365  NULL, true);
366  }
367  *private = PointerGetDatum(stack);
368  }
369  Assert(!stack->old_label);
370  if (stack->new_label)
371  {
372  stack->old_label = client_label_func;
373  client_label_func = stack->new_label;
374  }
375  if (next_fmgr_hook)
376  (*next_fmgr_hook) (event, flinfo, &stack->next_private);
377  break;
378 
379  case FHET_END:
380  case FHET_ABORT:
381  stack = (void *) DatumGetPointer(*private);
382 
383  if (next_fmgr_hook)
384  (*next_fmgr_hook) (event, flinfo, &stack->next_private);
385 
386  if (stack->new_label)
387  {
388  client_label_func = stack->old_label;
389  stack->old_label = NULL;
390  }
391  break;
392 
393  default:
394  elog(ERROR, "unexpected event type: %d", (int) event);
395  break;
396  }
397 }
bool sepgsql_avc_check_perms_label(const char *tcontext, uint16 tclass, uint32 required, const char *audit_name, bool abort_on_violation)
Definition: uavc.c:341
static char * client_label_func
Definition: label.c:66
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define PointerGetDatum(X)
Definition: postgres.h:556
bool sepgsql_avc_check_perms(const ObjectAddress *tobject, uint16 tclass, uint32 required, const char *audit_name, bool abort_on_violation)
Definition: uavc.c:423
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define SEPG_PROCESS__TRANSITION
Definition: sepgsql.h:59
char * getObjectDescription(const ObjectAddress *object)
#define SEPG_CLASS_PROCESS
Definition: sepgsql.h:36
#define ERROR
Definition: elog.h:43
char * sepgsql_avc_trusted_proc(Oid functionId)
Definition: uavc.c:448
#define SEPG_CLASS_DB_PROCEDURE
Definition: sepgsql.h:48
Definition: fmgr.h:750
uintptr_t Datum
Definition: postgres.h:367
Oid fn_oid
Definition: fmgr.h:59
#define SEPG_DB_PROCEDURE__ENTRYPOINT
Definition: sepgsql.h:166
#define Assert(condition)
Definition: c.h:732
#define DatumGetPointer(X)
Definition: postgres.h:549
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:226
static fmgr_hook_type next_fmgr_hook
Definition: label.c:46

◆ sepgsql_get_client_label()

char* sepgsql_get_client_label ( void  )

Definition at line 82 of file label.c.

References Assert, client_label_committed, client_label_func, client_label_peer, pending_label::label, and llast.

Referenced by sepgsql_attribute_post_create(), sepgsql_avc_check_perms_label(), sepgsql_avc_trusted_proc(), sepgsql_database_post_create(), sepgsql_getcon(), sepgsql_proc_post_create(), sepgsql_relation_post_create(), sepgsql_schema_post_create(), and sepgsql_set_client_label().

83 {
84  /* trusted procedure client label override */
86  return client_label_func;
87 
88  /* uncommitted sepgsql_setcon() value */
90  {
92 
93  if (plabel->label)
94  return plabel->label;
95  }
96  else if (client_label_committed)
97  return client_label_committed; /* set by sepgsql_setcon() committed */
98 
99  /* default label */
100  Assert(client_label_peer != NULL);
101  return client_label_peer;
102 }
static char * client_label_func
Definition: label.c:66
static char * client_label_committed
Definition: label.c:64
#define llast(l)
Definition: pg_list.h:215
char * label
Definition: label.c:71
static List * client_label_pending
Definition: label.c:62
#define Assert(condition)
Definition: c.h:732
static char * client_label_peer
Definition: label.c:61

◆ sepgsql_get_label()

char* sepgsql_get_label ( Oid  classId,
Oid  objectId,
int32  subId 
)

Definition at line 447 of file label.c.

References ereport, errcode(), errmsg(), ERROR, GetSecurityLabel(), label, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, pstrdup(), and SEPGSQL_LABEL_TAG.

Referenced by sepgsql_attribute_post_create(), sepgsql_database_post_create(), sepgsql_proc_post_create(), sepgsql_relation_post_create(), and sepgsql_schema_post_create().

448 {
449  ObjectAddress object;
450  char *label;
451 
452  object.classId = classId;
453  object.objectId = objectId;
454  object.objectSubId = subId;
455 
456  label = GetSecurityLabel(&object, SEPGSQL_LABEL_TAG);
457  if (!label || security_check_context_raw((security_context_t) label))
458  {
459  security_context_t unlabeled;
460 
461  if (security_get_initial_context_raw("unlabeled", &unlabeled) < 0)
462  ereport(ERROR,
463  (errcode(ERRCODE_INTERNAL_ERROR),
464  errmsg("SELinux: failed to get initial security label: %m")));
465  PG_TRY();
466  {
467  label = pstrdup(unlabeled);
468  }
469  PG_CATCH();
470  {
471  freecon(unlabeled);
472  PG_RE_THROW();
473  }
474  PG_END_TRY();
475 
476  freecon(unlabeled);
477  }
478  return label;
479 }
char * pstrdup(const char *in)
Definition: mcxt.c:1186
int errcode(int sqlerrcode)
Definition: elog.c:570
#define ERROR
Definition: elog.h:43
char * GetSecurityLabel(const ObjectAddress *object, const char *provider)
Definition: seclabel.c:195
#define SEPGSQL_LABEL_TAG
Definition: sepgsql.h:23
#define ereport(elevel, rest)
Definition: elog.h:141
static char * label
Definition: pg_basebackup.c:86
#define PG_CATCH()
Definition: elog.h:310
#define PG_RE_THROW()
Definition: elog.h:331
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define PG_TRY()
Definition: elog.h:301
#define PG_END_TRY()
Definition: elog.h:317

◆ sepgsql_getcon()

Datum sepgsql_getcon ( PG_FUNCTION_ARGS  )

Definition at line 542 of file label.c.

References cstring_to_text(), PG_FUNCTION_INFO_V1(), PG_RETURN_NULL, PG_RETURN_TEXT_P, sepgsql_get_client_label(), sepgsql_is_enabled(), and sepgsql_setcon().

Referenced by sepgsql_object_relabel().

543 {
544  char *client_label;
545 
546  if (!sepgsql_is_enabled())
547  PG_RETURN_NULL();
548 
549  client_label = sepgsql_get_client_label();
550 
551  PG_RETURN_TEXT_P(cstring_to_text(client_label));
552 }
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
bool sepgsql_is_enabled(void)
Definition: selinux.c:613
text * cstring_to_text(const char *s)
Definition: varlena.c:171
char * sepgsql_get_client_label(void)
Definition: label.c:82
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ sepgsql_init_client_label()

void sepgsql_init_client_label ( void  )

Definition at line 406 of file label.c.

References client_label_peer, ClientAuthentication_hook, ereport, errcode(), errmsg(), ERROR, fmgr_hook, needs_fmgr_hook, next_client_auth_hook, next_fmgr_hook, next_needs_fmgr_hook, RegisterSubXactCallback(), RegisterXactCallback(), sepgsql_client_auth(), sepgsql_fmgr_hook(), sepgsql_needs_fmgr_hook(), sepgsql_subxact_callback(), and sepgsql_xact_callback().

Referenced by _PG_init().

407 {
408  /*
409  * Set up dummy client label.
410  *
411  * XXX - note that PostgreSQL launches background worker process like
412  * autovacuum without authentication steps. So, we initialize sepgsql_mode
413  * with SEPGSQL_MODE_INTERNAL, and client_label with the security context
414  * of server process. Later, it also launches background of user session.
415  * In this case, the process is always hooked on post-authentication, and
416  * we can initialize the sepgsql_mode and client_label correctly.
417  */
418  if (getcon_raw(&client_label_peer) < 0)
419  ereport(ERROR,
420  (errcode(ERRCODE_INTERNAL_ERROR),
421  errmsg("SELinux: failed to get server security label: %m")));
422 
423  /* Client authentication hook */
426 
427  /* Trusted procedure hooks */
430 
433 
434  /* Transaction/Sub-transaction callbacks */
437 }
int errcode(int sqlerrcode)
Definition: elog.c:570
static void sepgsql_xact_callback(XactEvent event, void *arg)
Definition: label.c:167
static ClientAuthentication_hook_type next_client_auth_hook
Definition: label.c:44
static bool sepgsql_needs_fmgr_hook(Oid functionId)
Definition: label.c:270
#define ERROR
Definition: elog.h:43
ClientAuthentication_hook_type ClientAuthentication_hook
Definition: auth.c:239
#define ereport(elevel, rest)
Definition: elog.h:141
static void sepgsql_client_auth(Port *port, int status)
Definition: label.c:232
static needs_fmgr_hook_type next_needs_fmgr_hook
Definition: label.c:45
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
Definition: xact.c:3532
PGDLLIMPORT fmgr_hook_type fmgr_hook
Definition: fmgr.c:37
PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook
Definition: fmgr.c:36
static void sepgsql_subxact_callback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
Definition: label.c:206
void RegisterXactCallback(XactCallback callback, void *arg)
Definition: xact.c:3477
static char * client_label_peer
Definition: label.c:61
static void sepgsql_fmgr_hook(FmgrHookEventType event, FmgrInfo *flinfo, Datum *private)
Definition: label.c:313
int errmsg(const char *fmt,...)
Definition: elog.c:784
static fmgr_hook_type next_fmgr_hook
Definition: label.c:46

◆ sepgsql_mcstrans_in()

Datum sepgsql_mcstrans_in ( PG_FUNCTION_ARGS  )

Definition at line 583 of file label.c.

References cstring_to_text(), ereport, errcode(), errmsg(), ERROR, label, PG_CATCH, PG_END_TRY, PG_FUNCTION_INFO_V1(), PG_GETARG_TEXT_PP, PG_RE_THROW, PG_RETURN_TEXT_P, PG_TRY, pstrdup(), sepgsql_is_enabled(), sepgsql_mcstrans_out(), and text_to_cstring().

Referenced by sepgsql_setcon().

584 {
586  char *raw_label;
587  char *result;
588 
589  if (!sepgsql_is_enabled())
590  ereport(ERROR,
591  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
592  errmsg("sepgsql is not enabled")));
593 
594  if (selinux_trans_to_raw_context(text_to_cstring(label),
595  &raw_label) < 0)
596  ereport(ERROR,
597  (errcode(ERRCODE_INTERNAL_ERROR),
598  errmsg("SELinux: could not translate security label: %m")));
599 
600  PG_TRY();
601  {
602  result = pstrdup(raw_label);
603  }
604  PG_CATCH();
605  {
606  freecon(raw_label);
607  PG_RE_THROW();
608  }
609  PG_END_TRY();
610  freecon(raw_label);
611 
613 }
char * pstrdup(const char *in)
Definition: mcxt.c:1186
int errcode(int sqlerrcode)
Definition: elog.c:570
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
static char * label
Definition: pg_basebackup.c:86
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
#define PG_CATCH()
Definition: elog.h:310
bool sepgsql_is_enabled(void)
Definition: selinux.c:613
text * cstring_to_text(const char *s)
Definition: varlena.c:171
#define PG_RE_THROW()
Definition: elog.h:331
char * text_to_cstring(const text *t)
Definition: varlena.c:204
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: c.h:549
#define PG_TRY()
Definition: elog.h:301
#define PG_END_TRY()
Definition: elog.h:317

◆ sepgsql_mcstrans_out()

Datum sepgsql_mcstrans_out ( PG_FUNCTION_ARGS  )

Definition at line 623 of file label.c.

References cstring_to_text(), ereport, errcode(), errmsg(), ERROR, label, PG_CATCH, PG_END_TRY, PG_GETARG_TEXT_PP, PG_RE_THROW, PG_RETURN_TEXT_P, PG_TRY, pstrdup(), sepgsql_is_enabled(), and text_to_cstring().

Referenced by sepgsql_mcstrans_in().

624 {
626  char *qual_label;
627  char *result;
628 
629  if (!sepgsql_is_enabled())
630  ereport(ERROR,
631  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
632  errmsg("sepgsql is not currently enabled")));
633 
634  if (selinux_raw_to_trans_context(text_to_cstring(label),
635  &qual_label) < 0)
636  ereport(ERROR,
637  (errcode(ERRCODE_INTERNAL_ERROR),
638  errmsg("SELinux: could not translate security label: %m")));
639 
640  PG_TRY();
641  {
642  result = pstrdup(qual_label);
643  }
644  PG_CATCH();
645  {
646  freecon(qual_label);
647  PG_RE_THROW();
648  }
649  PG_END_TRY();
650  freecon(qual_label);
651 
653 }
char * pstrdup(const char *in)
Definition: mcxt.c:1186
int errcode(int sqlerrcode)
Definition: elog.c:570
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
static char * label
Definition: pg_basebackup.c:86
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
#define PG_CATCH()
Definition: elog.h:310
bool sepgsql_is_enabled(void)
Definition: selinux.c:613
text * cstring_to_text(const char *s)
Definition: varlena.c:171
#define PG_RE_THROW()
Definition: elog.h:331
char * text_to_cstring(const text *t)
Definition: varlena.c:204
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: c.h:549
#define PG_TRY()
Definition: elog.h:301
#define PG_END_TRY()
Definition: elog.h:317

◆ sepgsql_needs_fmgr_hook()

static bool sepgsql_needs_fmgr_hook ( Oid  functionId)
static

Definition at line 270 of file label.c.

References ObjectAddress::classId, next_needs_fmgr_hook, SEPG_CLASS_DB_PROCEDURE, SEPG_DB_PROCEDURE__ENTRYPOINT, SEPG_DB_PROCEDURE__EXECUTE, sepgsql_avc_check_perms(), SEPGSQL_AVC_NOAUDIT, and sepgsql_avc_trusted_proc().

Referenced by sepgsql_init_client_label().

271 {
272  ObjectAddress object;
273 
274  if (next_needs_fmgr_hook &&
275  (*next_needs_fmgr_hook) (functionId))
276  return true;
277 
278  /*
279  * SELinux needs the function to be called via security_definer wrapper,
280  * if this invocation will take a domain-transition. We call these
281  * functions as trusted-procedure, if the security policy has a rule that
282  * switches security label of the client on execution.
283  */
284  if (sepgsql_avc_trusted_proc(functionId) != NULL)
285  return true;
286 
287  /*
288  * Even if not a trusted-procedure, this function should not be inlined
289  * unless the client has db_procedure:{execute} permission. Please note
290  * that it shall be actually failed later because of same reason with
291  * ACL_EXECUTE.
292  */
293  object.classId = ProcedureRelationId;
294  object.objectId = functionId;
295  object.objectSubId = 0;
296  if (!sepgsql_avc_check_perms(&object,
300  SEPGSQL_AVC_NOAUDIT, false))
301  return true;
302 
303  return false;
304 }
#define SEPG_DB_PROCEDURE__EXECUTE
Definition: sepgsql.h:165
bool sepgsql_avc_check_perms(const ObjectAddress *tobject, uint16 tclass, uint32 required, const char *audit_name, bool abort_on_violation)
Definition: uavc.c:423
#define SEPGSQL_AVC_NOAUDIT
Definition: sepgsql.h:255
char * sepgsql_avc_trusted_proc(Oid functionId)
Definition: uavc.c:448
#define SEPG_CLASS_DB_PROCEDURE
Definition: sepgsql.h:48
static needs_fmgr_hook_type next_needs_fmgr_hook
Definition: label.c:45
#define SEPG_DB_PROCEDURE__ENTRYPOINT
Definition: sepgsql.h:166

◆ sepgsql_object_relabel()

void sepgsql_object_relabel ( const ObjectAddress object,
const char *  seclabel 
)

Definition at line 487 of file label.c.

References ObjectAddress::classId, ereport, errcode(), errmsg(), ERROR, getObjectTypeDescription(), ObjectAddress::objectId, ObjectAddress::objectSubId, PG_FUNCTION_INFO_V1(), sepgsql_attribute_relabel(), sepgsql_database_relabel(), sepgsql_getcon(), sepgsql_proc_relabel(), sepgsql_relation_relabel(), and sepgsql_schema_relabel().

Referenced by _PG_init(), and exec_object_restorecon().

488 {
489  /*
490  * validate format of the supplied security label, if it is security
491  * context of selinux.
492  */
493  if (seclabel &&
494  security_check_context_raw((security_context_t) seclabel) < 0)
495  ereport(ERROR,
496  (errcode(ERRCODE_INVALID_NAME),
497  errmsg("SELinux: invalid security label: \"%s\"", seclabel)));
498 
499  /*
500  * Do actual permission checks for each object classes
501  */
502  switch (object->classId)
503  {
504  case DatabaseRelationId:
505  sepgsql_database_relabel(object->objectId, seclabel);
506  break;
507 
508  case NamespaceRelationId:
509  sepgsql_schema_relabel(object->objectId, seclabel);
510  break;
511 
512  case RelationRelationId:
513  if (object->objectSubId == 0)
515  seclabel);
516  else
518  object->objectSubId,
519  seclabel);
520  break;
521 
522  case ProcedureRelationId:
523  sepgsql_proc_relabel(object->objectId, seclabel);
524  break;
525 
526  default:
527  ereport(ERROR,
528  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
529  errmsg("sepgsql provider does not support labels on %s",
530  getObjectTypeDescription(object))));
531  break;
532  }
533 }
void sepgsql_schema_relabel(Oid namespaceId, const char *seclabel)
Definition: schema.c:144
char * getObjectTypeDescription(const ObjectAddress *object)
int errcode(int sqlerrcode)
Definition: elog.c:570
void sepgsql_database_relabel(Oid databaseId, const char *seclabel)
Definition: database.c:188
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
void sepgsql_relation_relabel(Oid relOid, const char *seclabel)
Definition: relation.c:526
void sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum, const char *seclabel)
Definition: relation.c:167
void sepgsql_proc_relabel(Oid functionId, const char *seclabel)
Definition: proc.c:200
int errmsg(const char *fmt,...)
Definition: elog.c:784

◆ sepgsql_restorecon()

Datum sepgsql_restorecon ( PG_FUNCTION_ARGS  )

Definition at line 892 of file label.c.

References ereport, errcode(), errmsg(), ERROR, exec_object_restorecon(), PG_ARGISNULL, PG_CATCH, PG_END_TRY, PG_GETARG_DATUM, PG_RE_THROW, PG_RETURN_BOOL, PG_TRY, sepgsql_is_enabled(), superuser(), and TextDatumGetCString.

Referenced by exec_object_restorecon().

893 {
894  struct selabel_handle *sehnd;
895  struct selinux_opt seopts;
896 
897  /*
898  * SELinux has to be enabled on the running platform.
899  */
900  if (!sepgsql_is_enabled())
901  ereport(ERROR,
902  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
903  errmsg("sepgsql is not currently enabled")));
904 
905  /*
906  * Check DAC permission. Only superuser can set up initial security
907  * labels, like root-user in filesystems
908  */
909  if (!superuser())
910  ereport(ERROR,
911  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
912  errmsg("SELinux: must be superuser to restore initial contexts")));
913 
914  /*
915  * Open selabel_lookup(3) stuff. It provides a set of mapping between an
916  * initial security label and object class/name due to the system setting.
917  */
918  if (PG_ARGISNULL(0))
919  {
920  seopts.type = SELABEL_OPT_UNUSED;
921  seopts.value = NULL;
922  }
923  else
924  {
925  seopts.type = SELABEL_OPT_PATH;
926  seopts.value = TextDatumGetCString(PG_GETARG_DATUM(0));
927  }
928  sehnd = selabel_open(SELABEL_CTX_DB, &seopts, 1);
929  if (!sehnd)
930  ereport(ERROR,
931  (errcode(ERRCODE_INTERNAL_ERROR),
932  errmsg("SELinux: failed to initialize labeling handle: %m")));
933  PG_TRY();
934  {
935  exec_object_restorecon(sehnd, DatabaseRelationId);
936  exec_object_restorecon(sehnd, NamespaceRelationId);
937  exec_object_restorecon(sehnd, RelationRelationId);
938  exec_object_restorecon(sehnd, AttributeRelationId);
939  exec_object_restorecon(sehnd, ProcedureRelationId);
940  }
941  PG_CATCH();
942  {
943  selabel_close(sehnd);
944  PG_RE_THROW();
945  }
946  PG_END_TRY();
947 
948  selabel_close(sehnd);
949 
950  PG_RETURN_BOOL(true);
951 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
static void exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
Definition: label.c:708
int errcode(int sqlerrcode)
Definition: elog.c:570
bool superuser(void)
Definition: superuser.c:47
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define TextDatumGetCString(d)
Definition: builtins.h:84
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
#define PG_CATCH()
Definition: elog.h:310
bool sepgsql_is_enabled(void)
Definition: selinux.c:613
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define PG_RE_THROW()
Definition: elog.h:331
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define PG_TRY()
Definition: elog.h:301
#define PG_END_TRY()
Definition: elog.h:317

◆ sepgsql_set_client_label()

static void sepgsql_set_client_label ( const char *  new_label)
static

Definition at line 113 of file label.c.

References client_label_peer, CurTransactionContext, ereport, errcode(), errmsg(), ERROR, GetCurrentSubTransactionId(), pending_label::label, lappend(), MemoryContextSwitchTo(), palloc0(), pstrdup(), SEPG_CLASS_PROCESS, SEPG_PROCESS__DYNTRANSITION, SEPG_PROCESS__SETCURRENT, sepgsql_avc_check_perms_label(), sepgsql_get_client_label(), and pending_label::subid.

Referenced by sepgsql_setcon().

114 {
115  const char *tcontext;
116  MemoryContext oldcxt;
117  pending_label *plabel;
118 
119  /* Reset to the initial client label, if NULL */
120  if (!new_label)
121  tcontext = client_label_peer;
122  else
123  {
124  if (security_check_context_raw((security_context_t) new_label) < 0)
125  ereport(ERROR,
126  (errcode(ERRCODE_INVALID_NAME),
127  errmsg("SELinux: invalid security label: \"%s\"",
128  new_label)));
129  tcontext = new_label;
130  }
131 
132  /* Check process:{setcurrent} permission. */
136  NULL,
137  true);
138  /* Check process:{dyntransition} permission. */
142  NULL,
143  true);
144 
145  /*
146  * Append the supplied new_label on the pending list until the current
147  * transaction is committed.
148  */
150 
151  plabel = palloc0(sizeof(pending_label));
152  plabel->subid = GetCurrentSubTransactionId();
153  if (new_label)
154  plabel->label = pstrdup(new_label);
156 
157  MemoryContextSwitchTo(oldcxt);
158 }
bool sepgsql_avc_check_perms_label(const char *tcontext, uint16 tclass, uint32 required, const char *audit_name, bool abort_on_violation)
Definition: uavc.c:341
#define SEPG_PROCESS__DYNTRANSITION
Definition: sepgsql.h:60
char * pstrdup(const char *in)
Definition: mcxt.c:1186
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext CurTransactionContext
Definition: mcxt.c:50
int errcode(int sqlerrcode)
Definition: elog.c:570
#define SEPG_CLASS_PROCESS
Definition: sepgsql.h:36
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
List * lappend(List *list, void *datum)
Definition: list.c:322
char * label
Definition: label.c:71
void * palloc0(Size size)
Definition: mcxt.c:980
static List * client_label_pending
Definition: label.c:62
SubTransactionId subid
Definition: label.c:70
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:708
static char * client_label_peer
Definition: label.c:61
char * sepgsql_get_client_label(void)
Definition: label.c:82
#define SEPG_PROCESS__SETCURRENT
Definition: sepgsql.h:61
int errmsg(const char *fmt,...)
Definition: elog.c:784

◆ sepgsql_setcon()

Datum sepgsql_setcon ( PG_FUNCTION_ARGS  )

Definition at line 561 of file label.c.

References PG_ARGISNULL, PG_FUNCTION_INFO_V1(), PG_GETARG_DATUM, PG_RETURN_BOOL, sepgsql_mcstrans_in(), sepgsql_set_client_label(), and TextDatumGetCString.

Referenced by sepgsql_getcon().

562 {
563  const char *new_label;
564 
565  if (PG_ARGISNULL(0))
566  new_label = NULL;
567  else
568  new_label = TextDatumGetCString(PG_GETARG_DATUM(0));
569 
570  sepgsql_set_client_label(new_label);
571 
572  PG_RETURN_BOOL(true);
573 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define TextDatumGetCString(d)
Definition: builtins.h:84
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
static void sepgsql_set_client_label(const char *new_label)
Definition: label.c:113

◆ sepgsql_subxact_callback()

static void sepgsql_subxact_callback ( SubXactEvent  event,
SubTransactionId  mySubid,
SubTransactionId  parentSubid,
void *  arg 
)
static

Definition at line 206 of file label.c.

References foreach_delete_current, lfirst, pending_label::subid, and SUBXACT_EVENT_ABORT_SUB.

Referenced by sepgsql_init_client_label().

208 {
209  ListCell *cell;
210 
211  if (event == SUBXACT_EVENT_ABORT_SUB)
212  {
213  foreach(cell, client_label_pending)
214  {
215  pending_label *plabel = lfirst(cell);
216 
217  if (plabel->subid == mySubid)
220  }
221  }
222 }
#define foreach_delete_current(lst, cell)
Definition: pg_list.h:368
static List * client_label_pending
Definition: label.c:62
SubTransactionId subid
Definition: label.c:70
#define lfirst(lc)
Definition: pg_list.h:190

◆ sepgsql_xact_callback()

static void sepgsql_xact_callback ( XactEvent  event,
void *  arg 
)
static

Definition at line 167 of file label.c.

References client_label_committed, pending_label::label, llast, MemoryContextStrdup(), NIL, pfree(), TopMemoryContext, XACT_EVENT_ABORT, and XACT_EVENT_COMMIT.

Referenced by sepgsql_init_client_label().

168 {
169  if (event == XACT_EVENT_COMMIT)
170  {
171  if (client_label_pending != NIL)
172  {
174  char *new_label;
175 
176  if (plabel->label)
178  plabel->label);
179  else
180  new_label = NULL;
181 
184 
185  client_label_committed = new_label;
186 
187  /*
188  * XXX - Note that items of client_label_pending are allocated on
189  * CurTransactionContext, thus, all acquired memory region shall
190  * be released implicitly.
191  */
193  }
194  }
195  else if (event == XACT_EVENT_ABORT)
197 }
#define NIL
Definition: pg_list.h:65
static char * client_label_committed
Definition: label.c:64
#define llast(l)
Definition: pg_list.h:215
void pfree(void *pointer)
Definition: mcxt.c:1056
MemoryContext TopMemoryContext
Definition: mcxt.c:44
char * label
Definition: label.c:71
static List * client_label_pending
Definition: label.c:62
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1173

Variable Documentation

◆ client_label_committed

char* client_label_committed = NULL
static

Definition at line 64 of file label.c.

Referenced by sepgsql_get_client_label(), and sepgsql_xact_callback().

◆ client_label_func

char* client_label_func = NULL
static

Definition at line 66 of file label.c.

Referenced by sepgsql_fmgr_hook(), and sepgsql_get_client_label().

◆ client_label_peer

char* client_label_peer = NULL
static

◆ client_label_pending

List* client_label_pending = NIL
static

Definition at line 62 of file label.c.

◆ next_client_auth_hook

ClientAuthentication_hook_type next_client_auth_hook = NULL
static

Definition at line 44 of file label.c.

Referenced by sepgsql_client_auth(), and sepgsql_init_client_label().

◆ next_fmgr_hook

fmgr_hook_type next_fmgr_hook = NULL
static

Definition at line 46 of file label.c.

Referenced by sepgsql_fmgr_hook(), and sepgsql_init_client_label().

◆ next_needs_fmgr_hook

needs_fmgr_hook_type next_needs_fmgr_hook = NULL
static

Definition at line 45 of file label.c.

Referenced by sepgsql_init_client_label(), and sepgsql_needs_fmgr_hook().