]> granicus.if.org Git - postgresql/blob - contrib/sepgsql/relation.c
pgindent run prior to branching
[postgresql] / contrib / sepgsql / relation.c
1 /* -------------------------------------------------------------------------
2  *
3  * contrib/sepgsql/relation.c
4  *
5  * Routines corresponding to relation/attribute objects
6  *
7  * Copyright (c) 2010-2018, PostgreSQL Global Development Group
8  *
9  * -------------------------------------------------------------------------
10  */
11 #include "postgres.h"
12
13 #include "access/genam.h"
14 #include "access/heapam.h"
15 #include "access/htup_details.h"
16 #include "access/sysattr.h"
17 #include "catalog/indexing.h"
18 #include "catalog/dependency.h"
19 #include "catalog/pg_attribute.h"
20 #include "catalog/pg_class.h"
21 #include "catalog/pg_namespace.h"
22 #include "commands/seclabel.h"
23 #include "lib/stringinfo.h"
24 #include "utils/builtins.h"
25 #include "utils/fmgroids.h"
26 #include "utils/catcache.h"
27 #include "utils/lsyscache.h"
28 #include "utils/rel.h"
29 #include "utils/syscache.h"
30 #include "utils/tqual.h"
31
32 #include "sepgsql.h"
33
34 static void sepgsql_index_modify(Oid indexOid);
35
36 /*
37  * sepgsql_attribute_post_create
38  *
39  * This routine assigns a default security label on a newly defined
40  * column, using ALTER TABLE ... ADD COLUMN.
41  * Note that this routine is not invoked in the case of CREATE TABLE,
42  * although it also defines columns in addition to table.
43  */
44 void
45 sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
46 {
47         Relation        rel;
48         ScanKeyData skey[2];
49         SysScanDesc sscan;
50         HeapTuple       tuple;
51         char       *scontext;
52         char       *tcontext;
53         char       *ncontext;
54         ObjectAddress object;
55         Form_pg_attribute attForm;
56         StringInfoData audit_name;
57         char            relkind = get_rel_relkind(relOid);
58
59         /*
60          * Only attributes within regular relations or partition relations have
61          * individual security labels.
62          */
63         if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
64                 return;
65
66         /*
67          * Compute a default security label of the new column underlying the
68          * specified relation, and check permission to create it.
69          */
70         rel = heap_open(AttributeRelationId, AccessShareLock);
71
72         ScanKeyInit(&skey[0],
73                                 Anum_pg_attribute_attrelid,
74                                 BTEqualStrategyNumber, F_OIDEQ,
75                                 ObjectIdGetDatum(relOid));
76         ScanKeyInit(&skey[1],
77                                 Anum_pg_attribute_attnum,
78                                 BTEqualStrategyNumber, F_INT2EQ,
79                                 Int16GetDatum(attnum));
80
81         sscan = systable_beginscan(rel, AttributeRelidNumIndexId, true,
82                                                            SnapshotSelf, 2, &skey[0]);
83
84         tuple = systable_getnext(sscan);
85         if (!HeapTupleIsValid(tuple))
86                 elog(ERROR, "could not find tuple for column %d of relation %u",
87                          attnum, relOid);
88
89         attForm = (Form_pg_attribute) GETSTRUCT(tuple);
90
91         scontext = sepgsql_get_client_label();
92         tcontext = sepgsql_get_label(RelationRelationId, relOid, 0);
93         ncontext = sepgsql_compute_create(scontext, tcontext,
94                                                                           SEPG_CLASS_DB_COLUMN,
95                                                                           NameStr(attForm->attname));
96
97         /*
98          * check db_column:{create} permission
99          */
100         object.classId = RelationRelationId;
101         object.objectId = relOid;
102         object.objectSubId = 0;
103
104         initStringInfo(&audit_name);
105         appendStringInfo(&audit_name, "%s.%s",
106                                          getObjectIdentity(&object),
107                                          quote_identifier(NameStr(attForm->attname)));
108         sepgsql_avc_check_perms_label(ncontext,
109                                                                   SEPG_CLASS_DB_COLUMN,
110                                                                   SEPG_DB_COLUMN__CREATE,
111                                                                   audit_name.data,
112                                                                   true);
113
114         /*
115          * Assign the default security label on a new procedure
116          */
117         object.classId = RelationRelationId;
118         object.objectId = relOid;
119         object.objectSubId = attnum;
120         SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
121
122         systable_endscan(sscan);
123         heap_close(rel, AccessShareLock);
124
125         pfree(tcontext);
126         pfree(ncontext);
127 }
128
129 /*
130  * sepgsql_attribute_drop
131  *
132  * It checks privileges to drop the supplied column.
133  */
134 void
135 sepgsql_attribute_drop(Oid relOid, AttrNumber attnum)
136 {
137         ObjectAddress object;
138         char       *audit_name;
139         char            relkind = get_rel_relkind(relOid);
140
141         if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
142                 return;
143
144         /*
145          * check db_column:{drop} permission
146          */
147         object.classId = RelationRelationId;
148         object.objectId = relOid;
149         object.objectSubId = attnum;
150         audit_name = getObjectIdentity(&object);
151
152         sepgsql_avc_check_perms(&object,
153                                                         SEPG_CLASS_DB_COLUMN,
154                                                         SEPG_DB_COLUMN__DROP,
155                                                         audit_name,
156                                                         true);
157         pfree(audit_name);
158 }
159
160 /*
161  * sepgsql_attribute_relabel
162  *
163  * It checks privileges to relabel the supplied column
164  * by the `seclabel'.
165  */
166 void
167 sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
168                                                   const char *seclabel)
169 {
170         ObjectAddress object;
171         char       *audit_name;
172         char            relkind = get_rel_relkind(relOid);
173
174         if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
175                 ereport(ERROR,
176                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
177                                  errmsg("cannot set security label on non-regular columns")));
178
179         object.classId = RelationRelationId;
180         object.objectId = relOid;
181         object.objectSubId = attnum;
182         audit_name = getObjectIdentity(&object);
183
184         /*
185          * check db_column:{setattr relabelfrom} permission
186          */
187         sepgsql_avc_check_perms(&object,
188                                                         SEPG_CLASS_DB_COLUMN,
189                                                         SEPG_DB_COLUMN__SETATTR |
190                                                         SEPG_DB_COLUMN__RELABELFROM,
191                                                         audit_name,
192                                                         true);
193
194         /*
195          * check db_column:{relabelto} permission
196          */
197         sepgsql_avc_check_perms_label(seclabel,
198                                                                   SEPG_CLASS_DB_COLUMN,
199                                                                   SEPG_DB_PROCEDURE__RELABELTO,
200                                                                   audit_name,
201                                                                   true);
202         pfree(audit_name);
203 }
204
205 /*
206  * sepgsql_attribute_setattr
207  *
208  * It checks privileges to alter the supplied column.
209  */
210 void
211 sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum)
212 {
213         ObjectAddress object;
214         char       *audit_name;
215         char            relkind = get_rel_relkind(relOid);
216
217         if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
218                 return;
219
220         /*
221          * check db_column:{setattr} permission
222          */
223         object.classId = RelationRelationId;
224         object.objectId = relOid;
225         object.objectSubId = attnum;
226         audit_name = getObjectIdentity(&object);
227
228         sepgsql_avc_check_perms(&object,
229                                                         SEPG_CLASS_DB_COLUMN,
230                                                         SEPG_DB_COLUMN__SETATTR,
231                                                         audit_name,
232                                                         true);
233         pfree(audit_name);
234 }
235
236 /*
237  * sepgsql_relation_post_create
238  *
239  * The post creation hook of relation/attribute
240  */
241 void
242 sepgsql_relation_post_create(Oid relOid)
243 {
244         Relation        rel;
245         ScanKeyData skey;
246         SysScanDesc sscan;
247         HeapTuple       tuple;
248         Form_pg_class classForm;
249         ObjectAddress object;
250         uint16_t        tclass;
251         char       *scontext;           /* subject */
252         char       *tcontext;           /* schema */
253         char       *rcontext;           /* relation */
254         char       *ccontext;           /* column */
255         char       *nsp_name;
256         StringInfoData audit_name;
257
258         /*
259          * Fetch catalog record of the new relation. Because pg_class entry is not
260          * visible right now, we need to scan the catalog using SnapshotSelf.
261          */
262         rel = heap_open(RelationRelationId, AccessShareLock);
263
264         ScanKeyInit(&skey,
265                                 ObjectIdAttributeNumber,
266                                 BTEqualStrategyNumber, F_OIDEQ,
267                                 ObjectIdGetDatum(relOid));
268
269         sscan = systable_beginscan(rel, ClassOidIndexId, true,
270                                                            SnapshotSelf, 1, &skey);
271
272         tuple = systable_getnext(sscan);
273         if (!HeapTupleIsValid(tuple))
274                 elog(ERROR, "could not find tuple for relation %u", relOid);
275
276         classForm = (Form_pg_class) GETSTRUCT(tuple);
277
278         /* ignore indexes on toast tables */
279         if (classForm->relkind == RELKIND_INDEX &&
280                 classForm->relnamespace == PG_TOAST_NAMESPACE)
281                 goto out;
282
283         /*
284          * check db_schema:{add_name} permission of the namespace
285          */
286         object.classId = NamespaceRelationId;
287         object.objectId = classForm->relnamespace;
288         object.objectSubId = 0;
289         sepgsql_avc_check_perms(&object,
290                                                         SEPG_CLASS_DB_SCHEMA,
291                                                         SEPG_DB_SCHEMA__ADD_NAME,
292                                                         getObjectIdentity(&object),
293                                                         true);
294
295         switch (classForm->relkind)
296         {
297                 case RELKIND_RELATION:
298                 case RELKIND_PARTITIONED_TABLE:
299                         tclass = SEPG_CLASS_DB_TABLE;
300                         break;
301                 case RELKIND_SEQUENCE:
302                         tclass = SEPG_CLASS_DB_SEQUENCE;
303                         break;
304                 case RELKIND_VIEW:
305                         tclass = SEPG_CLASS_DB_VIEW;
306                         break;
307                 case RELKIND_INDEX:
308                         /* deal with indexes specially; no need for tclass */
309                         sepgsql_index_modify(relOid);
310                         goto out;
311                 default:
312                         /* ignore other relkinds */
313                         goto out;
314         }
315
316         /*
317          * Compute a default security label when we create a new relation object
318          * under the specified namespace.
319          */
320         scontext = sepgsql_get_client_label();
321         tcontext = sepgsql_get_label(NamespaceRelationId,
322                                                                  classForm->relnamespace, 0);
323         rcontext = sepgsql_compute_create(scontext, tcontext, tclass,
324                                                                           NameStr(classForm->relname));
325
326         /*
327          * check db_xxx:{create} permission
328          */
329         nsp_name = get_namespace_name(classForm->relnamespace);
330         initStringInfo(&audit_name);
331         appendStringInfo(&audit_name, "%s.%s",
332                                          quote_identifier(nsp_name),
333                                          quote_identifier(NameStr(classForm->relname)));
334         sepgsql_avc_check_perms_label(rcontext,
335                                                                   tclass,
336                                                                   SEPG_DB_DATABASE__CREATE,
337                                                                   audit_name.data,
338                                                                   true);
339
340         /*
341          * Assign the default security label on the new regular or partitioned
342          * relation.
343          */
344         object.classId = RelationRelationId;
345         object.objectId = relOid;
346         object.objectSubId = 0;
347         SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, rcontext);
348
349         /*
350          * We also assign a default security label on columns of a new table.
351          */
352         if (classForm->relkind == RELKIND_RELATION ||
353                 classForm->relkind == RELKIND_PARTITIONED_TABLE)
354         {
355                 Relation        arel;
356                 ScanKeyData akey;
357                 SysScanDesc ascan;
358                 HeapTuple       atup;
359                 Form_pg_attribute attForm;
360
361                 arel = heap_open(AttributeRelationId, AccessShareLock);
362
363                 ScanKeyInit(&akey,
364                                         Anum_pg_attribute_attrelid,
365                                         BTEqualStrategyNumber, F_OIDEQ,
366                                         ObjectIdGetDatum(relOid));
367
368                 ascan = systable_beginscan(arel, AttributeRelidNumIndexId, true,
369                                                                    SnapshotSelf, 1, &akey);
370
371                 while (HeapTupleIsValid(atup = systable_getnext(ascan)))
372                 {
373                         attForm = (Form_pg_attribute) GETSTRUCT(atup);
374
375                         resetStringInfo(&audit_name);
376                         appendStringInfo(&audit_name, "%s.%s.%s",
377                                                          quote_identifier(nsp_name),
378                                                          quote_identifier(NameStr(classForm->relname)),
379                                                          quote_identifier(NameStr(attForm->attname)));
380
381                         ccontext = sepgsql_compute_create(scontext,
382                                                                                           rcontext,
383                                                                                           SEPG_CLASS_DB_COLUMN,
384                                                                                           NameStr(attForm->attname));
385
386                         /*
387                          * check db_column:{create} permission
388                          */
389                         sepgsql_avc_check_perms_label(ccontext,
390                                                                                   SEPG_CLASS_DB_COLUMN,
391                                                                                   SEPG_DB_COLUMN__CREATE,
392                                                                                   audit_name.data,
393                                                                                   true);
394
395                         object.classId = RelationRelationId;
396                         object.objectId = relOid;
397                         object.objectSubId = attForm->attnum;
398                         SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ccontext);
399
400                         pfree(ccontext);
401                 }
402                 systable_endscan(ascan);
403                 heap_close(arel, AccessShareLock);
404         }
405         pfree(rcontext);
406
407 out:
408         systable_endscan(sscan);
409         heap_close(rel, AccessShareLock);
410 }
411
412 /*
413  * sepgsql_relation_drop
414  *
415  * It checks privileges to drop the supplied relation.
416  */
417 void
418 sepgsql_relation_drop(Oid relOid)
419 {
420         ObjectAddress object;
421         char       *audit_name;
422         uint16_t        tclass = 0;
423         char            relkind = get_rel_relkind(relOid);
424
425         switch (relkind)
426         {
427                 case RELKIND_RELATION:
428                 case RELKIND_PARTITIONED_TABLE:
429                         tclass = SEPG_CLASS_DB_TABLE;
430                         break;
431                 case RELKIND_SEQUENCE:
432                         tclass = SEPG_CLASS_DB_SEQUENCE;
433                         break;
434                 case RELKIND_VIEW:
435                         tclass = SEPG_CLASS_DB_VIEW;
436                         break;
437                 case RELKIND_INDEX:
438                         /* ignore indexes on toast tables */
439                         if (get_rel_namespace(relOid) == PG_TOAST_NAMESPACE)
440                                 return;
441                         /* other indexes are handled specially below; no need for tclass */
442                         break;
443                 default:
444                         /* ignore other relkinds */
445                         return;
446         }
447
448         /*
449          * check db_schema:{remove_name} permission
450          */
451         object.classId = NamespaceRelationId;
452         object.objectId = get_rel_namespace(relOid);
453         object.objectSubId = 0;
454         audit_name = getObjectIdentity(&object);
455
456         sepgsql_avc_check_perms(&object,
457                                                         SEPG_CLASS_DB_SCHEMA,
458                                                         SEPG_DB_SCHEMA__REMOVE_NAME,
459                                                         audit_name,
460                                                         true);
461         pfree(audit_name);
462
463         /* deal with indexes specially */
464         if (relkind == RELKIND_INDEX)
465         {
466                 sepgsql_index_modify(relOid);
467                 return;
468         }
469
470         /*
471          * check db_table/sequence/view:{drop} permission
472          */
473         object.classId = RelationRelationId;
474         object.objectId = relOid;
475         object.objectSubId = 0;
476         audit_name = getObjectIdentity(&object);
477
478         sepgsql_avc_check_perms(&object,
479                                                         tclass,
480                                                         SEPG_DB_TABLE__DROP,
481                                                         audit_name,
482                                                         true);
483         pfree(audit_name);
484
485         /*
486          * check db_column:{drop} permission
487          */
488         if (relkind == RELKIND_RELATION || relkind == RELKIND_PARTITIONED_TABLE)
489         {
490                 Form_pg_attribute attForm;
491                 CatCList   *attrList;
492                 HeapTuple       atttup;
493                 int                     i;
494
495                 attrList = SearchSysCacheList1(ATTNUM, ObjectIdGetDatum(relOid));
496                 for (i = 0; i < attrList->n_members; i++)
497                 {
498                         atttup = &attrList->members[i]->tuple;
499                         attForm = (Form_pg_attribute) GETSTRUCT(atttup);
500
501                         if (attForm->attisdropped)
502                                 continue;
503
504                         object.classId = RelationRelationId;
505                         object.objectId = relOid;
506                         object.objectSubId = attForm->attnum;
507                         audit_name = getObjectIdentity(&object);
508
509                         sepgsql_avc_check_perms(&object,
510                                                                         SEPG_CLASS_DB_COLUMN,
511                                                                         SEPG_DB_COLUMN__DROP,
512                                                                         audit_name,
513                                                                         true);
514                         pfree(audit_name);
515                 }
516                 ReleaseCatCacheList(attrList);
517         }
518 }
519
520 /*
521  * sepgsql_relation_relabel
522  *
523  * It checks privileges to relabel the supplied relation by the `seclabel'.
524  */
525 void
526 sepgsql_relation_relabel(Oid relOid, const char *seclabel)
527 {
528         ObjectAddress object;
529         char       *audit_name;
530         char            relkind = get_rel_relkind(relOid);
531         uint16_t        tclass = 0;
532
533         if (relkind == RELKIND_RELATION || relkind == RELKIND_PARTITIONED_TABLE)
534                 tclass = SEPG_CLASS_DB_TABLE;
535         else if (relkind == RELKIND_SEQUENCE)
536                 tclass = SEPG_CLASS_DB_SEQUENCE;
537         else if (relkind == RELKIND_VIEW)
538                 tclass = SEPG_CLASS_DB_VIEW;
539         else
540                 ereport(ERROR,
541                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
542                                  errmsg("cannot set security labels on relations except "
543                                                 "for tables, sequences or views")));
544
545         object.classId = RelationRelationId;
546         object.objectId = relOid;
547         object.objectSubId = 0;
548         audit_name = getObjectIdentity(&object);
549
550         /*
551          * check db_xxx:{setattr relabelfrom} permission
552          */
553         sepgsql_avc_check_perms(&object,
554                                                         tclass,
555                                                         SEPG_DB_TABLE__SETATTR |
556                                                         SEPG_DB_TABLE__RELABELFROM,
557                                                         audit_name,
558                                                         true);
559
560         /*
561          * check db_xxx:{relabelto} permission
562          */
563         sepgsql_avc_check_perms_label(seclabel,
564                                                                   tclass,
565                                                                   SEPG_DB_TABLE__RELABELTO,
566                                                                   audit_name,
567                                                                   true);
568         pfree(audit_name);
569 }
570
571 /*
572  * sepgsql_relation_setattr
573  *
574  * It checks privileges to set attribute of the supplied relation
575  */
576 void
577 sepgsql_relation_setattr(Oid relOid)
578 {
579         Relation        rel;
580         ScanKeyData skey;
581         SysScanDesc sscan;
582         HeapTuple       oldtup;
583         HeapTuple       newtup;
584         Form_pg_class oldform;
585         Form_pg_class newform;
586         ObjectAddress object;
587         char       *audit_name;
588         uint16_t        tclass;
589
590         switch (get_rel_relkind(relOid))
591         {
592                 case RELKIND_RELATION:
593                 case RELKIND_PARTITIONED_TABLE:
594                         tclass = SEPG_CLASS_DB_TABLE;
595                         break;
596                 case RELKIND_SEQUENCE:
597                         tclass = SEPG_CLASS_DB_SEQUENCE;
598                         break;
599                 case RELKIND_VIEW:
600                         tclass = SEPG_CLASS_DB_VIEW;
601                         break;
602                 case RELKIND_INDEX:
603                         /* deal with indexes specially */
604                         sepgsql_index_modify(relOid);
605                         return;
606                 default:
607                         /* other relkinds don't need additional work */
608                         return;
609         }
610
611         /*
612          * Fetch newer catalog
613          */
614         rel = heap_open(RelationRelationId, AccessShareLock);
615
616         ScanKeyInit(&skey,
617                                 ObjectIdAttributeNumber,
618                                 BTEqualStrategyNumber, F_OIDEQ,
619                                 ObjectIdGetDatum(relOid));
620
621         sscan = systable_beginscan(rel, ClassOidIndexId, true,
622                                                            SnapshotSelf, 1, &skey);
623
624         newtup = systable_getnext(sscan);
625         if (!HeapTupleIsValid(newtup))
626                 elog(ERROR, "could not find tuple for relation %u", relOid);
627         newform = (Form_pg_class) GETSTRUCT(newtup);
628
629         /*
630          * Fetch older catalog
631          */
632         oldtup = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
633         if (!HeapTupleIsValid(oldtup))
634                 elog(ERROR, "cache lookup failed for relation %u", relOid);
635         oldform = (Form_pg_class) GETSTRUCT(oldtup);
636
637         /*
638          * Does this ALTER command takes operation to namespace?
639          */
640         if (newform->relnamespace != oldform->relnamespace)
641         {
642                 sepgsql_schema_remove_name(oldform->relnamespace);
643                 sepgsql_schema_add_name(newform->relnamespace);
644         }
645         if (strcmp(NameStr(newform->relname), NameStr(oldform->relname)) != 0)
646                 sepgsql_schema_rename(oldform->relnamespace);
647
648         /*
649          * XXX - In the future version, db_tuple:{use} of system catalog entry
650          * shall be checked, if tablespace configuration is changed.
651          */
652
653         /*
654          * check db_xxx:{setattr} permission
655          */
656         object.classId = RelationRelationId;
657         object.objectId = relOid;
658         object.objectSubId = 0;
659         audit_name = getObjectIdentity(&object);
660
661         sepgsql_avc_check_perms(&object,
662                                                         tclass,
663                                                         SEPG_DB_TABLE__SETATTR,
664                                                         audit_name,
665                                                         true);
666         pfree(audit_name);
667
668         ReleaseSysCache(oldtup);
669         systable_endscan(sscan);
670         heap_close(rel, AccessShareLock);
671 }
672
673 /*
674  * sepgsql_relation_setattr_extra
675  *
676  * It checks permission of the relation being referenced by extra attributes,
677  * such as pg_index entries. Like core PostgreSQL, sepgsql also does not deal
678  * with such entries as individual "objects", thus, modification of these
679  * entries shall be considered as setting an attribute of the underlying
680  * relation.
681  */
682 static void
683 sepgsql_relation_setattr_extra(Relation catalog,
684                                                            Oid catindex_id,
685                                                            Oid extra_oid,
686                                                            AttrNumber anum_relation_id,
687                                                            AttrNumber anum_extra_id)
688 {
689         ScanKeyData skey;
690         SysScanDesc sscan;
691         HeapTuple       tuple;
692         Datum           datum;
693         bool            isnull;
694
695         ScanKeyInit(&skey, anum_extra_id,
696                                 BTEqualStrategyNumber, F_OIDEQ,
697                                 ObjectIdGetDatum(extra_oid));
698
699         sscan = systable_beginscan(catalog, catindex_id, true,
700                                                            SnapshotSelf, 1, &skey);
701         tuple = systable_getnext(sscan);
702         if (!HeapTupleIsValid(tuple))
703                 elog(ERROR, "could not find tuple for object %u in catalog \"%s\"",
704                          extra_oid, RelationGetRelationName(catalog));
705
706         datum = heap_getattr(tuple, anum_relation_id,
707                                                  RelationGetDescr(catalog), &isnull);
708         Assert(!isnull);
709
710         sepgsql_relation_setattr(DatumGetObjectId(datum));
711
712         systable_endscan(sscan);
713 }
714
715 /*
716  * sepgsql_index_modify
717  *              Handle index create, update, drop
718  *
719  * Unlike other relation kinds, indexes do not have their own security labels,
720  * so instead of doing checks directly, treat them as extra attributes of their
721  * owning tables; so check 'setattr' permissions on the table.
722  */
723 static void
724 sepgsql_index_modify(Oid indexOid)
725 {
726         Relation        catalog = heap_open(IndexRelationId, AccessShareLock);
727
728         /* check db_table:{setattr} permission of the table being indexed */
729         sepgsql_relation_setattr_extra(catalog,
730                                                                    IndexRelidIndexId,
731                                                                    indexOid,
732                                                                    Anum_pg_index_indrelid,
733                                                                    Anum_pg_index_indexrelid);
734         heap_close(catalog, AccessShareLock);
735 }