#include "postgres.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "access/tupdesc.h"
#include "catalog/catalog.h"
#include "catalog/heap.h"
#include "catalog/dependency.h"
#include "catalog/pg_attribute.h"
#include "catalog/pg_class.h"
#include "catalog/pg_inherits_fn.h"
#include "commands/seclabel.h"
#include "commands/tablecmds.h"
#include "executor/executor.h"
#include "nodes/bitmapset.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "sepgsql.h"
Go to the source code of this file.
Functions | |
static Bitmapset * | fixup_whole_row_references (Oid relOid, Bitmapset *columns) |
static Bitmapset * | fixup_inherited_columns (Oid parentId, Oid childId, Bitmapset *columns) |
static bool | check_relation_privileges (Oid relOid, Bitmapset *selected, Bitmapset *modified, uint32 required, bool abort_on_violation) |
bool | sepgsql_dml_privileges (List *rangeTabls, bool abort_on_violation) |
static bool check_relation_privileges | ( | Oid | relOid, | |
Bitmapset * | selected, | |||
Bitmapset * | modified, | |||
uint32 | required, | |||
bool | abort_on_violation | |||
) | [static] |
Definition at line 148 of file dml.c.
References Assert, bms_first_member(), bms_is_member(), bms_union(), ereport, errcode(), errmsg(), ERROR, fixup_whole_row_references(), get_rel_namespace(), get_rel_relkind(), getObjectDescription(), getObjectIdentity(), IsSystemNamespace(), pfree(), RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_TOASTVALUE, RELKIND_VIEW, SEPG_CLASS_DB_COLUMN, SEPG_CLASS_DB_SEQUENCE, SEPG_CLASS_DB_TABLE, SEPG_CLASS_DB_VIEW, SEPG_DB_SEQUENCE__GET_VALUE, SEPG_DB_TABLE__DELETE, SEPG_DB_TABLE__INSERT, SEPG_DB_TABLE__SELECT, SEPG_DB_TABLE__UPDATE, SEPG_DB_VIEW__EXPAND, sepgsql_avc_check_perms(), and sepgsql_getenforce().
Referenced by sepgsql_dml_privileges().
{ ObjectAddress object; char *audit_name; Bitmapset *columns; int index; char relkind = get_rel_relkind(relOid); bool result = true; /* * Hardwired Policies: SE-PostgreSQL enforces - clients cannot modify * system catalogs using DMLs - clients cannot reference/modify toast * relations using DMLs */ if (sepgsql_getenforce() > 0) { Oid relnamespace = get_rel_namespace(relOid); if (IsSystemNamespace(relnamespace) && (required & (SEPG_DB_TABLE__UPDATE | SEPG_DB_TABLE__INSERT | SEPG_DB_TABLE__DELETE)) != 0) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("SELinux: hardwired security policy violation"))); if (relkind == RELKIND_TOASTVALUE) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("SELinux: hardwired security policy violation"))); } /* * Check permissions on the relation */ object.classId = RelationRelationId; object.objectId = relOid; object.objectSubId = 0; audit_name = getObjectIdentity(&object); switch (relkind) { case RELKIND_RELATION: result = sepgsql_avc_check_perms(&object, SEPG_CLASS_DB_TABLE, required, audit_name, abort_on_violation); break; case RELKIND_SEQUENCE: Assert((required & ~SEPG_DB_TABLE__SELECT) == 0); if (required & SEPG_DB_TABLE__SELECT) result = sepgsql_avc_check_perms(&object, SEPG_CLASS_DB_SEQUENCE, SEPG_DB_SEQUENCE__GET_VALUE, audit_name, abort_on_violation); break; case RELKIND_VIEW: result = sepgsql_avc_check_perms(&object, SEPG_CLASS_DB_VIEW, SEPG_DB_VIEW__EXPAND, audit_name, abort_on_violation); break; default: /* nothing to be checked */ break; } pfree(audit_name); /* * Only columns owned by relations shall be checked */ if (relkind != RELKIND_RELATION) return true; /* * Check permissions on the columns */ selected = fixup_whole_row_references(relOid, selected); modified = fixup_whole_row_references(relOid, modified); columns = bms_union(selected, modified); while ((index = bms_first_member(columns)) >= 0) { AttrNumber attnum; uint32 column_perms = 0; if (bms_is_member(index, selected)) column_perms |= SEPG_DB_COLUMN__SELECT; if (bms_is_member(index, modified)) { if (required & SEPG_DB_TABLE__UPDATE) column_perms |= SEPG_DB_COLUMN__UPDATE; if (required & SEPG_DB_TABLE__INSERT) column_perms |= SEPG_DB_COLUMN__INSERT; } if (column_perms == 0) continue; /* obtain column's permission */ attnum = index + FirstLowInvalidHeapAttributeNumber; object.classId = RelationRelationId; object.objectId = relOid; object.objectSubId = attnum; audit_name = getObjectDescription(&object); result = sepgsql_avc_check_perms(&object, SEPG_CLASS_DB_COLUMN, column_perms, audit_name, abort_on_violation); pfree(audit_name); if (!result) return result; } return true; }
static Bitmapset* fixup_inherited_columns | ( | Oid | parentId, | |
Oid | childId, | |||
Bitmapset * | columns | |||
) | [static] |
Definition at line 94 of file dml.c.
References bms_add_member(), bms_copy(), bms_first_member(), bms_free(), elog, ERROR, get_attname(), get_attnum(), InvalidAttrNumber, and pfree().
Referenced by sepgsql_dml_privileges().
{ AttrNumber attno; Bitmapset *tmpset; Bitmapset *result = NULL; char *attname; int index; /* * obviously, no need to do anything here */ if (parentId == childId) return columns; tmpset = bms_copy(columns); while ((index = bms_first_member(tmpset)) > 0) { attno = index + FirstLowInvalidHeapAttributeNumber; /* * whole-row-reference shall be fixed-up later */ if (attno == InvalidAttrNumber) { result = bms_add_member(result, index); continue; } attname = get_attname(parentId, attno); if (!attname) elog(ERROR, "cache lookup failed for attribute %d of relation %u", attno, parentId); attno = get_attnum(childId, attname); if (attno == InvalidAttrNumber) elog(ERROR, "cache lookup failed for attribute %s of relation %u", attname, childId); index = attno - FirstLowInvalidHeapAttributeNumber; result = bms_add_member(result, index); pfree(attname); } bms_free(tmpset); return result; }
Definition at line 39 of file dml.c.
References ATTNUM, bms_add_member(), bms_copy(), bms_del_member(), bms_is_member(), elog, ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum, InvalidAttrNumber, ObjectIdGetDatum, ReleaseSysCache(), RELOID, SearchSysCache1, and SearchSysCache2.
Referenced by check_relation_privileges().
{ Bitmapset *result; HeapTuple tuple; AttrNumber natts; AttrNumber attno; int index; /* if no whole of row references, do not anything */ index = InvalidAttrNumber - FirstLowInvalidHeapAttributeNumber; if (!bms_is_member(index, columns)) return columns; /* obtain number of attributes */ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for relation %u", relOid); natts = ((Form_pg_class) GETSTRUCT(tuple))->relnatts; ReleaseSysCache(tuple); /* fix up the given columns */ result = bms_copy(columns); result = bms_del_member(result, index); for (attno = 1; attno <= natts; attno++) { tuple = SearchSysCache2(ATTNUM, ObjectIdGetDatum(relOid), Int16GetDatum(attno)); if (!HeapTupleIsValid(tuple)) continue; if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped) continue; index = attno - FirstLowInvalidHeapAttributeNumber; result = bms_add_member(result, index); ReleaseSysCache(tuple); } return result; }
Definition at line 283 of file dml.c.
References ACL_DELETE, ACL_INSERT, ACL_SELECT, ACL_UPDATE, bms_is_empty(), check_relation_privileges(), find_all_inheritors(), fixup_inherited_columns(), RangeTblEntry::inh, lfirst, lfirst_oid, list_free(), list_make1_oid, RangeTblEntry::modifiedCols, NoLock, NULL, RangeTblEntry::relid, RangeTblEntry::requiredPerms, RTE_RELATION, RangeTblEntry::rtekind, and RangeTblEntry::selectedCols.
Referenced by sepgsql_exec_check_perms().
{ ListCell *lr; foreach(lr, rangeTabls) { RangeTblEntry *rte = lfirst(lr); uint32 required = 0; List *tableIds; ListCell *li; /* * Only regular relations shall be checked */ if (rte->rtekind != RTE_RELATION) continue; /* * Find out required permissions */ if (rte->requiredPerms & ACL_SELECT) required |= SEPG_DB_TABLE__SELECT; if (rte->requiredPerms & ACL_INSERT) required |= SEPG_DB_TABLE__INSERT; if (rte->requiredPerms & ACL_UPDATE) { if (!bms_is_empty(rte->modifiedCols)) required |= SEPG_DB_TABLE__UPDATE; else required |= SEPG_DB_TABLE__LOCK; } if (rte->requiredPerms & ACL_DELETE) required |= SEPG_DB_TABLE__DELETE; /* * Skip, if nothing to be checked */ if (required == 0) continue; /* * If this RangeTblEntry is also supposed to reference inherited * tables, we need to check security label of the child tables. So, we * expand rte->relid into list of OIDs of inheritance hierarchy, then * checker routine will be invoked for each relations. */ if (!rte->inh) tableIds = list_make1_oid(rte->relid); else tableIds = find_all_inheritors(rte->relid, NoLock, NULL); foreach(li, tableIds) { Oid tableOid = lfirst_oid(li); Bitmapset *selectedCols; Bitmapset *modifiedCols; /* * child table has different attribute numbers, so we need to fix * up them. */ selectedCols = fixup_inherited_columns(rte->relid, tableOid, rte->selectedCols); modifiedCols = fixup_inherited_columns(rte->relid, tableOid, rte->modifiedCols); /* * check permissions on individual tables */ if (!check_relation_privileges(tableOid, selectedCols, modifiedCols, required, abort_on_violation)) return false; } list_free(tableIds); } return true; }