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

Generated by: LCOV version 2.0-1