pgsql-v9.1-security-label-1.v2.patch
application/octect-stream
Filename: pgsql-v9.1-security-label-1.v2.patch
Type: application/octect-stream
Part: 1
Message:
Re: security label support, part.2
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v9
| File | + | − |
|---|---|---|
| doc/src/sgml/catalogs.sgml | 90 | 0 |
| src/backend/catalog/dependency.c | 8 | 0 |
| src/backend/catalog/Makefile | 1 | 1 |
| src/backend/commands/Makefile | 1 | 1 |
| src/backend/commands/seclabel.c | 271 | 0 |
| src/include/catalog/indexing.h | 3 | 0 |
| src/include/catalog/pg_seclabel.h | 43 | 0 |
| src/include/catalog/toasting.h | 1 | 0 |
| src/include/commands/seclabel.h | 25 | 0 |
| src/test/regress/expected/sanity_check.out | 2 | 1 |
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index d2710db..e19cad6 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -209,6 +209,11 @@
</row>
<row>
+ <entry><link linkend="catalog-pg-seclabel"><structname>pg_seclabel</structname></link></entry>
+ <entry>security labels on local database objects</entry>
+ </row>
+
+ <row>
<entry><link linkend="catalog-pg-shdepend"><structname>pg_shdepend</structname></link></entry>
<entry>dependencies on shared objects</entry>
</row>
@@ -4204,6 +4209,91 @@
</table>
</sect1>
+ <sect1 id="catalog-pg-seclabel">
+ <title><structname>pg_seclabel</structname></title>
+
+ <indexterm zone="catalog-pg-seclabel">
+ <primary>pg_seclabel</primary>
+ </indexterm>
+
+ <para>
+ The catalog <structname>pg_seclabel</structname> stores the security
+ label of database objects. This information allows external security
+ providers to apply label based mandatory access controls.
+ </para>
+
+ <para>
+ When external security providers with label based mandatory access
+ control are installed, its security label shall be assigned on
+ creation of database obejcts.
+ (Please note that only relations are supported right now.)
+ </para>
+ <para>
+ The security labels shall be automatically cleaned up when the database
+ object being labeled is dropped.
+ </para>
+ <para>
+ See also <link linkend="sql-security-label"><command>SECURITY LABEL</command></link>,
+ which provides a functionality to relabel a certain database object,
+ as long as user has enough privileges.
+ </para>
+
+ <table>
+ <title><structname>pg_seclabel</structname> Columns</title>
+
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>References</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><structfield>reloid</structfield></entry>
+ <entry><type>oid</type></entry>
+ <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
+ <entry>The OID of the system catalog this object appears in</entry>
+ </row>
+
+ <row>
+ <entry><structfield>objoid</structfield></entry>
+ <entry><type>oid</type></entry>
+ <entry>any OID column</entry>
+ <entry>The OID of the object this security label assigned on</entry>
+ </row>
+
+ <row>
+ <entry><structfield>subid</structfield></entry>
+ <entry><type>int4</type></entry>
+ <entry></entry>
+ <entry>For a security label on a table column, this is the column number
+ (the <structfield>objoid</structfield> and <structfield>classoid</structfield>
+ refer to the table itself). For all other object types, this column is
+ zero
+ </entry>
+ </row>
+
+ <row>
+ <entry><structfield>tag</structfield></entry>
+ <entry><type>text</type></entry>
+ <entry></entry>
+ <entry>identifier of external security provider</entry>
+ </row>
+
+ <row>
+ <entry><structfield>label</structfield></entry>
+ <entry><type>text</type></entry>
+ <entry></entry>
+ <entry>security label in text format</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </sect1>
<sect1 id="catalog-pg-shdepend">
<title><structname>pg_shdepend</structname></title>
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 82f761d..362b153 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -37,7 +37,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
pg_ts_config.h pg_ts_config_map.h pg_ts_dict.h \
pg_ts_parser.h pg_ts_template.h \
pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \
- pg_default_acl.h \
+ pg_default_acl.h pg_seclabel.h \
toasting.h indexing.h \
)
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 12b5d85..b171f01 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -57,6 +57,7 @@
#include "commands/defrem.h"
#include "commands/proclang.h"
#include "commands/schemacmds.h"
+#include "commands/seclabel.h"
#include "commands/tablespace.h"
#include "commands/trigger.h"
#include "commands/typecmds.h"
@@ -1010,6 +1011,13 @@ deleteOneObject(const ObjectAddress *object, Relation depRel)
DeleteComments(object->objectId, object->classId, object->objectSubId);
/*
+ * Delete any security labels associated with this object. (This is also
+ * a convenient place to do it instead of having every object type know
+ * to do it.)
+ */
+ DeleteSecurityLabel(object);
+
+ /*
* CommandCounterIncrement here to ensure that preceding changes are all
* visible to the next deletion step.
*/
diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile
index a2cc786..17ce32b 100644
--- a/src/backend/commands/Makefile
+++ b/src/backend/commands/Makefile
@@ -17,7 +17,7 @@ OBJS = aggregatecmds.o alter.o analyze.o async.o cluster.o comment.o \
dbcommands.o define.o discard.o explain.o foreigncmds.o functioncmds.o \
indexcmds.o lockcmds.o operatorcmds.o opclasscmds.o \
portalcmds.o prepare.o proclang.o \
- schemacmds.o sequence.o tablecmds.o tablespace.o trigger.o \
+ schemacmds.o seclabel.o sequence.o tablecmds.o tablespace.o trigger.o \
tsearchcmds.o typecmds.o user.o vacuum.o vacuumlazy.o \
variable.o view.o
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
new file mode 100644
index 0000000..5f914fa
--- /dev/null
+++ b/src/backend/commands/seclabel.c
@@ -0,0 +1,271 @@
+/* -------------------------------------------------------------------------
+ *
+ * seclabel.c
+ * routines to support security label feature.
+ *
+ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_seclabel.h"
+#include "commands/seclabel.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/rel.h"
+#include "utils/tqual.h"
+
+/*
+ * GetLocalSecLabel
+ *
+ * It tries to look up a security label entry for the given OID of the
+ * relation, object itself and sub identifier (if needed) from the
+ * pg_seclabel system catalog.
+ * It returns NULL, if no valid entry. Elsewhere, it returns a security
+ * label of the specified object.
+ */
+static char *
+GetLocalSecLabel(const ObjectAddress *object, const char *tag)
+{
+ Relation pg_seclabel;
+ ScanKeyData keys[4];
+ SysScanDesc scan;
+ HeapTuple tuple;
+ Datum datum;
+ bool isnull;
+ char *seclabel = NULL;
+
+ ScanKeyInit(&keys[0],
+ Anum_pg_seclabel_reloid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->classId));
+ ScanKeyInit(&keys[1],
+ Anum_pg_seclabel_objoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+ ScanKeyInit(&keys[2],
+ Anum_pg_seclabel_subid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(object->objectSubId));
+ ScanKeyInit(&keys[3],
+ Anum_pg_seclabel_tag,
+ BTEqualStrategyNumber, F_TEXTEQ,
+ CStringGetTextDatum(tag));
+
+ pg_seclabel = heap_open(SecLabelRelationId, AccessShareLock);
+
+ scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
+ SnapshotNow, 4, keys);
+
+ tuple = systable_getnext(scan);
+ if (HeapTupleIsValid(tuple))
+ {
+ datum = heap_getattr(tuple, Anum_pg_seclabel_label,
+ RelationGetDescr(pg_seclabel), &isnull);
+ if (!isnull)
+ seclabel = TextDatumGetCString(datum);
+ }
+ systable_endscan(scan);
+
+ heap_close(pg_seclabel, AccessShareLock);
+
+ return seclabel;
+}
+
+/*
+ * SetLocalSecLabel
+ *
+ * It tries to insert/update/delete a security label for the given OID
+ * of the relation, object itself and sub identifier (if needed) on the
+ * pg_seclabel system catalog.
+ * If given 'new_label' is NULL, it tries to delete the specified entry.
+ * Elsewhere, it tries to insert (if no specified entry now) or update
+ * security label of the specified entry.
+ */
+static void
+SetLocalSecLabel(const ObjectAddress *object,
+ const char *tag, const char *seclabel)
+{
+ Relation pg_seclabel;
+ ScanKeyData keys[4];
+ SysScanDesc scan;
+ HeapTuple oldtup;
+ HeapTuple newtup = NULL;
+ Datum values[Natts_pg_seclabel];
+ bool nulls[Natts_pg_seclabel];
+ bool replaces[Natts_pg_seclabel];
+
+ ScanKeyInit(&keys[0],
+ Anum_pg_seclabel_reloid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->classId));
+ ScanKeyInit(&keys[1],
+ Anum_pg_seclabel_objoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+ ScanKeyInit(&keys[2],
+ Anum_pg_seclabel_subid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(object->objectSubId));
+ ScanKeyInit(&keys[3],
+ Anum_pg_seclabel_tag,
+ BTEqualStrategyNumber, F_TEXTEQ,
+ CStringGetTextDatum(tag));
+
+ pg_seclabel = heap_open(SecLabelRelationId, RowExclusiveLock);
+
+ scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
+ SnapshotNow, 4, keys);
+
+ oldtup = systable_getnext(scan);
+ if (HeapTupleIsValid(oldtup))
+ {
+ if (seclabel != NULL)
+ {
+ /*
+ * update the specified security label entry
+ */
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_seclabel_label - 1] = true;
+ values[Anum_pg_seclabel_label - 1]
+ = CStringGetTextDatum(seclabel);
+
+ newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel),
+ values, nulls, replaces);
+ simple_heap_update(pg_seclabel, &oldtup->t_self, newtup);
+
+ CatalogUpdateIndexes(pg_seclabel, newtup);
+
+ heap_freetuple(newtup);
+ }
+ else
+ {
+ /*
+ * when seclabel = NULL, it means to remove the matched
+ * entry from pg_seclabel.
+ */
+ simple_heap_delete(pg_seclabel, &oldtup->t_self);
+ }
+ }
+ else if (seclabel != NULL)
+ {
+ /*
+ * insert a new security label entry
+ */
+ memset(nulls, false, sizeof(nulls));
+ values[Anum_pg_seclabel_reloid - 1] = ObjectIdGetDatum(object->classId);
+ values[Anum_pg_seclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
+ values[Anum_pg_seclabel_subid - 1] = Int32GetDatum(object->objectSubId);
+ values[Anum_pg_seclabel_tag - 1] = CStringGetTextDatum(tag);
+ values[Anum_pg_seclabel_label - 1] = CStringGetTextDatum(seclabel);
+
+ newtup = heap_form_tuple(RelationGetDescr(pg_seclabel),
+ values, nulls);
+ simple_heap_insert(pg_seclabel, newtup);
+
+ CatalogUpdateIndexes(pg_seclabel, newtup);
+
+ heap_freetuple(newtup);
+ }
+ systable_endscan(scan);
+
+ heap_close(pg_seclabel, RowExclusiveLock);
+}
+
+/*
+ * DeleteLocalSecLabel
+ *
+ * It tries to delete entries of security labels for the given OID
+ * of the relation, object itself and sub identifier (if needed) on
+ * the pg_seclabel system catalog.
+ * If given 'objectSubId' is 0, all security labels matching with
+ * classId and objectId will be removed.
+ */
+static void
+DeleteLocalSecLabel(const ObjectAddress *object)
+{
+ Relation pg_seclabel;
+ ScanKeyData keys[3];
+ SysScanDesc scan;
+ HeapTuple oldtup;
+ int nkeys = 0;
+
+ ScanKeyInit(&keys[nkeys++],
+ Anum_pg_seclabel_reloid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->classId));
+ ScanKeyInit(&keys[nkeys++],
+ Anum_pg_seclabel_objoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+ if (object->objectSubId != 0)
+ {
+ ScanKeyInit(&keys[nkeys++],
+ Anum_pg_seclabel_subid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(object->objectSubId));
+ }
+
+ pg_seclabel = heap_open(SecLabelRelationId, RowExclusiveLock);
+
+ scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
+ SnapshotNow, nkeys, keys);
+ while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
+ {
+ simple_heap_delete(pg_seclabel, &oldtup->t_self);
+ }
+ systable_endscan(scan);
+
+ heap_close(pg_seclabel, RowExclusiveLock);
+}
+
+/*
+ * GetSecurityLabel
+ *
+ * An internal API to get a security label of the specified object.
+ */
+char *
+GetSecurityLabel(const ObjectAddress *object, const char *tag)
+{
+ Assert(!IsSharedRelation(object->classId));
+
+ return GetLocalSecLabel(object, tag);
+}
+
+/*
+ * SetSecurityLabel
+ *
+ * An internal API to set a security label of the specified object.
+ */
+void
+SetSecurityLabel(const ObjectAddress *object,
+ const char *tag, const char *seclabel)
+{
+ Assert(!IsSharedRelation(object->classId));
+
+ SetLocalSecLabel(object, tag, seclabel);
+}
+
+/*
+ * DeleteSecurityLabel
+ *
+ * An internal API to delete all the security labels of the specified object.
+ */
+void
+DeleteSecurityLabel(const ObjectAddress *object)
+{
+ /* Right now, nothing to do for the shared relation */
+ if (IsSharedRelation(object->classId))
+ return;
+
+ DeleteLocalSecLabel(object);
+}
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index 4f437fd..a297402 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -281,6 +281,9 @@ DECLARE_UNIQUE_INDEX(pg_default_acl_oid_index, 828, on pg_default_acl using btre
DECLARE_UNIQUE_INDEX(pg_db_role_setting_databaseid_rol_index, 2965, on pg_db_role_setting using btree(setdatabase oid_ops, setrole oid_ops));
#define DbRoleSettingDatidRolidIndexId 2965
+DECLARE_UNIQUE_INDEX(pg_seclabel_object_index, 3038, on pg_seclabel using btree(reloid oid_ops, objoid oid_ops, subid int4_ops, tag text_ops));
+#define SecLabelObjectIndexId 3038
+
/* last step of initialization script: build the indexes declared above */
BUILD_INDICES
diff --git a/src/include/catalog/pg_seclabel.h b/src/include/catalog/pg_seclabel.h
new file mode 100644
index 0000000..7c1255c
--- /dev/null
+++ b/src/include/catalog/pg_seclabel.h
@@ -0,0 +1,43 @@
+/* -------------------------------------------------------------------------
+ *
+ * pg_seclabel.h
+ * definition of the system "security label" relation (pg_seclabel)
+ *
+ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * -------------------------------------------------------------------------
+ */
+#ifndef PG_SECLABEL_H
+#define PG_SECLABEL_H
+
+#include "catalog/genbki.h"
+
+/* ----------------
+ * pg_seclabel definition. cpp turns this into
+ * typedef struct FormData_pg_seclabel
+ * ----------------
+ */
+#define SecLabelRelationId 3037
+
+CATALOG(pg_seclabel,3037) BKI_WITHOUT_OIDS
+{
+ Oid reloid; /* OID of table containing the object */
+ Oid objoid; /* OID of the object itself */
+ int4 subid; /* column number, or 0 if not used */
+ text tag; /* identifier of external security provider */
+ text label; /* security label of the object */
+} FormData_pg_seclabel;
+
+/* ----------------
+ * compiler constants for pg_seclabel
+ * ----------------
+ */
+#define Natts_pg_seclabel 5
+#define Anum_pg_seclabel_reloid 1
+#define Anum_pg_seclabel_objoid 2
+#define Anum_pg_seclabel_subid 3
+#define Anum_pg_seclabel_tag 4
+#define Anum_pg_seclabel_label 5
+
+#endif /* PG_SECLABEL_H */
diff --git a/src/include/catalog/toasting.h b/src/include/catalog/toasting.h
index fb6f678..fa47938 100644
--- a/src/include/catalog/toasting.h
+++ b/src/include/catalog/toasting.h
@@ -45,6 +45,7 @@ DECLARE_TOAST(pg_constraint, 2832, 2833);
DECLARE_TOAST(pg_description, 2834, 2835);
DECLARE_TOAST(pg_proc, 2836, 2837);
DECLARE_TOAST(pg_rewrite, 2838, 2839);
+DECLARE_TOAST(pg_seclabel, 3039, 3040);
DECLARE_TOAST(pg_statistic, 2840, 2841);
DECLARE_TOAST(pg_trigger, 2336, 2337);
diff --git a/src/include/commands/seclabel.h b/src/include/commands/seclabel.h
new file mode 100644
index 0000000..b69fc07
--- /dev/null
+++ b/src/include/commands/seclabel.h
@@ -0,0 +1,25 @@
+/*
+ * seclabel.h
+ *
+ * Prototypes for functions in commands/seclabel.c
+ *
+ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ */
+#ifndef SECLABEL_H
+#define SECLABEL_H
+
+#include "catalog/dependency.h"
+
+/*
+ * Internal APIs
+ */
+extern char *GetSecurityLabel(const ObjectAddress *object,
+ const char *tag);
+extern void SetSecurityLabel(const ObjectAddress *object,
+ const char *tag,
+ const char *seclabel);
+extern void DeleteSecurityLabel(const ObjectAddress *object);
+
+#endif /* SECLABEL_H */
+
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 1d9e110..9596b0b 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -114,6 +114,7 @@ SELECT relname, relhasindex
pg_pltemplate | t
pg_proc | t
pg_rewrite | t
+ pg_seclabel | t
pg_shdepend | t
pg_shdescription | t
pg_statistic | t
@@ -153,7 +154,7 @@ SELECT relname, relhasindex
timetz_tbl | f
tinterval_tbl | f
varchar_tbl | f
-(142 rows)
+(143 rows)
--
-- another sanity check: every system catalog that has OIDs should have