LCOV - code coverage report
Current view: top level - src/backend/commands - seclabel.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 70.0 % 190 133
Test Date: 2026-03-22 08:15:57 Functions: 77.8 % 9 7
Legend: Lines:     hit not hit

            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
      37           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              : 
      64            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
     116           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")));
     134           27 :         if (list_length(label_provider_list) != 1)
     135            0 :             ereport(ERROR,
     136              :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     137              :                      errmsg("must specify provider when multiple security label providers have been loaded")));
     138           27 :         provider = (LabelProvider *) linitial(label_provider_list);
     139              :     }
     140              :     else
     141              :     {
     142           18 :         foreach(lc, label_provider_list)
     143              :         {
     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              : 
     159           33 :     if (!SecLabelSupportsObjectType(stmt->objtype))
     160            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              :      */
     170           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              :      */
     178           33 :     address = get_object_address(stmt->objtype, stmt->object,
     179              :                                  &relation, ShareUpdateExclusiveLock,
     180              :                                  missing_ok);
     181              : 
     182              :     /* Require ownership of the target object. */
     183           30 :     check_object_ownership(GetUserId(), stmt->objtype, address,
     184              :                            stmt->object, relation);
     185              : 
     186              :     /* Perform other integrity checks as needed. */
     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              :              */
     196            1 :             if (relation->rd_rel->relkind != RELKIND_RELATION &&
     197            0 :                 relation->rd_rel->relkind != RELKIND_VIEW &&
     198            0 :                 relation->rd_rel->relkind != RELKIND_MATVIEW &&
     199            0 :                 relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
     200            0 :                 relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
     201            0 :                 relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
     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)));
     207            1 :             break;
     208           26 :         default:
     209           26 :             break;
     210              :     }
     211              : 
     212              :     /* Provider gets control here, may throw ERROR to veto new label. */
     213           27 :     provider->hook(&address, stmt->label);
     214              : 
     215              :     /* Apply new label. */
     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              : 
     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 *
     235            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,
     256            0 :                 CStringGetTextDatum(provider));
     257              : 
     258            0 :     pg_shseclabel = table_open(SharedSecLabelRelationId, AccessShareLock);
     259              : 
     260            0 :     scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId,
     261              :                               criticalSharedRelcachesBuilt, NULL, 3, keys);
     262              : 
     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              : 
     273            0 :     table_close(pg_shseclabel, AccessShareLock);
     274              : 
     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 *
     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. */
     294            0 :     if (IsSharedRelation(object->classId))
     295            0 :         return GetSharedSecurityLabel(object, provider);
     296              : 
     297              :     /* Must be an unshared object, so examine pg_seclabel. */
     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,
     313            0 :                 CStringGetTextDatum(provider));
     314              : 
     315            0 :     pg_seclabel = table_open(SecLabelRelationId, AccessShareLock);
     316              : 
     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              : 
     330            0 :     table_close(pg_seclabel, AccessShareLock);
     331              : 
     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
     340            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);
     357            3 :     values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider);
     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,
     373            3 :                 CStringGetTextDatum(provider));
     374              : 
     375            3 :     pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
     376              : 
     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              :     {
     383            0 :         if (label == NULL)
     384            0 :             CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
     385              :         else
     386              :         {
     387            0 :             replaces[Anum_pg_shseclabel_label - 1] = true;
     388            0 :             newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_shseclabel),
     389              :                                        values, nulls, replaces);
     390            0 :             CatalogTupleUpdate(pg_shseclabel, &oldtup->t_self, newtup);
     391              :         }
     392              :     }
     393            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);
     400            3 :         CatalogTupleInsert(pg_shseclabel, newtup);
     401              :     }
     402              : 
     403            3 :     if (newtup != NULL)
     404            3 :         heap_freetuple(newtup);
     405              : 
     406            3 :     table_close(pg_shseclabel, RowExclusiveLock);
     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
     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. */
     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. */
     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);
     440           20 :     values[Anum_pg_seclabel_provider - 1] = CStringGetTextDatum(provider);
     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,
     460           20 :                 CStringGetTextDatum(provider));
     461              : 
     462           20 :     pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
     463              : 
     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)
     471            0 :             CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
     472              :         else
     473              :         {
     474            3 :             replaces[Anum_pg_seclabel_label - 1] = true;
     475            3 :             newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel),
     476              :                                        values, nulls, replaces);
     477            3 :             CatalogTupleUpdate(pg_seclabel, &oldtup->t_self, newtup);
     478              :         }
     479              :     }
     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);
     487           17 :         CatalogTupleInsert(pg_seclabel, newtup);
     488              :     }
     489              : 
     490              :     /* Update indexes, if necessary */
     491           20 :     if (newtup != NULL)
     492           20 :         heap_freetuple(newtup);
     493              : 
     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
     502         1062 : DeleteSharedSecurityLabel(Oid objectId, Oid classId)
     503              : {
     504              :     Relation    pg_shseclabel;
     505              :     ScanKeyData skey[2];
     506              :     SysScanDesc scan;
     507              :     HeapTuple   oldtup;
     508              : 
     509         1062 :     ScanKeyInit(&skey[0],
     510              :                 Anum_pg_shseclabel_objoid,
     511              :                 BTEqualStrategyNumber, F_OIDEQ,
     512              :                 ObjectIdGetDatum(objectId));
     513         1062 :     ScanKeyInit(&skey[1],
     514              :                 Anum_pg_shseclabel_classoid,
     515              :                 BTEqualStrategyNumber, F_OIDEQ,
     516              :                 ObjectIdGetDatum(classId));
     517              : 
     518         1062 :     pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
     519              : 
     520         1062 :     scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
     521              :                               NULL, 2, skey);
     522         1064 :     while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
     523            2 :         CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
     524         1062 :     systable_endscan(scan);
     525              : 
     526         1062 :     table_close(pg_shseclabel, RowExclusiveLock);
     527         1062 : }
     528              : 
     529              : /*
     530              :  * DeleteSecurityLabel removes all security labels for an object (and any
     531              :  * sub-objects, if applicable).
     532              :  */
     533              : void
     534       143626 : 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       143626 :     if (IsSharedRelation(object->classId))
     544              :     {
     545              :         Assert(object->objectSubId == 0);
     546            4 :         DeleteSharedSecurityLabel(object->objectId, object->classId);
     547            4 :         return;
     548              :     }
     549              : 
     550       143622 :     ScanKeyInit(&skey[0],
     551              :                 Anum_pg_seclabel_objoid,
     552              :                 BTEqualStrategyNumber, F_OIDEQ,
     553       143622 :                 ObjectIdGetDatum(object->objectId));
     554       143622 :     ScanKeyInit(&skey[1],
     555              :                 Anum_pg_seclabel_classoid,
     556              :                 BTEqualStrategyNumber, F_OIDEQ,
     557       143622 :                 ObjectIdGetDatum(object->classId));
     558       143622 :     if (object->objectSubId != 0)
     559              :     {
     560         1384 :         ScanKeyInit(&skey[2],
     561              :                     Anum_pg_seclabel_objsubid,
     562              :                     BTEqualStrategyNumber, F_INT4EQ,
     563         1384 :                     Int32GetDatum(object->objectSubId));
     564         1384 :         nkeys = 3;
     565              :     }
     566              :     else
     567       142238 :         nkeys = 2;
     568              : 
     569       143622 :     pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
     570              : 
     571       143622 :     scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
     572              :                               NULL, nkeys, skey);
     573       143627 :     while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
     574            5 :         CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
     575       143622 :     systable_endscan(scan);
     576              : 
     577       143622 :     table_close(pg_seclabel, RowExclusiveLock);
     578              : }
     579              : 
     580              : void
     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);
     587           15 :     provider = palloc_object(LabelProvider);
     588           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 : }
        

Generated by: LCOV version 2.0-1