diff options
| author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2012-10-23 18:07:26 -0300 |
|---|---|---|
| committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2012-10-23 18:24:24 -0300 |
| commit | f4c4335a4aaf5f2ee6e741cdf4f5c8e338d86a2f (patch) | |
| tree | 5367e466c939f55a3bf9dba7275887b309378b16 /contrib/sepgsql/relation.c | |
| parent | 4c9d0901f135d724a9f3cfa4140a5afd44b10f08 (diff) | |
| download | postgresql-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.c | 194 |
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); +} |
