Commit 1cea9bbb authored by Robert Haas's avatar Robert Haas

sepgsql: Support for new post-ALTER access hook.

KaiGai Kohei
parent bc5334d8
...@@ -148,6 +148,33 @@ sepgsql_database_drop(Oid databaseId) ...@@ -148,6 +148,33 @@ sepgsql_database_drop(Oid databaseId)
pfree(audit_name); pfree(audit_name);
} }
/*
* sepgsql_database_post_alter
*
* It checks privileges to alter the supplied database
*/
void
sepgsql_database_setattr(Oid databaseId)
{
ObjectAddress object;
char *audit_name;
/*
* check db_database:{setattr} permission
*/
object.classId = DatabaseRelationId;
object.objectId = databaseId;
object.objectSubId = 0;
audit_name = getObjectDescription(&object);
sepgsql_avc_check_perms(&object,
SEPG_CLASS_DB_DATABASE,
SEPG_DB_DATABASE__SETATTR,
audit_name,
true);
pfree(audit_name);
}
/* /*
* sepgsql_database_relabel * sepgsql_database_relabel
* *
......
This diff is collapsed.
-- --
-- Regression Test for DDL of Object Permission Checks -- Regression Test for DDL of Object Permission Checks
-- --
-- clean-up in case a prior regression run failed
SET client_min_messages TO 'warning';
DROP DATABASE IF EXISTS regtest_sepgsql_test_database;
DROP USER IF EXISTS regtest_sepgsql_test_user;
RESET client_min_messages;
-- confirm required permissions using audit messages -- confirm required permissions using audit messages
SELECT sepgsql_getcon(); -- confirm client privilege SELECT sepgsql_getcon(); -- confirm client privilege
sepgsql_getcon sepgsql_getcon
...@@ -36,6 +41,7 @@ LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_ ...@@ -36,6 +41,7 @@ LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column y" LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column y"
LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema" LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table" LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table"
LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_table_x_seq"
ALTER TABLE regtest_table ADD COLUMN z int; ALTER TABLE regtest_table ADD COLUMN z int;
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column z" LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column z"
CREATE TABLE regtest_table_2 (a int) WITH OIDS; CREATE TABLE regtest_table_2 (a int) WITH OIDS;
...@@ -61,6 +67,7 @@ CREATE SEQUENCE regtest_seq; ...@@ -61,6 +67,7 @@ CREATE SEQUENCE regtest_seq;
LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema" LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_seq" LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_seq"
CREATE TYPE regtest_comptype AS (a int, b text); CREATE TYPE regtest_comptype AS (a int, b text);
LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
CREATE FUNCTION regtest_func(text,int[]) RETURNS bool LANGUAGE plpgsql CREATE FUNCTION regtest_func(text,int[]) RETURNS bool LANGUAGE plpgsql
AS 'BEGIN RAISE NOTICE ''regtest_func => %'', $1; RETURN true; END'; AS 'BEGIN RAISE NOTICE ''regtest_func => %'', $1; RETURN true; END';
LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema" LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
...@@ -86,6 +93,7 @@ LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_ ...@@ -86,6 +93,7 @@ LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column ctid" LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column ctid"
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column x" LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column x"
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column y" LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column y"
LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_table_3_y_seq"
CREATE VIEW regtest_view_2 AS SELECT * FROM regtest_table_3 WHERE x < y; CREATE VIEW regtest_view_2 AS SELECT * FROM regtest_table_3 WHERE x < y;
LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema" LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_2" LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_2"
...@@ -118,6 +126,7 @@ CREATE INDEX regtest_index_tbl4_z ON regtest_table_4(z); ...@@ -118,6 +126,7 @@ CREATE INDEX regtest_index_tbl4_z ON regtest_table_4(z);
LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema" LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4" LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4"
ALTER TABLE regtest_table_4 ALTER COLUMN y TYPE float; ALTER TABLE regtest_table_4 ALTER COLUMN y TYPE float;
LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_4 column y"
DROP INDEX regtest_index_tbl4_y; DROP INDEX regtest_index_tbl4_y;
LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema" LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4" LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4"
......
...@@ -188,6 +188,54 @@ sepgsql_object_access(ObjectAccessType access, ...@@ -188,6 +188,54 @@ sepgsql_object_access(ObjectAccessType access,
} }
break; break;
case OAT_POST_ALTER:
{
ObjectAccessPostAlter *pa_arg = arg;
bool is_internal = pa_arg->is_internal;
switch (classId)
{
case DatabaseRelationId:
Assert(!is_internal);
sepgsql_database_setattr(objectId);
break;
case NamespaceRelationId:
Assert(!is_internal);
sepgsql_schema_setattr(objectId);
break;
case RelationRelationId:
if (subId == 0)
{
/*
* A case when we don't want to apply permission
* check is that relation is internally altered
* without user's intention. E.g, no need to
* check on toast table/index to be renamed at
* end of the table rewrites.
*/
if (is_internal)
break;
sepgsql_relation_setattr(objectId);
}
else
sepgsql_attribute_setattr(objectId, subId);
break;
case ProcedureRelationId:
Assert(!is_internal);
sepgsql_proc_setattr(objectId);
break;
default:
/* Ignore unsupported object classes */
break;
}
}
break;
default: default:
elog(ERROR, "unexpected object access type: %d", (int) access); elog(ERROR, "unexpected object access type: %d", (int) access);
break; break;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h" #include "utils/fmgroids.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/tqual.h" #include "utils/tqual.h"
#include "sepgsql.h" #include "sepgsql.h"
...@@ -43,6 +44,7 @@ sepgsql_proc_post_create(Oid functionId) ...@@ -43,6 +44,7 @@ sepgsql_proc_post_create(Oid functionId)
char *scontext; char *scontext;
char *tcontext; char *tcontext;
char *ncontext; char *ncontext;
uint32 required;
int i; int i;
StringInfoData audit_name; StringInfoData audit_name;
ObjectAddress object; ObjectAddress object;
...@@ -96,7 +98,7 @@ sepgsql_proc_post_create(Oid functionId) ...@@ -96,7 +98,7 @@ sepgsql_proc_post_create(Oid functionId)
SEPG_CLASS_DB_PROCEDURE); SEPG_CLASS_DB_PROCEDURE);
/* /*
* check db_procedure:{create} permission * check db_procedure:{create (install)} permission
*/ */
initStringInfo(&audit_name); initStringInfo(&audit_name);
appendStringInfo(&audit_name, "function %s(", NameStr(proForm->proname)); appendStringInfo(&audit_name, "function %s(", NameStr(proForm->proname));
...@@ -110,9 +112,13 @@ sepgsql_proc_post_create(Oid functionId) ...@@ -110,9 +112,13 @@ sepgsql_proc_post_create(Oid functionId)
} }
appendStringInfoChar(&audit_name, ')'); appendStringInfoChar(&audit_name, ')');
required = SEPG_DB_PROCEDURE__CREATE;
if (proForm->proleakproof)
required |= SEPG_DB_PROCEDURE__INSTALL;
sepgsql_avc_check_perms_label(ncontext, sepgsql_avc_check_perms_label(ncontext,
SEPG_CLASS_DB_PROCEDURE, SEPG_CLASS_DB_PROCEDURE,
SEPG_DB_PROCEDURE__CREATE, required,
audit_name.data, audit_name.data,
true); true);
...@@ -214,3 +220,83 @@ sepgsql_proc_relabel(Oid functionId, const char *seclabel) ...@@ -214,3 +220,83 @@ sepgsql_proc_relabel(Oid functionId, const char *seclabel)
true); true);
pfree(audit_name); pfree(audit_name);
} }
/*
* sepgsql_proc_setattr
*
* It checks privileges to alter the supplied function.
*/
void
sepgsql_proc_setattr(Oid functionId)
{
Relation rel;
ScanKeyData skey;
SysScanDesc sscan;
HeapTuple oldtup;
HeapTuple newtup;
Form_pg_proc oldform;
Form_pg_proc newform;
uint32 required;
ObjectAddress object;
char *audit_name;
/*
* Fetch newer catalog
*/
rel = heap_open(ProcedureRelationId, AccessShareLock);
ScanKeyInit(&skey,
ObjectIdAttributeNumber,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(functionId));
sscan = systable_beginscan(rel, ProcedureOidIndexId, true,
SnapshotSelf, 1, &skey);
newtup = systable_getnext(sscan);
if (!HeapTupleIsValid(newtup))
elog(ERROR, "catalog lookup failed for function %u", functionId);
newform = (Form_pg_proc) GETSTRUCT(newtup);
/*
* Fetch older catalog
*/
oldtup = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
if (!HeapTupleIsValid(oldtup))
elog(ERROR, "cache lookup failed for function %u", functionId);
oldform = (Form_pg_proc) GETSTRUCT(oldtup);
/*
* Does this ALTER command takes operation to namespace?
*/
if (newform->pronamespace != oldform->pronamespace)
{
sepgsql_schema_remove_name(oldform->pronamespace);
sepgsql_schema_add_name(oldform->pronamespace);
}
if (strcmp(NameStr(newform->proname), NameStr(oldform->proname)) != 0)
sepgsql_schema_rename(oldform->pronamespace);
/*
* check db_procedure:{setattr (install)} permission
*/
required = SEPG_DB_PROCEDURE__SETATTR;
if (!oldform->proleakproof && newform->proleakproof)
required |= SEPG_DB_PROCEDURE__INSTALL;
object.classId = ProcedureRelationId;
object.objectId = functionId;
object.objectSubId = 0;
audit_name = getObjectDescription(&object);
sepgsql_avc_check_perms(&object,
SEPG_CLASS_DB_PROCEDURE,
required,
audit_name,
true);
/* cleanups */
pfree(audit_name);
ReleaseSysCache(oldtup);
systable_endscan(sscan);
heap_close(rel, AccessShareLock);
}
...@@ -190,6 +190,36 @@ sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum, ...@@ -190,6 +190,36 @@ sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
pfree(audit_name); pfree(audit_name);
} }
/*
* sepgsql_attribute_setattr
*
* It checks privileges to alter the supplied column.
*/
void
sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum)
{
ObjectAddress object;
char *audit_name;
if (get_rel_relkind(relOid) != RELKIND_RELATION)
return;
/*
* check db_column:{setattr} permission
*/
object.classId = RelationRelationId;
object.objectId = relOid;
object.objectSubId = attnum;
audit_name = getObjectDescription(&object);
sepgsql_avc_check_perms(&object,
SEPG_CLASS_DB_COLUMN,
SEPG_DB_COLUMN__SETATTR,
audit_name,
true);
pfree(audit_name);
}
/* /*
* sepgsql_relation_post_create * sepgsql_relation_post_create
* *
...@@ -529,6 +559,13 @@ sepgsql_relation_relabel(Oid relOid, const char *seclabel) ...@@ -529,6 +559,13 @@ sepgsql_relation_relabel(Oid relOid, const char *seclabel)
void void
sepgsql_relation_setattr(Oid relOid) sepgsql_relation_setattr(Oid relOid)
{ {
Relation rel;
ScanKeyData skey;
SysScanDesc sscan;
HeapTuple oldtup;
HeapTuple newtup;
Form_pg_class oldform;
Form_pg_class newform;
ObjectAddress object; ObjectAddress object;
char *audit_name; char *audit_name;
uint16_t tclass; uint16_t tclass;
...@@ -553,26 +590,66 @@ sepgsql_relation_setattr(Oid relOid) ...@@ -553,26 +590,66 @@ sepgsql_relation_setattr(Oid relOid)
return; return;
} }
object.classId = RelationRelationId; /*
object.objectId = relOid; * Fetch newer catalog
object.objectSubId = 0; */
audit_name = getObjectDescription(&object); rel = heap_open(RelationRelationId, AccessShareLock);
ScanKeyInit(&skey,
ObjectIdAttributeNumber,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relOid));
sscan = systable_beginscan(rel, ClassOidIndexId, true,
SnapshotSelf, 1, &skey);
newtup = systable_getnext(sscan);
if (!HeapTupleIsValid(newtup))
elog(ERROR, "catalog lookup failed for relation %u", relOid);
newform = (Form_pg_class) GETSTRUCT(newtup);
/* /*
* XXX - we should add checks related to namespace stuff, when * Fetch older catalog
* object_access_hook get support for ALTER statement. Right now, there is */
* no invocation path on ALTER ... RENAME TO / SET SCHEMA. oldtup = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
if (!HeapTupleIsValid(oldtup))
elog(ERROR, "cache lookup failed for relation %u", relOid);
oldform = (Form_pg_class) GETSTRUCT(oldtup);
/*
* Does this ALTER command takes operation to namespace?
*/
if (newform->relnamespace != oldform->relnamespace)
{
sepgsql_schema_remove_name(oldform->relnamespace);
sepgsql_schema_add_name(newform->relnamespace);
}
if (strcmp(NameStr(newform->relname), NameStr(oldform->relname)) != 0)
sepgsql_schema_rename(oldform->relnamespace);
/*
* XXX - In the future version, db_tuple:{use} of system catalog entry
* shall be checked, if tablespace configuration is changed.
*/ */
/* /*
* check db_xxx:{setattr} permission * check db_xxx:{setattr} permission
*/ */
object.classId = RelationRelationId;
object.objectId = relOid;
object.objectSubId = 0;
audit_name = getObjectDescription(&object);
sepgsql_avc_check_perms(&object, sepgsql_avc_check_perms(&object,
tclass, tclass,
SEPG_DB_TABLE__SETATTR, SEPG_DB_TABLE__SETATTR,
audit_name, audit_name,
true); true);
pfree(audit_name); pfree(audit_name);
ReleaseSysCache(oldtup);
systable_endscan(sscan);
heap_close(rel, AccessShareLock);
} }
/* /*
......
...@@ -162,3 +162,54 @@ sepgsql_schema_relabel(Oid namespaceId, const char *seclabel) ...@@ -162,3 +162,54 @@ sepgsql_schema_relabel(Oid namespaceId, const char *seclabel)
true); true);
pfree(audit_name); pfree(audit_name);
} }
/*
* sepgsql_schema_check_perms
*
* utility routine to check db_schema:{xxx} permissions
*/
static void
check_schema_perms(Oid namespaceId, uint32 required)
{
ObjectAddress object;
char *audit_name;
object.classId = NamespaceRelationId;
object.objectId = namespaceId;
object.objectSubId = 0;
audit_name = getObjectDescription(&object);
sepgsql_avc_check_perms(&object,
SEPG_CLASS_DB_SCHEMA,
required,
audit_name,
true);
pfree(audit_name);
}
/* db_schema:{setattr} permission */
void
sepgsql_schema_setattr(Oid namespaceId)
{
check_schema_perms(namespaceId, SEPG_DB_SCHEMA__SETATTR);
}
void
sepgsql_schema_add_name(Oid namespaceId)
{
check_schema_perms(namespaceId, SEPG_DB_SCHEMA__ADD_NAME);
}
void
sepgsql_schema_remove_name(Oid namespaceId)
{
check_schema_perms(namespaceId, SEPG_DB_SCHEMA__REMOVE_NAME);
}
void
sepgsql_schema_rename(Oid namespaceId)
{
check_schema_perms(namespaceId,
SEPG_DB_SCHEMA__ADD_NAME |
SEPG_DB_SCHEMA__REMOVE_NAME);
}
...@@ -293,6 +293,7 @@ extern void sepgsql_database_post_create(Oid databaseId, ...@@ -293,6 +293,7 @@ extern void sepgsql_database_post_create(Oid databaseId,
const char *dtemplate); const char *dtemplate);
extern void sepgsql_database_drop(Oid databaseId); extern void sepgsql_database_drop(Oid databaseId);
extern void sepgsql_database_relabel(Oid databaseId, const char *seclabel); extern void sepgsql_database_relabel(Oid databaseId, const char *seclabel);
extern void sepgsql_database_setattr(Oid databaseId);
/* /*
* schema.c * schema.c
...@@ -300,6 +301,10 @@ extern void sepgsql_database_relabel(Oid databaseId, const char *seclabel); ...@@ -300,6 +301,10 @@ extern void sepgsql_database_relabel(Oid databaseId, const char *seclabel);
extern void sepgsql_schema_post_create(Oid namespaceId); extern void sepgsql_schema_post_create(Oid namespaceId);
extern void sepgsql_schema_drop(Oid namespaceId); extern void sepgsql_schema_drop(Oid namespaceId);
extern void sepgsql_schema_relabel(Oid namespaceId, const char *seclabel); extern void sepgsql_schema_relabel(Oid namespaceId, const char *seclabel);
extern void sepgsql_schema_setattr(Oid namespaceId);
extern void sepgsql_schema_add_name(Oid namespaceId);
extern void sepgsql_schema_remove_name(Oid namespaceId);
extern void sepgsql_schema_rename(Oid namespaceId);
/* /*
* relation.c * relation.c
...@@ -308,6 +313,7 @@ extern void sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum); ...@@ -308,6 +313,7 @@ extern void sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum);
extern void sepgsql_attribute_drop(Oid relOid, AttrNumber attnum); extern void sepgsql_attribute_drop(Oid relOid, AttrNumber attnum);
extern void sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum, extern void sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
const char *seclabel); const char *seclabel);
extern void sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum);
extern void sepgsql_relation_post_create(Oid relOid); extern void sepgsql_relation_post_create(Oid relOid);
extern void sepgsql_relation_drop(Oid relOid); extern void sepgsql_relation_drop(Oid relOid);
extern void sepgsql_relation_relabel(Oid relOid, const char *seclabel); extern void sepgsql_relation_relabel(Oid relOid, const char *seclabel);
...@@ -319,5 +325,6 @@ extern void sepgsql_relation_setattr(Oid relOid); ...@@ -319,5 +325,6 @@ extern void sepgsql_relation_setattr(Oid relOid);
extern void sepgsql_proc_post_create(Oid functionId); extern void sepgsql_proc_post_create(Oid functionId);
extern void sepgsql_proc_drop(Oid functionId); extern void sepgsql_proc_drop(Oid functionId);
extern void sepgsql_proc_relabel(Oid functionId, const char *seclabel); extern void sepgsql_proc_relabel(Oid functionId, const char *seclabel);
extern void sepgsql_proc_setattr(Oid functionId);
#endif /* SEPGSQL_H */ #endif /* SEPGSQL_H */
--
-- Test for various ALTER statements
--
-- clean-up in case a prior regression run failed
SET client_min_messages TO 'warning';
DROP DATABASE IF EXISTS regtest_sepgsql_test_database_1;
DROP DATABASE IF EXISTS regtest_sepgsql_test_database;
DROP USER IF EXISTS regtest_sepgsql_test_user;
RESET client_min_messages;
-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0
--
-- CREATE Objects to be altered (with debug_audit being silent)
--
CREATE DATABASE regtest_sepgsql_test_database_1;
CREATE USER regtest_sepgsql_test_user;
CREATE SCHEMA regtest_schema_1;
CREATE SCHEMA regtest_schema_2;
GRANT ALL ON SCHEMA regtest_schema_1 TO public;
GRANT ALL ON SCHEMA regtest_schema_2 TO public;
SET search_path = regtest_schema_1, regtest_schema_2, public;
CREATE TABLE regtest_table_1 (a int, b text);
CREATE TABLE regtest_table_2 (c text) inherits (regtest_table_1);
CREATE TABLE regtest_table_3 (x int primary key, y text);
CREATE SEQUENCE regtest_seq_1;
CREATE VIEW regtest_view_1 AS SELECT * FROM regtest_table_1 WHERE a > 0;
CREATE FUNCTION regtest_func_1 (text) RETURNS bool
AS 'BEGIN RETURN true; END' LANGUAGE 'plpgsql';
-- switch on debug_audit
SET sepgsql.debug_audit = true;
SET client_min_messages = LOG;
--
-- ALTER xxx OWNER TO
--
-- XXX: It should take db_xxx:{setattr} permission checks even if
-- owner is not actually changed.
--
ALTER DATABASE regtest_sepgsql_test_database_1 OWNER TO regtest_sepgsql_test_user;
ALTER DATABASE regtest_sepgsql_test_database_1 OWNER TO regtest_sepgsql_test_user;
ALTER SCHEMA regtest_schema_1 OWNER TO regtest_sepgsql_test_user;
ALTER SCHEMA regtest_schema_1 OWNER TO regtest_sepgsql_test_user;
ALTER TABLE regtest_table_1 OWNER TO regtest_sepgsql_test_user;
ALTER TABLE regtest_table_1 OWNER TO regtest_sepgsql_test_user;
ALTER SEQUENCE regtest_seq_1 OWNER TO regtest_sepgsql_test_user;
ALTER SEQUENCE regtest_seq_1 OWNER TO regtest_sepgsql_test_user;
ALTER VIEW regtest_view_1 OWNER TO regtest_sepgsql_test_user;
ALTER VIEW regtest_view_1 OWNER TO regtest_sepgsql_test_user;
ALTER FUNCTION regtest_func_1(text) OWNER TO regtest_sepgsql_test_user;
ALTER FUNCTION regtest_func_1(text) OWNER TO regtest_sepgsql_test_user;
--
-- ALTER xxx SET SCHEMA
--
ALTER TABLE regtest_table_1 SET SCHEMA regtest_schema_2;
ALTER SEQUENCE regtest_seq_1 SET SCHEMA regtest_schema_2;
ALTER VIEW regtest_view_1 SET SCHEMA regtest_schema_2;
ALTER FUNCTION regtest_func_1(text) SET SCHEMA regtest_schema_2;
--
-- ALTER xxx RENAME TO
--
ALTER DATABASE regtest_sepgsql_test_database_1 RENAME TO regtest_sepgsql_test_database;
ALTER SCHEMA regtest_schema_1 RENAME TO regtest_schema;
ALTER TABLE regtest_table_1 RENAME TO regtest_table;
ALTER SEQUENCE regtest_seq_1 RENAME TO regtest_seq;
ALTER VIEW regtest_view_1 RENAME TO regtest_view;
ALTER FUNCTION regtest_func_1(text) RENAME TO regtest_func;
SET search_path = regtest_schema, regtest_schema_2, public;
--
-- misc ALTER commands
--
ALTER DATABASE regtest_sepgsql_test_database CONNECTION LIMIT 999;
ALTER DATABASE regtest_sepgsql_test_database SET search_path TO regtest_schema, public; -- not supported yet
ALTER TABLE regtest_table ADD COLUMN d float;
ALTER TABLE regtest_table DROP COLUMN d;
ALTER TABLE regtest_table ALTER b SET DEFAULT 'abcd'; -- not supported yet
ALTER TABLE regtest_table ALTER b SET DEFAULT 'XYZ'; -- not supported yet
ALTER TABLE regtest_table ALTER b DROP DEFAULT; -- not supported yet
ALTER TABLE regtest_table ALTER b SET NOT NULL;
ALTER TABLE regtest_table ALTER b DROP NOT NULL;
ALTER TABLE regtest_table ALTER b SET STATISTICS -1;
ALTER TABLE regtest_table ALTER b SET (n_distinct = 999);
ALTER TABLE regtest_table ALTER b SET STORAGE PLAIN;
ALTER TABLE regtest_table ADD CONSTRAINT test_fk FOREIGN KEY (a) REFERENCES regtest_table_3(x); -- not supported
ALTER TABLE regtest_table ADD CONSTRAINT test_ck CHECK (b like '%abc%') NOT VALID; -- not supported
ALTER TABLE regtest_table VALIDATE CONSTRAINT test_ck; -- not supported
ALTER TABLE regtest_table DROP CONSTRAINT test_ck; -- not supported
CREATE TRIGGER regtest_test_trig BEFORE UPDATE ON regtest_table
FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
ALTER TABLE regtest_table DISABLE TRIGGER regtest_test_trig; -- not supported
ALTER TABLE regtest_table ENABLE TRIGGER regtest_test_trig; -- not supported
CREATE RULE regtest_test_rule AS ON INSERT TO regtest_table_3 DO ALSO NOTHING;
ALTER TABLE regtest_table_3 DISABLE RULE regtest_test_rule; -- not supported
ALTER TABLE regtest_table_3 ENABLE RULE regtest_test_rule; -- not supported
ALTER TABLE regtest_table SET WITH OIDS;
ALTER TABLE regtest_table SET WITHOUT OIDS;
ALTER TABLE regtest_table SET (fillfactor = 75);
ALTER TABLE regtest_table RESET (fillfactor);
ALTER TABLE regtest_table_2 NO INHERIT regtest_table; -- not supported
ALTER TABLE regtest_table_2 INHERIT regtest_table; -- not supported
ALTER TABLE regtest_table SET TABLESPACE pg_default;
ALTER VIEW regtest_view SET (security_barrier);
ALTER SEQUENCE regtest_seq INCREMENT BY 10 START WITH 1000;
--
-- clean-up objects
--
RESET sepgsql.debug_audit;
RESET client_min_messages;
DROP DATABASE regtest_sepgsql_test_database;
DROP SCHEMA regtest_schema CASCADE;
DROP SCHEMA regtest_schema_2 CASCADE;
DROP USER regtest_sepgsql_test_user;
...@@ -2,6 +2,12 @@ ...@@ -2,6 +2,12 @@
-- Regression Test for DDL of Object Permission Checks -- Regression Test for DDL of Object Permission Checks
-- --
-- clean-up in case a prior regression run failed
SET client_min_messages TO 'warning';
DROP DATABASE IF EXISTS regtest_sepgsql_test_database;
DROP USER IF EXISTS regtest_sepgsql_test_user;
RESET client_min_messages;
-- confirm required permissions using audit messages -- confirm required permissions using audit messages
-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0 -- @SECURITY-CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0
SET sepgsql.debug_audit = true; SET sepgsql.debug_audit = true;
......
...@@ -162,6 +162,31 @@ if [ "${POLICY_STATUS}" != on ]; then ...@@ -162,6 +162,31 @@ if [ "${POLICY_STATUS}" != on ]; then
echo "" echo ""
exit 1 exit 1
fi fi
POLICY_STATUS=`getsebool sepgsql_enable_users_ddl | awk '{print $3}'`
echo ${POLICY_STATUS:-failed}
if [ "${POLICY_STATUS}" != on ]; then
echo ""
echo "The SELinux boolean 'sepgsql_enable_users_ddl' must be"
echo "turned on in order to enable the rules necessary to run"
echo "the regression tests."
echo ""
if [ "${POLICY_STATUS}" = "" ]; then
echo "We attempted to determine the state of this Boolean using"
echo "'getsebool', but that command did not produce the expected"
echo "output. Please verify that getsebool is available and in"
echo "your PATH."
else
echo "You can turn on this variable using the following commands:"
echo ""
echo " \$ sudo setsebool sepgsql_enable_users_ddl on"
echo ""
echo "For security reasons, it is suggested that you turn off this"
echo "variable when regression testing is complete, unless you"
echo "don't want to allow unprivileged users DDL commands."
fi
echo ""
exit 1
fi
# 'psql' command must be executable from test domain # 'psql' command must be executable from test domain
echo -n "checking whether we can run psql ... " echo -n "checking whether we can run psql ... "
...@@ -259,6 +284,6 @@ echo "found ${NUM}" ...@@ -259,6 +284,6 @@ echo "found ${NUM}"
echo echo
echo "============== running sepgsql regression tests ==============" echo "============== running sepgsql regression tests =============="
make REGRESS="label dml ddl misc" REGRESS_OPTS="--launcher ./launcher" installcheck make REGRESS="label dml ddl alter misc" REGRESS_OPTS="--launcher ./launcher" installcheck
# exit with the exit code provided by "make" # exit with the exit code provided by "make"
...@@ -438,6 +438,12 @@ UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100; ...@@ -438,6 +438,12 @@ UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
On creation of objects within a particular schema (tables, views, On creation of objects within a particular schema (tables, views,
sequences and procedures), <literal>add_name</> will be also checked sequences and procedures), <literal>add_name</> will be also checked
on the schema, not only <literal>create</> on the new object itself. on the schema, not only <literal>create</> on the new object itself.
On <xref linkend="sql-createfunction">, <literal>install</> permission
will be checked if <literal>leakproof</> attribute was given, not only
<literal>create</> on the new function. This permission will be also
checked when user tries to turn on <literal>leakproof</> attribute
using <xref linkend="sql-alterfunction"> command, with
<literal>setattr</> permission on the function being altered.
</para> </para>
<para> <para>
...@@ -450,9 +456,19 @@ UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100; ...@@ -450,9 +456,19 @@ UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
</para> </para>
<para> <para>
When objects that are subsidiary of other objects (such as a table's indexes When <literal>ALTER</> command is executed, <literal>setattr</> will be
or triggers) are created or dropped, <literal>setattr</> permission will be checked on the object being modified for each object types.
checked on the main object, instead of the subsidiary object itself. In addition, <literal>remove_name</> and <literal>add_name</>
will be checked on the old and new schemas, respectively, when an
object is moved to a new schema.
For certain object types, additional checks are performed.
</para>
<para>
When objects that are subsidiary of other objects (such as a table's
indexes or triggers) are created, dropped or altered,
<literal>setattr</> permission will be checked on the main object,
instead of the subsidiary object itself.
</para> </para>
<para> <para>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment