PostgreSQL Source Code  git master
label.c File Reference
#include "postgres.h"
#include <selinux/label.h>
#include "access/genam.h"
#include "access/htup_details.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 "sepgsql.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 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 700 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_END_TRY, PG_FINALLY, PG_FUNCTION_INFO_V1(), 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().

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

◆ 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 653 of file label.c.

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

Referenced by exec_object_restorecon().

655 {
656  StringInfoData result;
657  const char *temp;
658 
659  initStringInfo(&result);
660 
661  if (src1)
662  {
663  temp = quote_identifier(src1);
664  appendStringInfoString(&result, temp);
665  if (src1 != temp)
666  pfree((void *) temp);
667  }
668  if (src2)
669  {
670  temp = quote_identifier(src2);
671  appendStringInfo(&result, ".%s", temp);
672  if (src2 != temp)
673  pfree((void *) temp);
674  }
675  if (src3)
676  {
677  temp = quote_identifier(src3);
678  appendStringInfo(&result, ".%s", temp);
679  if (src3 != temp)
680  pfree((void *) temp);
681  }
682  if (src4)
683  {
684  temp = quote_identifier(src4);
685  appendStringInfo(&result, ".%s", temp);
686  if (src4 != temp)
687  pfree((void *) temp);
688  }
689  return result.data;
690 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10709
void pfree(void *pointer)
Definition: mcxt.c:1057
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59

◆ sepgsql_client_auth()

static void sepgsql_client_auth ( Port port,
int  status 
)
static

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

232 {
234  (*next_client_auth_hook) (port, status);
235 
236  /*
237  * In the case when authentication failed, the supplied socket shall be
238  * closed soon, so we don't need to do anything here.
239  */
240  if (status != STATUS_OK)
241  return;
242 
243  /*
244  * Getting security label of the peer process using API of libselinux.
245  */
246  if (getpeercon_raw(port->sock, &client_label_peer) < 0)
247  ereport(FATAL,
248  (errcode(ERRCODE_INTERNAL_ERROR),
249  errmsg("SELinux: unable to get peer label: %m")));
250 
251  /*
252  * Switch the current performing mode from INTERNAL to either DEFAULT or
253  * PERMISSIVE.
254  */
257  else
259 }
int errcode(int sqlerrcode)
Definition: elog.c:610
static ClientAuthentication_hook_type next_client_auth_hook
Definition: label.c:43
#define FATAL
Definition: elog.h:52
int sepgsql_set_mode(int new_mode)
Definition: selinux.c:634
#define STATUS_OK
Definition: c.h:1112
static int port
Definition: pg_regress.c:92
#define ereport(elevel,...)
Definition: elog.h:144
#define SEPGSQL_MODE_DEFAULT
Definition: sepgsql.h:28
#define SEPGSQL_MODE_PERMISSIVE
Definition: sepgsql.h:29
static char * client_label_peer
Definition: label.c:60
bool sepgsql_get_permissive(void)
Definition: hooks.c:64
int errmsg(const char *fmt,...)
Definition: elog.c:821
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 312 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().

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

◆ sepgsql_get_client_label()

char* sepgsql_get_client_label ( void  )

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

82 {
83  /* trusted procedure client label override */
85  return client_label_func;
86 
87  /* uncommitted sepgsql_setcon() value */
89  {
91 
92  if (plabel->label)
93  return plabel->label;
94  }
95  else if (client_label_committed)
96  return client_label_committed; /* set by sepgsql_setcon() committed */
97 
98  /* default label */
99  Assert(client_label_peer != NULL);
100  return client_label_peer;
101 }
static char * client_label_func
Definition: label.c:65
static char * client_label_committed
Definition: label.c:63
#define llast(l)
Definition: pg_list.h:194
char * label
Definition: label.c:70
static List * client_label_pending
Definition: label.c:61
#define Assert(condition)
Definition: c.h:746
static char * client_label_peer
Definition: label.c:60

◆ sepgsql_get_label()

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

Definition at line 446 of file label.c.

References ereport, errcode(), errmsg(), ERROR, GetSecurityLabel(), label, PG_END_TRY, PG_FINALLY, 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().

447 {
448  ObjectAddress object;
449  char *label;
450 
451  object.classId = classId;
452  object.objectId = objectId;
453  object.objectSubId = subId;
454 
455  label = GetSecurityLabel(&object, SEPGSQL_LABEL_TAG);
456  if (!label || security_check_context_raw(label))
457  {
458  char *unlabeled;
459 
460  if (security_get_initial_context_raw("unlabeled", &unlabeled) < 0)
461  ereport(ERROR,
462  (errcode(ERRCODE_INTERNAL_ERROR),
463  errmsg("SELinux: failed to get initial security label: %m")));
464  PG_TRY();
465  {
466  label = pstrdup(unlabeled);
467  }
468  PG_FINALLY();
469  {
470  freecon(unlabeled);
471  }
472  PG_END_TRY();
473  }
474  return label;
475 }
char * pstrdup(const char *in)
Definition: mcxt.c:1187
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
char * GetSecurityLabel(const ObjectAddress *object, const char *provider)
Definition: seclabel.c:269
#define SEPGSQL_LABEL_TAG
Definition: sepgsql.h:23
#define PG_FINALLY()
Definition: elog.h:312
static char * label
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define PG_TRY()
Definition: elog.h:295
#define PG_END_TRY()
Definition: elog.h:320

◆ sepgsql_getcon()

Datum sepgsql_getcon ( PG_FUNCTION_ARGS  )

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

539 {
540  char *client_label;
541 
542  if (!sepgsql_is_enabled())
543  PG_RETURN_NULL();
544 
545  client_label = sepgsql_get_client_label();
546 
547  PG_RETURN_TEXT_P(cstring_to_text(client_label));
548 }
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
bool sepgsql_is_enabled(void)
Definition: selinux.c:616
text * cstring_to_text(const char *s)
Definition: varlena.c:188
char * sepgsql_get_client_label(void)
Definition: label.c:81
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ sepgsql_init_client_label()

void sepgsql_init_client_label ( void  )

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

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

◆ sepgsql_mcstrans_in()

Datum sepgsql_mcstrans_in ( PG_FUNCTION_ARGS  )

Definition at line 579 of file label.c.

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

Referenced by sepgsql_setcon().

580 {
582  char *raw_label;
583  char *result;
584 
585  if (!sepgsql_is_enabled())
586  ereport(ERROR,
587  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
588  errmsg("sepgsql is not enabled")));
589 
590  if (selinux_trans_to_raw_context(text_to_cstring(label),
591  &raw_label) < 0)
592  ereport(ERROR,
593  (errcode(ERRCODE_INTERNAL_ERROR),
594  errmsg("SELinux: could not translate security label: %m")));
595 
596  PG_TRY();
597  {
598  result = pstrdup(raw_label);
599  }
600  PG_FINALLY();
601  {
602  freecon(raw_label);
603  }
604  PG_END_TRY();
605 
607 }
char * pstrdup(const char *in)
Definition: mcxt.c:1187
int errcode(int sqlerrcode)
Definition: elog.c:610
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
#define ERROR
Definition: elog.h:43
#define PG_FINALLY()
Definition: elog.h:312
static char * label
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
bool sepgsql_is_enabled(void)
Definition: selinux.c:616
text * cstring_to_text(const char *s)
Definition: varlena.c:188
char * text_to_cstring(const text *t)
Definition: varlena.c:221
int errmsg(const char *fmt,...)
Definition: elog.c:821
Definition: c.h:563
#define PG_TRY()
Definition: elog.h:295
#define PG_END_TRY()
Definition: elog.h:320

