#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;
}
1.7.1