summaryrefslogtreecommitdiff
path: root/contrib/sepgsql/relation.c
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2012-10-23 18:07:26 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2012-10-23 18:24:24 -0300
commitf4c4335a4aaf5f2ee6e741cdf4f5c8e338d86a2f (patch)
tree5367e466c939f55a3bf9dba7275887b309378b16 /contrib/sepgsql/relation.c
parent4c9d0901f135d724a9f3cfa4140a5afd44b10f08 (diff)
downloadpostgresql-f4c4335a4aaf5f2ee6e741cdf4f5c8e338d86a2f.tar.gz
Add context info to OAT_POST_CREATE security hook
... and have sepgsql use it to determine whether to check permissions during certain operations. Indexes that are being created as a result of REINDEX, for instance, do not need to have their permissions checked; they were already checked when the index was created. Author: KaiGai Kohei, slightly revised by me
Diffstat (limited to 'contrib/sepgsql/relation.c')
-rw-r--r--contrib/sepgsql/relation.c194
1 files changed, 173 insertions, 21 deletions
diff --git a/contrib/sepgsql/relation.c b/contrib/sepgsql/relation.c
index 4ab7fc8be9..783f330d1c 100644
--- a/contrib/sepgsql/relation.c
+++ b/contrib/sepgsql/relation.c
@@ -23,11 +23,14 @@
#include "utils/fmgroids.h"
#include "utils/catcache.h"
#include "utils/lsyscache.h"
+#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
#include "sepgsql.h"
+static void sepgsql_index_modify(Oid indexOid);
+
/*
* sepgsql_attribute_post_create
*
@@ -229,6 +232,23 @@ sepgsql_relation_post_create(Oid relOid)
classForm = (Form_pg_class) GETSTRUCT(tuple);
+ /* ignore indexes on toast tables */
+ if (classForm->relkind == RELKIND_INDEX &&
+ classForm->relnamespace == PG_TOAST_NAMESPACE)
+ goto out;
+
+ /*
+ * check db_schema:{add_name} permission of the namespace
+ */
+ object.classId = NamespaceRelationId;
+ object.objectId = classForm->relnamespace;
+ object.objectSubId = 0;
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_SCHEMA,
+ SEPG_DB_SCHEMA__ADD_NAME,
+ getObjectDescription(&object),
+ true);
+
switch (classForm->relkind)
{
case RELKIND_RELATION:
@@ -243,23 +263,16 @@ sepgsql_relation_post_create(Oid relOid)
tclass = SEPG_CLASS_DB_VIEW;
tclass_text = "view";
break;
+ case RELKIND_INDEX:
+ /* deal with indexes specially; no need for tclass */
+ sepgsql_index_modify(relOid);
+ goto out;
default:
+ /* ignore other relkinds */
goto out;
}
/*
- * check db_schema:{add_name} permission of the namespace
- */
- object.classId = NamespaceRelationId;
- object.objectId = classForm->relnamespace;
- object.objectSubId = 0;
- sepgsql_avc_check_perms(&object,
- SEPG_CLASS_DB_SCHEMA,
- SEPG_DB_SCHEMA__ADD_NAME,
- getObjectDescription(&object),
- true);
-
- /*
* Compute a default security label when we create a new relation object
* under the specified namespace.
*/
@@ -342,6 +355,7 @@ sepgsql_relation_post_create(Oid relOid)
heap_close(arel, AccessShareLock);
}
pfree(rcontext);
+
out:
systable_endscan(sscan);
heap_close(rel, AccessShareLock);
@@ -357,18 +371,31 @@ sepgsql_relation_drop(Oid relOid)
{
ObjectAddress object;
char *audit_name;
- uint16_t tclass = 0;
+ uint16_t tclass;
char relkind;
relkind = get_rel_relkind(relOid);
- if (relkind == RELKIND_RELATION)
- tclass = SEPG_CLASS_DB_TABLE;
- else if (relkind == RELKIND_SEQUENCE)
- tclass = SEPG_CLASS_DB_SEQUENCE;
- else if (relkind == RELKIND_VIEW)
- tclass = SEPG_CLASS_DB_VIEW;
- else
- return;
+ switch (relkind)
+ {
+ case RELKIND_RELATION:
+ tclass = SEPG_CLASS_DB_TABLE;
+ break;
+ case RELKIND_SEQUENCE:
+ tclass = SEPG_CLASS_DB_SEQUENCE;
+ break;
+ case RELKIND_VIEW:
+ tclass = SEPG_CLASS_DB_VIEW;
+ break;
+ case RELKIND_INDEX:
+ /* ignore indexes on toast tables */
+ if (get_rel_namespace(relOid) == PG_TOAST_NAMESPACE)
+ return;
+ /* other indexes are handled specially below; no need for tclass */
+ break;
+ default:
+ /* ignore other relkinds */
+ return;
+ }
/*
* check db_schema:{remove_name} permission
@@ -385,6 +412,13 @@ sepgsql_relation_drop(Oid relOid)
true);
pfree(audit_name);
+ /* deal with indexes specially */
+ if (relkind == RELKIND_INDEX)
+ {
+ sepgsql_index_modify(relOid);
+ return;
+ }
+
/*
* check db_table/sequence/view:{drop} permission
*/
@@ -486,3 +520,121 @@ sepgsql_relation_relabel(Oid relOid, const char *seclabel)
true);
pfree(audit_name);
}
+
+/*
+ * sepgsql_relation_setattr
+ *
+ * It checks privileges to set attribute of the supplied relation
+ */
+void
+sepgsql_relation_setattr(Oid relOid)
+{
+ ObjectAddress object;
+ char *audit_name;
+ uint16_t tclass;
+
+ switch (get_rel_relkind(relOid))
+ {
+ case RELKIND_RELATION:
+ tclass = SEPG_CLASS_DB_TABLE;
+ break;
+ case RELKIND_SEQUENCE:
+ tclass = SEPG_CLASS_DB_SEQUENCE;
+ break;
+ case RELKIND_VIEW:
+ tclass = SEPG_CLASS_DB_VIEW;
+ break;
+ case RELKIND_INDEX:
+ /* deal with indexes specially */
+ sepgsql_index_modify(relOid);
+ return;
+ default:
+ /* other relkinds don't need additional work */
+ return;
+ }
+
+ object.classId = RelationRelationId;
+ object.objectId = relOid;
+ object.objectSubId = 0;
+ audit_name = getObjectDescription(&object);
+
+ /*
+ * XXX - we should add checks related to namespace stuff, when
+ * object_access_hook get support for ALTER statement. Right now, there is
+ * no invocation path on ALTER ... RENAME TO / SET SCHEMA.
+ */
+
+ /*
+ * check db_xxx:{setattr} permission
+ */
+ sepgsql_avc_check_perms(&object,
+ tclass,
+ SEPG_DB_TABLE__SETATTR,
+ audit_name,
+ true);
+ pfree(audit_name);
+}
+
+/*
+ * sepgsql_relation_setattr_extra
+ *
+ * It checks permission of the relation being referenced by extra attributes,
+ * such as pg_index entries. Like core PostgreSQL, sepgsql also does not deal
+ * with such entries as individual "objects", thus, modification of these
+ * entries shall be considered as setting an attribute of the underlying
+ * relation.
+ */
+static void
+sepgsql_relation_setattr_extra(Relation catalog,
+ Oid catindex_id,
+ Oid extra_oid,
+ AttrNumber anum_relation_id,
+ AttrNumber anum_extra_id)
+{
+ ScanKeyData skey;
+ SysScanDesc sscan;
+ HeapTuple tuple;
+ Datum datum;
+ bool isnull;
+
+ ScanKeyInit(&skey, anum_extra_id,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(extra_oid));
+
+ sscan = systable_beginscan(catalog, catindex_id, true,
+ SnapshotSelf, 1, &skey);
+ tuple = systable_getnext(sscan);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "catalog lookup failed for object %u in catalog \"%s\"",
+ extra_oid, RelationGetRelationName(catalog));
+
+ datum = heap_getattr(tuple, anum_relation_id,
+ RelationGetDescr(catalog), &isnull);
+ Assert(!isnull);
+
+ sepgsql_relation_setattr(DatumGetObjectId(datum));
+
+ systable_endscan(sscan);
+}
+
+/*
+ * sepgsql_index_modify
+ * Handle index create, update, drop
+ *
+ * Unlike other relation kinds, indexes do not have their own security labels,
+ * so instead of doing checks directly, treat them as extra attributes of their
+ * owning tables; so check 'setattr' permissions on the table.
+ */
+static void
+sepgsql_index_modify(Oid indexOid)
+{
+ Relation catalog = heap_open(IndexRelationId, AccessShareLock);
+
+ /* check db_table:{setattr} permission of the table being indexed */
+ sepgsql_relation_setattr_extra(catalog,
+ IndexRelidIndexId,
+ indexOid,
+ Anum_pg_index_indrelid,
+ Anum_pg_index_indexrelid);
+ heap_close(catalog, AccessShareLock);
+}