PostgreSQL Source Code  git master
label.c
Go to the documentation of this file.
1 /* -------------------------------------------------------------------------
2  *
3  * contrib/sepgsql/label.c
4  *
5  * Routines to support SELinux labels (security context)
6  *
7  * Copyright (c) 2010-2019, PostgreSQL Global Development Group
8  *
9  * -------------------------------------------------------------------------
10  */
11 #include "postgres.h"
12 
13 #include <selinux/label.h>
14 
15 #include "access/htup_details.h"
16 #include "access/genam.h"
17 #include "access/table.h"
18 #include "access/xact.h"
19 #include "catalog/catalog.h"
20 #include "catalog/dependency.h"
21 #include "catalog/indexing.h"
22 #include "catalog/pg_attribute.h"
23 #include "catalog/pg_class.h"
24 #include "catalog/pg_database.h"
25 #include "catalog/pg_namespace.h"
26 #include "catalog/pg_proc.h"
27 #include "commands/dbcommands.h"
28 #include "commands/seclabel.h"
29 #include "libpq/auth.h"
30 #include "libpq/libpq-be.h"
31 #include "miscadmin.h"
32 #include "utils/builtins.h"
33 #include "utils/fmgroids.h"
34 #include "utils/guc.h"
35 #include "utils/lsyscache.h"
36 #include "utils/memutils.h"
37 #include "utils/rel.h"
38 
39 #include "sepgsql.h"
40 
41 /*
42  * Saved hook entries (if stacked)
43  */
47 
48 /*
49  * client_label_*
50  *
51  * security label of the database client. Initially the client security label
52  * is equal to client_label_peer, and can be changed by one or more calls to
53  * sepgsql_setcon(), and also be temporarily overridden during execution of a
54  * trusted-procedure.
55  *
56  * sepgsql_setcon() is a transaction-aware operation; a (sub-)transaction
57  * rollback should also rollback the current client security label. Therefore
58  * we use the list client_label_pending of pending_label to keep track of which
59  * labels were set during the (sub-)transactions.
60  */
61 static char *client_label_peer = NULL; /* set by getpeercon(3) */
62 static List *client_label_pending = NIL; /* pending list being set by
63  * sepgsql_setcon() */
64 static char *client_label_committed = NULL; /* set by sepgsql_setcon(), and
65  * already committed */
66 static char *client_label_func = NULL; /* set by trusted procedure */
67 
68 typedef struct
69 {
71  char *label;
73 
74 /*
75  * sepgsql_get_client_label
76  *
77  * Returns the current security label of the client. All code should use this
78  * routine to get the current label, instead of referring to the client_label_*
79  * variables above.
80  */
81 char *
83 {
84  /* trusted procedure client label override */
86  return client_label_func;
87 
88  /* uncommitted sepgsql_setcon() value */
89  if (client_label_pending)
90  {
91  pending_label *plabel = llast(client_label_pending);
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 }
103 
104 /*
105  * sepgsql_set_client_label
106  *
107  * This routine tries to switch the current security label of the client, and
108  * checks related permissions. The supplied new label shall be added to the
109  * client_label_pending list, then saved at transaction-commit time to ensure
110  * transaction-awareness.
111  */
112 static void
113 sepgsql_set_client_label(const char *new_label)
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);
155  client_label_pending = lappend(client_label_pending, plabel);
156 
157  MemoryContextSwitchTo(oldcxt);
158 }
159 
160 /*
161  * sepgsql_xact_callback
162  *
163  * A callback routine of transaction commit/abort/prepare. Commit or abort
164  * changes in the client_label_pending list.
165  */
166 static void
168 {
169  if (event == XACT_EVENT_COMMIT)
170  {
171  if (client_label_pending != NIL)
172  {
173  pending_label *plabel = llast(client_label_pending);
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  */
192  client_label_pending = NIL;
193  }
194  }
195  else if (event == XACT_EVENT_ABORT)
196  client_label_pending = NIL;
197 }
198 
199 /*
200  * sepgsql_subxact_callback
201  *
202  * A callback routine of sub-transaction start/abort/commit. Releases all
203  * security labels that are set within the sub-transaction that is aborted.
204  */
205 static void
207  SubTransactionId parentSubid, void *arg)
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)
218  client_label_pending
219  = foreach_delete_current(client_label_pending, cell);
220  }
221  }
222 }
223 
224 /*
225  * sepgsql_client_auth
226  *
227  * Entrypoint of the client authentication hook.
228  * It switches the client label according to getpeercon(), and the current
229  * performing mode according to the GUC setting.
230  */
231 static void
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 }
261 
262 /*
263  * sepgsql_needs_fmgr_hook
264  *
265  * It informs the core whether the supplied function is trusted procedure,
266  * or not. If true, sepgsql_fmgr_hook shall be invoked at start, end, and
267  * abort time of function invocation.
268  */
269 static bool
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 }
305 
306 /*
307  * sepgsql_fmgr_hook
308  *
309  * It switches security label of the client on execution of trusted
310  * procedures.
311  */
312 static void
314  FmgrInfo *flinfo, Datum *private)
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 }
398 
399 /*
400  * sepgsql_init_client_label
401  *
402  * Initializes the client security label and sets up related hooks for client
403  * label management.
404  */
405 void
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 }
438 
439 /*
440  * sepgsql_get_label
441  *
442  * It returns a security context of the specified database object.
443  * If unlabeled or incorrectly labeled, the system "unlabeled" label
444  * shall be returned.
445  */
446 char *
447 sepgsql_get_label(Oid classId, Oid objectId, int32 subId)
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 }
480 
481 /*
482  * sepgsql_object_relabel
483  *
484  * An entrypoint of SECURITY LABEL statement
485  */
486 void
487 sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
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 }
534 
535 /*
536  * TEXT sepgsql_getcon(VOID)
537  *
538  * It returns the security label of the client.
539  */
541 Datum
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 }
553 
554 /*
555  * BOOL sepgsql_setcon(TEXT)
556  *
557  * It switches the security label of the client.
558  */
560 Datum
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 }
574 
575 /*
576  * TEXT sepgsql_mcstrans_in(TEXT)
577  *
578  * It translate the given qualified MLS/MCS range into raw format
579  * when mcstrans daemon is working.
580  */
582 Datum
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 }
614 
615 /*
616  * TEXT sepgsql_mcstrans_out(TEXT)
617  *
618  * It translate the given raw MLS/MCS range into qualified format
619  * when mcstrans daemon is working.
620  */
622 Datum
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 }
654 
655 /*
656  * quote_object_name
657  *
658  * It tries to quote the supplied identifiers
659  */
660 static char *
661 quote_object_name(const char *src1, const char *src2,
662  const char *src3, const char *src4)
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 }
699 
700 /*
701  * exec_object_restorecon
702  *
703  * This routine is a helper called by sepgsql_restorecon; it set up
704  * initial security labels of database objects within the supplied
705  * catalog OID.
706  */
707 static void
708 exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
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 }
878 
879 /*
880  * BOOL sepgsql_restorecon(TEXT specfile)
881  *
882  * This function tries to assign initial security labels on all the object
883  * within the current database, according to the system setting.
884  * It is typically invoked by sepgsql-install script just after initdb, to
885  * assign initial security labels.
886  *
887  * If @specfile is not NULL, it uses explicitly specified specfile, instead
888  * of the system default.
889  */
891 Datum
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 NIL
Definition: pg_list.h:65
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
Datum sepgsql_getcon(PG_FUNCTION_ARGS)
Definition: label.c:542
XactEvent
Definition: xact.h:108
Definition: fmgr.h:56
#define SEPG_DB_PROCEDURE__EXECUTE
Definition: sepgsql.h:165
static char * client_label_func
Definition: label.c:66
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
MemoryContext fn_mcxt
Definition: fmgr.h:65
void SetSecurityLabel(const ObjectAddress *object, const char *provider, const char *label)
Definition: seclabel.c:327
void sepgsql_schema_relabel(Oid namespaceId, const char *seclabel)
Definition: schema.c:144
char * getObjectTypeDescription(const ObjectAddress *object)
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
#define SEPG_PROCESS__DYNTRANSITION
Definition: sepgsql.h:60
Datum sepgsql_restorecon(PG_FUNCTION_ARGS)
Definition: label.c:892
Datum sepgsql_mcstrans_in(PG_FUNCTION_ARGS)
Definition: label.c:583
static char * client_label_committed
Definition: label.c:64
void(* fmgr_hook_type)(FmgrHookEventType event, FmgrInfo *flinfo, Datum *arg)
Definition: fmgr.h:756
FormData_pg_database * Form_pg_database
Definition: pg_database.h:81
#define PointerGetDatum(X)
Definition: postgres.h:556
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1805
char * pstrdup(const char *in)
Definition: mcxt.c:1186
static void exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
Definition: label.c:708
char * sepgsql_get_label(Oid classId, Oid objectId, int32 subId)
Definition: label.c:447
bool sepgsql_avc_check_perms(const ObjectAddress *tobject, uint16 tclass, uint32 required, const char *audit_name, bool abort_on_violation)
Definition: uavc.c:423
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1754
#define llast(l)
Definition: pg_list.h:215
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
void sepgsql_init_client_label(void)
Definition: label.c:406
MemoryContext CurTransactionContext
Definition: mcxt.c:50
int errcode(int sqlerrcode)
Definition: elog.c:570
Definition: libpq-be.h:120
bool superuser(void)
Definition: superuser.c:47
static void sepgsql_xact_callback(XactEvent event, void *arg)
Definition: label.c:167
uint32 SubTransactionId
Definition: c.h:511
#define SEPG_PROCESS__TRANSITION
Definition: sepgsql.h:59
unsigned int Oid
Definition: postgres_ext.h:31
static ClientAuthentication_hook_type next_client_auth_hook
Definition: label.c:44
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
#define SEPGSQL_AVC_NOAUDIT
Definition: sepgsql.h:255
char * getObjectDescription(const ObjectAddress *object)
void sepgsql_database_relabel(Oid databaseId, const char *seclabel)
Definition: database.c:188
signed int int32
Definition: c.h:346
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
#define SEPG_CLASS_PROCESS
Definition: sepgsql.h:36
#define foreach_delete_current(lst, cell)
Definition: pg_list.h:368
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
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static bool sepgsql_needs_fmgr_hook(Oid functionId)
Definition: label.c:270
#define ERROR
Definition: elog.h:43
bool(* needs_fmgr_hook_type)(Oid fn_oid)
Definition: fmgr.h:754
char * GetSecurityLabel(const ObjectAddress *object, const char *provider)
Definition: seclabel.c:195
#define FATAL
Definition: elog.h:52
char * sepgsql_avc_trusted_proc(Oid functionId)
Definition: uavc.c:448
int sepgsql_set_mode(int new_mode)
Definition: selinux.c:631
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2100
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
#define NoLock
Definition: lockdefs.h:34
FmgrHookEventType
Definition: fmgr.h:747
#define SEPG_CLASS_DB_PROCEDURE
Definition: sepgsql.h:48
ClientAuthentication_hook_type ClientAuthentication_hook
Definition: auth.c:239
#define SEPGSQL_LABEL_TAG
Definition: sepgsql.h:23
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
Definition: fmgr.h:750
#define ereport(elevel, rest)
Definition: elog.h:141
Datum sepgsql_mcstrans_out(PG_FUNCTION_ARGS)
Definition: label.c:623
void(* ClientAuthentication_hook_type)(Port *, int)
Definition: auth.h:26
#define STATUS_OK
Definition: c.h:1089
static void sepgsql_client_auth(Port *port, int status)
Definition: label.c:232
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static int port
Definition: pg_regress.c:92
List * lappend(List *list, void *datum)
Definition: list.c:322
char * label
Definition: label.c:71
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define WARNING
Definition: elog.h:40
SubXactEvent
Definition: xact.h:122
#define TextDatumGetCString(d)
Definition: builtins.h:84
static needs_fmgr_hook_type next_needs_fmgr_hook
Definition: label.c:45
void * palloc0(Size size)
Definition: mcxt.c:980
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
uintptr_t Datum
Definition: postgres.h:367
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
Definition: xact.c:3532
static char * label
Definition: pg_basebackup.c:86
Oid MyDatabaseId
Definition: globals.c:85
static List * client_label_pending
Definition: label.c:62
PGDLLIMPORT fmgr_hook_type fmgr_hook
Definition: fmgr.c:37
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:134
PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook
Definition: fmgr.c:36
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:59
#define SEPGSQL_MODE_DEFAULT
Definition: sepgsql.h:28
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
SubTransactionId subid
Definition: label.c:70
#define PG_CATCH()
Definition: elog.h:310
#define SEPG_DB_PROCEDURE__ENTRYPOINT
Definition: sepgsql.h:166
bool sepgsql_is_enabled(void)
Definition: selinux.c:613
text * cstring_to_text(const char *s)
Definition: varlena.c:171
static void sepgsql_subxact_callback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
Definition: label.c:206
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
#define SEPGSQL_MODE_PERMISSIVE
Definition: sepgsql.h:29
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:708
void RegisterXactCallback(XactCallback callback, void *arg)
Definition: xact.c:3477
static char * client_label_peer
Definition: label.c:61
void sepgsql_relation_relabel(Oid relOid, const char *seclabel)
Definition: relation.c:526
#define PG_RE_THROW()
Definition: elog.h:331
char * sepgsql_get_client_label(void)
Definition: label.c:82
#define DatumGetPointer(X)
Definition: postgres.h:549
bool sepgsql_get_permissive(void)
Definition: hooks.c:65
Datum sepgsql_setcon(PG_FUNCTION_ARGS)
Definition: label.c:561
#define SEPG_PROCESS__SETCURRENT
Definition: sepgsql.h:61
void sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum, const char *seclabel)
Definition: relation.c:167
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
char * text_to_cstring(const text *t)
Definition: varlena.c:204
static void sepgsql_fmgr_hook(FmgrHookEventType event, FmgrInfo *flinfo, Datum *private)
Definition: label.c:313
void sepgsql_proc_relabel(Oid functionId, const char *seclabel)
Definition: proc.c:200
void sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
Definition: label.c:487
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1173
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
void * arg
Definition: c.h:549
#define PG_FUNCTION_ARGS
Definition: fmgr.h:188
static fmgr_hook_type next_fmgr_hook
Definition: label.c:46
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define PG_TRY()
Definition: elog.h:301
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1730
PG_FUNCTION_INFO_V1(sepgsql_getcon)
#define PG_RETURN_NULL()
Definition: fmgr.h:335
#define PG_END_TRY()
Definition: elog.h:317
static void sepgsql_set_client_label(const char *new_label)
Definition: label.c:113