Age Owner Branch data TLA Line data Source code
1 : : /* -------------------------------------------------------------------------
2 : : *
3 : : * seclabel.c
4 : : * routines to support security label feature.
5 : : *
6 : : * Portions Copyright (c) 1996-2026, 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
2101 peter@eisentraut.org 37 :CBC 33 : SecLabelSupportsObjectType(ObjectType objtype)
38 : : {
39 [ + - - ]: 33 : switch (objtype)
40 : : {
41 : 33 : 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 : 33 : return true;
63 : :
2101 peter@eisentraut.org 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
5648 rhaas@postgresql.org 115 :CBC 59 : ExecSecLabelStmt(SecLabelStmt *stmt)
116 : : {
117 : 59 : LabelProvider *provider = NULL;
118 : : ObjectAddress address;
119 : : Relation relation;
120 : : ListCell *lc;
121 : : bool missing_ok;
122 : :
123 : : /*
124 : : * Find the named label provider, or if none specified, check whether
125 : : * there's exactly one, and if so use it.
126 : : */
127 [ + + ]: 59 : if (stmt->provider == NULL)
128 : : {
129 [ + + ]: 45 : if (label_provider_list == NIL)
130 [ + - ]: 18 : ereport(ERROR,
131 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
132 : : errmsg("no security label providers have been loaded")));
2435 tgl@sss.pgh.pa.us 133 [ - + ]: 27 : if (list_length(label_provider_list) != 1)
5648 rhaas@postgresql.org 134 [ # # ]:UBC 0 : ereport(ERROR,
135 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
136 : : errmsg("must specify provider when multiple security label providers have been loaded")));
5648 rhaas@postgresql.org 137 :CBC 27 : provider = (LabelProvider *) linitial(label_provider_list);
138 : : }
139 : : else
140 : : {
5453 bruce@momjian.us 141 [ + + + + : 16 : foreach(lc, label_provider_list)
+ + ]
142 : : {
5648 rhaas@postgresql.org 143 : 8 : LabelProvider *lp = lfirst(lc);
144 : :
145 [ + + ]: 8 : if (strcmp(stmt->provider, lp->provider_name) == 0)
146 : : {
147 : 6 : provider = lp;
148 : 6 : break;
149 : : }
150 : : }
151 [ + + ]: 14 : if (provider == NULL)
152 [ + - ]: 8 : ereport(ERROR,
153 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
154 : : errmsg("security label provider \"%s\" is not loaded",
155 : : stmt->provider)));
156 : : }
157 : :
2101 peter@eisentraut.org 158 [ - + ]: 33 : if (!SecLabelSupportsObjectType(stmt->objtype))
2101 peter@eisentraut.org 159 [ # # ]:UBC 0 : ereport(ERROR,
160 : : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
161 : : errmsg("security labels are not supported for this type of object")));
162 : :
163 : : /*
164 : : * During binary upgrade, allow nonexistent large objects so that we don't
165 : : * have to create them during schema restoration. pg_upgrade will
166 : : * transfer the contents of pg_largeobject_metadata via COPY or by
167 : : * copying/linking its files from the old cluster later on.
168 : : */
34 nathan@postgresql.or 169 [ + + + - ]:GNC 33 : missing_ok = IsBinaryUpgrade && stmt->objtype == OBJECT_LARGEOBJECT;
170 : :
171 : : /*
172 : : * Translate the parser representation which identifies this object into
173 : : * an ObjectAddress. get_object_address() will throw an error if the
174 : : * object does not exist, and will also acquire a lock on the target to
175 : : * guard against concurrent modifications.
176 : : */
3410 peter_e@gmx.net 177 :CBC 33 : address = get_object_address(stmt->objtype, stmt->object,
178 : : &relation, ShareUpdateExclusiveLock,
179 : : missing_ok);
180 : :
181 : : /* Require ownership of the target object. */
5490 rhaas@postgresql.org 182 : 30 : check_object_ownership(GetUserId(), stmt->objtype, address,
183 : : stmt->object, relation);
184 : :
185 : : /* Perform other integrity checks as needed. */
5648 186 [ + + ]: 27 : switch (stmt->objtype)
187 : : {
188 : 1 : case OBJECT_COLUMN:
189 : :
190 : : /*
191 : : * Allow security labels only on columns of tables, views,
192 : : * materialized views, composite types, and foreign tables (which
193 : : * are the only relkinds for which pg_dump will dump labels).
194 : : */
5490 195 [ - + ]: 1 : if (relation->rd_rel->relkind != RELKIND_RELATION &&
5490 rhaas@postgresql.org 196 [ # # ]:UBC 0 : relation->rd_rel->relkind != RELKIND_VIEW &&
4760 kgrittn@postgresql.o 197 [ # # ]: 0 : relation->rd_rel->relkind != RELKIND_MATVIEW &&
5490 rhaas@postgresql.org 198 [ # # ]: 0 : relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
3385 199 [ # # ]: 0 : relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
200 [ # # ]: 0 : relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
5648 201 [ # # ]: 0 : ereport(ERROR,
202 : : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
203 : : errmsg("cannot set security label on relation \"%s\"",
204 : : RelationGetRelationName(relation)),
205 : : errdetail_relkind_not_supported(relation->rd_rel->relkind)));
5648 rhaas@postgresql.org 206 :CBC 1 : break;
207 : 26 : default:
5490 208 : 26 : break;
209 : : }
210 : :
211 : : /* Provider gets control here, may throw ERROR to veto new label. */
3111 peter_e@gmx.net 212 : 27 : provider->hook(&address, stmt->label);
213 : :
214 : : /* Apply new label. */
5648 rhaas@postgresql.org 215 : 23 : SetSecurityLabel(&address, provider->provider_name, stmt->label);
216 : :
217 : : /*
218 : : * If get_object_address() opened the relation for us, we close it to keep
219 : : * the reference count correct - but we retain any locks acquired by
220 : : * get_object_address() until commit time, to guard against concurrent
221 : : * activity.
222 : : */
223 [ + + ]: 23 : if (relation != NULL)
224 : 7 : relation_close(relation, NoLock);
225 : :
4030 alvherre@alvh.no-ip. 226 : 23 : return address;
227 : : }
228 : :
229 : : /*
230 : : * GetSharedSecurityLabel returns the security label for a shared object for
231 : : * a given provider, or NULL if there is no such label.
232 : : */
233 : : static char *
5352 rhaas@postgresql.org 234 :UBC 0 : GetSharedSecurityLabel(const ObjectAddress *object, const char *provider)
235 : : {
236 : : Relation pg_shseclabel;
237 : : ScanKeyData keys[3];
238 : : SysScanDesc scan;
239 : : HeapTuple tuple;
240 : : Datum datum;
241 : : bool isnull;
242 : 0 : char *seclabel = NULL;
243 : :
244 : 0 : ScanKeyInit(&keys[0],
245 : : Anum_pg_shseclabel_objoid,
246 : : BTEqualStrategyNumber, F_OIDEQ,
247 : 0 : ObjectIdGetDatum(object->objectId));
248 : 0 : ScanKeyInit(&keys[1],
249 : : Anum_pg_shseclabel_classoid,
250 : : BTEqualStrategyNumber, F_OIDEQ,
251 : 0 : ObjectIdGetDatum(object->classId));
252 : 0 : ScanKeyInit(&keys[2],
253 : : Anum_pg_shseclabel_provider,
254 : : BTEqualStrategyNumber, F_TEXTEQ,
3953 tgl@sss.pgh.pa.us 255 : 0 : CStringGetTextDatum(provider));
256 : :
2610 andres@anarazel.de 257 : 0 : pg_shseclabel = table_open(SharedSecLabelRelationId, AccessShareLock);
258 : :
1613 jdavis@postgresql.or 259 : 0 : scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId,
260 : : criticalSharedRelcachesBuilt, NULL, 3, keys);
261 : :
5352 rhaas@postgresql.org 262 : 0 : tuple = systable_getnext(scan);
263 [ # # ]: 0 : if (HeapTupleIsValid(tuple))
264 : : {
265 : 0 : datum = heap_getattr(tuple, Anum_pg_shseclabel_label,
266 : : RelationGetDescr(pg_shseclabel), &isnull);
267 [ # # ]: 0 : if (!isnull)
268 : 0 : seclabel = TextDatumGetCString(datum);
269 : : }
270 : 0 : systable_endscan(scan);
271 : :
2610 andres@anarazel.de 272 : 0 : table_close(pg_shseclabel, AccessShareLock);
273 : :
5352 rhaas@postgresql.org 274 : 0 : return seclabel;
275 : : }
276 : :
277 : : /*
278 : : * GetSecurityLabel returns the security label for a shared or database object
279 : : * for a given provider, or NULL if there is no such label.
280 : : */
281 : : char *
5648 282 : 0 : GetSecurityLabel(const ObjectAddress *object, const char *provider)
283 : : {
284 : : Relation pg_seclabel;
285 : : ScanKeyData keys[4];
286 : : SysScanDesc scan;
287 : : HeapTuple tuple;
288 : : Datum datum;
289 : : bool isnull;
290 : 0 : char *seclabel = NULL;
291 : :
292 : : /* Shared objects have their own security label catalog. */
5352 293 [ # # ]: 0 : if (IsSharedRelation(object->classId))
294 : 0 : return GetSharedSecurityLabel(object, provider);
295 : :
296 : : /* Must be an unshared object, so examine pg_seclabel. */
5648 297 : 0 : ScanKeyInit(&keys[0],
298 : : Anum_pg_seclabel_objoid,
299 : : BTEqualStrategyNumber, F_OIDEQ,
300 : 0 : ObjectIdGetDatum(object->objectId));
301 : 0 : ScanKeyInit(&keys[1],
302 : : Anum_pg_seclabel_classoid,
303 : : BTEqualStrategyNumber, F_OIDEQ,
304 : 0 : ObjectIdGetDatum(object->classId));
305 : 0 : ScanKeyInit(&keys[2],
306 : : Anum_pg_seclabel_objsubid,
307 : : BTEqualStrategyNumber, F_INT4EQ,
308 : 0 : Int32GetDatum(object->objectSubId));
309 : 0 : ScanKeyInit(&keys[3],
310 : : Anum_pg_seclabel_provider,
311 : : BTEqualStrategyNumber, F_TEXTEQ,
3953 tgl@sss.pgh.pa.us 312 : 0 : CStringGetTextDatum(provider));
313 : :
2610 andres@anarazel.de 314 : 0 : pg_seclabel = table_open(SecLabelRelationId, AccessShareLock);
315 : :
5648 rhaas@postgresql.org 316 : 0 : scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
317 : : NULL, 4, keys);
318 : :
319 : 0 : tuple = systable_getnext(scan);
320 [ # # ]: 0 : if (HeapTupleIsValid(tuple))
321 : : {
322 : 0 : datum = heap_getattr(tuple, Anum_pg_seclabel_label,
323 : : RelationGetDescr(pg_seclabel), &isnull);
324 [ # # ]: 0 : if (!isnull)
325 : 0 : seclabel = TextDatumGetCString(datum);
326 : : }
327 : 0 : systable_endscan(scan);
328 : :
2610 andres@anarazel.de 329 : 0 : table_close(pg_seclabel, AccessShareLock);
330 : :
5648 rhaas@postgresql.org 331 : 0 : return seclabel;
332 : : }
333 : :
334 : : /*
335 : : * SetSharedSecurityLabel is a helper function of SetSecurityLabel to
336 : : * handle shared database objects.
337 : : */
338 : : static void
5352 rhaas@postgresql.org 339 :CBC 3 : SetSharedSecurityLabel(const ObjectAddress *object,
340 : : const char *provider, const char *label)
341 : : {
342 : : Relation pg_shseclabel;
343 : : ScanKeyData keys[4];
344 : : SysScanDesc scan;
345 : : HeapTuple oldtup;
346 : 3 : HeapTuple newtup = NULL;
347 : : Datum values[Natts_pg_shseclabel];
348 : : bool nulls[Natts_pg_shseclabel];
349 : : bool replaces[Natts_pg_shseclabel];
350 : :
351 : : /* Prepare to form or update a tuple, if necessary. */
352 : 3 : memset(nulls, false, sizeof(nulls));
353 : 3 : memset(replaces, false, sizeof(replaces));
354 : 3 : values[Anum_pg_shseclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
355 : 3 : values[Anum_pg_shseclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
3953 tgl@sss.pgh.pa.us 356 : 3 : values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider);
5352 rhaas@postgresql.org 357 [ + - ]: 3 : if (label != NULL)
358 : 3 : values[Anum_pg_shseclabel_label - 1] = CStringGetTextDatum(label);
359 : :
360 : : /* Use the index to search for a matching old tuple */
361 : 3 : ScanKeyInit(&keys[0],
362 : : Anum_pg_shseclabel_objoid,
363 : : BTEqualStrategyNumber, F_OIDEQ,
364 : 3 : ObjectIdGetDatum(object->objectId));
365 : 3 : ScanKeyInit(&keys[1],
366 : : Anum_pg_shseclabel_classoid,
367 : : BTEqualStrategyNumber, F_OIDEQ,
368 : 3 : ObjectIdGetDatum(object->classId));
369 : 3 : ScanKeyInit(&keys[2],
370 : : Anum_pg_shseclabel_provider,
371 : : BTEqualStrategyNumber, F_TEXTEQ,
3953 tgl@sss.pgh.pa.us 372 : 3 : CStringGetTextDatum(provider));
373 : :
2610 andres@anarazel.de 374 : 3 : pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
375 : :
5352 rhaas@postgresql.org 376 : 3 : scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
377 : : NULL, 3, keys);
378 : :
379 : 3 : oldtup = systable_getnext(scan);
380 [ - + ]: 3 : if (HeapTupleIsValid(oldtup))
381 : : {
5352 rhaas@postgresql.org 382 [ # # ]:UBC 0 : if (label == NULL)
3329 tgl@sss.pgh.pa.us 383 : 0 : CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
384 : : else
385 : : {
5352 rhaas@postgresql.org 386 : 0 : replaces[Anum_pg_shseclabel_label - 1] = true;
387 : 0 : newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_shseclabel),
388 : : values, nulls, replaces);
3330 alvherre@alvh.no-ip. 389 : 0 : CatalogTupleUpdate(pg_shseclabel, &oldtup->t_self, newtup);
390 : : }
391 : : }
5352 rhaas@postgresql.org 392 :CBC 3 : systable_endscan(scan);
393 : :
394 : : /* If we didn't find an old tuple, insert a new one */
395 [ + - + - ]: 3 : if (newtup == NULL && label != NULL)
396 : : {
397 : 3 : newtup = heap_form_tuple(RelationGetDescr(pg_shseclabel),
398 : : values, nulls);
3330 alvherre@alvh.no-ip. 399 : 3 : CatalogTupleInsert(pg_shseclabel, newtup);
400 : : }
401 : :
5352 rhaas@postgresql.org 402 [ + - ]: 3 : if (newtup != NULL)
403 : 3 : heap_freetuple(newtup);
404 : :
2610 andres@anarazel.de 405 : 3 : table_close(pg_shseclabel, RowExclusiveLock);
5352 rhaas@postgresql.org 406 : 3 : }
407 : :
408 : : /*
409 : : * SetSecurityLabel attempts to set the security label for the specified
410 : : * provider on the specified object to the given value. NULL means that any
411 : : * existing label should be deleted.
412 : : */
413 : : void
5648 414 : 23 : SetSecurityLabel(const ObjectAddress *object,
415 : : const char *provider, const char *label)
416 : : {
417 : : Relation pg_seclabel;
418 : : ScanKeyData keys[4];
419 : : SysScanDesc scan;
420 : : HeapTuple oldtup;
421 : 23 : HeapTuple newtup = NULL;
422 : : Datum values[Natts_pg_seclabel];
423 : : bool nulls[Natts_pg_seclabel];
424 : : bool replaces[Natts_pg_seclabel];
425 : :
426 : : /* Shared objects have their own security label catalog. */
5352 427 [ + + ]: 23 : if (IsSharedRelation(object->classId))
428 : : {
429 : 3 : SetSharedSecurityLabel(object, provider, label);
430 : 3 : return;
431 : : }
432 : :
433 : : /* Prepare to form or update a tuple, if necessary. */
5648 434 : 20 : memset(nulls, false, sizeof(nulls));
435 : 20 : memset(replaces, false, sizeof(replaces));
436 : 20 : values[Anum_pg_seclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
437 : 20 : values[Anum_pg_seclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
438 : 20 : values[Anum_pg_seclabel_objsubid - 1] = Int32GetDatum(object->objectSubId);
3953 tgl@sss.pgh.pa.us 439 : 20 : values[Anum_pg_seclabel_provider - 1] = CStringGetTextDatum(provider);
5648 rhaas@postgresql.org 440 [ + - ]: 20 : if (label != NULL)
441 : 20 : values[Anum_pg_seclabel_label - 1] = CStringGetTextDatum(label);
442 : :
443 : : /* Use the index to search for a matching old tuple */
444 : 20 : ScanKeyInit(&keys[0],
445 : : Anum_pg_seclabel_objoid,
446 : : BTEqualStrategyNumber, F_OIDEQ,
447 : 20 : ObjectIdGetDatum(object->objectId));
448 : 20 : ScanKeyInit(&keys[1],
449 : : Anum_pg_seclabel_classoid,
450 : : BTEqualStrategyNumber, F_OIDEQ,
451 : 20 : ObjectIdGetDatum(object->classId));
452 : 20 : ScanKeyInit(&keys[2],
453 : : Anum_pg_seclabel_objsubid,
454 : : BTEqualStrategyNumber, F_INT4EQ,
455 : 20 : Int32GetDatum(object->objectSubId));
456 : 20 : ScanKeyInit(&keys[3],
457 : : Anum_pg_seclabel_provider,
458 : : BTEqualStrategyNumber, F_TEXTEQ,
3953 tgl@sss.pgh.pa.us 459 : 20 : CStringGetTextDatum(provider));
460 : :
2610 andres@anarazel.de 461 : 20 : pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
462 : :
5648 rhaas@postgresql.org 463 : 20 : scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
464 : : NULL, 4, keys);
465 : :
466 : 20 : oldtup = systable_getnext(scan);
467 [ + + ]: 20 : if (HeapTupleIsValid(oldtup))
468 : : {
469 [ - + ]: 3 : if (label == NULL)
3329 tgl@sss.pgh.pa.us 470 :UBC 0 : CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
471 : : else
472 : : {
5648 rhaas@postgresql.org 473 :CBC 3 : replaces[Anum_pg_seclabel_label - 1] = true;
474 : 3 : newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel),
475 : : values, nulls, replaces);
3330 alvherre@alvh.no-ip. 476 : 3 : CatalogTupleUpdate(pg_seclabel, &oldtup->t_self, newtup);
477 : : }
478 : : }
5648 rhaas@postgresql.org 479 : 20 : systable_endscan(scan);
480 : :
481 : : /* If we didn't find an old tuple, insert a new one */
482 [ + + + - ]: 20 : if (newtup == NULL && label != NULL)
483 : : {
484 : 17 : newtup = heap_form_tuple(RelationGetDescr(pg_seclabel),
485 : : values, nulls);
3330 alvherre@alvh.no-ip. 486 : 17 : CatalogTupleInsert(pg_seclabel, newtup);
487 : : }
488 : :
489 : : /* Update indexes, if necessary */
5648 rhaas@postgresql.org 490 [ + - ]: 20 : if (newtup != NULL)
491 : 20 : heap_freetuple(newtup);
492 : :
2610 andres@anarazel.de 493 : 20 : table_close(pg_seclabel, RowExclusiveLock);
494 : : }
495 : :
496 : : /*
497 : : * DeleteSharedSecurityLabel is a helper function of DeleteSecurityLabel
498 : : * to handle shared database objects.
499 : : */
500 : : void
5352 rhaas@postgresql.org 501 : 791 : DeleteSharedSecurityLabel(Oid objectId, Oid classId)
502 : : {
503 : : Relation pg_shseclabel;
504 : : ScanKeyData skey[2];
505 : : SysScanDesc scan;
506 : : HeapTuple oldtup;
507 : :
508 : 791 : ScanKeyInit(&skey[0],
509 : : Anum_pg_shseclabel_objoid,
510 : : BTEqualStrategyNumber, F_OIDEQ,
511 : : ObjectIdGetDatum(objectId));
512 : 791 : ScanKeyInit(&skey[1],
513 : : Anum_pg_shseclabel_classoid,
514 : : BTEqualStrategyNumber, F_OIDEQ,
515 : : ObjectIdGetDatum(classId));
516 : :
2610 andres@anarazel.de 517 : 791 : pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
518 : :
5352 rhaas@postgresql.org 519 : 791 : scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
520 : : NULL, 2, skey);
521 [ + + ]: 793 : while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
3329 tgl@sss.pgh.pa.us 522 : 2 : CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
5352 rhaas@postgresql.org 523 : 791 : systable_endscan(scan);
524 : :
2610 andres@anarazel.de 525 : 791 : table_close(pg_shseclabel, RowExclusiveLock);
5352 rhaas@postgresql.org 526 : 791 : }
527 : :
528 : : /*
529 : : * DeleteSecurityLabel removes all security labels for an object (and any
530 : : * sub-objects, if applicable).
531 : : */
532 : : void
5648 533 : 116695 : DeleteSecurityLabel(const ObjectAddress *object)
534 : : {
535 : : Relation pg_seclabel;
536 : : ScanKeyData skey[3];
537 : : SysScanDesc scan;
538 : : HeapTuple oldtup;
539 : : int nkeys;
540 : :
541 : : /* Shared objects have their own security label catalog. */
542 [ + + ]: 116695 : if (IsSharedRelation(object->classId))
543 : : {
5352 544 [ - + ]: 3 : Assert(object->objectSubId == 0);
545 : 3 : DeleteSharedSecurityLabel(object->objectId, object->classId);
5648 546 : 3 : return;
547 : : }
548 : :
549 : 116692 : ScanKeyInit(&skey[0],
550 : : Anum_pg_seclabel_objoid,
551 : : BTEqualStrategyNumber, F_OIDEQ,
552 : 116692 : ObjectIdGetDatum(object->objectId));
553 : 116692 : ScanKeyInit(&skey[1],
554 : : Anum_pg_seclabel_classoid,
555 : : BTEqualStrategyNumber, F_OIDEQ,
556 : 116692 : ObjectIdGetDatum(object->classId));
557 [ + + ]: 116692 : if (object->objectSubId != 0)
558 : : {
559 : 1070 : ScanKeyInit(&skey[2],
560 : : Anum_pg_seclabel_objsubid,
561 : : BTEqualStrategyNumber, F_INT4EQ,
562 : 1070 : Int32GetDatum(object->objectSubId));
563 : 1070 : nkeys = 3;
564 : : }
565 : : else
566 : 115622 : nkeys = 2;
567 : :
2610 andres@anarazel.de 568 : 116692 : pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
569 : :
5648 rhaas@postgresql.org 570 : 116692 : scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
571 : : NULL, nkeys, skey);
572 [ + + ]: 116697 : while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
3329 tgl@sss.pgh.pa.us 573 : 5 : CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
5648 rhaas@postgresql.org 574 : 116692 : systable_endscan(scan);
575 : :
2610 andres@anarazel.de 576 : 116692 : table_close(pg_seclabel, RowExclusiveLock);
577 : : }
578 : :
579 : : void
5648 rhaas@postgresql.org 580 : 15 : register_label_provider(const char *provider_name, check_object_relabel_type hook)
581 : : {
582 : : LabelProvider *provider;
583 : : MemoryContext oldcxt;
584 : :
585 : 15 : oldcxt = MemoryContextSwitchTo(TopMemoryContext);
95 michael@paquier.xyz 586 :GNC 15 : provider = palloc_object(LabelProvider);
5648 rhaas@postgresql.org 587 :CBC 15 : provider->provider_name = pstrdup(provider_name);
588 : 15 : provider->hook = hook;
589 : 15 : label_provider_list = lappend(label_provider_list, provider);
590 : 15 : MemoryContextSwitchTo(oldcxt);
591 : 15 : }
|