LCOV - code coverage report
Current view: top level - src/backend/commands - seclabel.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 20.9 % 254 53
Test Date: 2026-01-26 10:56:24 Functions: 33.3 % 9 3
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 16.5 % 109 18

             Branch data     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                 :           0 : SecLabelSupportsObjectType(ObjectType objtype)
      38                 :             : {
      39      [ #  #  # ]:           0 :         switch (objtype)
      40                 :             :         {
      41                 :             :                 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                 :           0 :                         return true;
      63                 :             : 
      64                 :             :                 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                 :           0 : }
     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                 :           8 : ExecSecLabelStmt(SecLabelStmt *stmt)
     116                 :             : {
     117                 :           8 :         LabelProvider *provider = NULL;
     118                 :             :         ObjectAddress address;
     119                 :           8 :         Relation        relation;
     120                 :           8 :         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         [ +  + ]:           8 :         if (stmt->provider == NULL)
     127                 :             :         {
     128         [ -  + ]:           6 :                 if (label_provider_list == NIL)
     129   [ +  -  +  - ]:           6 :                         ereport(ERROR,
     130                 :             :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     131                 :             :                                          errmsg("no security label providers have been loaded")));
     132         [ #  # ]:           0 :                 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                 :           0 :                 provider = (LabelProvider *) linitial(label_provider_list);
     137                 :           0 :         }
     138                 :             :         else
     139                 :             :         {
     140   [ -  +  #  #  :           2 :                 foreach(lc, label_provider_list)
                   -  + ]
     141                 :             :                 {
     142                 :           0 :                         LabelProvider *lp = lfirst(lc);
     143                 :             : 
     144         [ #  # ]:           0 :                         if (strcmp(stmt->provider, lp->provider_name) == 0)
     145                 :             :                         {
     146                 :           0 :                                 provider = lp;
     147                 :           0 :                                 break;
     148                 :             :                         }
     149         [ #  # ]:           0 :                 }
     150         [ -  + ]:           2 :                 if (provider == NULL)
     151   [ +  -  +  - ]:           2 :                         ereport(ERROR,
     152                 :             :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     153                 :             :                                          errmsg("security label provider \"%s\" is not loaded",
     154                 :             :                                                         stmt->provider)));
     155                 :             :         }
     156                 :             : 
     157         [ #  # ]:           0 :         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                 :           0 :         address = get_object_address(stmt->objtype, stmt->object,
     169                 :             :                                                                  &relation, ShareUpdateExclusiveLock, false);
     170                 :             : 
     171                 :             :         /* Require ownership of the target object. */
     172                 :           0 :         check_object_ownership(GetUserId(), stmt->objtype, address,
     173                 :           0 :                                                    stmt->object, relation);
     174                 :             : 
     175                 :             :         /* Perform other integrity checks as needed. */
     176         [ #  # ]:           0 :         switch (stmt->objtype)
     177                 :             :         {
     178                 :             :                 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         [ #  # ]:           0 :                         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                 :           0 :                         break;
     197                 :             :                 default:
     198                 :           0 :                         break;
     199                 :             :         }
     200                 :             : 
     201                 :             :         /* Provider gets control here, may throw ERROR to veto new label. */
     202                 :           0 :         provider->hook(&address, stmt->label);
     203                 :             : 
     204                 :             :         /* Apply new label. */
     205                 :           0 :         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         [ #  # ]:           0 :         if (relation != NULL)
     214                 :           0 :                 relation_close(relation, NoLock);
     215                 :             : 
     216                 :             :         return address;
     217                 :           0 : }
     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                 :           0 :         Relation        pg_shseclabel;
     227                 :           0 :         ScanKeyData keys[3];
     228                 :           0 :         SysScanDesc scan;
     229                 :           0 :         HeapTuple       tuple;
     230                 :           0 :         Datum           datum;
     231                 :           0 :         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                 :           0 :                                                           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                 :           0 :                                                          RelationGetDescr(pg_shseclabel), &isnull);
     257         [ #  # ]:           0 :                 if (!isnull)
     258                 :           0 :                         seclabel = TextDatumGetCString(datum);
     259                 :           0 :         }
     260                 :           0 :         systable_endscan(scan);
     261                 :             : 
     262                 :           0 :         table_close(pg_shseclabel, AccessShareLock);
     263                 :             : 
     264                 :           0 :         return seclabel;
     265                 :           0 : }
     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                 :           0 :         Relation        pg_seclabel;
     275                 :           0 :         ScanKeyData keys[4];
     276                 :           0 :         SysScanDesc scan;
     277                 :           0 :         HeapTuple       tuple;
     278                 :           0 :         Datum           datum;
     279                 :           0 :         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                 :           0 :                                                           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                 :           0 :                                                          RelationGetDescr(pg_seclabel), &isnull);
     314         [ #  # ]:           0 :                 if (!isnull)
     315                 :           0 :                         seclabel = TextDatumGetCString(datum);
     316                 :           0 :         }
     317                 :           0 :         systable_endscan(scan);
     318                 :             : 
     319                 :           0 :         table_close(pg_seclabel, AccessShareLock);
     320                 :             : 
     321                 :           0 :         return seclabel;
     322                 :           0 : }
     323                 :             : 
     324                 :             : /*
     325                 :             :  * SetSharedSecurityLabel is a helper function of SetSecurityLabel to
     326                 :             :  * handle shared database objects.
     327                 :             :  */
     328                 :             : static void
     329                 :           0 : SetSharedSecurityLabel(const ObjectAddress *object,
     330                 :             :                                            const char *provider, const char *label)
     331                 :             : {
     332                 :           0 :         Relation        pg_shseclabel;
     333                 :           0 :         ScanKeyData keys[4];
     334                 :           0 :         SysScanDesc scan;
     335                 :           0 :         HeapTuple       oldtup;
     336                 :           0 :         HeapTuple       newtup = NULL;
     337                 :           0 :         Datum           values[Natts_pg_shseclabel];
     338                 :           0 :         bool            nulls[Natts_pg_shseclabel];
     339                 :           0 :         bool            replaces[Natts_pg_shseclabel];
     340                 :             : 
     341                 :             :         /* Prepare to form or update a tuple, if necessary. */
     342                 :           0 :         memset(nulls, false, sizeof(nulls));
     343                 :           0 :         memset(replaces, false, sizeof(replaces));
     344                 :           0 :         values[Anum_pg_shseclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
     345                 :           0 :         values[Anum_pg_shseclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
     346                 :           0 :         values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider);
     347         [ #  # ]:           0 :         if (label != NULL)
     348                 :           0 :                 values[Anum_pg_shseclabel_label - 1] = CStringGetTextDatum(label);
     349                 :             : 
     350                 :             :         /* Use the index to search for a matching old tuple */
     351                 :           0 :         ScanKeyInit(&keys[0],
     352                 :             :                                 Anum_pg_shseclabel_objoid,
     353                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
     354                 :           0 :                                 ObjectIdGetDatum(object->objectId));
     355                 :           0 :         ScanKeyInit(&keys[1],
     356                 :             :                                 Anum_pg_shseclabel_classoid,
     357                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
     358                 :           0 :                                 ObjectIdGetDatum(object->classId));
     359                 :           0 :         ScanKeyInit(&keys[2],
     360                 :             :                                 Anum_pg_shseclabel_provider,
     361                 :             :                                 BTEqualStrategyNumber, F_TEXTEQ,
     362                 :           0 :                                 CStringGetTextDatum(provider));
     363                 :             : 
     364                 :           0 :         pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
     365                 :             : 
     366                 :           0 :         scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
     367                 :           0 :                                                           NULL, 3, keys);
     368                 :             : 
     369                 :           0 :         oldtup = systable_getnext(scan);
     370         [ #  # ]:           0 :         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                 :           0 :                                                                            values, nulls, replaces);
     379                 :           0 :                         CatalogTupleUpdate(pg_shseclabel, &oldtup->t_self, newtup);
     380                 :             :                 }
     381                 :           0 :         }
     382                 :           0 :         systable_endscan(scan);
     383                 :             : 
     384                 :             :         /* If we didn't find an old tuple, insert a new one */
     385   [ #  #  #  # ]:           0 :         if (newtup == NULL && label != NULL)
     386                 :             :         {
     387                 :           0 :                 newtup = heap_form_tuple(RelationGetDescr(pg_shseclabel),
     388                 :           0 :                                                                  values, nulls);
     389                 :           0 :                 CatalogTupleInsert(pg_shseclabel, newtup);
     390                 :           0 :         }
     391                 :             : 
     392         [ #  # ]:           0 :         if (newtup != NULL)
     393                 :           0 :                 heap_freetuple(newtup);
     394                 :             : 
     395                 :           0 :         table_close(pg_shseclabel, RowExclusiveLock);
     396                 :           0 : }
     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                 :           0 : SetSecurityLabel(const ObjectAddress *object,
     405                 :             :                                  const char *provider, const char *label)
     406                 :             : {
     407                 :           0 :         Relation        pg_seclabel;
     408                 :           0 :         ScanKeyData keys[4];
     409                 :           0 :         SysScanDesc scan;
     410                 :           0 :         HeapTuple       oldtup;
     411                 :           0 :         HeapTuple       newtup = NULL;
     412                 :           0 :         Datum           values[Natts_pg_seclabel];
     413                 :           0 :         bool            nulls[Natts_pg_seclabel];
     414                 :           0 :         bool            replaces[Natts_pg_seclabel];
     415                 :             : 
     416                 :             :         /* Shared objects have their own security label catalog. */
     417         [ #  # ]:           0 :         if (IsSharedRelation(object->classId))
     418                 :             :         {
     419                 :           0 :                 SetSharedSecurityLabel(object, provider, label);
     420                 :           0 :                 return;
     421                 :             :         }
     422                 :             : 
     423                 :             :         /* Prepare to form or update a tuple, if necessary. */
     424                 :           0 :         memset(nulls, false, sizeof(nulls));
     425                 :           0 :         memset(replaces, false, sizeof(replaces));
     426                 :           0 :         values[Anum_pg_seclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
     427                 :           0 :         values[Anum_pg_seclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
     428                 :           0 :         values[Anum_pg_seclabel_objsubid - 1] = Int32GetDatum(object->objectSubId);
     429                 :           0 :         values[Anum_pg_seclabel_provider - 1] = CStringGetTextDatum(provider);
     430         [ #  # ]:           0 :         if (label != NULL)
     431                 :           0 :                 values[Anum_pg_seclabel_label - 1] = CStringGetTextDatum(label);
     432                 :             : 
     433                 :             :         /* Use the index to search for a matching old tuple */
     434                 :           0 :         ScanKeyInit(&keys[0],
     435                 :             :                                 Anum_pg_seclabel_objoid,
     436                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
     437                 :           0 :                                 ObjectIdGetDatum(object->objectId));
     438                 :           0 :         ScanKeyInit(&keys[1],
     439                 :             :                                 Anum_pg_seclabel_classoid,
     440                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
     441                 :           0 :                                 ObjectIdGetDatum(object->classId));
     442                 :           0 :         ScanKeyInit(&keys[2],
     443                 :             :                                 Anum_pg_seclabel_objsubid,
     444                 :             :                                 BTEqualStrategyNumber, F_INT4EQ,
     445                 :           0 :                                 Int32GetDatum(object->objectSubId));
     446                 :           0 :         ScanKeyInit(&keys[3],
     447                 :             :                                 Anum_pg_seclabel_provider,
     448                 :             :                                 BTEqualStrategyNumber, F_TEXTEQ,
     449                 :           0 :                                 CStringGetTextDatum(provider));
     450                 :             : 
     451                 :           0 :         pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
     452                 :             : 
     453                 :           0 :         scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
     454                 :           0 :                                                           NULL, 4, keys);
     455                 :             : 
     456                 :           0 :         oldtup = systable_getnext(scan);
     457         [ #  # ]:           0 :         if (HeapTupleIsValid(oldtup))
     458                 :             :         {
     459         [ #  # ]:           0 :                 if (label == NULL)
     460                 :           0 :                         CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
     461                 :             :                 else
     462                 :             :                 {
     463                 :           0 :                         replaces[Anum_pg_seclabel_label - 1] = true;
     464                 :           0 :                         newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel),
     465                 :           0 :                                                                            values, nulls, replaces);
     466                 :           0 :                         CatalogTupleUpdate(pg_seclabel, &oldtup->t_self, newtup);
     467                 :             :                 }
     468                 :           0 :         }
     469                 :           0 :         systable_endscan(scan);
     470                 :             : 
     471                 :             :         /* If we didn't find an old tuple, insert a new one */
     472   [ #  #  #  # ]:           0 :         if (newtup == NULL && label != NULL)
     473                 :             :         {
     474                 :           0 :                 newtup = heap_form_tuple(RelationGetDescr(pg_seclabel),
     475                 :           0 :                                                                  values, nulls);
     476                 :           0 :                 CatalogTupleInsert(pg_seclabel, newtup);
     477                 :           0 :         }
     478                 :             : 
     479                 :             :         /* Update indexes, if necessary */
     480         [ #  # ]:           0 :         if (newtup != NULL)
     481                 :           0 :                 heap_freetuple(newtup);
     482                 :             : 
     483                 :           0 :         table_close(pg_seclabel, RowExclusiveLock);
     484         [ #  # ]:           0 : }
     485                 :             : 
     486                 :             : /*
     487                 :             :  * DeleteSharedSecurityLabel is a helper function of DeleteSecurityLabel
     488                 :             :  * to handle shared database objects.
     489                 :             :  */
     490                 :             : void
     491                 :         211 : DeleteSharedSecurityLabel(Oid objectId, Oid classId)
     492                 :             : {
     493                 :         211 :         Relation        pg_shseclabel;
     494                 :         211 :         ScanKeyData skey[2];
     495                 :         211 :         SysScanDesc scan;
     496                 :         211 :         HeapTuple       oldtup;
     497                 :             : 
     498                 :         422 :         ScanKeyInit(&skey[0],
     499                 :             :                                 Anum_pg_shseclabel_objoid,
     500                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
     501                 :         211 :                                 ObjectIdGetDatum(objectId));
     502                 :         422 :         ScanKeyInit(&skey[1],
     503                 :             :                                 Anum_pg_shseclabel_classoid,
     504                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
     505                 :         211 :                                 ObjectIdGetDatum(classId));
     506                 :             : 
     507                 :         211 :         pg_shseclabel = table_open(SharedSecLabelRelationId, RowExclusiveLock);
     508                 :             : 
     509                 :         422 :         scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
     510                 :         211 :                                                           NULL, 2, skey);
     511         [ -  + ]:         211 :         while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
     512                 :           0 :                 CatalogTupleDelete(pg_shseclabel, &oldtup->t_self);
     513                 :         211 :         systable_endscan(scan);
     514                 :             : 
     515                 :         211 :         table_close(pg_shseclabel, RowExclusiveLock);
     516                 :         211 : }
     517                 :             : 
     518                 :             : /*
     519                 :             :  * DeleteSecurityLabel removes all security labels for an object (and any
     520                 :             :  * sub-objects, if applicable).
     521                 :             :  */
     522                 :             : void
     523                 :       24705 : DeleteSecurityLabel(const ObjectAddress *object)
     524                 :             : {
     525                 :       24705 :         Relation        pg_seclabel;
     526                 :       24705 :         ScanKeyData skey[3];
     527                 :       24705 :         SysScanDesc scan;
     528                 :       24705 :         HeapTuple       oldtup;
     529                 :       24705 :         int                     nkeys;
     530                 :             : 
     531                 :             :         /* Shared objects have their own security label catalog. */
     532         [ +  + ]:       24705 :         if (IsSharedRelation(object->classId))
     533                 :             :         {
     534         [ +  - ]:           1 :                 Assert(object->objectSubId == 0);
     535                 :           1 :                 DeleteSharedSecurityLabel(object->objectId, object->classId);
     536                 :           1 :                 return;
     537                 :             :         }
     538                 :             : 
     539                 :       49408 :         ScanKeyInit(&skey[0],
     540                 :             :                                 Anum_pg_seclabel_objoid,
     541                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
     542                 :       24704 :                                 ObjectIdGetDatum(object->objectId));
     543                 :       49408 :         ScanKeyInit(&skey[1],
     544                 :             :                                 Anum_pg_seclabel_classoid,
     545                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
     546                 :       24704 :                                 ObjectIdGetDatum(object->classId));
     547         [ +  + ]:       24704 :         if (object->objectSubId != 0)
     548                 :             :         {
     549                 :         612 :                 ScanKeyInit(&skey[2],
     550                 :             :                                         Anum_pg_seclabel_objsubid,
     551                 :             :                                         BTEqualStrategyNumber, F_INT4EQ,
     552                 :         306 :                                         Int32GetDatum(object->objectSubId));
     553                 :         306 :                 nkeys = 3;
     554                 :         306 :         }
     555                 :             :         else
     556                 :       24398 :                 nkeys = 2;
     557                 :             : 
     558                 :       24704 :         pg_seclabel = table_open(SecLabelRelationId, RowExclusiveLock);
     559                 :             : 
     560                 :       49408 :         scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
     561                 :       24704 :                                                           NULL, nkeys, skey);
     562         [ -  + ]:       24704 :         while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
     563                 :           0 :                 CatalogTupleDelete(pg_seclabel, &oldtup->t_self);
     564                 :       24704 :         systable_endscan(scan);
     565                 :             : 
     566                 :       24704 :         table_close(pg_seclabel, RowExclusiveLock);
     567         [ -  + ]:       24705 : }
     568                 :             : 
     569                 :             : void
     570                 :           0 : register_label_provider(const char *provider_name, check_object_relabel_type hook)
     571                 :             : {
     572                 :           0 :         LabelProvider *provider;
     573                 :           0 :         MemoryContext oldcxt;
     574                 :             : 
     575                 :           0 :         oldcxt = MemoryContextSwitchTo(TopMemoryContext);
     576                 :           0 :         provider = palloc_object(LabelProvider);
     577                 :           0 :         provider->provider_name = pstrdup(provider_name);
     578                 :           0 :         provider->hook = hook;
     579                 :           0 :         label_provider_list = lappend(label_provider_list, provider);
     580                 :           0 :         MemoryContextSwitchTo(oldcxt);
     581                 :           0 : }
        

Generated by: LCOV version 2.3.2-1