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