LCOV - code coverage report
Current view: top level - src/backend/commands - seclabel.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 124 176 70.5 %
Date: 2024-04-24 08:11:43 Functions: 7 9 77.8 %
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-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
      37          48 : SecLabelSupportsObjectType(ObjectType objtype)
      38             : {
      39          48 :     switch (objtype)
      40             :     {
      41          48 :         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          48 :             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_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
     115         100 : ExecSecLabelStmt(SecLabelStmt *stmt)
     116             : {
     117         100 :     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         100 :     if (stmt->provider == NULL)
     127             :     {
     128          80 :         if (label_provider_list == NIL)
     129          36 :             ereport(ERROR,
     130             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     131             :                      errmsg("no security label providers have been loaded")));
     132          44 :         if (list_length(label_provider_list) != 1)
     133           0 :             ereport(ERROR,
     134             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     135             :                      errmsg("must specify provider when multiple security label providers have been loaded")));
     136          44 :         provider = (LabelProvider *) linitial(label_provider_list);
     137             :     }
     138             :     else
     139             :     {
     140          24 :         foreach(lc, label_provider_list)
     141             :         {
     142           8 :             LabelProvider *lp = lfirst(lc);
     143             : 
     144           8 :             if (strcmp(stmt->provider, lp->provider_name) == 0)
     145             :             {
     146           4 :                 provider = lp;
     147           4 :                 break;
     148             :             }
     149             :         }
     150          20 :         if (provider == NULL)
     151          16 :             ereport(ERROR,
     152             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     153             :                      errmsg("security label provider \"%s\" is not loaded",
     154             :                             stmt->provider)));
     155             :     }
     156             : 
     157          48 :     if (!SecLabelSupportsObjectType(stmt->objtype))
     158           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             :      */
     168          48 :     address = get_object_address(stmt->objtype, stmt->object,
     169             :                                  &relation, ShareUpdateExclusiveLock, false);
     170             : 
     171             :     /* Require ownership of the target object. */
     172          42 :     check_object_ownership(GetUserId(), stmt->objtype, address,
     173             :                            stmt->object, relation);
     174             : 
     175             :     /* Perform other integrity checks as needed. */
     176          36 :     switch (stmt->objtype)
     177             :     {
     178           2 :         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             :              */
     185           2 :             if (relation->rd_rel->relkind != RELKIND_RELATION &&
     186           0 :                 relation->rd_rel->relkind != RELKIND_VIEW &&
     187           0 :                 relation->rd_rel->relkind != RELKIND_MATVIEW &&
     188           0 :                 relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
     189           0 :                 relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
     190           0 :                 relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
     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)));
     196           2 :             break;
     197          34 :         default:
     198          34 :             break;
     199             :     }
     200             : 
     201             :     /* Provider gets control here, may throw ERROR to veto new label. */
     202          36 :     provider->hook(&address, stmt->label);
     203             : 
     204             :     /* Apply new label. */
     205          28 :     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          28 :     if (relation != NULL)
     214          14 :         relation_close(relation, NoLock);
     215             : 
     216          28 :     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 *
     224           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             :                 ObjectIdGetDatum(object->objectId));
     238           0 :     ScanKeyInit(&keys[1],
     239             :                 Anum_pg_shseclabel_classoid,
     240             :                 BTEqualStrategyNumber, F_OIDEQ,
     241             :                 ObjectIdGetDatum(object->classId));
     242           0 :     ScanKeyInit(&keys[2],
     243             :                 Anum_pg_shseclabel_provider,
     244             :                 BTEqualStrategyNumber, F_TEXTEQ,
     245           0 :                 CStringGetTextDatum(provider));
     246             : 
     247           0 :     pg_shseclabel = table_open(SharedSecLabelRelationId, AccessShareLock);
     248             : 
     249           0 :     scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId,
     250             :                               criticalSharedRelcachesBuilt, NULL, 3, keys);
     251             : 
     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             : 
     262           0 :     table_close(pg_shseclabel, AccessShareLock);
     263             : 
     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 *
     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. */
     283           0 :     if (IsSharedRelation(object->classId))
     284           0 :         return GetSharedSecurityLabel(object, provider);
     285             : 
     286             :     /* Must be an unshared object, so examine pg_seclabel. */
     287           0 :     ScanKeyInit(&keys[0],
     288             :                 Anum_pg_seclabel_objoid,
     289             :                 BTEqualStrategyNumber, F_OIDEQ,
     290             :                 ObjectIdGetDatum(object->objectId));
     291           0 :     ScanKeyInit(&keys[1],
     292             :                 Anum_pg_seclabel_classoid,
     293             :                 BTEqualStrategyNumber, F_OIDEQ,
     294             :                 ObjectIdGetDatum(object->classId));
     295           0 :     ScanKeyInit(&keys[2],
     296             :                 Anum_pg_seclabel_objsubid,
     297             :                 BTEqualStrategyNumber, F_INT4EQ,
     298             :                 Int32GetDatum(object->objectSubId));
     299           0 :     ScanKeyInit(&keys[3],
     300             :                 Anum_pg_seclabel_provider,
     301             :                 BTEqualStrategyNumber, F_TEXTEQ,
     302           0 :                 CStringGetTextDatum(provider));
     303             : 
     304           0 :     pg_seclabel = table_open(SecLabelRelationId, AccessShareLock);
     305             : 
     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             : 
     319           0 :     table_close(pg_seclabel, AccessShareLock);
     320             : 
     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
     329           6 : 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           6 :     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           6 :     memset(nulls, false, sizeof(nulls));
     343           6 :     memset(replaces, false, sizeof(replaces));
     344           6 :     values[Anum_pg_shseclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
     345           6 :     values[Anum_pg_shseclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
     346           6 :     values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider);
     347           6 :     if (label != NULL)
     348           6 :         values[Anum_pg_shseclabel_label - 1] = CStringGetTextDatum(label);
     349             : 
     350             :     /* Use the index to search for a matching old tuple */
     351           6 :     ScanKeyInit(&keys[0],
     352             :                 Anum_pg_shseclabel_objoid,
     353             :                 BTEqualStrategyNumber, F_OIDEQ,
     354             :                 ObjectIdGetDatum(object->objectId));
     355           6 :     ScanKeyInit(&keys[1],
     356             :                 Anum_pg_shseclabel_classoid,
     357             :                 BTEqualStrategyNumber, F_OIDEQ,
     358             :                 ObjectIdGetDatum(object->classId));
     359           6 :     ScanKeyInit(&keys[2],
     360             :                 Anum_pg_shseclabel_provider,
     361             :                 BTEqualStrategyNumber, F_TEXTEQ,
     362           6 :                 CStringGetTextDatum(provider));
     363             : 
     364           6 :     pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
     365             : 
     366           6 :     scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
     367             :                               NULL, 3, keys);
     368             : 
     369           6 :     oldtup = systable_getnext(scan);
     370           6 :     if (HeapTupleIsValid(oldtup))
     371             :     {
     372           0 :         if (label == NULL)
     373           0 :             CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
     374             :         else
     375             :         {
     376           0 :             replaces[Anum_pg_shseclabel_label - 1] = true;
     377           0 :             newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_shseclabel),
     378             :                                        values, nulls, replaces);
     379           0 :             CatalogTupleUpdate(pg_shseclabel, &oldtup->t_self, newtup);
     380             :         }
     381             :     }
     382           6 :     systable_endscan(scan);
     383             : 
     384             :     /* If we didn't find an old tuple, insert a new one */
     385           6 :     if (newtup == NULL && label != NULL)
     386             :     {
     387           6 :         newtup = heap_form_tuple(RelationGetDescr(pg_shseclabel),
     388             :                                  values, nulls);
     389           6 :         CatalogTupleInsert(pg_shseclabel, newtup);
     390             :     }
     391             : 
     392           6 :     if (newtup != NULL)
     393           6 :         heap_freetuple(newtup);
     394             : 
     395           6 :     table_close(pg_shseclabel, RowExclusiveLock);
     396           6 : }
     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
     404          28 : 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          28 :     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. */
     417          28 :     if (IsSharedRelation(object->classId))
     418             :     {
     419           6 :         SetSharedSecurityLabel(object, provider, label);
     420           6 :         return;
     421             :     }
     422             : 
     423             :     /* Prepare to form or update a tuple, if necessary. */
     424          22 :     memset(nulls, false, sizeof(nulls));
     425          22 :     memset(replaces, false, sizeof(replaces));
     426          22 :     values[Anum_pg_seclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
     427          22 :     values[Anum_pg_seclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
     428          22 :     values[Anum_pg_seclabel_objsubid - 1] = Int32GetDatum(object->objectSubId);
     429          22 :     values[Anum_pg_seclabel_provider - 1] = CStringGetTextDatum(provider);
     430          22 :     if (label != NULL)
     431          22 :         values[Anum_pg_seclabel_label - 1] = CStringGetTextDatum(label);
     432             : 
     433             :     /* Use the index to search for a matching old tuple */
     434          22 :     ScanKeyInit(&keys[0],
     435             :                 Anum_pg_seclabel_objoid,
     436             :                 BTEqualStrategyNumber, F_OIDEQ,
     437             :                 ObjectIdGetDatum(object->objectId));
     438          22 :     ScanKeyInit(&keys[1],
     439             :                 Anum_pg_seclabel_classoid,
     440             :                 BTEqualStrategyNumber, F_OIDEQ,
     441             :                 ObjectIdGetDatum(object->classId));
     442          22 :     ScanKeyInit(&keys[2],
     443             :                 Anum_pg_seclabel_objsubid,
     444             :                 BTEqualStrategyNumber, F_INT4EQ,
     445             :                 Int32GetDatum(object->objectSubId));
     446          22 :     ScanKeyInit(&keys[3],
     447             :                 Anum_pg_seclabel_provider,
     448             :                 BTEqualStrategyNumber, F_TEXTEQ,
     449          22 :                 CStringGetTextDatum(provider));
     450             : 
     451          22 :     pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
     452             : 
     453          22 :     scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
     454             :                               NULL, 4, keys);
     455             : 
     456          22 :     oldtup = systable_getnext(scan);
     457          22 :     if (HeapTupleIsValid(oldtup))
     458             :     {
     459           6 :         if (label == NULL)
     460           0 :             CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
     461             :         else
     462             :         {
     463           6 :             replaces[Anum_pg_seclabel_label - 1] = true;
     464           6 :             newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel),
     465             :                                        values, nulls, replaces);
     466           6 :             CatalogTupleUpdate(pg_seclabel, &oldtup->t_self, newtup);
     467             :         }
     468             :     }
     469          22 :     systable_endscan(scan);
     470             : 
     471             :     /* If we didn't find an old tuple, insert a new one */
     472          22 :     if (newtup == NULL && label != NULL)
     473             :     {
     474          16 :         newtup = heap_form_tuple(RelationGetDescr(pg_seclabel),
     475             :                                  values, nulls);
     476          16 :         CatalogTupleInsert(pg_seclabel, newtup);
     477             :     }
     478             : 
     479             :     /* Update indexes, if necessary */
     480          22 :     if (newtup != NULL)
     481          22 :         heap_freetuple(newtup);
     482             : 
     483          22 :     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
     491        1420 : DeleteSharedSecurityLabel(Oid objectId, Oid classId)
     492             : {
     493             :     Relation    pg_shseclabel;
     494             :     ScanKeyData skey[2];
     495             :     SysScanDesc scan;
     496             :     HeapTuple   oldtup;
     497             : 
     498        1420 :     ScanKeyInit(&skey[0],
     499             :                 Anum_pg_shseclabel_objoid,
     500             :                 BTEqualStrategyNumber, F_OIDEQ,
     501             :                 ObjectIdGetDatum(objectId));
     502        1420 :     ScanKeyInit(&skey[1],
     503             :                 Anum_pg_shseclabel_classoid,
     504             :                 BTEqualStrategyNumber, F_OIDEQ,
     505             :                 ObjectIdGetDatum(classId));
     506             : 
     507        1420 :     pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
     508             : 
     509        1420 :     scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
     510             :                               NULL, 2, skey);
     511        1424 :     while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
     512           4 :         CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
     513        1420 :     systable_endscan(scan);
     514             : 
     515        1420 :     table_close(pg_shseclabel, RowExclusiveLock);
     516        1420 : }
     517             : 
     518             : /*
     519             :  * DeleteSecurityLabel removes all security labels for an object (and any
     520             :  * sub-objects, if applicable).
     521             :  */
     522             : void
     523      184608 : 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      184608 :     if (IsSharedRelation(object->classId))
     533             :     {
     534             :         Assert(object->objectSubId == 0);
     535           6 :         DeleteSharedSecurityLabel(object->objectId, object->classId);
     536           6 :         return;
     537             :     }
     538             : 
     539      184602 :     ScanKeyInit(&skey[0],
     540             :                 Anum_pg_seclabel_objoid,
     541             :                 BTEqualStrategyNumber, F_OIDEQ,
     542             :                 ObjectIdGetDatum(object->objectId));
     543      184602 :     ScanKeyInit(&skey[1],
     544             :                 Anum_pg_seclabel_classoid,
     545             :                 BTEqualStrategyNumber, F_OIDEQ,
     546             :                 ObjectIdGetDatum(object->classId));
     547      184602 :     if (object->objectSubId != 0)
     548             :     {
     549        2028 :         ScanKeyInit(&skey[2],
     550             :                     Anum_pg_seclabel_objsubid,
     551             :                     BTEqualStrategyNumber, F_INT4EQ,
     552             :                     Int32GetDatum(object->objectSubId));
     553        2028 :         nkeys = 3;
     554             :     }
     555             :     else
     556      182574 :         nkeys = 2;
     557             : 
     558      184602 :     pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
     559             : 
     560      184602 :     scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
     561             :                               NULL, nkeys, skey);
     562      184612 :     while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
     563          10 :         CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
     564      184602 :     systable_endscan(scan);
     565             : 
     566      184602 :     table_close(pg_seclabel, RowExclusiveLock);
     567             : }
     568             : 
     569             : void
     570           2 : register_label_provider(const char *provider_name, check_object_relabel_type hook)
     571             : {
     572             :     LabelProvider *provider;
     573             :     MemoryContext oldcxt;
     574             : 
     575           2 :     oldcxt = MemoryContextSwitchTo(TopMemoryContext);
     576           2 :     provider = palloc(sizeof(LabelProvider));
     577           2 :     provider->provider_name = pstrdup(provider_name);
     578           2 :     provider->hook = hook;
     579           2 :     label_provider_list = lappend(label_provider_list, provider);
     580           2 :     MemoryContextSwitchTo(oldcxt);
     581           2 : }

Generated by: LCOV version 1.14