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
32#include "utils/fmgroids.h"
37
38
39
40
44
45
46
47
48
49
50
51
52
53
54
55
56
57
60
62
64
65typedef struct
66{
70
71
72
73
74
75
76
77
78char *
80{
81
84
85
87 {
89
90 if (plabel->label)
91 return plabel->label;
92 }
95
96
99}
100
101
102
103
104
105
106
107
108
109static void
111{
112 const char *tcontext;
115
116
117 if (!new_label)
119 else
120 {
121 if (security_check_context_raw(new_label) < 0)
123 (errcode(ERRCODE_INVALID_NAME),
124 errmsg("SELinux: invalid security label: \"%s\"",
125 new_label)));
126 tcontext = new_label;
127 }
128
129
133 NULL,
134 true);
135
139 NULL,
140 true);
141
142
143
144
145
147
150 if (new_label)
153
155}
156
157
158
159
160
161
162
163static void
165{
167 {
169 {
171 char *new_label;
172
173 if (plabel->label)
176 else
177 new_label = NULL;
178
181
183
184
185
186
187
188
190 }
191 }
194}
195
196
197
198
199
200
201
202static void
205{
207
209 {
211 {
213
214 if (plabel->subid == mySubid)
217 }
218 }
219}
220
221
222
223
224
225
226
227
228static void
230{
232 (*next_client_auth_hook) (port, status);
233
234
235
236
237
239 return;
240
241
242
243
246 (errcode(ERRCODE_INTERNAL_ERROR),
247 errmsg("SELinux: unable to get peer label: %m")));
248
249
250
251
252
255 else
257}
258
259
260
261
262
263
264
265
266static bool
268{
270
273 return true;
274
275
276
277
278
279
280
282 return true;
283
284
285
286
287
288
289
290 object.classId = ProcedureRelationId;
291 object.objectId = functionId;
292 object.objectSubId = 0;
298 return true;
299
300 return false;
301}
302
303
304
305
306
307
308
309static void
312{
313 struct
314 {
315 char *old_label;
316 char *new_label;
317 Datum next_private;
318 } *stack;
319
320 switch (event)
321 {
324 if (!stack)
325 {
327
329 stack = palloc(sizeof(*stack));
330 stack->old_label = NULL;
332 stack->next_private = 0;
333
335
336
337
338
339
340
341
342
343
344
345
346 if (stack->new_label)
347 {
349
350 object.classId = ProcedureRelationId;
351 object.objectId = flinfo->fn_oid;
352 object.objectSubId = 0;
357 true);
358
362 NULL, true);
363 }
365 }
366 Assert(!stack->old_label);
367 if (stack->new_label)
368 {
371 }
373 (*next_fmgr_hook) (event, flinfo, &stack->next_private);
374 break;
375
379
381 (*next_fmgr_hook) (event, flinfo, &stack->next_private);
382
383 if (stack->new_label)
384 {
386 stack->old_label = NULL;
387 }
388 break;
389
390 default:
391 elog(ERROR, "unexpected event type: %d", (int) event);
392 break;
393 }
394}
395
396
397
398
399
400
401
402void
404{
405
406
407
408
409
410
411
412
413
414
417 (errcode(ERRCODE_INTERNAL_ERROR),
418 errmsg("SELinux: failed to get server security label: %m")));
419
420
423
424
427
430
431
434}
435
436
437
438
439
440
441
442
443char *
445{
448
449 object.classId = classId;
450 object.objectId = objectId;
451 object.objectSubId = subId;
452
454 if ( || security_check_context_raw(label))
455 {
456 char *unlabeled;
457
458 if (security_get_initial_context_raw("unlabeled", &unlabeled) < 0)
460 (errcode(ERRCODE_INTERNAL_ERROR),
461 errmsg("SELinux: failed to get initial security label: %m")));
463 {
465 }
467 {
468 freecon(unlabeled);
469 }
471 }
473}
474
475
476
477
478
479
480void
482{
483
484
485
486
487 if (seclabel &&
488 security_check_context_raw(seclabel) < 0)
490 (errcode(ERRCODE_INVALID_NAME),
491 errmsg("SELinux: invalid security label: \"%s\"", seclabel)));
492
493
494
495
497 {
498 case DatabaseRelationId:
500 break;
501
502 case NamespaceRelationId:
504 break;
505
506 case RelationRelationId:
509 seclabel);
510 else
513 seclabel);
514 break;
515
516 case ProcedureRelationId:
518 break;
519
520 default:
522 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
523 errmsg("sepgsql provider does not support labels on %s",
525 break;
526 }
527}
528
529
530
531
532
533
537{
538 char *client_label;
539
542
544
546}
547
548
549
550
551
552
556{
557 const char *new_label;
558
560 new_label = NULL;
561 else
563
565
567}
568
569
570
571
572
573
574
578{
580 char *raw_label;
581 char *result;
582
585 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
586 errmsg("sepgsql is not enabled")));
587
589 &raw_label) < 0)
591 (errcode(ERRCODE_INTERNAL_ERROR),
592 errmsg("SELinux: could not translate security label: %m")));
593
595 {
596 result = pstrdup(raw_label);
597 }
599 {
600 freecon(raw_label);
601 }
603
605}
606
607
608
609
610
611
612
616{
618 char *qual_label;
619 char *result;
620
623 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
624 errmsg("sepgsql is not currently enabled")));
625
627 &qual_label) < 0)
629 (errcode(ERRCODE_INTERNAL_ERROR),
630 errmsg("SELinux: could not translate security label: %m")));
631
633 {
634 result = pstrdup(qual_label);
635 }
637 {
638 freecon(qual_label);
639 }
641
643}
644
645
646
647
648
649
650
651static char *
653 const char *src3, const char *src4)
654{
656
658 if (src1)
660 if (src2)
662 if (src3)
664 if (src4)
666 return result.data;
667}
668
669
670
671
672
673
674
675
676static void
678{
683 char *namespace_name;
684 Oid namespace_id;
685 char *relation_name;
686
687
688
689
690
692
694 NULL, 0, NULL);
696 {
702 char *objname;
703 int objtype = 1234;
705 char *context;
706
707
708
709
710
711 switch (catalogId)
712 {
713 case DatabaseRelationId:
715
716 objtype = SELABEL_DB_DATABASE;
717
719 NULL, NULL, NULL);
720
721 object.classId = DatabaseRelationId;
722 object.objectId = datForm->oid;
723 object.objectSubId = 0;
724 break;
725
726 case NamespaceRelationId:
728
729 objtype = SELABEL_DB_SCHEMA;
730
732 NameStr(nspForm->nspname),
733 NULL, NULL);
734
735 object.classId = NamespaceRelationId;
736 object.objectId = nspForm->oid;
737 object.objectSubId = 0;
738 break;
739
740 case RelationRelationId:
742
743 if (relForm->relkind == RELKIND_RELATION ||
744 relForm->relkind == RELKIND_PARTITIONED_TABLE)
745 objtype = SELABEL_DB_TABLE;
746 else if (relForm->relkind == RELKIND_SEQUENCE)
747 objtype = SELABEL_DB_SEQUENCE;
748 else if (relForm->relkind == RELKIND_VIEW)
749 objtype = SELABEL_DB_VIEW;
750 else
751 continue;
752
755 namespace_name,
756 NameStr(relForm->relname),
757 NULL);
758 pfree(namespace_name);
759
760 object.classId = RelationRelationId;
761 object.objectId = relForm->oid;
762 object.objectSubId = 0;
763 break;
764
765 case AttributeRelationId:
767
768 if (get_rel_relkind(attForm->attrelid) != RELKIND_RELATION &&
769 get_rel_relkind(attForm->attrelid) != RELKIND_PARTITIONED_TABLE)
770 continue;
771
772 objtype = SELABEL_DB_COLUMN;
773
776 relation_name = get_rel_name(attForm->attrelid);
778 namespace_name,
779 relation_name,
780 NameStr(attForm->attname));
781 pfree(namespace_name);
782 pfree(relation_name);
783
784 object.classId = RelationRelationId;
785 object.objectId = attForm->attrelid;
786 object.objectSubId = attForm->attnum;
787 break;
788
789 case ProcedureRelationId:
791
792 objtype = SELABEL_DB_PROCEDURE;
793
796 namespace_name,
797 NameStr(proForm->proname),
798 NULL);
799 pfree(namespace_name);
800
801 object.classId = ProcedureRelationId;
802 object.objectId = proForm->oid;
803 object.objectSubId = 0;
804 break;
805
806 default:
807 elog(ERROR, "unexpected catalog id: %u", catalogId);
808 objname = NULL;
809 break;
810 }
811
812 if (selabel_lookup_raw(sehnd, &context, objname, objtype) == 0)
813 {
815 {
816
817
818
819
821
823 }
825 {
826 freecon(context);
827 }
829 }
830 else if (errno == ENOENT)
832 (errmsg("SELinux: no initial label assigned for %s (type=%d), skipping",
833 objname, objtype)));
834 else
836 (errcode(ERRCODE_INTERNAL_ERROR),
837 errmsg("SELinux: could not determine initial security label for %s (type=%d): %m", objname, objtype)));
838
840 }
842
844}
845
846
847
848
849
850
851
852
853
854
855
856
860{
861 struct selabel_handle *sehnd;
862 struct selinux_opt seopts;
863
864
865
866
869 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
870 errmsg("sepgsql is not currently enabled")));
871
872
873
874
875
878 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
879 errmsg("SELinux: must be superuser to restore initial contexts")));
880
881
882
883
884
886 {
887 seopts.type = SELABEL_OPT_UNUSED;
888 seopts.value = NULL;
889 }
890 else
891 {
892 seopts.type = SELABEL_OPT_PATH;
894 }
895 sehnd = selabel_open(SELABEL_CTX_DB, &seopts, 1);
896 if (!sehnd)
898 (errcode(ERRCODE_INTERNAL_ERROR),
899 errmsg("SELinux: failed to initialize labeling handle: %m")));
901 {
907 }
909 {
910 selabel_close(sehnd);
911 }
913
915}
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)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define palloc0_object(type)
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_database_name(Oid dbid)
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)
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