◆ sepgsql_mcstrans_out()

Datum sepgsql_mcstrans_out ( PG_FUNCTION_ARGS  )

Definition at line 617 of file label.c.

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

Referenced by sepgsql_mcstrans_in().

618 {
620  char *qual_label;
621  char *result;
622 
623  if (!sepgsql_is_enabled())
624  ereport(ERROR,
625  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
626  errmsg("sepgsql is not currently enabled")));
627 
628  if (selinux_raw_to_trans_context(text_to_cstring(label),
629  &qual_label) < 0)
630  ereport(ERROR,
631  (errcode(ERRCODE_INTERNAL_ERROR),
632  errmsg("SELinux: could not translate security label: %m")));
633 
634  PG_TRY();
635  {
636  result = pstrdup(qual_label);
637  }
638  PG_FINALLY();
639  {
640  freecon(qual_label);
641  }
642  PG_END_TRY();
643 
645 }
char * pstrdup(const char *in)
Definition: mcxt.c:1187
int errcode(int sqlerrcode)
Definition: elog.c:610
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
#define ERROR
Definition: elog.h:43
#define PG_FINALLY()
Definition: elog.h:312
static char * label
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
bool sepgsql_is_enabled(void)
Definition: selinux.c:616
text * cstring_to_text(const char *s)
Definition: varlena.c:188
char * text_to_cstring(const text *t)
Definition: varlena.c:221
int errmsg(const char *fmt,...)
Definition: elog.c:821
Definition: c.h:563
#define PG_TRY()
Definition: elog.h:295
#define PG_END_TRY()
Definition: elog.h:320

◆ sepgsql_needs_fmgr_hook()

static bool sepgsql_needs_fmgr_hook ( Oid  functionId)
static

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

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

◆ sepgsql_object_relabel()

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

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

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

◆ sepgsql_restorecon()

Datum sepgsql_restorecon ( PG_FUNCTION_ARGS  )

