Header And Logo

PostgreSQL
| The world's most advanced open source database.

relation.c

Go to the documentation of this file.
00001 /* -------------------------------------------------------------------------
00002  *
00003  * contrib/sepgsql/label.c
00004  *
00005  * Routines corresponding to relation/attribute objects
00006  *
00007  * Copyright (c) 2010-2013, PostgreSQL Global Development Group
00008  *
00009  * -------------------------------------------------------------------------
00010  */
00011 #include "postgres.h"
00012 
00013 #include "access/genam.h"
00014 #include "access/heapam.h"
00015 #include "access/htup_details.h"
00016 #include "access/sysattr.h"
00017 #include "catalog/indexing.h"
00018 #include "catalog/dependency.h"
00019 #include "catalog/pg_attribute.h"
00020 #include "catalog/pg_class.h"
00021 #include "catalog/pg_namespace.h"
00022 #include "commands/seclabel.h"
00023 #include "lib/stringinfo.h"
00024 #include "utils/builtins.h"
00025 #include "utils/fmgroids.h"
00026 #include "utils/catcache.h"
00027 #include "utils/lsyscache.h"
00028 #include "utils/rel.h"
00029 #include "utils/syscache.h"
00030 #include "utils/tqual.h"
00031 
00032 #include "sepgsql.h"
00033 
00034 static void     sepgsql_index_modify(Oid indexOid);
00035 
00036 /*
00037  * sepgsql_attribute_post_create
00038  *
00039  * This routine assigns a default security label on a newly defined
00040  * column, using ALTER TABLE ... ADD COLUMN.
00041  * Note that this routine is not invoked in the case of CREATE TABLE,
00042  * although it also defines columns in addition to table.
00043  */
00044 void
00045 sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
00046 {
00047     Relation    rel;
00048     ScanKeyData skey[2];
00049     SysScanDesc sscan;
00050     HeapTuple   tuple;
00051     char       *scontext;
00052     char       *tcontext;
00053     char       *ncontext;
00054     ObjectAddress object;
00055     Form_pg_attribute attForm;
00056     StringInfoData audit_name;
00057 
00058     /*
00059      * Only attributes within regular relation have individual security
00060      * labels.
00061      */
00062     if (get_rel_relkind(relOid) != RELKIND_RELATION)
00063         return;
00064 
00065     /*
00066      * Compute a default security label of the new column underlying the
00067      * specified relation, and check permission to create it.
00068      */
00069     rel = heap_open(AttributeRelationId, AccessShareLock);
00070 
00071     ScanKeyInit(&skey[0],
00072                 Anum_pg_attribute_attrelid,
00073                 BTEqualStrategyNumber, F_OIDEQ,
00074                 ObjectIdGetDatum(relOid));
00075     ScanKeyInit(&skey[1],
00076                 Anum_pg_attribute_attnum,
00077                 BTEqualStrategyNumber, F_INT2EQ,
00078                 Int16GetDatum(attnum));
00079 
00080     sscan = systable_beginscan(rel, AttributeRelidNumIndexId, true,
00081                                SnapshotSelf, 2, &skey[0]);
00082 
00083     tuple = systable_getnext(sscan);
00084     if (!HeapTupleIsValid(tuple))
00085         elog(ERROR, "catalog lookup failed for column %d of relation %u",
00086              attnum, relOid);
00087 
00088     attForm = (Form_pg_attribute) GETSTRUCT(tuple);
00089 
00090     scontext = sepgsql_get_client_label();
00091     tcontext = sepgsql_get_label(RelationRelationId, relOid, 0);
00092     ncontext = sepgsql_compute_create(scontext, tcontext,
00093                                       SEPG_CLASS_DB_COLUMN,
00094                                       NameStr(attForm->attname));
00095 
00096     /*
00097      * check db_column:{create} permission
00098      */
00099     object.classId = RelationRelationId;
00100     object.objectId = relOid;
00101     object.objectSubId = 0;
00102 
00103     initStringInfo(&audit_name);
00104     appendStringInfo(&audit_name, "%s.%s",
00105                      getObjectIdentity(&object),
00106                      quote_identifier(NameStr(attForm->attname)));
00107     sepgsql_avc_check_perms_label(ncontext,
00108                                   SEPG_CLASS_DB_COLUMN,
00109                                   SEPG_DB_COLUMN__CREATE,
00110                                   audit_name.data,
00111                                   true);
00112 
00113     /*
00114      * Assign the default security label on a new procedure
00115      */
00116     object.classId = RelationRelationId;
00117     object.objectId = relOid;
00118     object.objectSubId = attnum;
00119     SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
00120 
00121     systable_endscan(sscan);
00122     heap_close(rel, AccessShareLock);
00123 
00124     pfree(tcontext);
00125     pfree(ncontext);
00126 }
00127 
00128 /*
00129  * sepgsql_attribute_drop
00130  *
00131  * It checks privileges to drop the supplied column.
00132  */
00133 void
00134 sepgsql_attribute_drop(Oid relOid, AttrNumber attnum)
00135 {
00136     ObjectAddress object;
00137     char       *audit_name;
00138 
00139     if (get_rel_relkind(relOid) != RELKIND_RELATION)
00140         return;
00141 
00142     /*
00143      * check db_column:{drop} permission
00144      */
00145     object.classId = RelationRelationId;
00146     object.objectId = relOid;
00147     object.objectSubId = attnum;
00148     audit_name = getObjectIdentity(&object);
00149 
00150     sepgsql_avc_check_perms(&object,
00151                             SEPG_CLASS_DB_COLUMN,
00152                             SEPG_DB_COLUMN__DROP,
00153                             audit_name,
00154                             true);
00155     pfree(audit_name);
00156 }
00157 
00158 /*
00159  * sepgsql_attribute_relabel
00160  *
00161  * It checks privileges to relabel the supplied column
00162  * by the `seclabel'.
00163  */
00164 void
00165 sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
00166                           const char *seclabel)
00167 {
00168     ObjectAddress object;
00169     char       *audit_name;
00170 
00171     if (get_rel_relkind(relOid) != RELKIND_RELATION)
00172         ereport(ERROR,
00173                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00174                  errmsg("cannot set security label on non-regular columns")));
00175 
00176     object.classId = RelationRelationId;
00177     object.objectId = relOid;
00178     object.objectSubId = attnum;
00179     audit_name = getObjectIdentity(&object);
00180 
00181     /*
00182      * check db_column:{setattr relabelfrom} permission
00183      */
00184     sepgsql_avc_check_perms(&object,
00185                             SEPG_CLASS_DB_COLUMN,
00186                             SEPG_DB_COLUMN__SETATTR |
00187                             SEPG_DB_COLUMN__RELABELFROM,
00188                             audit_name,
00189                             true);
00190 
00191     /*
00192      * check db_column:{relabelto} permission
00193      */
00194     sepgsql_avc_check_perms_label(seclabel,
00195                                   SEPG_CLASS_DB_COLUMN,
00196                                   SEPG_DB_PROCEDURE__RELABELTO,
00197                                   audit_name,
00198                                   true);
00199     pfree(audit_name);
00200 }
00201 
00202 /*
00203  * sepgsql_attribute_setattr
00204  *
00205  * It checks privileges to alter the supplied column.
00206  */
00207 void
00208 sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum)
00209 {
00210     ObjectAddress object;
00211     char       *audit_name;
00212 
00213     if (get_rel_relkind(relOid) != RELKIND_RELATION)
00214         return;
00215 
00216     /*
00217      * check db_column:{setattr} permission
00218      */
00219     object.classId = RelationRelationId;
00220     object.objectId = relOid;
00221     object.objectSubId = attnum;
00222     audit_name = getObjectIdentity(&object);
00223 
00224     sepgsql_avc_check_perms(&object,
00225                             SEPG_CLASS_DB_COLUMN,
00226                             SEPG_DB_COLUMN__SETATTR,
00227                             audit_name,
00228                             true);
00229     pfree(audit_name);
00230 }
00231 
00232 /*
00233  * sepgsql_relation_post_create
00234  *
00235  * The post creation hook of relation/attribute
00236  */
00237 void
00238 sepgsql_relation_post_create(Oid relOid)
00239 {
00240     Relation    rel;
00241     ScanKeyData skey;
00242     SysScanDesc sscan;
00243     HeapTuple   tuple;
00244     Form_pg_class classForm;
00245     ObjectAddress object;
00246     uint16      tclass;
00247     char       *scontext;       /* subject */
00248     char       *tcontext;       /* schema */
00249     char       *rcontext;       /* relation */
00250     char       *ccontext;       /* column */
00251     char       *nsp_name;
00252     StringInfoData audit_name;
00253 
00254     /*
00255      * Fetch catalog record of the new relation. Because pg_class entry is not
00256      * visible right now, we need to scan the catalog using SnapshotSelf.
00257      */
00258     rel = heap_open(RelationRelationId, AccessShareLock);
00259 
00260     ScanKeyInit(&skey,
00261                 ObjectIdAttributeNumber,
00262                 BTEqualStrategyNumber, F_OIDEQ,
00263                 ObjectIdGetDatum(relOid));
00264 
00265     sscan = systable_beginscan(rel, ClassOidIndexId, true,
00266                                SnapshotSelf, 1, &skey);
00267 
00268     tuple = systable_getnext(sscan);
00269     if (!HeapTupleIsValid(tuple))
00270         elog(ERROR, "catalog lookup failed for relation %u", relOid);
00271 
00272     classForm = (Form_pg_class) GETSTRUCT(tuple);
00273 
00274     /* ignore indexes on toast tables */
00275     if (classForm->relkind == RELKIND_INDEX &&
00276         classForm->relnamespace == PG_TOAST_NAMESPACE)
00277         goto out;
00278 
00279     /*
00280      * check db_schema:{add_name} permission of the namespace
00281      */
00282     object.classId = NamespaceRelationId;
00283     object.objectId = classForm->relnamespace;
00284     object.objectSubId = 0;
00285     sepgsql_avc_check_perms(&object,
00286                             SEPG_CLASS_DB_SCHEMA,
00287                             SEPG_DB_SCHEMA__ADD_NAME,
00288                             getObjectIdentity(&object),
00289                             true);
00290 
00291     switch (classForm->relkind)
00292     {
00293         case RELKIND_RELATION:
00294             tclass = SEPG_CLASS_DB_TABLE;
00295             break;
00296         case RELKIND_SEQUENCE:
00297             tclass = SEPG_CLASS_DB_SEQUENCE;
00298             break;
00299         case RELKIND_VIEW:
00300             tclass = SEPG_CLASS_DB_VIEW;
00301             break;
00302         case RELKIND_INDEX:
00303             /* deal with indexes specially; no need for tclass */
00304             sepgsql_index_modify(relOid);
00305             goto out;
00306         default:
00307             /* ignore other relkinds */
00308             goto out;
00309     }
00310 
00311     /*
00312      * Compute a default security label when we create a new relation object
00313      * under the specified namespace.
00314      */
00315     scontext = sepgsql_get_client_label();
00316     tcontext = sepgsql_get_label(NamespaceRelationId,
00317                                  classForm->relnamespace, 0);
00318     rcontext = sepgsql_compute_create(scontext, tcontext, tclass,
00319                                       NameStr(classForm->relname));
00320 
00321     /*
00322      * check db_xxx:{create} permission
00323      */
00324     nsp_name = get_namespace_name(classForm->relnamespace);
00325     initStringInfo(&audit_name);
00326     appendStringInfo(&audit_name, "%s.%s",
00327                      quote_identifier(nsp_name),
00328                      quote_identifier(NameStr(classForm->relname)));
00329     sepgsql_avc_check_perms_label(rcontext,
00330                                   tclass,
00331                                   SEPG_DB_DATABASE__CREATE,
00332                                   audit_name.data,
00333                                   true);
00334 
00335     /*
00336      * Assign the default security label on the new relation
00337      */
00338     object.classId = RelationRelationId;
00339     object.objectId = relOid;
00340     object.objectSubId = 0;
00341     SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, rcontext);
00342 
00343     /*
00344      * We also assigns a default security label on columns of the new regular
00345      * tables.
00346      */
00347     if (classForm->relkind == RELKIND_RELATION)
00348     {
00349         Relation    arel;
00350         ScanKeyData akey;
00351         SysScanDesc ascan;
00352         HeapTuple   atup;
00353         Form_pg_attribute attForm;
00354 
00355         arel = heap_open(AttributeRelationId, AccessShareLock);
00356 
00357         ScanKeyInit(&akey,
00358                     Anum_pg_attribute_attrelid,
00359                     BTEqualStrategyNumber, F_OIDEQ,
00360                     ObjectIdGetDatum(relOid));
00361 
00362         ascan = systable_beginscan(arel, AttributeRelidNumIndexId, true,
00363                                    SnapshotSelf, 1, &akey);
00364 
00365         while (HeapTupleIsValid(atup = systable_getnext(ascan)))
00366         {
00367             attForm = (Form_pg_attribute) GETSTRUCT(atup);
00368 
00369             resetStringInfo(&audit_name);
00370             appendStringInfo(&audit_name, "%s.%s.%s",
00371                              quote_identifier(nsp_name),
00372                              quote_identifier(NameStr(classForm->relname)),
00373                              quote_identifier(NameStr(attForm->attname)));
00374 
00375             ccontext = sepgsql_compute_create(scontext,
00376                                               rcontext,
00377                                               SEPG_CLASS_DB_COLUMN,
00378                                               NameStr(attForm->attname));
00379 
00380             /*
00381              * check db_column:{create} permission
00382              */
00383             sepgsql_avc_check_perms_label(ccontext,
00384                                           SEPG_CLASS_DB_COLUMN,
00385                                           SEPG_DB_COLUMN__CREATE,
00386                                           audit_name.data,
00387                                           true);
00388 
00389             object.classId = RelationRelationId;
00390             object.objectId = relOid;
00391             object.objectSubId = attForm->attnum;
00392             SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ccontext);
00393 
00394             pfree(ccontext);
00395         }
00396         systable_endscan(ascan);
00397         heap_close(arel, AccessShareLock);
00398     }
00399     pfree(rcontext);
00400 
00401 out:
00402     systable_endscan(sscan);
00403     heap_close(rel, AccessShareLock);
00404 }
00405 
00406 /*
00407  * sepgsql_relation_drop
00408  *
00409  * It checks privileges to drop the supplied relation.
00410  */
00411 void
00412 sepgsql_relation_drop(Oid relOid)
00413 {
00414     ObjectAddress object;
00415     char       *audit_name;
00416     uint16_t    tclass;
00417     char        relkind;
00418 
00419     relkind = get_rel_relkind(relOid);
00420     switch (relkind)
00421     {
00422         case RELKIND_RELATION:
00423             tclass = SEPG_CLASS_DB_TABLE;
00424             break;
00425         case RELKIND_SEQUENCE:
00426             tclass = SEPG_CLASS_DB_SEQUENCE;
00427             break;
00428         case RELKIND_VIEW:
00429             tclass = SEPG_CLASS_DB_VIEW;
00430             break;
00431         case RELKIND_INDEX:
00432             /* ignore indexes on toast tables */
00433             if (get_rel_namespace(relOid) == PG_TOAST_NAMESPACE)
00434                 return;
00435             /* other indexes are handled specially below; no need for tclass */
00436             break;
00437         default:
00438             /* ignore other relkinds */
00439             return;
00440     }
00441 
00442     /*
00443      * check db_schema:{remove_name} permission
00444      */
00445     object.classId = NamespaceRelationId;
00446     object.objectId = get_rel_namespace(relOid);
00447     object.objectSubId = 0;
00448     audit_name = getObjectIdentity(&object);
00449 
00450     sepgsql_avc_check_perms(&object,
00451                             SEPG_CLASS_DB_SCHEMA,
00452                             SEPG_DB_SCHEMA__REMOVE_NAME,
00453                             audit_name,
00454                             true);
00455     pfree(audit_name);
00456 
00457     /* deal with indexes specially */
00458     if (relkind == RELKIND_INDEX)
00459     {
00460         sepgsql_index_modify(relOid);
00461         return;
00462     }
00463 
00464     /*
00465      * check db_table/sequence/view:{drop} permission
00466      */
00467     object.classId = RelationRelationId;
00468     object.objectId = relOid;
00469     object.objectSubId = 0;
00470     audit_name = getObjectIdentity(&object);
00471 
00472     sepgsql_avc_check_perms(&object,
00473                             tclass,
00474                             SEPG_DB_TABLE__DROP,
00475                             audit_name,
00476                             true);
00477     pfree(audit_name);
00478 
00479     /*
00480      * check db_column:{drop} permission
00481      */
00482     if (relkind == RELKIND_RELATION)
00483     {
00484         Form_pg_attribute attForm;
00485         CatCList   *attrList;
00486         HeapTuple   atttup;
00487         int         i;
00488 
00489         attrList = SearchSysCacheList1(ATTNUM, ObjectIdGetDatum(relOid));
00490         for (i = 0; i < attrList->n_members; i++)
00491         {
00492             atttup = &attrList->members[i]->tuple;
00493             attForm = (Form_pg_attribute) GETSTRUCT(atttup);
00494 
00495             if (attForm->attisdropped)
00496                 continue;
00497 
00498             object.classId = RelationRelationId;
00499             object.objectId = relOid;
00500             object.objectSubId = attForm->attnum;
00501             audit_name = getObjectIdentity(&object);
00502 
00503             sepgsql_avc_check_perms(&object,
00504                                     SEPG_CLASS_DB_COLUMN,
00505                                     SEPG_DB_COLUMN__DROP,
00506                                     audit_name,
00507                                     true);
00508             pfree(audit_name);
00509         }
00510         ReleaseCatCacheList(attrList);
00511     }
00512 }
00513 
00514 /*
00515  * sepgsql_relation_relabel
00516  *
00517  * It checks privileges to relabel the supplied relation by the `seclabel'.
00518  */
00519 void
00520 sepgsql_relation_relabel(Oid relOid, const char *seclabel)
00521 {
00522     ObjectAddress object;
00523     char       *audit_name;
00524     char        relkind;
00525     uint16_t    tclass = 0;
00526 
00527     relkind = get_rel_relkind(relOid);
00528     if (relkind == RELKIND_RELATION)
00529         tclass = SEPG_CLASS_DB_TABLE;
00530     else if (relkind == RELKIND_SEQUENCE)
00531         tclass = SEPG_CLASS_DB_SEQUENCE;
00532     else if (relkind == RELKIND_VIEW)
00533         tclass = SEPG_CLASS_DB_VIEW;
00534     else
00535         ereport(ERROR,
00536                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00537                  errmsg("cannot set security labels on relations except "
00538                         "for tables, sequences or views")));
00539 
00540     object.classId = RelationRelationId;
00541     object.objectId = relOid;
00542     object.objectSubId = 0;
00543     audit_name = getObjectIdentity(&object);
00544 
00545     /*
00546      * check db_xxx:{setattr relabelfrom} permission
00547      */
00548     sepgsql_avc_check_perms(&object,
00549                             tclass,
00550                             SEPG_DB_TABLE__SETATTR |
00551                             SEPG_DB_TABLE__RELABELFROM,
00552                             audit_name,
00553                             true);
00554 
00555     /*
00556      * check db_xxx:{relabelto} permission
00557      */
00558     sepgsql_avc_check_perms_label(seclabel,
00559                                   tclass,
00560                                   SEPG_DB_TABLE__RELABELTO,
00561                                   audit_name,
00562                                   true);
00563     pfree(audit_name);
00564 }
00565 
00566 /*
00567  * sepgsql_relation_setattr
00568  *
00569  * It checks privileges to set attribute of the supplied relation
00570  */
00571 void
00572 sepgsql_relation_setattr(Oid relOid)
00573 {
00574     Relation        rel;
00575     ScanKeyData     skey;
00576     SysScanDesc     sscan;
00577     HeapTuple       oldtup;
00578     HeapTuple       newtup;
00579     Form_pg_class   oldform;
00580     Form_pg_class   newform;
00581     ObjectAddress object;
00582     char       *audit_name;
00583     uint16_t    tclass;
00584 
00585     switch (get_rel_relkind(relOid))
00586     {
00587         case RELKIND_RELATION:
00588             tclass = SEPG_CLASS_DB_TABLE;
00589             break;
00590         case RELKIND_SEQUENCE:
00591             tclass = SEPG_CLASS_DB_SEQUENCE;
00592             break;
00593         case RELKIND_VIEW:
00594             tclass = SEPG_CLASS_DB_VIEW;
00595             break;
00596         case RELKIND_INDEX:
00597             /* deal with indexes specially */
00598             sepgsql_index_modify(relOid);
00599             return;
00600         default:
00601             /* other relkinds don't need additional work */
00602             return;
00603     }
00604 
00605     /*
00606      * Fetch newer catalog
00607      */
00608     rel = heap_open(RelationRelationId, AccessShareLock);
00609 
00610     ScanKeyInit(&skey,
00611                 ObjectIdAttributeNumber,
00612                 BTEqualStrategyNumber, F_OIDEQ,
00613                 ObjectIdGetDatum(relOid));
00614 
00615     sscan = systable_beginscan(rel, ClassOidIndexId, true,
00616                                SnapshotSelf, 1, &skey);
00617 
00618     newtup = systable_getnext(sscan);
00619     if (!HeapTupleIsValid(newtup))
00620         elog(ERROR, "catalog lookup failed for relation %u", relOid);
00621     newform = (Form_pg_class) GETSTRUCT(newtup);
00622 
00623     /*
00624      * Fetch older catalog
00625      */
00626     oldtup = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
00627     if (!HeapTupleIsValid(oldtup))
00628         elog(ERROR, "cache lookup failed for relation %u", relOid);
00629     oldform = (Form_pg_class) GETSTRUCT(oldtup);
00630 
00631     /*
00632      * Does this ALTER command takes operation to namespace?
00633      */
00634     if (newform->relnamespace != oldform->relnamespace)
00635     {
00636         sepgsql_schema_remove_name(oldform->relnamespace);
00637         sepgsql_schema_add_name(newform->relnamespace);
00638     }
00639     if (strcmp(NameStr(newform->relname), NameStr(oldform->relname)) != 0)
00640         sepgsql_schema_rename(oldform->relnamespace);
00641 
00642     /*
00643      * XXX - In the future version, db_tuple:{use} of system catalog entry
00644      * shall be checked, if tablespace configuration is changed.
00645      */
00646 
00647     /*
00648      * check db_xxx:{setattr} permission
00649      */
00650     object.classId = RelationRelationId;
00651     object.objectId = relOid;
00652     object.objectSubId = 0;
00653     audit_name = getObjectIdentity(&object);
00654 
00655     sepgsql_avc_check_perms(&object,
00656                             tclass,
00657                             SEPG_DB_TABLE__SETATTR,
00658                             audit_name,
00659                             true);
00660     pfree(audit_name);
00661 
00662     ReleaseSysCache(oldtup);
00663     systable_endscan(sscan);
00664     heap_close(rel, AccessShareLock);
00665 }
00666 
00667 /*
00668  * sepgsql_relation_setattr_extra
00669  *
00670  * It checks permission of the relation being referenced by extra attributes,
00671  * such as pg_index entries. Like core PostgreSQL, sepgsql also does not deal
00672  * with such entries as individual "objects", thus, modification of these
00673  * entries shall be considered as setting an attribute of the underlying
00674  * relation.
00675  */
00676 static void
00677 sepgsql_relation_setattr_extra(Relation catalog,
00678                                Oid catindex_id,
00679                                Oid extra_oid,
00680                                AttrNumber anum_relation_id,
00681                                AttrNumber anum_extra_id)
00682 {
00683     ScanKeyData skey;
00684     SysScanDesc sscan;
00685     HeapTuple   tuple;
00686     Datum       datum;
00687     bool        isnull;
00688 
00689     ScanKeyInit(&skey, anum_extra_id,
00690                 BTEqualStrategyNumber, F_OIDEQ,
00691                 ObjectIdGetDatum(extra_oid));
00692 
00693     sscan = systable_beginscan(catalog, catindex_id, true,
00694                                SnapshotSelf, 1, &skey);
00695     tuple = systable_getnext(sscan);
00696     if (!HeapTupleIsValid(tuple))
00697         elog(ERROR, "catalog lookup failed for object %u in catalog \"%s\"",
00698              extra_oid, RelationGetRelationName(catalog));
00699 
00700     datum = heap_getattr(tuple, anum_relation_id,
00701                          RelationGetDescr(catalog), &isnull);
00702     Assert(!isnull);
00703 
00704     sepgsql_relation_setattr(DatumGetObjectId(datum));
00705 
00706     systable_endscan(sscan);
00707 }
00708 
00709 /*
00710  * sepgsql_index_modify
00711  *      Handle index create, update, drop
00712  *
00713  * Unlike other relation kinds, indexes do not have their own security labels,
00714  * so instead of doing checks directly, treat them as extra attributes of their
00715  * owning tables; so check 'setattr' permissions on the table.
00716  */
00717 static void
00718 sepgsql_index_modify(Oid indexOid)
00719 {
00720     Relation    catalog = heap_open(IndexRelationId, AccessShareLock);
00721 
00722     /* check db_table:{setattr} permission of the table being indexed */
00723     sepgsql_relation_setattr_extra(catalog,
00724                                    IndexRelidIndexId,
00725                                    indexOid,
00726                                    Anum_pg_index_indrelid,
00727                                    Anum_pg_index_indexrelid);
00728     heap_close(catalog, AccessShareLock);
00729 }