security label support, part.1
The attached patch is a part of efforts to support security label
on database objects.
It adds a new system catalog named pg_seclabel, that has similar
structure with pg_description.
#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 label; /* security label of the object */
} FormData_pg_seclabel;
This patch provides only its definition and basic internal APIs to
get/set/delete security labels, so, we also need to apply the part.2
patch to support ALTER statement to manage security labels, in addition
to the part.1.
Right now, modular sepgsql will perform on the patch.
It can be checked out using:
% svn checkout http://sepgsql.googlecode.com/svn/trunk/sepgsql
Thanks,
--
KaiGai Kohei <kaigai@ak.jp.nec.com>
Attachments:
pgsql-v9.1-security-label-1.v1.patchapplication/octect-stream; name=pgsql-v9.1-security-label-1.v1.patchDownload
*** a/src/backend/catalog/Makefile
--- b/src/backend/catalog/Makefile
***************
*** 37,43 **** 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 \
toasting.h indexing.h \
)
--- 37,43 ----
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_seclabel.h \
toasting.h indexing.h \
)
*** a/src/backend/catalog/dependency.c
--- b/src/backend/catalog/dependency.c
***************
*** 57,62 ****
--- 57,63 ----
#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,1015 **** deleteOneObject(const ObjectAddress *object, Relation depRel)
--- 1011,1023 ----
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->classId, object->objectId, object->objectSubId);
+
+ /*
* CommandCounterIncrement here to ensure that preceding changes are all
* visible to the next deletion step.
*/
*** a/src/backend/commands/Makefile
--- b/src/backend/commands/Makefile
***************
*** 17,23 **** 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 \
tsearchcmds.o typecmds.o user.o vacuum.o vacuumlazy.o \
variable.o view.o
--- 17,23 ----
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 seclabel.o sequence.o tablecmds.o tablespace.o trigger.o \
tsearchcmds.o typecmds.o user.o vacuum.o vacuumlazy.o \
variable.o view.o
*** /dev/null
--- b/src/backend/commands/seclabel.c
***************
*** 0 ****
--- 1,259 ----
+ /* -------------------------------------------------------------------------
+ *
+ * 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/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(Oid classOid, Oid objOid, int4 subId)
+ {
+ Relation pg_seclabel;
+ ScanKeyData keys[3];
+ SysScanDesc scan;
+ HeapTuple tuple;
+ Datum datum;
+ bool isnull;
+ char *seclabel = NULL;
+
+ ScanKeyInit(&keys[0],
+ Anum_pg_seclabel_reloid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classOid));
+ ScanKeyInit(&keys[1],
+ Anum_pg_seclabel_objoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objOid));
+ ScanKeyInit(&keys[2],
+ Anum_pg_seclabel_subid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(subId));
+
+ pg_seclabel = heap_open(SecLabelRelationId, AccessShareLock);
+
+ scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
+ SnapshotNow, 3, 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(Oid classOid, Oid objOid, int4 subId, const char *seclabel)
+ {
+ Relation pg_seclabel;
+ ScanKeyData keys[3];
+ 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(classOid));
+ ScanKeyInit(&keys[1],
+ Anum_pg_seclabel_objoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objOid));
+ ScanKeyInit(&keys[2],
+ Anum_pg_seclabel_subid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(subId));
+
+ pg_seclabel = heap_open(SecLabelRelationId, RowExclusiveLock);
+
+ scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
+ SnapshotNow, 3, 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 new_label = 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(classOid);
+ values[Anum_pg_seclabel_objoid - 1] = ObjectIdGetDatum(objOid);
+ values[Anum_pg_seclabel_subid - 1] = Int32GetDatum(subId);
+ 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 'subId' is 0, all security labels matching the classOid
+ * and objOid will be removed.
+ */
+ static void
+ DeleteLocalSecLabel(Oid classOid, Oid objOid, int4 subId)
+ {
+ Relation pg_seclabel;
+ ScanKeyData keys[3];
+ SysScanDesc scan;
+ HeapTuple oldtup;
+ int nkeys = 2;
+
+ ScanKeyInit(&keys[0],
+ Anum_pg_seclabel_reloid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classOid));
+ ScanKeyInit(&keys[1],
+ Anum_pg_seclabel_objoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objOid));
+ if (subId != 0)
+ {
+ ScanKeyInit(&keys[2],
+ Anum_pg_seclabel_subid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(subId));
+ nkeys++;
+ }
+
+ 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(Oid classOid, Oid objOid, int4 subId)
+ {
+ Assert(!IsSharedRelation(classOid));
+
+ return GetLocalSecLabel(classOid, objOid, subId);
+ }
+
+ /*
+ * SetSecurityLabel
+ *
+ * An internal API to set a security label of the specified object.
+ */
+ void
+ SetSecurityLabel(Oid classOid, Oid objOid, int4 subId,
+ const char *seclabel)
+ {
+ Assert(!IsSharedRelation(classOid));
+
+ SetLocalSecLabel(classOid, objOid, subId, seclabel);
+ }
+
+ /*
+ * DeleteSecurityLabel
+ *
+ * An internal API to delete a security label of the specified object.
+ */
+ void
+ DeleteSecurityLabel(Oid classOid, Oid objOid, int4 subId)
+ {
+ Assert(!IsSharedRelation(classOid));
+
+ DeleteLocalSecLabel(classOid, objOid, subId);
+ }
*** a/src/include/catalog/indexing.h
--- b/src/include/catalog/indexing.h
***************
*** 281,286 **** DECLARE_UNIQUE_INDEX(pg_default_acl_oid_index, 828, on pg_default_acl using btre
--- 281,289 ----
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));
+ #define SecLabelObjectIndexId 3038
+
/* last step of initialization script: build the indexes declared above */
BUILD_INDICES
*** /dev/null
--- b/src/include/catalog/pg_seclabel.h
***************
*** 0 ****
--- 1,41 ----
+ /* -------------------------------------------------------------------------
+ *
+ * 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 label; /* security label of the object */
+ } FormData_pg_seclabel;
+
+ /* ----------------
+ * compiler constants for pg_seclabel
+ * ----------------
+ */
+ #define Natts_pg_seclabel 4
+ #define Anum_pg_seclabel_reloid 1
+ #define Anum_pg_seclabel_objoid 2
+ #define Anum_pg_seclabel_subid 3
+ #define Anum_pg_seclabel_label 4
+
+ #endif /* PG_SECLABEL_H */
*** a/src/include/catalog/toasting.h
--- b/src/include/catalog/toasting.h
***************
*** 45,50 **** DECLARE_TOAST(pg_constraint, 2832, 2833);
--- 45,51 ----
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);
*** /dev/null
--- b/src/include/commands/seclabel.h
***************
*** 0 ****
--- 1,21 ----
+ /*
+ * 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
+
+ /*
+ * Internal APIs
+ */
+ extern char *GetSecurityLabel(Oid classOid, Oid objOid, int4 subId);
+ extern void SetSecurityLabel(Oid classOid, Oid objOid, int4 subId,
+ const char *seclabel);
+ extern void DeleteSecurityLabel(Oid classOid, Oid objOid, int4 subId);
+
+ #endif /* SECLABEL_H */
+
*** a/src/test/regress/expected/sanity_check.out
--- b/src/test/regress/expected/sanity_check.out
***************
*** 114,119 **** SELECT relname, relhasindex
--- 114,120 ----
pg_pltemplate | t
pg_proc | t
pg_rewrite | t
+ pg_seclabel | t
pg_shdepend | t
pg_shdescription | t
pg_statistic | t
***************
*** 153,159 **** SELECT relname, relhasindex
timetz_tbl | f
tinterval_tbl | f
varchar_tbl | f
! (142 rows)
--
-- another sanity check: every system catalog that has OIDs should have
--- 154,160 ----
timetz_tbl | f
tinterval_tbl | f
varchar_tbl | f
! (143 rows)
--
-- another sanity check: every system catalog that has OIDs should have