Age Owner TLA Line data Source code
1 : /* -------------------------------------------------------------------------
2 : *
3 : * seclabel.c
4 : * routines to support security label feature.
5 : *
6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : * -------------------------------------------------------------------------
10 : */
11 : #include "postgres.h"
12 :
13 : #include "access/genam.h"
14 : #include "access/htup_details.h"
15 : #include "access/relation.h"
16 : #include "access/table.h"
17 : #include "catalog/catalog.h"
18 : #include "catalog/indexing.h"
19 : #include "catalog/pg_seclabel.h"
20 : #include "catalog/pg_shseclabel.h"
21 : #include "commands/seclabel.h"
22 : #include "miscadmin.h"
23 : #include "utils/builtins.h"
24 : #include "utils/fmgroids.h"
25 : #include "utils/memutils.h"
26 : #include "utils/rel.h"
27 :
28 : typedef struct
29 : {
30 : const char *provider_name;
31 : check_object_relabel_type hook;
32 : } LabelProvider;
33 :
34 : static List *label_provider_list = NIL;
35 :
36 : static bool
1030 peter 37 CBC 24 : SecLabelSupportsObjectType(ObjectType objtype)
38 : {
39 24 : switch (objtype)
40 : {
41 24 : case OBJECT_AGGREGATE:
42 : case OBJECT_COLUMN:
43 : case OBJECT_DATABASE:
44 : case OBJECT_DOMAIN:
45 : case OBJECT_EVENT_TRIGGER:
46 : case OBJECT_FOREIGN_TABLE:
47 : case OBJECT_FUNCTION:
48 : case OBJECT_LANGUAGE:
49 : case OBJECT_LARGEOBJECT:
50 : case OBJECT_MATVIEW:
51 : case OBJECT_PROCEDURE:
52 : case OBJECT_PUBLICATION:
53 : case OBJECT_ROLE:
54 : case OBJECT_ROUTINE:
55 : case OBJECT_SCHEMA:
56 : case OBJECT_SEQUENCE:
57 : case OBJECT_SUBSCRIPTION:
58 : case OBJECT_TABLE:
59 : case OBJECT_TABLESPACE:
60 : case OBJECT_TYPE:
61 : case OBJECT_VIEW:
62 24 : return true;
63 :
1030 peter 64 UBC 0 : case OBJECT_ACCESS_METHOD:
65 : case OBJECT_AMOP:
66 : case OBJECT_AMPROC:
67 : case OBJECT_ATTRIBUTE:
68 : case OBJECT_CAST:
69 : case OBJECT_COLLATION:
70 : case OBJECT_CONVERSION:
71 : case OBJECT_DEFAULT:
72 : case OBJECT_DEFACL:
73 : case OBJECT_DOMCONSTRAINT:
74 : case OBJECT_EXTENSION:
75 : case OBJECT_FDW:
76 : case OBJECT_FOREIGN_SERVER:
77 : case OBJECT_INDEX:
78 : case OBJECT_OPCLASS:
79 : case OBJECT_OPERATOR:
80 : case OBJECT_OPFAMILY:
81 : case OBJECT_PARAMETER_ACL:
82 : case OBJECT_POLICY:
83 : case OBJECT_PUBLICATION_NAMESPACE:
84 : case OBJECT_PUBLICATION_REL:
85 : case OBJECT_RULE:
86 : case OBJECT_STATISTIC_EXT:
87 : case OBJECT_TABCONSTRAINT:
88 : case OBJECT_TRANSFORM:
89 : case OBJECT_TRIGGER:
90 : case OBJECT_TSCONFIGURATION:
91 : case OBJECT_TSDICTIONARY:
92 : case OBJECT_TSPARSER:
93 : case OBJECT_TSTEMPLATE:
94 : case OBJECT_USER_MAPPING:
95 0 : return false;
96 :
97 : /*
98 : * There's intentionally no default: case here; we want the
99 : * compiler to warn if a new ObjectType hasn't been handled above.
100 : */
101 : }
102 :
103 : /* Shouldn't get here, but if we do, say "no support" */
104 0 : return false;
105 : }
106 :
107 : /*
108 : * ExecSecLabelStmt --
109 : *
110 : * Apply a security label to a database object.
111 : *
112 : * Returns the ObjectAddress of the object to which the policy was applied.
113 : */
114 : ObjectAddress
4577 rhaas 115 CBC 50 : ExecSecLabelStmt(SecLabelStmt *stmt)
116 : {
117 50 : LabelProvider *provider = NULL;
118 : ObjectAddress address;
119 : Relation relation;
120 : ListCell *lc;
121 :
122 : /*
123 : * Find the named label provider, or if none specified, check whether
124 : * there's exactly one, and if so use it.
125 : */
126 50 : if (stmt->provider == NULL)
127 : {
128 40 : if (label_provider_list == NIL)
129 18 : ereport(ERROR,
130 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
131 : errmsg("no security label providers have been loaded")));
1364 tgl 132 22 : if (list_length(label_provider_list) != 1)
4577 rhaas 133 UBC 0 : ereport(ERROR,
134 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
135 : errmsg("must specify provider when multiple security label providers have been loaded")));
4577 rhaas 136 CBC 22 : provider = (LabelProvider *) linitial(label_provider_list);
137 : }
138 : else
139 : {
4382 bruce 140 12 : foreach(lc, label_provider_list)
141 : {
4577 rhaas 142 4 : LabelProvider *lp = lfirst(lc);
143 :
144 4 : if (strcmp(stmt->provider, lp->provider_name) == 0)
145 : {
146 2 : provider = lp;
147 2 : break;
148 : }
149 : }
150 10 : if (provider == NULL)
151 8 : ereport(ERROR,
152 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
153 : errmsg("security label provider \"%s\" is not loaded",
154 : stmt->provider)));
155 : }
156 :
1030 peter 157 24 : if (!SecLabelSupportsObjectType(stmt->objtype))
1030 peter 158 UBC 0 : ereport(ERROR,
159 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
160 : errmsg("security labels are not supported for this type of object")));
161 :
162 : /*
163 : * Translate the parser representation which identifies this object into
164 : * an ObjectAddress. get_object_address() will throw an error if the
165 : * object does not exist, and will also acquire a lock on the target to
166 : * guard against concurrent modifications.
167 : */
2339 peter_e 168 CBC 24 : address = get_object_address(stmt->objtype, stmt->object,
169 : &relation, ShareUpdateExclusiveLock, false);
170 :
171 : /* Require ownership of the target object. */
4419 rhaas 172 21 : check_object_ownership(GetUserId(), stmt->objtype, address,
173 : stmt->object, relation);
174 :
175 : /* Perform other integrity checks as needed. */
4577 176 18 : switch (stmt->objtype)
177 : {
178 1 : case OBJECT_COLUMN:
179 :
180 : /*
181 : * Allow security labels only on columns of tables, views,
182 : * materialized views, composite types, and foreign tables (which
183 : * are the only relkinds for which pg_dump will dump labels).
184 : */
4419 185 1 : if (relation->rd_rel->relkind != RELKIND_RELATION &&
4419 rhaas 186 UBC 0 : relation->rd_rel->relkind != RELKIND_VIEW &&
3689 kgrittn 187 0 : relation->rd_rel->relkind != RELKIND_MATVIEW &&
4419 rhaas 188 0 : relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
2314 189 0 : relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
190 0 : relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
4577 191 0 : ereport(ERROR,
192 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
193 : errmsg("cannot set security label on relation \"%s\"",
194 : RelationGetRelationName(relation)),
195 : errdetail_relkind_not_supported(relation->rd_rel->relkind)));
4577 rhaas 196 CBC 1 : break;
197 17 : default:
4419 198 17 : break;
199 : }
200 :
201 : /* Provider gets control here, may throw ERROR to veto new label. */
2040 peter_e 202 18 : provider->hook(&address, stmt->label);
203 :
204 : /* Apply new label. */
4577 rhaas 205 14 : SetSecurityLabel(&address, provider->provider_name, stmt->label);
206 :
207 : /*
208 : * If get_object_address() opened the relation for us, we close it to keep
209 : * the reference count correct - but we retain any locks acquired by
210 : * get_object_address() until commit time, to guard against concurrent
211 : * activity.
212 : */
213 14 : if (relation != NULL)
214 7 : relation_close(relation, NoLock);
215 :
2959 alvherre 216 14 : return address;
217 : }
218 :
219 : /*
220 : * GetSharedSecurityLabel returns the security label for a shared object for
221 : * a given provider, or NULL if there is no such label.
222 : */
223 : static char *
4281 rhaas 224 UBC 0 : GetSharedSecurityLabel(const ObjectAddress *object, const char *provider)
225 : {
226 : Relation pg_shseclabel;
227 : ScanKeyData keys[3];
228 : SysScanDesc scan;
229 : HeapTuple tuple;
230 : Datum datum;
231 : bool isnull;
232 0 : char *seclabel = NULL;
233 :
234 0 : ScanKeyInit(&keys[0],
235 : Anum_pg_shseclabel_objoid,
236 : BTEqualStrategyNumber, F_OIDEQ,
237 0 : ObjectIdGetDatum(object->objectId));
238 0 : ScanKeyInit(&keys[1],
239 : Anum_pg_shseclabel_classoid,
240 : BTEqualStrategyNumber, F_OIDEQ,
241 0 : ObjectIdGetDatum(object->classId));
242 0 : ScanKeyInit(&keys[2],
243 : Anum_pg_shseclabel_provider,
244 : BTEqualStrategyNumber, F_TEXTEQ,
2882 tgl 245 0 : CStringGetTextDatum(provider));
246 :
1539 andres 247 0 : pg_shseclabel = table_open(SharedSecLabelRelationId, AccessShareLock);
248 :
542 jdavis 249 0 : scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId,
250 : criticalSharedRelcachesBuilt, NULL, 3, keys);
251 :
4281 rhaas 252 0 : tuple = systable_getnext(scan);
253 0 : if (HeapTupleIsValid(tuple))
254 : {
255 0 : datum = heap_getattr(tuple, Anum_pg_shseclabel_label,
256 : RelationGetDescr(pg_shseclabel), &isnull);
257 0 : if (!isnull)
258 0 : seclabel = TextDatumGetCString(datum);
259 : }
260 0 : systable_endscan(scan);
261 :
1539 andres 262 0 : table_close(pg_shseclabel, AccessShareLock);
263 :
4281 rhaas 264 0 : return seclabel;
265 : }
266 :
267 : /*
268 : * GetSecurityLabel returns the security label for a shared or database object
269 : * for a given provider, or NULL if there is no such label.
270 : */
271 : char *
4577 272 0 : GetSecurityLabel(const ObjectAddress *object, const char *provider)
273 : {
274 : Relation pg_seclabel;
275 : ScanKeyData keys[4];
276 : SysScanDesc scan;
277 : HeapTuple tuple;
278 : Datum datum;
279 : bool isnull;
280 0 : char *seclabel = NULL;
281 :
282 : /* Shared objects have their own security label catalog. */
4281 283 0 : if (IsSharedRelation(object->classId))
284 0 : return GetSharedSecurityLabel(object, provider);
285 :
286 : /* Must be an unshared object, so examine pg_seclabel. */
4577 287 0 : ScanKeyInit(&keys[0],
288 : Anum_pg_seclabel_objoid,
289 : BTEqualStrategyNumber, F_OIDEQ,
290 0 : ObjectIdGetDatum(object->objectId));
291 0 : ScanKeyInit(&keys[1],
292 : Anum_pg_seclabel_classoid,
293 : BTEqualStrategyNumber, F_OIDEQ,
294 0 : ObjectIdGetDatum(object->classId));
295 0 : ScanKeyInit(&keys[2],
296 : Anum_pg_seclabel_objsubid,
297 : BTEqualStrategyNumber, F_INT4EQ,
298 0 : Int32GetDatum(object->objectSubId));
299 0 : ScanKeyInit(&keys[3],
300 : Anum_pg_seclabel_provider,
301 : BTEqualStrategyNumber, F_TEXTEQ,
2882 tgl 302 0 : CStringGetTextDatum(provider));
303 :
1539 andres 304 0 : pg_seclabel = table_open(SecLabelRelationId, AccessShareLock);
305 :
4577 rhaas 306 0 : scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
307 : NULL, 4, keys);
308 :
309 0 : tuple = systable_getnext(scan);
310 0 : if (HeapTupleIsValid(tuple))
311 : {
312 0 : datum = heap_getattr(tuple, Anum_pg_seclabel_label,
313 : RelationGetDescr(pg_seclabel), &isnull);
314 0 : if (!isnull)
315 0 : seclabel = TextDatumGetCString(datum);
316 : }
317 0 : systable_endscan(scan);
318 :
1539 andres 319 0 : table_close(pg_seclabel, AccessShareLock);
320 :
4577 rhaas 321 0 : return seclabel;
322 : }
323 :
324 : /*
325 : * SetSharedSecurityLabel is a helper function of SetSecurityLabel to
326 : * handle shared database objects.
327 : */
328 : static void
4281 rhaas 329 CBC 3 : SetSharedSecurityLabel(const ObjectAddress *object,
330 : const char *provider, const char *label)
331 : {
332 : Relation pg_shseclabel;
333 : ScanKeyData keys[4];
334 : SysScanDesc scan;
335 : HeapTuple oldtup;
336 3 : HeapTuple newtup = NULL;
337 : Datum values[Natts_pg_shseclabel];
338 : bool nulls[Natts_pg_shseclabel];
339 : bool replaces[Natts_pg_shseclabel];
340 :
341 : /* Prepare to form or update a tuple, if necessary. */
342 3 : memset(nulls, false, sizeof(nulls));
343 3 : memset(replaces, false, sizeof(replaces));
344 3 : values[Anum_pg_shseclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
345 3 : values[Anum_pg_shseclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
2882 tgl 346 3 : values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider);
4281 rhaas 347 3 : if (label != NULL)
348 3 : values[Anum_pg_shseclabel_label - 1] = CStringGetTextDatum(label);
349 :
350 : /* Use the index to search for a matching old tuple */
351 3 : ScanKeyInit(&keys[0],
352 : Anum_pg_shseclabel_objoid,
353 : BTEqualStrategyNumber, F_OIDEQ,
354 3 : ObjectIdGetDatum(object->objectId));
355 3 : ScanKeyInit(&keys[1],
356 : Anum_pg_shseclabel_classoid,
357 : BTEqualStrategyNumber, F_OIDEQ,
358 3 : ObjectIdGetDatum(object->classId));
359 3 : ScanKeyInit(&keys[2],
360 : Anum_pg_shseclabel_provider,
361 : BTEqualStrategyNumber, F_TEXTEQ,
2882 tgl 362 3 : CStringGetTextDatum(provider));
363 :
1539 andres 364 3 : pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
365 :
4281 rhaas 366 3 : scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
367 : NULL, 3, keys);
368 :
369 3 : oldtup = systable_getnext(scan);
370 3 : if (HeapTupleIsValid(oldtup))
371 : {
4281 rhaas 372 UBC 0 : if (label == NULL)
2258 tgl 373 0 : CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
374 : else
375 : {
4281 rhaas 376 0 : replaces[Anum_pg_shseclabel_label - 1] = true;
377 0 : newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_shseclabel),
378 : values, nulls, replaces);
2259 alvherre 379 0 : CatalogTupleUpdate(pg_shseclabel, &oldtup->t_self, newtup);
380 : }
381 : }
4281 rhaas 382 CBC 3 : systable_endscan(scan);
383 :
384 : /* If we didn't find an old tuple, insert a new one */
385 3 : if (newtup == NULL && label != NULL)
386 : {
387 3 : newtup = heap_form_tuple(RelationGetDescr(pg_shseclabel),
388 : values, nulls);
2259 alvherre 389 3 : CatalogTupleInsert(pg_shseclabel, newtup);
390 : }
391 :
4281 rhaas 392 3 : if (newtup != NULL)
393 3 : heap_freetuple(newtup);
394 :
1539 andres 395 3 : table_close(pg_shseclabel, RowExclusiveLock);
4281 rhaas 396 3 : }
397 :
398 : /*
399 : * SetSecurityLabel attempts to set the security label for the specified
400 : * provider on the specified object to the given value. NULL means that any
401 : * existing label should be deleted.
402 : */
403 : void
4577 404 14 : SetSecurityLabel(const ObjectAddress *object,
405 : const char *provider, const char *label)
406 : {
407 : Relation pg_seclabel;
408 : ScanKeyData keys[4];
409 : SysScanDesc scan;
410 : HeapTuple oldtup;
411 14 : HeapTuple newtup = NULL;
412 : Datum values[Natts_pg_seclabel];
413 : bool nulls[Natts_pg_seclabel];
414 : bool replaces[Natts_pg_seclabel];
415 :
416 : /* Shared objects have their own security label catalog. */
4281 417 14 : if (IsSharedRelation(object->classId))
418 : {
419 3 : SetSharedSecurityLabel(object, provider, label);
420 3 : return;
421 : }
422 :
423 : /* Prepare to form or update a tuple, if necessary. */
4577 424 11 : memset(nulls, false, sizeof(nulls));
425 11 : memset(replaces, false, sizeof(replaces));
426 11 : values[Anum_pg_seclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
427 11 : values[Anum_pg_seclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
428 11 : values[Anum_pg_seclabel_objsubid - 1] = Int32GetDatum(object->objectSubId);
2882 tgl 429 11 : values[Anum_pg_seclabel_provider - 1] = CStringGetTextDatum(provider);
4577 rhaas 430 11 : if (label != NULL)
431 11 : values[Anum_pg_seclabel_label - 1] = CStringGetTextDatum(label);
432 :
433 : /* Use the index to search for a matching old tuple */
434 11 : ScanKeyInit(&keys[0],
435 : Anum_pg_seclabel_objoid,
436 : BTEqualStrategyNumber, F_OIDEQ,
437 11 : ObjectIdGetDatum(object->objectId));
438 11 : ScanKeyInit(&keys[1],
439 : Anum_pg_seclabel_classoid,
440 : BTEqualStrategyNumber, F_OIDEQ,
441 11 : ObjectIdGetDatum(object->classId));
442 11 : ScanKeyInit(&keys[2],
443 : Anum_pg_seclabel_objsubid,
444 : BTEqualStrategyNumber, F_INT4EQ,
445 11 : Int32GetDatum(object->objectSubId));
446 11 : ScanKeyInit(&keys[3],
447 : Anum_pg_seclabel_provider,
448 : BTEqualStrategyNumber, F_TEXTEQ,
2882 tgl 449 11 : CStringGetTextDatum(provider));
450 :
1539 andres 451 11 : pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
452 :
4577 rhaas 453 11 : scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
454 : NULL, 4, keys);
455 :
456 11 : oldtup = systable_getnext(scan);
457 11 : if (HeapTupleIsValid(oldtup))
458 : {
459 3 : if (label == NULL)
2258 tgl 460 UBC 0 : CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
461 : else
462 : {
4577 rhaas 463 CBC 3 : replaces[Anum_pg_seclabel_label - 1] = true;
464 3 : newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel),
465 : values, nulls, replaces);
2259 alvherre 466 3 : CatalogTupleUpdate(pg_seclabel, &oldtup->t_self, newtup);
467 : }
468 : }
4577 rhaas 469 11 : systable_endscan(scan);
470 :
471 : /* If we didn't find an old tuple, insert a new one */
472 11 : if (newtup == NULL && label != NULL)
473 : {
474 8 : newtup = heap_form_tuple(RelationGetDescr(pg_seclabel),
475 : values, nulls);
2259 alvherre 476 8 : CatalogTupleInsert(pg_seclabel, newtup);
477 : }
478 :
479 : /* Update indexes, if necessary */
4577 rhaas 480 11 : if (newtup != NULL)
481 11 : heap_freetuple(newtup);
482 :
1539 andres 483 11 : table_close(pg_seclabel, RowExclusiveLock);
484 : }
485 :
486 : /*
487 : * DeleteSharedSecurityLabel is a helper function of DeleteSecurityLabel
488 : * to handle shared database objects.
489 : */
490 : void
4281 rhaas 491 669 : DeleteSharedSecurityLabel(Oid objectId, Oid classId)
492 : {
493 : Relation pg_shseclabel;
494 : ScanKeyData skey[2];
495 : SysScanDesc scan;
496 : HeapTuple oldtup;
497 :
498 669 : ScanKeyInit(&skey[0],
499 : Anum_pg_shseclabel_objoid,
500 : BTEqualStrategyNumber, F_OIDEQ,
501 : ObjectIdGetDatum(objectId));
502 669 : ScanKeyInit(&skey[1],
503 : Anum_pg_shseclabel_classoid,
504 : BTEqualStrategyNumber, F_OIDEQ,
505 : ObjectIdGetDatum(classId));
506 :
1539 andres 507 669 : pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
508 :
4281 rhaas 509 669 : scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
510 : NULL, 2, skey);
511 671 : while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
2258 tgl 512 2 : CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
4281 rhaas 513 669 : systable_endscan(scan);
514 :
1539 andres 515 669 : table_close(pg_shseclabel, RowExclusiveLock);
4281 rhaas 516 669 : }
517 :
518 : /*
519 : * DeleteSecurityLabel removes all security labels for an object (and any
520 : * sub-objects, if applicable).
521 : */
522 : void
4577 523 83399 : DeleteSecurityLabel(const ObjectAddress *object)
524 : {
525 : Relation pg_seclabel;
526 : ScanKeyData skey[3];
527 : SysScanDesc scan;
528 : HeapTuple oldtup;
529 : int nkeys;
530 :
531 : /* Shared objects have their own security label catalog. */
532 83399 : if (IsSharedRelation(object->classId))
533 : {
4281 534 3 : Assert(object->objectSubId == 0);
535 3 : DeleteSharedSecurityLabel(object->objectId, object->classId);
4577 536 3 : return;
537 : }
538 :
539 83396 : ScanKeyInit(&skey[0],
540 : Anum_pg_seclabel_objoid,
541 : BTEqualStrategyNumber, F_OIDEQ,
542 83396 : ObjectIdGetDatum(object->objectId));
543 83396 : ScanKeyInit(&skey[1],
544 : Anum_pg_seclabel_classoid,
545 : BTEqualStrategyNumber, F_OIDEQ,
546 83396 : ObjectIdGetDatum(object->classId));
547 83396 : if (object->objectSubId != 0)
548 : {
549 977 : ScanKeyInit(&skey[2],
550 : Anum_pg_seclabel_objsubid,
551 : BTEqualStrategyNumber, F_INT4EQ,
552 977 : Int32GetDatum(object->objectSubId));
553 977 : nkeys = 3;
554 : }
555 : else
556 82419 : nkeys = 2;
557 :
1539 andres 558 83396 : pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
559 :
4577 rhaas 560 83396 : scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
561 : NULL, nkeys, skey);
562 83401 : while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
2258 tgl 563 5 : CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
4577 rhaas 564 83396 : systable_endscan(scan);
565 :
1539 andres 566 83396 : table_close(pg_seclabel, RowExclusiveLock);
567 : }
568 :
569 : void
4577 rhaas 570 1 : register_label_provider(const char *provider_name, check_object_relabel_type hook)
571 : {
572 : LabelProvider *provider;
573 : MemoryContext oldcxt;
574 :
575 1 : oldcxt = MemoryContextSwitchTo(TopMemoryContext);
576 1 : provider = palloc(sizeof(LabelProvider));
577 1 : provider->provider_name = pstrdup(provider_name);
578 1 : provider->hook = hook;
579 1 : label_provider_list = lappend(label_provider_list, provider);
580 1 : MemoryContextSwitchTo(oldcxt);
581 1 : }
|