PostgreSQL Source Code: contrib/sepgsql/label.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
12
13#include <selinux/label.h>
14
33#include "utils/fmgroids.h"
38
39
40
41
45
46
47
48
49
50
51
52
53
54
55
56
57
58
61
63
65
66typedef struct
67{
71
72
73
74
75
76
77
78
79char *
81{
82
85
86
88 {
90
91 if (plabel->label)
92 return plabel->label;
93 }
96
97
100}
101
102
103
104
105
106
107
108
109
110static void
112{
113 const char *tcontext;
116
117
118 if (!new_label)
120 else
121 {
122 if (security_check_context_raw(new_label) < 0)
124 (errcode(ERRCODE_INVALID_NAME),
125 errmsg("SELinux: invalid security label: \"%s\"",
126 new_label)));
127 tcontext = new_label;
128 }
129
130
134 NULL,
135 true);
136
140 NULL,
141 true);
142
143
144
145
146
148
151 if (new_label)
154
156}
157
158
159
160
161
162
163
164static void
166{
168 {
170 {
172 char *new_label;
173
174 if (plabel->label)
177 else
178 new_label = NULL;
179
182
184
185
186
187
188
189
191 }
192 }
195}
196
197
198
199
200
201
202
203static void
206{
208
210 {
212 {
214
215 if (plabel->subid == mySubid)
218 }
219 }
220}
221
222
223
224
225
226
227
228
229static void
231{
233 (*next_client_auth_hook) (port, status);
234
235
236
237
238
240 return;
241
242
243
244
247 (errcode(ERRCODE_INTERNAL_ERROR),
248 errmsg("SELinux: unable to get peer label: %m")));
249
250
251
252
253
256 else
258}
259
260
261
262
263
264
265
266
267static bool
269{
271
274 return true;
275
276
277
278
279
280
281
283 return true;
284
285
286
287
288
289
290
291 object.classId = ProcedureRelationId;
292 object.objectId = functionId;
293 object.objectSubId = 0;
299 return true;
300
301 return false;
302}
303
304
305
306
307
308
309
310static void
313{
314 struct
315 {
316 char *old_label;
317 char *new_label;
318 Datum next_private;
319 } *stack;
320
321 switch (event)
322 {
325 if (!stack)
326 {
328
330 stack = palloc(sizeof(*stack));
331 stack->old_label = NULL;
333 stack->next_private = 0;
334
336
337
338
339
340
341
342
343
344
345
346
347 if (stack->new_label)
348 {
350
351 object.classId = ProcedureRelationId;
352 object.objectId = flinfo->fn_oid;
353 object.objectSubId = 0;
358 true);
359
363 NULL, true);
364 }
366 }
367 Assert(!stack->old_label);
368 if (stack->new_label)
369 {
372 }
374 (*next_fmgr_hook) (event, flinfo, &stack->next_private);
375 break;
376
380
382 (*next_fmgr_hook) (event, flinfo, &stack->next_private);
383
384 if (stack->new_label)
385 {
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
399
400
401
402
403void
405{
406
407
408
409
410
411
412
413
414
415
418 (errcode(ERRCODE_INTERNAL_ERROR),
419 errmsg("SELinux: failed to get server security label: %m")));
420
421
424
425
428
431
432
435}
436
437
438
439
440
441
442
443
444char *
446{
449
450 object.classId = classId;
451 object.objectId = objectId;
452 object.objectSubId = subId;
453
455 if ( || security_check_context_raw(label))
456 {
457 char *unlabeled;
458
459 if (security_get_initial_context_raw("unlabeled", &unlabeled) < 0)
461 (errcode(ERRCODE_INTERNAL_ERROR),
462 errmsg("SELinux: failed to get initial security label: %m")));
464 {
466 }
468 {
469 freecon(unlabeled);
470 }
472 }
474}
475
476
477
478
479
480
481void
483{
484
485
486
487
488 if (seclabel &&
489 security_check_context_raw(seclabel) < 0)
491 (errcode(ERRCODE_INVALID_NAME),
492 errmsg("SELinux: invalid security label: \"%s\"", seclabel)));
493
494
495
496
498 {
499 case DatabaseRelationId:
501 break;
502
503 case NamespaceRelationId:
505 break;
506
507 case RelationRelationId:
510 seclabel);
511 else
514 seclabel);
515 break;
516
517 case ProcedureRelationId:
519 break;
520
521 default:
523 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
524 errmsg("sepgsql provider does not support labels on %s",
526 break;
527 }
528}
529
530
531
532
533
534
538{
539 char *client_label;
540
543
545
547}
548
549
550
551
552
553
557{
558 const char *new_label;
559
561 new_label = NULL;
562 else
564
566
568}
569
570
571
572
573
574
575
579{
581 char *raw_label;
582 char *result;
583
586 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
587 errmsg("sepgsql is not enabled")));
588
590 &raw_label) < 0)
592 (errcode(ERRCODE_INTERNAL_ERROR),
593 errmsg("SELinux: could not translate security label: %m")));
594
596 {
597 result = pstrdup(raw_label);
598 }
600 {
601 freecon(raw_label);
602 }
604
606}
607
608
609
610
611
612
613
617{
619 char *qual_label;
620 char *result;
621
624 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
625 errmsg("sepgsql is not currently enabled")));
626
628 &qual_label) < 0)
630 (errcode(ERRCODE_INTERNAL_ERROR),
631 errmsg("SELinux: could not translate security label: %m")));
632
634 {
635 result = pstrdup(qual_label);
636 }
638 {
639 freecon(qual_label);
640 }
642
644}
645
646
647
648
649
650
651
652static char *
654 const char *src3, const char *src4)
655{
657
659 if (src1)
661 if (src2)
663 if (src3)
665 if (src4)
667 return result.data;
668}
669
670
671
672
673
674
675
676
677static void
679{
684 char *namespace_name;
685 Oid namespace_id;
686 char *relation_name;
687
688
689
690
691
693
695 NULL, 0, NULL);
697 {
703 char *objname;
704 int objtype = 1234;
706 char *context;
707
708
709
710
711
712 switch (catalogId)
713 {
714 case DatabaseRelationId:
716
717 objtype = SELABEL_DB_DATABASE;
718
720 NULL, NULL, NULL);
721
722 object.classId = DatabaseRelationId;
723 object.objectId = datForm->oid;
724 object.objectSubId = 0;
725 break;
726
727 case NamespaceRelationId:
729
730 objtype = SELABEL_DB_SCHEMA;
731
733 NameStr(nspForm->nspname),
734 NULL, NULL);
735
736 object.classId = NamespaceRelationId;
737 object.objectId = nspForm->oid;
738 object.objectSubId = 0;
739 break;
740
741 case RelationRelationId:
743
744 if (relForm->relkind == RELKIND_RELATION ||
745 relForm->relkind == RELKIND_PARTITIONED_TABLE)
746 objtype = SELABEL_DB_TABLE;
747 else if (relForm->relkind == RELKIND_SEQUENCE)
748 objtype = SELABEL_DB_SEQUENCE;
749 else if (relForm->relkind == RELKIND_VIEW)
750 objtype = SELABEL_DB_VIEW;
751 else
752 continue;
753
756 namespace_name,
757 NameStr(relForm->relname),
758 NULL);
759 pfree(namespace_name);
760
761 object.classId = RelationRelationId;
762 object.objectId = relForm->oid;
763 object.objectSubId = 0;
764 break;
765
766 case AttributeRelationId:
768
769 if (get_rel_relkind(attForm->attrelid) != RELKIND_RELATION &&
770 get_rel_relkind(attForm->attrelid) != RELKIND_PARTITIONED_TABLE)
771 continue;
772
773 objtype = SELABEL_DB_COLUMN;
774
777 relation_name = get_rel_name(attForm->attrelid);
779 namespace_name,
780 relation_name,
781 NameStr(attForm->attname));
782 pfree(namespace_name);
783 pfree(relation_name);
784
785 object.classId = RelationRelationId;
786 object.objectId = attForm->attrelid;
787 object.objectSubId = attForm->attnum;
788 break;
789
790 case ProcedureRelationId:
792
793 objtype = SELABEL_DB_PROCEDURE;
794
797 namespace_name,
798 NameStr(proForm->proname),
799 NULL);
800 pfree(namespace_name);
801
802 object.classId = ProcedureRelationId;
803 object.objectId = proForm->oid;
804 object.objectSubId = 0;
805 break;
806
807 default:
808 elog(ERROR, "unexpected catalog id: %u", catalogId);
809 objname = NULL;
810 break;
811 }
812
813 if (selabel_lookup_raw(sehnd, &context, objname, objtype) == 0)
814 {
816 {
817
818
819
820
822
824 }
826 {
827 freecon(context);
828 }
830 }
831 else if (errno == ENOENT)
833 (errmsg("SELinux: no initial label assigned for %s (type=%d), skipping",
834 objname, objtype)));
835 else
837 (errcode(ERRCODE_INTERNAL_ERROR),
838 errmsg("SELinux: could not determine initial security label for %s (type=%d): %m", objname, objtype)));
839
841 }
843
845}
846
847
848
849
850
851
852
853
854
855
856
857
861{
862 struct selabel_handle *sehnd;
863 struct selinux_opt seopts;
864
865
866
867
870 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
871 errmsg("sepgsql is not currently enabled")));
872
873
874
875
876
879 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
880 errmsg("SELinux: must be superuser to restore initial contexts")));
881
882
883
884
885
887 {
888 seopts.type = SELABEL_OPT_UNUSED;
889 seopts.value = NULL;
890 }
891 else
892 {
893 seopts.type = SELABEL_OPT_PATH;
895 }
896 sehnd = selabel_open(SELABEL_CTX_DB, &seopts, 1);
897 if (!sehnd)
899 (errcode(ERRCODE_INTERNAL_ERROR),
900 errmsg("SELinux: failed to initialize labeling handle: %m")));
902 {
908 }
910 {
911 selabel_close(sehnd);
912 }
914
916}
ClientAuthentication_hook_type ClientAuthentication_hook
void(* ClientAuthentication_hook_type)(Port *, int)
#define TextDatumGetCString(d)
void sepgsql_proc_relabel(Oid functionId, const char *seclabel)
void sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum, const char *seclabel)
void sepgsql_relation_relabel(Oid relOid, const char *seclabel)
void sepgsql_database_relabel(Oid databaseId, const char *seclabel)
char * get_database_name(Oid dbid)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook
PGDLLIMPORT fmgr_hook_type fmgr_hook
#define PG_GETARG_TEXT_PP(n)
bool(* needs_fmgr_hook_type)(Oid fn_oid)
#define PG_GETARG_DATUM(n)
#define PG_RETURN_TEXT_P(x)
void(* fmgr_hook_type)(FmgrHookEventType event, FmgrInfo *flinfo, Datum *arg)
#define PG_RETURN_BOOL(x)
void systable_endscan(SysScanDesc sysscan)
HeapTuple systable_getnext(SysScanDesc sysscan)
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Assert(PointerIsAligned(start, uint64))
bool sepgsql_get_permissive(void)
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
Datum sepgsql_getcon(PG_FUNCTION_ARGS)
static fmgr_hook_type next_fmgr_hook
static void sepgsql_fmgr_hook(FmgrHookEventType event, FmgrInfo *flinfo, Datum *private)
void sepgsql_init_client_label(void)
static char * client_label_committed
static needs_fmgr_hook_type next_needs_fmgr_hook
static char * quote_object_name(const char *src1, const char *src2, const char *src3, const char *src4)
Datum sepgsql_mcstrans_out(PG_FUNCTION_ARGS)
static void exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
PG_FUNCTION_INFO_V1(sepgsql_getcon)
static char * client_label_peer
static List * client_label_pending
char * sepgsql_get_label(Oid classId, Oid objectId, int32 subId)
void sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
Datum sepgsql_restorecon(PG_FUNCTION_ARGS)
static void sepgsql_subxact_callback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
static void sepgsql_client_auth(Port *port, int status)
static char * client_label_func
char * sepgsql_get_client_label(void)
static void sepgsql_xact_callback(XactEvent event, void *arg)
Datum sepgsql_setcon(PG_FUNCTION_ARGS)
static ClientAuthentication_hook_type next_client_auth_hook
Datum sepgsql_mcstrans_in(PG_FUNCTION_ARGS)
static void sepgsql_set_client_label(const char *new_label)
static bool sepgsql_needs_fmgr_hook(Oid functionId)
List * lappend(List *list, void *datum)
char * get_rel_name(Oid relid)
char get_rel_relkind(Oid relid)
Oid get_rel_namespace(Oid relid)
char * get_namespace_name(Oid nspid)
char * MemoryContextStrdup(MemoryContext context, const char *string)
char * pstrdup(const char *in)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext TopMemoryContext
MemoryContext CurTransactionContext
char * getObjectTypeDescription(const ObjectAddress *object, bool missing_ok)
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
FormData_pg_attribute * Form_pg_attribute
FormData_pg_class * Form_pg_class
FormData_pg_database * Form_pg_database
#define foreach_delete_current(lst, var_or_cell)
FormData_pg_namespace * Form_pg_namespace
FormData_pg_proc * Form_pg_proc
static Datum PointerGetDatum(const void *X)
static Pointer DatumGetPointer(Datum X)
const char * quote_identifier(const char *ident)
void sepgsql_schema_relabel(Oid namespaceId, const char *seclabel)
void SetSecurityLabel(const ObjectAddress *object, const char *provider, const char *label)
char * GetSecurityLabel(const ObjectAddress *object, const char *provider)
int sepgsql_set_mode(int new_mode)
bool sepgsql_is_enabled(void)
char * sepgsql_avc_trusted_proc(Oid functionId)
bool sepgsql_avc_check_perms_label(const char *tcontext, uint16 tclass, uint32 required, const char *audit_name, bool abort_on_violation)
#define SEPG_DB_PROCEDURE__EXECUTE
#define SEPG_PROCESS__SETCURRENT
#define SEPG_PROCESS__TRANSITION
#define SEPG_PROCESS__DYNTRANSITION
#define SEPG_DB_PROCEDURE__ENTRYPOINT
#define SEPG_CLASS_DB_PROCEDURE
#define SEPGSQL_AVC_NOAUDIT
#define SEPGSQL_LABEL_TAG
#define SEPGSQL_MODE_DEFAULT
#define SEPG_CLASS_PROCESS
#define SEPGSQL_MODE_PERMISSIVE
bool sepgsql_avc_check_perms(const ObjectAddress *tobject, uint16 tclass, uint32 required, const char *audit_name, bool abort_on_violation)
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendStringInfoString(StringInfo str, const char *s)
void initStringInfo(StringInfo str)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
text * cstring_to_text(const char *s)
char * text_to_cstring(const text *t)
SubTransactionId GetCurrentSubTransactionId(void)
void RegisterXactCallback(XactCallback callback, void *arg)
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
@ SUBXACT_EVENT_ABORT_SUB