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 (label || 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