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-2020, PostgreSQL Global Development Group
8  *
9  * -------------------------------------------------------------------------
10  */
11 #include "postgres.h"
12 
13 #include <selinux/label.h>
14 
15 #include "access/genam.h"
16 #include "access/htup_details.h"
17 #include "access/table.h"
18 #include "access/xact.h"
19 #include "catalog/catalog.h"
20 #include "catalog/dependency.h"
21 #include "catalog/pg_attribute.h"
22 #include "catalog/pg_class.h"
23 #include "catalog/pg_database.h"
24 #include "catalog/pg_namespace.h"
25 #include "catalog/pg_proc.h"
26 #include "commands/dbcommands.h"
27 #include "commands/seclabel.h"
28 #include "libpq/auth.h"
29 #include "libpq/libpq-be.h"
30 #include "miscadmin.h"
31 #include "sepgsql.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 /*
40  * Saved hook entries (if stacked)
41  */
45 
46 /*
47  * client_label_*
48  *
49  * security label of the database client. Initially the client security label
50  * is equal to client_label_peer, and can be changed by one or more calls to
51  * sepgsql_setcon(), and also be temporarily overridden during execution of a
52  * trusted-procedure.
53  *
54  * sepgsql_setcon() is a transaction-aware operation; a (sub-)transaction
55  * rollback should also rollback the current client security label. Therefore
56  * we use the list client_label_pending of pending_label to keep track of which
57  * labels were set during the (sub-)transactions.
58  */
59 static char *client_label_peer = NULL; /* set by getpeercon(3) */
60 static List *client_label_pending = NIL; /* pending list being set by
61  * sepgsql_setcon() */
62 static char *client_label_committed = NULL; /* set by sepgsql_setcon(), and
63  * already committed */
64 static char *client_label_func = NULL; /* set by trusted procedure */
65 
66 typedef struct
67 {
69  char *label;
71 
72 /*
73  * sepgsql_get_client_label
74  *
75  * Returns the current security label of the client. All code should use this
76  * routine to get the current label, instead of referring to the client_label_*
77  * variables above.
78  */
79 char *
81 {
82  /* trusted procedure client label override */
84  return client_label_func;
85 
86  /* uncommitted sepgsql_setcon() value */
87  if (client_label_pending)
88  {
89  pending_label *plabel = llast(client_label_pending);
90 
91  if (plabel->label)
92  return plabel->label;
93  }
94  else if (client_label_committed)
95  return client_label_committed; /* set by sepgsql_setcon() committed */
96 
97  /* default label */
98  Assert(client_label_peer != NULL);
99  return client_label_peer;
100 }
101 
102 /*
103  * sepgsql_set_client_label
104  *
105  * This routine tries to switch the current security label of the client, and
106  * checks related permissions. The supplied new label shall be added to the
107  * client_label_pending list, then saved at transaction-commit time to ensure
108  * transaction-awareness.
109  */
110 static void
111 sepgsql_set_client_label(const char *new_label)
112 {
113  const char *tcontext;
114  MemoryContext oldcxt;
115  pending_label *plabel;
116 
117  /* Reset to the initial client label, if NULL */
118  if (!new_label)
119  tcontext = client_label_peer;
120  else
121  {
122  if (security_check_context_raw(new_label) < 0)
123  ereport(ERROR,
124  (errcode(ERRCODE_INVALID_NAME),
125  errmsg("SELinux: invalid security label: \"%s\"",
126  new_label)));
127  tcontext = new_label;
128  }
129 
130  /* Check process:{setcurrent} permission. */
134  NULL,
135  true);
136  /* Check process:{dyntransition} permission. */
140  NULL,
141  true);
142 
143  /*
144  * Append the supplied new_label on the pending list until the current
145  * transaction is committed.
146  */
148 
149  plabel = palloc0(sizeof(pending_label));
150  plabel->subid = GetCurrentSubTransactionId();
151  if (new_label)
152  plabel->label = pstrdup(new_label);
153  client_label_pending = lappend(client_label_pending, plabel);
154 
155  MemoryContextSwitchTo(oldcxt);
156 }
157 
158 /*
159  * sepgsql_xact_callback
160  *
161  * A callback routine of transaction commit/abort/prepare. Commit or abort
162  * changes in the client_label_pending list.
163  */
164 static void
166 {
167  if (event == XACT_EVENT_COMMIT)
168  {
169  if (client_label_pending != NIL)
170  {
171  pending_label *plabel = llast(client_label_pending);
172  char *new_label;
173 
174  if (plabel->label)
176  plabel->label);
177  else
178  new_label = NULL;
179 
182 
183  client_label_committed = new_label;
184 
185  /*
186  * XXX - Note that items of client_label_pending are allocated on
187  * CurTransactionContext, thus, all acquired memory region shall
188  * be released implicitly.
189  */
190  client_label_pending = NIL;
191  }
192  }
193  else if (event == XACT_EVENT_ABORT)
194  client_label_pending = NIL;
195 }
196 
197 /*
198  * sepgsql_subxact_callback
199  *
200  * A callback routine of sub-transaction start/abort/commit. Releases all
201  * security labels that are set within the sub-transaction that is aborted.
202  */
203 static void
205  SubTransactionId parentSubid, void *arg)
206 {
207  ListCell *cell;
208 
209  if (event == SUBXACT_EVENT_ABORT_SUB)
210  {
211  foreach(cell, client_label_pending)
212  {
213  pending_label *plabel = lfirst(cell);
214 
215  if (plabel->subid == mySubid)
216  client_label_pending
217  = foreach_delete_current(client_label_pending, cell);
218  }
219  }
220 }
221 
222 /*
223  * sepgsql_client_auth
224  *
225  * Entrypoint of the client authentication hook.
226  * It switches the client label according to getpeercon(), and the current
227  * performing mode according to the GUC setting.
228  */
229 static void
231 {
233  (*next_client_auth_hook) (port, status);
234 
235  /*
236  * In the case when authentication failed, the supplied socket shall be
237  * closed soon, so we don't need to do anything here.
238  */
239  if (status != STATUS_OK)
240  return;
241 
242  /*
243  * Getting security label of the peer process using API of libselinux.
244  */
245  if (getpeercon_raw(port->sock, &client_label_peer) < 0)
246  ereport(FATAL,
247  (errcode(ERRCODE_INTERNAL_ERROR),
248  errmsg("SELinux: unable to get peer label: %m")));
249 
250  /*
251  * Switch the current performing mode from INTERNAL to either DEFAULT or
252  * PERMISSIVE.
253  */
256  else
258 }
259 
260 /*
261  * sepgsql_needs_fmgr_hook
262  *
263  * It informs the core whether the supplied function is trusted procedure,
264  * or not. If true, sepgsql_fmgr_hook shall be invoked at start, end, and
265  * abort time of function invocation.
266  */
267 static bool
269 {
270  ObjectAddress object;
271 
272  if (next_needs_fmgr_hook &&
273  (*next_needs_fmgr_hook) (functionId))
274  return true;
275 
276  /*
277  * SELinux needs the function to be called via security_definer wrapper,
278  * if this invocation will take a domain-transition. We call these
279  * functions as trusted-procedure, if the security policy has a rule that
280  * switches security label of the client on execution.
281  */
282  if (sepgsql_avc_trusted_proc(functionId) != NULL)
283  return true;
284 
285  /*
286  * Even if not a trusted-procedure, this function should not be inlined
287  * unless the client has db_procedure:{execute} permission. Please note
288  * that it shall be actually failed later because of same reason with
289  * ACL_EXECUTE.
290  */
291  object.classId = ProcedureRelationId;
292  object.objectId = functionId;
293  object.objectSubId = 0;
294  if (!sepgsql_avc_check_perms(&object,
298  SEPGSQL_AVC_NOAUDIT, false))
299  return true;
300 
301  return false;
302 }
303 
304 /*
305  * sepgsql_fmgr_hook
306  *
307  * It switches security label of the client on execution of trusted
308  * procedures.
309  */
310 static void
312  FmgrInfo *flinfo, Datum *private)
313 {
314  struct
315  {
316  char *old_label;
317  char *new_label;
318  Datum next_private;
319  } *stack;
320 
321  switch (event)
322  {
323  case FHET_START:
324  stack = (void *) DatumGetPointer(*private);
325  if (!stack)
326  {
327  MemoryContext oldcxt;
328 
329  oldcxt = MemoryContextSwitchTo(flinfo->fn_mcxt);
330  stack = palloc(sizeof(*stack));
331  stack->old_label = NULL;
332  stack->new_label = sepgsql_avc_trusted_proc(flinfo->fn_oid);
333  stack->next_private = 0;
334 
335  MemoryContextSwitchTo(oldcxt);
336 
337  /*
338  * process:transition permission between old and new label,
339  * when user tries to switch security label of the client on
340  * execution of trusted procedure.
341  *
342  * Also, db_procedure:entrypoint permission should be checked
343  * whether this procedure can perform as an entrypoint of the
344  * trusted procedure, or not. Note that db_procedure:execute
345  * permission shall be checked individually.
346  */
347  if (stack->new_label)
348  {
349  ObjectAddress object;
350 
351  object.classId = ProcedureRelationId;
352  object.objectId = flinfo->fn_oid;
353  object.objectSubId = 0;
354  sepgsql_avc_check_perms(&object,
357  getObjectDescription(&object, false),
358  true);
359 
360  sepgsql_avc_check_perms_label(stack->new_label,
363  NULL, true);
364  }
365  *private = PointerGetDatum(stack);
366  }
367  Assert(!stack->old_label);
368  if (stack->new_label)
369  {
370  stack->old_label = client_label_func;
371  client_label_func = stack->new_label;
372  }
373  if (next_fmgr_hook)
374  (*next_fmgr_hook) (event, flinfo, &stack->next_private);
375  break;
376 
377  case FHET_END:
378  case FHET_ABORT:
379  stack = (void *) DatumGetPointer(*private);
380 
381  if (next_fmgr_hook)
382  (*next_fmgr_hook) (event, flinfo, &stack->next_private);
383 
384  if (stack->new_label)
385  {
386  client_label_func = stack->old_label;
387  stack->old_label = NULL;
388  }
389  break;
390 
391  default:
392  elog(ERROR, "unexpected event type: %d", (int) event);
393  break;
394  }
395 }
396 
397 /*
398  * sepgsql_init_client_label
399  *
400  * Initializes the client security label and sets up related hooks for client
401  * label management.
402  */
403 void
405 {
406  /*
407  * Set up dummy client label.
408  *
409  * XXX - note that PostgreSQL launches background worker process like
410  * autovacuum without authentication steps. So, we initialize sepgsql_mode
411  * with SEPGSQL_MODE_INTERNAL, and client_label with the security context
412  * of server process. Later, it also launches background of user session.
413  * In this case, the process is always hooked on post-authentication, and
414  * we can initialize the sepgsql_mode and client_label correctly.
415  */
416  if (getcon_raw(&client_label_peer) < 0)
417  ereport(ERROR,
418  (errcode(ERRCODE_INTERNAL_ERROR),
419  errmsg("SELinux: failed to get server security label: %m")));
420 
421  /* Client authentication hook */
424 
425  /* Trusted procedure hooks */
428 
431 
432  /* Transaction/Sub-transaction callbacks */
435 }
436 
437 /*
438  * sepgsql_get_label
439  *
440  * It returns a security context of the specified database object.
441  * If unlabeled or incorrectly labeled, the system "unlabeled" label
442  * shall be returned.
443  */
444 char *
445 sepgsql_get_label(Oid classId, Oid objectId, int32 subId)
446 {
447  ObjectAddress object;
448  char *label;
449 
450  object.classId = classId;
451  object.objectId = objectId;
452  object.objectSubId = subId;
453 
454  label = GetSecurityLabel(&object, SEPGSQL_LABEL_TAG);
455  if (!label || security_check_context_raw(label))
456  {
457  char *unlabeled;
458 
459  if (security_get_initial_context_raw("unlabeled", &unlabeled) < 0)
460  ereport(ERROR,
461  (errcode(ERRCODE_INTERNAL_ERROR),
462  errmsg("SELinux: failed to get initial security label: %m")));
463  PG_TRY();
464  {
465  label = pstrdup(unlabeled);
466  }
467  PG_FINALLY();
468  {
469  freecon(unlabeled);
470  }
471  PG_END_TRY();
472  }
473  return label;
474 }
475 
476 /*
477  * sepgsql_object_relabel
478  *
479  * An entrypoint of SECURITY LABEL statement
480  */
481 void
482 sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
483 {
484  /*
485  * validate format of the supplied security label, if it is security
486  * context of selinux.
487  */
488  if (seclabel &&
489  security_check_context_raw(seclabel) < 0)
490  ereport(ERROR,
491  (errcode(ERRCODE_INVALID_NAME),
492  errmsg("SELinux: invalid security label: \"%s\"", seclabel)));
493 
494  /*
495  * Do actual permission checks for each object classes
496  */
497  switch (object->classId)
498  {
499  case DatabaseRelationId:
500  sepgsql_database_relabel(object->objectId, seclabel);
501  break;
502 
503  case NamespaceRelationId:
504  sepgsql_schema_relabel(object->objectId, seclabel);
505  break;
506 
507  case RelationRelationId:
508  if (object->objectSubId == 0)
510  seclabel);
511  else
513  object->objectSubId,
514  seclabel);
515  break;
516 
517  case ProcedureRelationId:
518  sepgsql_proc_relabel(object->objectId, seclabel);
519  break;
520 
521  default:
522  ereport(ERROR,
523  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
524  errmsg("sepgsql provider does not support labels on %s",
525  getObjectTypeDescription(object, false))));
526  break;
527  }
528 }
529 
530 /*
531  * TEXT sepgsql_getcon(VOID)
532  *
533  * It returns the security label of the client.
534  */
536 Datum
538 {
539  char *client_label;
540 
541  if (!sepgsql_is_enabled())
542  PG_RETURN_NULL();
543 
544  client_label = sepgsql_get_client_label();
545 
546  PG_RETURN_TEXT_P(cstring_to_text(client_label));
547 }
548 
549 /*
550  * BOOL sepgsql_setcon(TEXT)
551  *
552  * It switches the security label of the client.
553  */
555 Datum
557 {
558  const char *new_label;
559 
560  if (PG_ARGISNULL(0))
561  new_label = NULL;
562  else
563  new_label = TextDatumGetCString(PG_GETARG_DATUM(0));
564 
565  sepgsql_set_client_label(new_label);
566 
567  PG_RETURN_BOOL(true);
568 }
569 
570 /*
571  * TEXT sepgsql_mcstrans_in(TEXT)
572  *
573  * It translate the given qualified MLS/MCS range into raw format
574  * when mcstrans daemon is working.
575  */
577 Datum
579 {
581  char *raw_label;
582  char *result;
583 
584  if (!sepgsql_is_enabled())
585  ereport(ERROR,
586  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
587  errmsg("sepgsql is not enabled")));
588 
589  if (selinux_trans_to_raw_context(text_to_cstring(label),
590  &raw_label) < 0)
591  ereport(ERROR,
592  (errcode(ERRCODE_INTERNAL_ERROR),
593  errmsg("SELinux: could not translate security label: %m")));
594 
595  PG_TRY();
596  {
597  result = pstrdup(raw_label);
598  }
599  PG_FINALLY();
600  {
601  freecon(raw_label);
602  }
603  PG_END_TRY();
604 
606 }
607 
608 /*
609  * TEXT sepgsql_mcstrans_out(TEXT)
610  *
611  * It translate the given raw MLS/MCS range into qualified format
612  * when mcstrans daemon is working.
613  */
615 Datum
617 {
619  char *qual_label;
620  char *result;
621 
622  if (!sepgsql_is_enabled())
623  ereport(ERROR,
624  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
625  errmsg("sepgsql is not currently enabled")));
626 
627  if (selinux_raw_to_trans_context(text_to_cstring(label),
628  &qual_label) < 0)
629  ereport(ERROR,
630  (errcode(ERRCODE_INTERNAL_ERROR),
631  errmsg("SELinux: could not translate security label: %m")));
632 
633  PG_TRY();
634  {
635  result = pstrdup(qual_label);
636  }
637  PG_FINALLY();
638  {
639  freecon(qual_label);
640  }
641  PG_END_TRY();
642 
644 }
645 
646 /*
647  * quote_object_name
648  *
649  * It tries to quote the supplied identifiers
650  */
651 static char *
652 quote_object_name(const char *src1, const char *src2,
653  const char *src3, const char *src4)
654 {
655  StringInfoData result;
656  const char *temp;
657 
658  initStringInfo(&result);
659 
660  if (src1)
661  {
662  temp = quote_identifier(src1);
663  appendStringInfoString(&result, temp);
664  if (src1 != temp)
665  pfree((void *) temp);
666  }
667  if (src2)
668  {
669  temp = quote_identifier(src2);
670  appendStringInfo(&result, ".%s", temp);
671  if (src2 != temp)
672  pfree((void *) temp);
673  }
674  if (src3)
675  {
676  temp = quote_identifier(src3);
677  appendStringInfo(&result, ".%s", temp);
678  if (src3 != temp)
679  pfree((void *) temp);
680  }
681  if (src4)
682  {
683  temp = quote_identifier(src4);
684  appendStringInfo(&result, ".%s", temp);
685  if (src4 != temp)
686  pfree((void *) temp);
687  }
688  return result.data;
689 }
690 
691 /*
692  * exec_object_restorecon
693  *
694  * This routine is a helper called by sepgsql_restorecon; it set up
695  * initial security labels of database objects within the supplied
696  * catalog OID.
697  */
698 static void
699 exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
700 {
701  Relation rel;
702  SysScanDesc sscan;
703  HeapTuple tuple;
704  char *database_name = get_database_name(MyDatabaseId);
705  char *namespace_name;
706  Oid namespace_id;
707  char *relation_name;
708 
709  /*
710  * Open the target catalog. We don't want to allow writable accesses by
711  * other session during initial labeling.
712  */
713  rel = table_open(catalogId, AccessShareLock);
714 
715  sscan = systable_beginscan(rel, InvalidOid, false,
716  NULL, 0, NULL);
717  while (HeapTupleIsValid(tuple = systable_getnext(sscan)))
718  {
719  Form_pg_database datForm;
720  Form_pg_namespace nspForm;
721  Form_pg_class relForm;
722  Form_pg_attribute attForm;
723  Form_pg_proc proForm;
724  char *objname;
725  int objtype = 1234;
726  ObjectAddress object;
727  char *context;
728 
729  /*
730  * The way to determine object name depends on object classes. So, any
731  * branches set up `objtype', `objname' and `object' here.
732  */
733  switch (catalogId)
734  {
735  case DatabaseRelationId:
736  datForm = (Form_pg_database) GETSTRUCT(tuple);
737 
738  objtype = SELABEL_DB_DATABASE;
739 
740  objname = quote_object_name(NameStr(datForm->datname),
741  NULL, NULL, NULL);
742 
743  object.classId = DatabaseRelationId;
744  object.objectId = datForm->oid;
745  object.objectSubId = 0;
746  break;
747 
748  case NamespaceRelationId:
749  nspForm = (Form_pg_namespace) GETSTRUCT(tuple);
750 
751  objtype = SELABEL_DB_SCHEMA;
752 
753  objname = quote_object_name(database_name,
754  NameStr(nspForm->nspname),
755  NULL, NULL);
756 
757  object.classId = NamespaceRelationId;
758  object.objectId = nspForm->oid;
759  object.objectSubId = 0;
760  break;
761 
762  case RelationRelationId:
763  relForm = (Form_pg_class) GETSTRUCT(tuple);
764 
765  if (relForm->relkind == RELKIND_RELATION ||
766  relForm->relkind == RELKIND_PARTITIONED_TABLE)
767  objtype = SELABEL_DB_TABLE;
768  else if (relForm->relkind == RELKIND_SEQUENCE)
769  objtype = SELABEL_DB_SEQUENCE;
770  else if (relForm->relkind == RELKIND_VIEW)
771  objtype = SELABEL_DB_VIEW;
772  else
773  continue; /* no need to assign security label */
774 
775  namespace_name = get_namespace_name(relForm->relnamespace);
776  objname = quote_object_name(database_name,
777  namespace_name,
778  NameStr(relForm->relname),
779  NULL);
780  pfree(namespace_name);
781 
782  object.classId = RelationRelationId;
783  object.objectId = relForm->oid;
784  object.objectSubId = 0;
785  break;
786 
787  case AttributeRelationId:
788  attForm = (Form_pg_attribute) GETSTRUCT(tuple);
789 
790  if (get_rel_relkind(attForm->attrelid) != RELKIND_RELATION &&
791  get_rel_relkind(attForm->attrelid) != RELKIND_PARTITIONED_TABLE)
792  continue; /* no need to assign security label */
793 
794  objtype = SELABEL_DB_COLUMN;
795 
796  namespace_id = get_rel_namespace(attForm->attrelid);
797  namespace_name = get_namespace_name(namespace_id);
798  relation_name = get_rel_name(attForm->attrelid);
799  objname = quote_object_name(database_name,
800  namespace_name,
801  relation_name,
802  NameStr(attForm->attname));
803  pfree(namespace_name);
804  pfree(relation_name);
805 
806  object.classId = RelationRelationId;
807  object.objectId = attForm->attrelid;
808  object.objectSubId = attForm->attnum;
809  break;
810 
811  case ProcedureRelationId:
812  proForm = (Form_pg_proc) GETSTRUCT(tuple);
813 
814  objtype = SELABEL_DB_PROCEDURE;
815 
816  namespace_name = get_namespace_name(proForm->pronamespace);
817  objname = quote_object_name(database_name,
818  namespace_name,
819  NameStr(proForm->proname),
820  NULL);
821  pfree(namespace_name);
822 
823  object.classId = ProcedureRelationId;
824  object.objectId = proForm->oid;
825  object.objectSubId = 0;
826  break;
827 
828  default:
829  elog(ERROR, "unexpected catalog id: %u", catalogId);
830  objname = NULL; /* for compiler quiet */
831  break;
832  }
833 
834  if (selabel_lookup_raw(sehnd, &context, objname, objtype) == 0)
835  {
836  PG_TRY();
837  {
838  /*
839  * Check SELinux permission to relabel the fetched object,
840  * then do the actual relabeling.
841  */
842  sepgsql_object_relabel(&object, context);
843 
844  SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, context);
845  }
846  PG_FINALLY();
847  {
848  freecon(context);
849  }
850  PG_END_TRY();
851  }
852  else if (errno == ENOENT)
854  (errmsg("SELinux: no initial label assigned for %s (type=%d), skipping",
855  objname, objtype)));
856  else
857  ereport(ERROR,
858  (errcode(ERRCODE_INTERNAL_ERROR),
859  errmsg("SELinux: could not determine initial security label for %s (type=%d): %m", objname, objtype)));
860 
861  pfree(objname);
862  }
863  systable_endscan(sscan);
864 
865  table_close(rel, NoLock);
866 }
867 
868 /*
869  * BOOL sepgsql_restorecon(TEXT specfile)
870  *
871  * This function tries to assign initial security labels on all the object
872  * within the current database, according to the system setting.
873  * It is typically invoked by sepgsql-install script just after initdb, to
874  * assign initial security labels.
875  *
876  * If @specfile is not NULL, it uses explicitly specified specfile, instead
877  * of the system default.
878  */
880 Datum
882 {
883  struct selabel_handle *sehnd;
884  struct selinux_opt seopts;
885 
886  /*
887  * SELinux has to be enabled on the running platform.
888  */
889  if (!sepgsql_is_enabled())
890  ereport(ERROR,
891  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
892  errmsg("sepgsql is not currently enabled")));
893 
894  /*
895  * Check DAC permission. Only superuser can set up initial security
896  * labels, like root-user in filesystems
897  */
898  if (!superuser())
899  ereport(ERROR,
900  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
901  errmsg("SELinux: must be superuser to restore initial contexts")));
902 
903  /*
904  * Open selabel_lookup(3) stuff. It provides a set of mapping between an
905  * initial security label and object class/name due to the system setting.
906  */
907  if (PG_ARGISNULL(0))
908  {
909  seopts.type = SELABEL_OPT_UNUSED;
910  seopts.value = NULL;
911  }
912  else
913  {
914  seopts.type = SELABEL_OPT_PATH;
915  seopts.value = TextDatumGetCString(PG_GETARG_DATUM(0));
916  }
917  sehnd = selabel_open(SELABEL_CTX_DB, &seopts, 1);
918  if (!sehnd)
919  ereport(ERROR,
920  (errcode(ERRCODE_INTERNAL_ERROR),
921  errmsg("SELinux: failed to initialize labeling handle: %m")));
922  PG_TRY();
923  {
924  exec_object_restorecon(sehnd, DatabaseRelationId);
925  exec_object_restorecon(sehnd, NamespaceRelationId);
926  exec_object_restorecon(sehnd, RelationRelationId);
927  exec_object_restorecon(sehnd, AttributeRelationId);
928  exec_object_restorecon(sehnd, ProcedureRelationId);
929  }
930  PG_FINALLY();
931  {
932  selabel_close(sehnd);
933  }
934  PG_END_TRY();
935 
936  PG_RETURN_BOOL(true);
937 }
#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:337
Datum sepgsql_getcon(PG_FUNCTION_ARGS)
Definition: label.c:537
XactEvent
Definition: xact.h:113
Definition: fmgr.h:56
#define SEPG_DB_PROCEDURE__EXECUTE
Definition: sepgsql.h:166
static char * client_label_func
Definition: label.c:64
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
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
MemoryContext fn_mcxt
Definition: fmgr.h:65
void SetSecurityLabel(const ObjectAddress *object, const char *provider, const char *label)
Definition: seclabel.c:401
void sepgsql_schema_relabel(Oid namespaceId, const char *seclabel)
Definition: schema.c:142
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10934
#define SEPG_PROCESS__DYNTRANSITION
Definition: sepgsql.h:60
Datum sepgsql_restorecon(PG_FUNCTION_ARGS)
Definition: label.c:881
Datum sepgsql_mcstrans_in(PG_FUNCTION_ARGS)
Definition: label.c:578
static char * client_label_committed
Definition: label.c:62
void(* fmgr_hook_type)(FmgrHookEventType event, FmgrInfo *flinfo, Datum *arg)
Definition: fmgr.h:768
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:268
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1920
char * pstrdup(const char *in)
Definition: mcxt.c:1187
static void exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
Definition: label.c:699
char * sepgsql_get_label(Oid classId, Oid objectId, int32 subId)
Definition: label.c:445
bool sepgsql_avc_check_perms(const ObjectAddress *tobject, uint16 tclass, uint32 required, const char *audit_name, bool abort_on_violation)
Definition: uavc.c:419
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1869
#define llast(l)
Definition: pg_list.h:194
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
void sepgsql_init_client_label(void)
Definition: label.c:404
MemoryContext CurTransactionContext
Definition: mcxt.c:50
int errcode(int sqlerrcode)
Definition: elog.c:691
Definition: libpq-be.h:120
bool superuser(void)
Definition: superuser.c:46
static void sepgsql_xact_callback(XactEvent event, void *arg)
Definition: label.c:165
uint32 SubTransactionId
Definition: c.h:579
#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:42
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
#define SEPGSQL_AVC_NOAUDIT
Definition: sepgsql.h:256
void sepgsql_database_relabel(Oid databaseId, const char *seclabel)
Definition: database.c:187
signed int int32
Definition: c.h:417
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define SEPG_CLASS_PROCESS
Definition: sepgsql.h:36
#define foreach_delete_current(lst, cell)
Definition: pg_list.h: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:652
void pfree(void *pointer)
Definition: mcxt.c:1057
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
static bool sepgsql_needs_fmgr_hook(Oid functionId)
Definition: label.c:268
#define ERROR
Definition: elog.h:43
bool(* needs_fmgr_hook_type)(Oid fn_oid)
Definition: fmgr.h:766
char * GetSecurityLabel(const ObjectAddress *object, const char *provider)
Definition: seclabel.c:269
#define FATAL
Definition: elog.h:52
char * sepgsql_avc_trusted_proc(Oid functionId)
Definition: uavc.c:444
int sepgsql_set_mode(int new_mode)
Definition: selinux.c:634
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3196
#define NoLock
Definition: lockdefs.h:34
FmgrHookEventType
Definition: fmgr.h:759
#define SEPG_CLASS_DB_PROCEDURE
Definition: sepgsql.h:48
ClientAuthentication_hook_type ClientAuthentication_hook
Definition: auth.c:241
#define SEPGSQL_LABEL_TAG
Definition: sepgsql.h:23
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
Definition: fmgr.h:762
Datum sepgsql_mcstrans_out(PG_FUNCTION_ARGS)
Definition: label.c:616
void(* ClientAuthentication_hook_type)(Port *, int)
Definition: auth.h:26
#define STATUS_OK
Definition: c.h:1166
static void sepgsql_client_auth(Port *port, int status)
Definition: label.c:230
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static int port
Definition: pg_regress.c:92
List * lappend(List *list, void *datum)
Definition: list.c:321
char * label
Definition: label.c:69
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define WARNING
Definition: elog.h:40
SubXactEvent
Definition: xact.h:127
#define PG_FINALLY()
Definition: elog.h:326
#define TextDatumGetCString(d)
Definition: builtins.h:87
static needs_fmgr_hook_type next_needs_fmgr_hook
Definition: label.c:43
void * palloc0(Size size)
Definition: mcxt.c:981
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
uintptr_t Datum
Definition: postgres.h:367
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
Definition: xact.c:3584
static char * label
Oid MyDatabaseId
Definition: globals.c:85
static List * client_label_pending
Definition: label.c:60
PGDLLIMPORT fmgr_hook_type fmgr_hook
Definition: fmgr.c:39
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook
Definition: fmgr.c:38
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:59
#define ereport(elevel,...)
Definition: elog.h:155
#define SEPGSQL_MODE_DEFAULT
Definition: sepgsql.h:28
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
SubTransactionId subid
Definition: label.c:68
#define SEPG_DB_PROCEDURE__ENTRYPOINT
Definition: sepgsql.h:167
bool sepgsql_is_enabled(void)
Definition: selinux.c:616
text * cstring_to_text(const char *s)
Definition: varlena.c:188
static void sepgsql_subxact_callback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
Definition: label.c:204
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:800
#define lfirst(lc)
Definition: pg_list.h:169
#define SEPGSQL_MODE_PERMISSIVE
Definition: sepgsql.h:29
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
void RegisterXactCallback(XactCallback callback, void *arg)
Definition: xact.c:3529
static char * client_label_peer
Definition: label.c:59
void sepgsql_relation_relabel(Oid relOid, const char *seclabel)
Definition: relation.c:564
char * getObjectTypeDescription(const ObjectAddress *object, bool missing_ok)
char * sepgsql_get_client_label(void)
Definition: label.c:80
#define DatumGetPointer(X)
Definition: postgres.h:549
bool sepgsql_get_permissive(void)
Definition: hooks.c:64
Datum sepgsql_setcon(PG_FUNCTION_ARGS)
Definition: label.c:556
#define SEPG_PROCESS__SETCURRENT
Definition: sepgsql.h:61
void sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum, const char *seclabel)
Definition: relation.c:165
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
char * text_to_cstring(const text *t)
Definition: varlena.c:221
static void sepgsql_fmgr_hook(FmgrHookEventType event, FmgrInfo *flinfo, Datum *private)
Definition: label.c:311
void sepgsql_proc_relabel(Oid functionId, const char *seclabel)
Definition: proc.c:198
void sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
Definition: label.c:482
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:902
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1174
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:677
void * arg
Definition: c.h:617
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
static fmgr_hook_type next_fmgr_hook
Definition: label.c:44
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define PG_TRY()
Definition: elog.h:309
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:1845
PG_FUNCTION_INFO_V1(sepgsql_getcon)
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_END_TRY()
Definition: elog.h:334
static void sepgsql_set_client_label(const char *new_label)
Definition: label.c:111