LCOV - differential code coverage report
Current view: top level - src/backend/commands - seclabel.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 70.0 % 190 133 57 133
Current Date: 2023-04-08 15:15:32 Functions: 77.8 % 9 7 2 7
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /* -------------------------------------------------------------------------
       2                 :  *
       3                 :  * seclabel.c
       4                 :  *    routines to support security label feature.
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, 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 CBC          24 : SecLabelSupportsObjectType(ObjectType objtype)
      38                 : {
      39              24 :     switch (objtype)
      40                 :     {
      41              24 :         case OBJECT_AGGREGATE:
      42                 :         case OBJECT_COLUMN:
      43                 :         case OBJECT_DATABASE:
      44                 :         case OBJECT_DOMAIN:
      45                 :         case OBJECT_EVENT_TRIGGER:
      46                 :         case OBJECT_FOREIGN_TABLE:
      47                 :         case OBJECT_FUNCTION:
      48                 :         case OBJECT_LANGUAGE:
      49                 :         case OBJECT_LARGEOBJECT:
      50                 :         case OBJECT_MATVIEW:
      51                 :         case OBJECT_PROCEDURE:
      52                 :         case OBJECT_PUBLICATION:
      53                 :         case OBJECT_ROLE:
      54                 :         case OBJECT_ROUTINE:
      55                 :         case OBJECT_SCHEMA:
      56                 :         case OBJECT_SEQUENCE:
      57                 :         case OBJECT_SUBSCRIPTION:
      58                 :         case OBJECT_TABLE:
      59                 :         case OBJECT_TABLESPACE:
      60                 :         case OBJECT_TYPE:
      61                 :         case OBJECT_VIEW:
      62              24 :             return true;
      63                 : 
      64 UBC           0 :         case OBJECT_ACCESS_METHOD:
      65                 :         case OBJECT_AMOP:
      66                 :         case OBJECT_AMPROC:
      67                 :         case OBJECT_ATTRIBUTE:
      68                 :         case OBJECT_CAST:
      69                 :         case OBJECT_COLLATION:
      70                 :         case OBJECT_CONVERSION:
      71                 :         case OBJECT_DEFAULT:
      72                 :         case OBJECT_DEFACL:
      73                 :         case OBJECT_DOMCONSTRAINT:
      74                 :         case OBJECT_EXTENSION:
      75                 :         case OBJECT_FDW:
      76                 :         case OBJECT_FOREIGN_SERVER:
      77                 :         case OBJECT_INDEX:
      78                 :         case OBJECT_OPCLASS:
      79                 :         case OBJECT_OPERATOR:
      80                 :         case OBJECT_OPFAMILY:
      81                 :         case OBJECT_PARAMETER_ACL:
      82                 :         case OBJECT_POLICY:
      83                 :         case OBJECT_PUBLICATION_NAMESPACE:
      84                 :         case OBJECT_PUBLICATION_REL:
      85                 :         case OBJECT_RULE:
      86                 :         case OBJECT_STATISTIC_EXT:
      87                 :         case OBJECT_TABCONSTRAINT:
      88                 :         case OBJECT_TRANSFORM:
      89                 :         case OBJECT_TRIGGER:
      90                 :         case OBJECT_TSCONFIGURATION:
      91                 :         case OBJECT_TSDICTIONARY:
      92                 :         case OBJECT_TSPARSER:
      93                 :         case OBJECT_TSTEMPLATE:
      94                 :         case OBJECT_USER_MAPPING:
      95               0 :             return false;
      96                 : 
      97                 :             /*
      98                 :              * There's intentionally no default: case here; we want the
      99                 :              * compiler to warn if a new ObjectType hasn't been handled above.
     100                 :              */
     101                 :     }
     102                 : 
     103                 :     /* Shouldn't get here, but if we do, say "no support" */
     104               0 :     return false;
     105                 : }
     106                 : 
     107                 : /*
     108                 :  * ExecSecLabelStmt --
     109                 :  *
     110                 :  * Apply a security label to a database object.
     111                 :  *
     112                 :  * Returns the ObjectAddress of the object to which the policy was applied.
     113                 :  */
     114                 : ObjectAddress
     115 CBC          50 : ExecSecLabelStmt(SecLabelStmt *stmt)
     116                 : {
     117              50 :     LabelProvider *provider = NULL;
     118                 :     ObjectAddress address;
     119                 :     Relation    relation;
     120                 :     ListCell   *lc;
     121                 : 
     122                 :     /*
     123                 :      * Find the named label provider, or if none specified, check whether
     124                 :      * there's exactly one, and if so use it.
     125                 :      */
     126              50 :     if (stmt->provider == NULL)
     127                 :     {
     128              40 :         if (label_provider_list == NIL)
     129              18 :             ereport(ERROR,
     130                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     131                 :                      errmsg("no security label providers have been loaded")));
     132              22 :         if (list_length(label_provider_list) != 1)
     133 UBC           0 :             ereport(ERROR,
     134                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     135                 :                      errmsg("must specify provider when multiple security label providers have been loaded")));
     136 CBC          22 :         provider = (LabelProvider *) linitial(label_provider_list);
     137                 :     }
     138                 :     else
     139                 :     {
     140              12 :         foreach(lc, label_provider_list)
     141                 :         {
     142               4 :             LabelProvider *lp = lfirst(lc);
     143                 : 
     144               4 :             if (strcmp(stmt->provider, lp->provider_name) == 0)
     145                 :             {
     146               2 :                 provider = lp;
     147               2 :                 break;
     148                 :             }
     149                 :         }
     150              10 :         if (provider == NULL)
     151               8 :             ereport(ERROR,
     152                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     153                 :                      errmsg("security label provider \"%s\" is not loaded",
     154                 :                             stmt->provider)));
     155                 :     }
     156                 : 
     157              24 :     if (!SecLabelSupportsObjectType(stmt->objtype))
     158 UBC           0 :         ereport(ERROR,
     159                 :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
     160                 :                  errmsg("security labels are not supported for this type of object")));
     161                 : 
     162                 :     /*
     163                 :      * Translate the parser representation which identifies this object into
     164                 :      * an ObjectAddress. get_object_address() will throw an error if the
     165                 :      * object does not exist, and will also acquire a lock on the target to
     166                 :      * guard against concurrent modifications.
     167                 :      */
     168 CBC          24 :     address = get_object_address(stmt->objtype, stmt->object,
     169                 :                                  &relation, ShareUpdateExclusiveLock, false);
     170                 : 
     171                 :     /* Require ownership of the target object. */
     172              21 :     check_object_ownership(GetUserId(), stmt->objtype, address,
     173                 :                            stmt->object, relation);
     174                 : 
     175                 :     /* Perform other integrity checks as needed. */
     176              18 :     switch (stmt->objtype)
     177                 :     {
     178               1 :         case OBJECT_COLUMN:
     179                 : 
     180                 :             /*
     181                 :              * Allow security labels only on columns of tables, views,
     182                 :              * materialized views, composite types, and foreign tables (which
     183                 :              * are the only relkinds for which pg_dump will dump labels).
     184                 :              */
     185               1 :             if (relation->rd_rel->relkind != RELKIND_RELATION &&
     186 UBC           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 CBC           1 :             break;
     197              17 :         default:
     198              17 :             break;
     199                 :     }
     200                 : 
     201                 :     /* Provider gets control here, may throw ERROR to veto new label. */
     202              18 :     provider->hook(&address, stmt->label);
     203                 : 
     204                 :     /* Apply new label. */
     205              14 :     SetSecurityLabel(&address, provider->provider_name, stmt->label);
     206                 : 
     207                 :     /*
     208                 :      * If get_object_address() opened the relation for us, we close it to keep
     209                 :      * the reference count correct - but we retain any locks acquired by
     210                 :      * get_object_address() until commit time, to guard against concurrent
     211                 :      * activity.
     212                 :      */
     213              14 :     if (relation != NULL)
     214               7 :         relation_close(relation, NoLock);
     215                 : 
     216              14 :     return address;
     217                 : }
     218                 : 
     219                 : /*
     220                 :  * GetSharedSecurityLabel returns the security label for a shared object for
     221                 :  * a given provider, or NULL if there is no such label.
     222                 :  */
     223                 : static char *
     224 UBC           0 : GetSharedSecurityLabel(const ObjectAddress *object, const char *provider)
     225                 : {
     226                 :     Relation    pg_shseclabel;
     227                 :     ScanKeyData keys[3];
     228                 :     SysScanDesc scan;
     229                 :     HeapTuple   tuple;
     230                 :     Datum       datum;
     231                 :     bool        isnull;
     232               0 :     char       *seclabel = NULL;
     233                 : 
     234               0 :     ScanKeyInit(&keys[0],
     235                 :                 Anum_pg_shseclabel_objoid,
     236                 :                 BTEqualStrategyNumber, F_OIDEQ,
     237               0 :                 ObjectIdGetDatum(object->objectId));
     238               0 :     ScanKeyInit(&keys[1],
     239                 :                 Anum_pg_shseclabel_classoid,
     240                 :                 BTEqualStrategyNumber, F_OIDEQ,
     241               0 :                 ObjectIdGetDatum(object->classId));
     242               0 :     ScanKeyInit(&keys[2],
     243                 :                 Anum_pg_shseclabel_provider,
     244                 :                 BTEqualStrategyNumber, F_TEXTEQ,
     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               0 :                 ObjectIdGetDatum(object->objectId));
     291               0 :     ScanKeyInit(&keys[1],
     292                 :                 Anum_pg_seclabel_classoid,
     293                 :                 BTEqualStrategyNumber, F_OIDEQ,
     294               0 :                 ObjectIdGetDatum(object->classId));
     295               0 :     ScanKeyInit(&keys[2],
     296                 :                 Anum_pg_seclabel_objsubid,
     297                 :                 BTEqualStrategyNumber, F_INT4EQ,
     298               0 :                 Int32GetDatum(object->objectSubId));
     299               0 :     ScanKeyInit(&keys[3],
     300                 :                 Anum_pg_seclabel_provider,
     301                 :                 BTEqualStrategyNumber, F_TEXTEQ,
     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 CBC           3 : SetSharedSecurityLabel(const ObjectAddress *object,
     330                 :                        const char *provider, const char *label)
     331                 : {
     332                 :     Relation    pg_shseclabel;
     333                 :     ScanKeyData keys[4];
     334                 :     SysScanDesc scan;
     335                 :     HeapTuple   oldtup;
     336               3 :     HeapTuple   newtup = NULL;
     337                 :     Datum       values[Natts_pg_shseclabel];
     338                 :     bool        nulls[Natts_pg_shseclabel];
     339                 :     bool        replaces[Natts_pg_shseclabel];
     340                 : 
     341                 :     /* Prepare to form or update a tuple, if necessary. */
     342               3 :     memset(nulls, false, sizeof(nulls));
     343               3 :     memset(replaces, false, sizeof(replaces));
     344               3 :     values[Anum_pg_shseclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
     345               3 :     values[Anum_pg_shseclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
     346               3 :     values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider);
     347               3 :     if (label != NULL)
     348               3 :         values[Anum_pg_shseclabel_label - 1] = CStringGetTextDatum(label);
     349                 : 
     350                 :     /* Use the index to search for a matching old tuple */
     351               3 :     ScanKeyInit(&keys[0],
     352                 :                 Anum_pg_shseclabel_objoid,
     353                 :                 BTEqualStrategyNumber, F_OIDEQ,
     354               3 :                 ObjectIdGetDatum(object->objectId));
     355               3 :     ScanKeyInit(&keys[1],
     356                 :                 Anum_pg_shseclabel_classoid,
     357                 :                 BTEqualStrategyNumber, F_OIDEQ,
     358               3 :                 ObjectIdGetDatum(object->classId));
     359               3 :     ScanKeyInit(&keys[2],
     360                 :                 Anum_pg_shseclabel_provider,
     361                 :                 BTEqualStrategyNumber, F_TEXTEQ,
     362               3 :                 CStringGetTextDatum(provider));
     363                 : 
     364               3 :     pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
     365                 : 
     366               3 :     scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
     367                 :                               NULL, 3, keys);
     368                 : 
     369               3 :     oldtup = systable_getnext(scan);
     370               3 :     if (HeapTupleIsValid(oldtup))
     371                 :     {
     372 UBC           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 CBC           3 :     systable_endscan(scan);
     383                 : 
     384                 :     /* If we didn't find an old tuple, insert a new one */
     385               3 :     if (newtup == NULL && label != NULL)
     386                 :     {
     387               3 :         newtup = heap_form_tuple(RelationGetDescr(pg_shseclabel),
     388                 :                                  values, nulls);
     389               3 :         CatalogTupleInsert(pg_shseclabel, newtup);
     390                 :     }
     391                 : 
     392               3 :     if (newtup != NULL)
     393               3 :         heap_freetuple(newtup);
     394                 : 
     395               3 :     table_close(pg_shseclabel, RowExclusiveLock);
     396               3 : }
     397                 : 
     398                 : /*
     399                 :  * SetSecurityLabel attempts to set the security label for the specified
     400                 :  * provider on the specified object to the given value.  NULL means that any
     401                 :  * existing label should be deleted.
     402                 :  */
     403                 : void
     404              14 : SetSecurityLabel(const ObjectAddress *object,
     405                 :                  const char *provider, const char *label)
     406                 : {
     407                 :     Relation    pg_seclabel;
     408                 :     ScanKeyData keys[4];
     409                 :     SysScanDesc scan;
     410                 :     HeapTuple   oldtup;
     411              14 :     HeapTuple   newtup = NULL;
     412                 :     Datum       values[Natts_pg_seclabel];
     413                 :     bool        nulls[Natts_pg_seclabel];
     414                 :     bool        replaces[Natts_pg_seclabel];
     415                 : 
     416                 :     /* Shared objects have their own security label catalog. */
     417              14 :     if (IsSharedRelation(object->classId))
     418                 :     {
     419               3 :         SetSharedSecurityLabel(object, provider, label);
     420               3 :         return;
     421                 :     }
     422                 : 
     423                 :     /* Prepare to form or update a tuple, if necessary. */
     424              11 :     memset(nulls, false, sizeof(nulls));
     425              11 :     memset(replaces, false, sizeof(replaces));
     426              11 :     values[Anum_pg_seclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
     427              11 :     values[Anum_pg_seclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
     428              11 :     values[Anum_pg_seclabel_objsubid - 1] = Int32GetDatum(object->objectSubId);
     429              11 :     values[Anum_pg_seclabel_provider - 1] = CStringGetTextDatum(provider);
     430              11 :     if (label != NULL)
     431              11 :         values[Anum_pg_seclabel_label - 1] = CStringGetTextDatum(label);
     432                 : 
     433                 :     /* Use the index to search for a matching old tuple */
     434              11 :     ScanKeyInit(&keys[0],
     435                 :                 Anum_pg_seclabel_objoid,
     436                 :                 BTEqualStrategyNumber, F_OIDEQ,
     437              11 :                 ObjectIdGetDatum(object->objectId));
     438              11 :     ScanKeyInit(&keys[1],
     439                 :                 Anum_pg_seclabel_classoid,
     440                 :                 BTEqualStrategyNumber, F_OIDEQ,
     441              11 :                 ObjectIdGetDatum(object->classId));
     442              11 :     ScanKeyInit(&keys[2],
     443                 :                 Anum_pg_seclabel_objsubid,
     444                 :                 BTEqualStrategyNumber, F_INT4EQ,
     445              11 :                 Int32GetDatum(object->objectSubId));
     446              11 :     ScanKeyInit(&keys[3],
     447                 :                 Anum_pg_seclabel_provider,
     448                 :                 BTEqualStrategyNumber, F_TEXTEQ,
     449              11 :                 CStringGetTextDatum(provider));
     450                 : 
     451              11 :     pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
     452                 : 
     453              11 :     scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
     454                 :                               NULL, 4, keys);
     455                 : 
     456              11 :     oldtup = systable_getnext(scan);
     457              11 :     if (HeapTupleIsValid(oldtup))
     458                 :     {
     459               3 :         if (label == NULL)
     460 UBC           0 :             CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
     461                 :         else
     462                 :         {
     463 CBC           3 :             replaces[Anum_pg_seclabel_label - 1] = true;
     464               3 :             newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel),
     465                 :                                        values, nulls, replaces);
     466               3 :             CatalogTupleUpdate(pg_seclabel, &oldtup->t_self, newtup);
     467                 :         }
     468                 :     }
     469              11 :     systable_endscan(scan);
     470                 : 
     471                 :     /* If we didn't find an old tuple, insert a new one */
     472              11 :     if (newtup == NULL && label != NULL)
     473                 :     {
     474               8 :         newtup = heap_form_tuple(RelationGetDescr(pg_seclabel),
     475                 :                                  values, nulls);
     476               8 :         CatalogTupleInsert(pg_seclabel, newtup);
     477                 :     }
     478                 : 
     479                 :     /* Update indexes, if necessary */
     480              11 :     if (newtup != NULL)
     481              11 :         heap_freetuple(newtup);
     482                 : 
     483              11 :     table_close(pg_seclabel, RowExclusiveLock);
     484                 : }
     485                 : 
     486                 : /*
     487                 :  * DeleteSharedSecurityLabel is a helper function of DeleteSecurityLabel
     488                 :  * to handle shared database objects.
     489                 :  */
     490                 : void
     491             669 : DeleteSharedSecurityLabel(Oid objectId, Oid classId)
     492                 : {
     493                 :     Relation    pg_shseclabel;
     494                 :     ScanKeyData skey[2];
     495                 :     SysScanDesc scan;
     496                 :     HeapTuple   oldtup;
     497                 : 
     498             669 :     ScanKeyInit(&skey[0],
     499                 :                 Anum_pg_shseclabel_objoid,
     500                 :                 BTEqualStrategyNumber, F_OIDEQ,
     501                 :                 ObjectIdGetDatum(objectId));
     502             669 :     ScanKeyInit(&skey[1],
     503                 :                 Anum_pg_shseclabel_classoid,
     504                 :                 BTEqualStrategyNumber, F_OIDEQ,
     505                 :                 ObjectIdGetDatum(classId));
     506                 : 
     507             669 :     pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
     508                 : 
     509             669 :     scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
     510                 :                               NULL, 2, skey);
     511             671 :     while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
     512               2 :         CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
     513             669 :     systable_endscan(scan);
     514                 : 
     515             669 :     table_close(pg_shseclabel, RowExclusiveLock);
     516             669 : }
     517                 : 
     518                 : /*
     519                 :  * DeleteSecurityLabel removes all security labels for an object (and any
     520                 :  * sub-objects, if applicable).
     521                 :  */
     522                 : void
     523           83399 : 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           83399 :     if (IsSharedRelation(object->classId))
     533                 :     {
     534               3 :         Assert(object->objectSubId == 0);
     535               3 :         DeleteSharedSecurityLabel(object->objectId, object->classId);
     536               3 :         return;
     537                 :     }
     538                 : 
     539           83396 :     ScanKeyInit(&skey[0],
     540                 :                 Anum_pg_seclabel_objoid,
     541                 :                 BTEqualStrategyNumber, F_OIDEQ,
     542           83396 :                 ObjectIdGetDatum(object->objectId));
     543           83396 :     ScanKeyInit(&skey[1],
     544                 :                 Anum_pg_seclabel_classoid,
     545                 :                 BTEqualStrategyNumber, F_OIDEQ,
     546           83396 :                 ObjectIdGetDatum(object->classId));
     547           83396 :     if (object->objectSubId != 0)
     548                 :     {
     549             977 :         ScanKeyInit(&skey[2],
     550                 :                     Anum_pg_seclabel_objsubid,
     551                 :                     BTEqualStrategyNumber, F_INT4EQ,
     552             977 :                     Int32GetDatum(object->objectSubId));
     553             977 :         nkeys = 3;
     554                 :     }
     555                 :     else
     556           82419 :         nkeys = 2;
     557                 : 
     558           83396 :     pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
     559                 : 
     560           83396 :     scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
     561                 :                               NULL, nkeys, skey);
     562           83401 :     while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
     563               5 :         CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
     564           83396 :     systable_endscan(scan);
     565                 : 
     566           83396 :     table_close(pg_seclabel, RowExclusiveLock);
     567                 : }
     568                 : 
     569                 : void
     570               1 : register_label_provider(const char *provider_name, check_object_relabel_type hook)
     571                 : {
     572                 :     LabelProvider *provider;
     573                 :     MemoryContext oldcxt;
     574                 : 
     575               1 :     oldcxt = MemoryContextSwitchTo(TopMemoryContext);
     576               1 :     provider = palloc(sizeof(LabelProvider));
     577               1 :     provider->provider_name = pstrdup(provider_name);
     578               1 :     provider->hook = hook;
     579               1 :     label_provider_list = lappend(label_provider_list, provider);
     580               1 :     MemoryContextSwitchTo(oldcxt);
     581               1 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a