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-2024, 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
1401 peter@eisentraut.org 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 : :
1401 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
4948 rhaas@postgresql.org 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")));
1735 tgl@sss.pgh.pa.us 132 [ - + ]: 22 : if (list_length(label_provider_list) != 1)
4948 rhaas@postgresql.org 133 [ # # ]:UBC 0 : ereport(ERROR,
134 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
135 : : errmsg("must specify provider when multiple security label providers have been loaded")));
4948 rhaas@postgresql.org 136 :CBC 22 : provider = (LabelProvider *) linitial(label_provider_list);
137 : : }
138 : : else
139 : : {
4753 bruce@momjian.us 140 [ + + + + : 12 : foreach(lc, label_provider_list)
+ + ]
141 : : {
4948 rhaas@postgresql.org 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 : :
1401 peter@eisentraut.org 157 [ - + ]: 24 : if (!SecLabelSupportsObjectType(stmt->objtype))
1401 peter@eisentraut.org 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 : : */
2710 peter_e@gmx.net 168 :CBC 24 : address = get_object_address(stmt->objtype, stmt->object,
169 : : &relation, ShareUpdateExclusiveLock, false);
170 : :
171 : : /* Require ownership of the target object. */
4790 rhaas@postgresql.org 172 : 21 : check_object_ownership(GetUserId(), stmt->objtype, address,
173 : : stmt->object, relation);
174 : :
175 : : /* Perform other integrity checks as needed. */
4948 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 : : */
4790 185 [ - + ]: 1 : if (relation->rd_rel->relkind != RELKIND_RELATION &&
4790 rhaas@postgresql.org 186 [ # # ]:UBC 0 : relation->rd_rel->relkind != RELKIND_VIEW &&
4060 kgrittn@postgresql.o 187 [ # # ]: 0 : relation->rd_rel->relkind != RELKIND_MATVIEW &&
4790 rhaas@postgresql.org 188 [ # # ]: 0 : relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
2685 189 [ # # ]: 0 : relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
190 [ # # ]: 0 : relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
4948 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)));
4948 rhaas@postgresql.org 196 :CBC 1 : break;
197 : 17 : default:
4790 198 : 17 : break;
199 : : }
200 : :
201 : : /* Provider gets control here, may throw ERROR to veto new label. */
2411 peter_e@gmx.net 202 : 18 : provider->hook(&address, stmt->label);
203 : :
204 : : /* Apply new label. */
4948 rhaas@postgresql.org 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 : :
3330 alvherre@alvh.no-ip. 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 *
4652 rhaas@postgresql.org 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,
3253 tgl@sss.pgh.pa.us 245 : 0 : CStringGetTextDatum(provider));
246 : :
1910 andres@anarazel.de 247 : 0 : pg_shseclabel = table_open(SharedSecLabelRelationId, AccessShareLock);
248 : :
913 jdavis@postgresql.or 249 : 0 : scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId,
250 : : criticalSharedRelcachesBuilt, NULL, 3, keys);
251 : :
4652 rhaas@postgresql.org 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 : :
1910 andres@anarazel.de 262 : 0 : table_close(pg_shseclabel, AccessShareLock);
263 : :
4652 rhaas@postgresql.org 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 *
4948 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. */
4652 283 [ # # ]: 0 : if (IsSharedRelation(object->classId))
284 : 0 : return GetSharedSecurityLabel(object, provider);
285 : :
286 : : /* Must be an unshared object, so examine pg_seclabel. */
4948 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,
3253 tgl@sss.pgh.pa.us 302 : 0 : CStringGetTextDatum(provider));
303 : :
1910 andres@anarazel.de 304 : 0 : pg_seclabel = table_open(SecLabelRelationId, AccessShareLock);
305 : :
4948 rhaas@postgresql.org 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 : :
1910 andres@anarazel.de 319 : 0 : table_close(pg_seclabel, AccessShareLock);
320 : :
4948 rhaas@postgresql.org 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
4652 rhaas@postgresql.org 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);
3253 tgl@sss.pgh.pa.us 346 : 3 : values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider);
4652 rhaas@postgresql.org 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,
3253 tgl@sss.pgh.pa.us 362 : 3 : CStringGetTextDatum(provider));
363 : :
1910 andres@anarazel.de 364 : 3 : pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
365 : :
4652 rhaas@postgresql.org 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 : : {
4652 rhaas@postgresql.org 372 [ # # ]:UBC 0 : if (label == NULL)
2629 tgl@sss.pgh.pa.us 373 : 0 : CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
374 : : else
375 : : {
4652 rhaas@postgresql.org 376 : 0 : replaces[Anum_pg_shseclabel_label - 1] = true;
377 : 0 : newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_shseclabel),
378 : : values, nulls, replaces);
2630 alvherre@alvh.no-ip. 379 : 0 : CatalogTupleUpdate(pg_shseclabel, &oldtup->t_self, newtup);
380 : : }
381 : : }
4652 rhaas@postgresql.org 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);
2630 alvherre@alvh.no-ip. 389 : 3 : CatalogTupleInsert(pg_shseclabel, newtup);
390 : : }
391 : :
4652 rhaas@postgresql.org 392 [ + - ]: 3 : if (newtup != NULL)
393 : 3 : heap_freetuple(newtup);
394 : :
1910 andres@anarazel.de 395 : 3 : table_close(pg_shseclabel, RowExclusiveLock);
4652 rhaas@postgresql.org 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
4948 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. */
4652 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. */
4948 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);
3253 tgl@sss.pgh.pa.us 429 : 11 : values[Anum_pg_seclabel_provider - 1] = CStringGetTextDatum(provider);
4948 rhaas@postgresql.org 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,
3253 tgl@sss.pgh.pa.us 449 : 11 : CStringGetTextDatum(provider));
450 : :
1910 andres@anarazel.de 451 : 11 : pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
452 : :
4948 rhaas@postgresql.org 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)
2629 tgl@sss.pgh.pa.us 460 :UBC 0 : CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
461 : : else
462 : : {
4948 rhaas@postgresql.org 463 :CBC 3 : replaces[Anum_pg_seclabel_label - 1] = true;
464 : 3 : newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel),
465 : : values, nulls, replaces);
2630 alvherre@alvh.no-ip. 466 : 3 : CatalogTupleUpdate(pg_seclabel, &oldtup->t_self, newtup);
467 : : }
468 : : }
4948 rhaas@postgresql.org 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);
2630 alvherre@alvh.no-ip. 476 : 8 : CatalogTupleInsert(pg_seclabel, newtup);
477 : : }
478 : :
479 : : /* Update indexes, if necessary */
4948 rhaas@postgresql.org 480 [ + - ]: 11 : if (newtup != NULL)
481 : 11 : heap_freetuple(newtup);
482 : :
1910 andres@anarazel.de 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
4652 rhaas@postgresql.org 491 : 709 : DeleteSharedSecurityLabel(Oid objectId, Oid classId)
492 : : {
493 : : Relation pg_shseclabel;
494 : : ScanKeyData skey[2];
495 : : SysScanDesc scan;
496 : : HeapTuple oldtup;
497 : :
498 : 709 : ScanKeyInit(&skey[0],
499 : : Anum_pg_shseclabel_objoid,
500 : : BTEqualStrategyNumber, F_OIDEQ,
501 : : ObjectIdGetDatum(objectId));
502 : 709 : ScanKeyInit(&skey[1],
503 : : Anum_pg_shseclabel_classoid,
504 : : BTEqualStrategyNumber, F_OIDEQ,
505 : : ObjectIdGetDatum(classId));
506 : :
1910 andres@anarazel.de 507 : 709 : pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
508 : :
4652 rhaas@postgresql.org 509 : 709 : scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
510 : : NULL, 2, skey);
511 [ + + ]: 711 : while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
2629 tgl@sss.pgh.pa.us 512 : 2 : CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
4652 rhaas@postgresql.org 513 : 709 : systable_endscan(scan);
514 : :
1910 andres@anarazel.de 515 : 709 : table_close(pg_shseclabel, RowExclusiveLock);
4652 rhaas@postgresql.org 516 : 709 : }
517 : :
518 : : /*
519 : : * DeleteSecurityLabel removes all security labels for an object (and any
520 : : * sub-objects, if applicable).
521 : : */
522 : : void
4948 523 : 91813 : 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 [ + + ]: 91813 : if (IsSharedRelation(object->classId))
533 : : {
4652 534 [ - + ]: 3 : Assert(object->objectSubId == 0);
535 : 3 : DeleteSharedSecurityLabel(object->objectId, object->classId);
4948 536 : 3 : return;
537 : : }
538 : :
539 : 91810 : ScanKeyInit(&skey[0],
540 : : Anum_pg_seclabel_objoid,
541 : : BTEqualStrategyNumber, F_OIDEQ,
542 : 91810 : ObjectIdGetDatum(object->objectId));
543 : 91810 : ScanKeyInit(&skey[1],
544 : : Anum_pg_seclabel_classoid,
545 : : BTEqualStrategyNumber, F_OIDEQ,
546 : 91810 : ObjectIdGetDatum(object->classId));
547 [ + + ]: 91810 : if (object->objectSubId != 0)
548 : : {
549 : 1001 : ScanKeyInit(&skey[2],
550 : : Anum_pg_seclabel_objsubid,
551 : : BTEqualStrategyNumber, F_INT4EQ,
552 : 1001 : Int32GetDatum(object->objectSubId));
553 : 1001 : nkeys = 3;
554 : : }
555 : : else
556 : 90809 : nkeys = 2;
557 : :
1910 andres@anarazel.de 558 : 91810 : pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
559 : :
4948 rhaas@postgresql.org 560 : 91810 : scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
561 : : NULL, nkeys, skey);
562 [ + + ]: 91815 : while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
2629 tgl@sss.pgh.pa.us 563 : 5 : CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
4948 rhaas@postgresql.org 564 : 91810 : systable_endscan(scan);
565 : :
1910 andres@anarazel.de 566 : 91810 : table_close(pg_seclabel, RowExclusiveLock);
567 : : }
568 : :
569 : : void
4948 rhaas@postgresql.org 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 : }
|