Definition at line 882 of file label.c.

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

Referenced by exec_object_restorecon().

883 {
884  struct selabel_handle *sehnd;
885  struct selinux_opt seopts;
886 
887  /*
888  * SELinux has to be enabled on the running platform.
889  */
890  if (!sepgsql_is_enabled())
891  ereport(ERROR,
892  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
893  errmsg("sepgsql is not currently enabled")));
894 
895  /*
896  * Check DAC permission. Only superuser can set up initial security
897  * labels, like root-user in filesystems
898  */
899  if (!superuser())
900  ereport(ERROR,
901  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
902  errmsg("SELinux: must be superuser to restore initial contexts")));
903 
904  /*
905  * Open selabel_lookup(3) stuff. It provides a set of mapping between an
906  * initial security label and object class/name due to the system setting.
907  */
908  if (PG_ARGISNULL(0))
909  {
910  seopts.type = SELABEL_OPT_UNUSED;
911  seopts.value = NULL;
912  }
913  else
914  {
915  seopts.type = SELABEL_OPT_PATH;
916  seopts.value = TextDatumGetCString(PG_GETARG_DATUM(0));
917  }
918  sehnd = selabel_open(SELABEL_CTX_DB, &seopts, 1);
919  if (!sehnd)
920  ereport(ERROR,
921  (errcode(ERRCODE_INTERNAL_ERROR),
922  errmsg("SELinux: failed to initialize labeling handle: %m")));
923  PG_TRY();
924  {
925  exec_object_restorecon(sehnd, DatabaseRelationId);
926  exec_object_restorecon(sehnd, NamespaceRelationId);
927  exec_object_restorecon(sehnd, RelationRelationId);
928  exec_object_restorecon(sehnd, AttributeRelationId);
929  exec_object_restorecon(sehnd, ProcedureRelationId);
930  }
931  PG_FINALLY();
932  {
933  selabel_close(sehnd);
934  }
935  PG_END_TRY();
936 
937  PG_RETURN_BOOL(true);
938 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
static void exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
Definition: label.c:700
int errcode(int sqlerrcode)
Definition: elog.c:610
bool superuser(void)
Definition: superuser.c:46
#define ERROR
Definition: elog.h:43
#define PG_FINALLY()
Definition: elog.h:312
#define TextDatumGetCString(d)
Definition: builtins.h:87
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:358
#define ereport(elevel,...)
Definition: elog.h:144
bool sepgsql_is_enabled(void)
Definition: selinux.c:616
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define PG_TRY()
Definition: elog.h:295
#define PG_END_TRY()
Definition: elog.h:320

◆ sepgsql_set_client_label()

static void sepgsql_set_client_label ( const char *  new_label)
static

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

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

◆ sepgsql_setcon()

Datum sepgsql_setcon ( PG_FUNCTION_ARGS  )

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

558 {
559  const char *new_label;
560 
561  if (PG_ARGISNULL(0))
562  new_label = NULL;
563  else
564  new_label = TextDatumGetCString(PG_GETARG_DATUM(0));
565 
566  sepgsql_set_client_label(new_label);
567 
568  PG_RETURN_BOOL(true);
569 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define TextDatumGetCString(d)
Definition: builtins.h:87
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:358
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
static void sepgsql_set_client_label(const char *new_label)
Definition: label.c:112

◆ sepgsql_subxact_callback()

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

Definition at line 205 of file label.c.

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

Referenced by sepgsql_init_client_label().

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

◆ sepgsql_xact_callback()

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

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

167 {
168  if (event == XACT_EVENT_COMMIT)
169  {
170  if (client_label_pending != NIL)
171  {
173  char *new_label;
174 
175  if (plabel->label)
177  plabel->label);
178  else
179  new_label = NULL;
180 
183 
184  client_label_committed = new_label;
185 
186  /*
187  * XXX - Note that items of client_label_pending are allocated on
188  * CurTransactionContext, thus, all acquired memory region shall
189  * be released implicitly.
190  */
192  }
193  }
194  else if (event == XACT_EVENT_ABORT)
196 }
#define NIL
Definition: pg_list.h:65
static char * client_label_committed
Definition: label.c:63
#define llast(l)
Definition: pg_list.h:194
void pfree(void *pointer)
Definition: mcxt.c:1057
MemoryContext TopMemoryContext
Definition: mcxt.c:44
char * label
Definition: label.c:70
static List * client_label_pending
Definition: label.c:61
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1174

Variable Documentation

◆ client_label_committed

char* client_label_committed = NULL
static

Definition at line 63 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 65 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 61 of file label.c.

◆ next_client_auth_hook

ClientAuthentication_hook_type next_client_auth_hook = NULL
static

Definition at line 43 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 45 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 44 of file label.c.

Referenced by sepgsql_init_client_label(), and sepgsql_needs_fmgr_hook().