@ -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,22 +263,15 @@ 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 ) ;
}