]> granicus.if.org Git - postgresql/commitdiff
sepgsql: Support for new post-ALTER access hook.
authorRobert Haas <rhaas@postgresql.org>
Wed, 27 Mar 2013 12:10:14 +0000 (08:10 -0400)
committerRobert Haas <rhaas@postgresql.org>
Wed, 27 Mar 2013 12:14:19 +0000 (08:14 -0400)
KaiGai Kohei

12 files changed:
contrib/sepgsql/database.c
contrib/sepgsql/expected/alter.out [new file with mode: 0644]
contrib/sepgsql/expected/ddl.out
contrib/sepgsql/hooks.c
contrib/sepgsql/proc.c
contrib/sepgsql/relation.c
contrib/sepgsql/schema.c
contrib/sepgsql/sepgsql.h
contrib/sepgsql/sql/alter.sql [new file with mode: 0644]
contrib/sepgsql/sql/ddl.sql
contrib/sepgsql/test_sepgsql
doc/src/sgml/sepgsql.sgml

index 975c1d47958fd04084b1f2c5f6f13e592c51ba3e..64d37a3ca9939b17bb31ac878a89c4141333fce5 100644 (file)
@@ -148,6 +148,33 @@ sepgsql_database_drop(Oid databaseId)
        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
  *
diff --git a/contrib/sepgsql/expected/alter.out b/contrib/sepgsql/expected/alter.out
new file mode 100644 (file)
index 0000000..ef9abb3
--- /dev/null
@@ -0,0 +1,192 @@
+--
+-- 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;
+SELECT sepgsql_getcon();       -- confirm client privilege
+              sepgsql_getcon               
+-------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0
+(1 row)
+
+--
+-- 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;
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_db_t:s0 tclass=db_database name="database regtest_sepgsql_test_database_1"
+ALTER DATABASE regtest_sepgsql_test_database_1 OWNER TO regtest_sepgsql_test_user;
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_db_t:s0 tclass=db_database name="database regtest_sepgsql_test_database_1"
+ALTER SCHEMA regtest_schema_1 OWNER TO regtest_sepgsql_test_user;
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_1"
+ALTER SCHEMA regtest_schema_1 OWNER TO regtest_sepgsql_test_user;
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_1"
+ALTER TABLE regtest_table_1 OWNER TO regtest_sepgsql_test_user;
+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_1"
+ALTER TABLE regtest_table_1 OWNER TO regtest_sepgsql_test_user;
+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_1"
+ALTER SEQUENCE regtest_seq_1 OWNER TO regtest_sepgsql_test_user;
+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_seq_1"
+ALTER SEQUENCE regtest_seq_1 OWNER TO regtest_sepgsql_test_user;
+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_seq_1"
+ALTER VIEW regtest_view_1 OWNER TO regtest_sepgsql_test_user;
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_1"
+ALTER VIEW regtest_view_1 OWNER TO regtest_sepgsql_test_user;
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_1"
+ALTER FUNCTION regtest_func_1(text) OWNER TO regtest_sepgsql_test_user;
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func_1(text)"
+ALTER FUNCTION regtest_func_1(text) OWNER TO regtest_sepgsql_test_user;
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func_1(text)"
+--
+-- ALTER xxx SET SCHEMA
+--
+ALTER TABLE regtest_table_1 SET SCHEMA regtest_schema_2;
+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_1"
+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_2"
+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_1"
+ALTER SEQUENCE regtest_seq_1 SET SCHEMA regtest_schema_2;
+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_1"
+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_2"
+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_seq_1"
+ALTER VIEW regtest_view_1 SET SCHEMA regtest_schema_2;
+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_1"
+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_2"
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_1"
+ALTER FUNCTION regtest_func_1(text) SET SCHEMA regtest_schema_2;
+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_1"
+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_1"
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func_1(text)"
+--
+-- ALTER xxx RENAME TO
+--
+ALTER DATABASE regtest_sepgsql_test_database_1 RENAME TO regtest_sepgsql_test_database;
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_db_t:s0 tclass=db_database name="database regtest_sepgsql_test_database_1"
+ALTER SCHEMA regtest_schema_1 RENAME TO regtest_schema;
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_1"
+ALTER TABLE regtest_table_1 RENAME TO regtest_table;
+LOG:  SELinux: allowed { add_name 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_2"
+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_1"
+ALTER SEQUENCE regtest_seq_1 RENAME TO regtest_seq;
+LOG:  SELinux: allowed { add_name 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_2"
+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_seq_1"
+ALTER VIEW regtest_view_1 RENAME TO regtest_view;
+LOG:  SELinux: allowed { add_name 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_2"
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_1"
+ALTER FUNCTION regtest_func_1(text) RENAME TO regtest_func;
+LOG:  SELinux: allowed { add_name 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_2"
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func_1(text)"
+SET search_path = regtest_schema, regtest_schema_2, public;
+--
+-- misc ALTER commands
+--
+ALTER DATABASE regtest_sepgsql_test_database CONNECTION LIMIT 999;
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_db_t:s0 tclass=db_database name="database regtest_sepgsql_test_database"
+ALTER DATABASE regtest_sepgsql_test_database SET search_path TO regtest_schema, public; -- not supported yet
+ALTER TABLE regtest_table ADD COLUMN d float;
+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 d"
+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_2 column d"
+ALTER TABLE regtest_table DROP COLUMN d;
+LOG:  SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column d"
+LOG:  SELinux: allowed { drop } 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 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;
+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 column b"
+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_2 column b"
+ALTER TABLE regtest_table ALTER b DROP NOT NULL;
+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 column b"
+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_2 column b"
+ALTER TABLE regtest_table ALTER b SET STATISTICS -1;
+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 column b"
+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_2 column b"
+ALTER TABLE regtest_table ALTER b SET (n_distinct = 999);
+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 column b"
+ALTER TABLE regtest_table ALTER b SET STORAGE PLAIN;
+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 column b"
+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_2 column b"
+ALTER TABLE regtest_table ADD CONSTRAINT test_fk FOREIGN KEY (a) REFERENCES regtest_table_3(x); -- not supported
+LOG:  SELinux: allowed { select } 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 { select } 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 a"
+LOG:  SELinux: allowed { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_3"
+LOG:  SELinux: allowed { select } 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 { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table"
+CONTEXT:  SQL statement "SELECT fk."a" FROM ONLY "regtest_schema_2"."regtest_table" fk LEFT OUTER JOIN ONLY "regtest_schema"."regtest_table_3" pk ON ( pk."x" OPERATOR(pg_catalog.=) fk."a") WHERE pk."x" IS NULL AND (fk."a" IS NOT NULL)"
+LOG:  SELinux: allowed { select } 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 a"
+CONTEXT:  SQL statement "SELECT fk."a" FROM ONLY "regtest_schema_2"."regtest_table" fk LEFT OUTER JOIN ONLY "regtest_schema"."regtest_table_3" pk ON ( pk."x" OPERATOR(pg_catalog.=) fk."a") WHERE pk."x" IS NULL AND (fk."a" IS NOT NULL)"
+LOG:  SELinux: allowed { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_3"
+CONTEXT:  SQL statement "SELECT fk."a" FROM ONLY "regtest_schema_2"."regtest_table" fk LEFT OUTER JOIN ONLY "regtest_schema"."regtest_table_3" pk ON ( pk."x" OPERATOR(pg_catalog.=) fk."a") WHERE pk."x" IS NULL AND (fk."a" IS NOT NULL)"
+LOG:  SELinux: allowed { select } 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"
+CONTEXT:  SQL statement "SELECT fk."a" FROM ONLY "regtest_schema_2"."regtest_table" fk LEFT OUTER JOIN ONLY "regtest_schema"."regtest_table_3" pk ON ( pk."x" OPERATOR(pg_catalog.=) fk."a") WHERE pk."x" IS NULL AND (fk."a" IS NOT NULL)"
+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;
+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 oid"
+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_2 column oid"
+ALTER TABLE regtest_table SET WITHOUT OIDS;
+LOG:  SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column oid"
+LOG:  SELinux: allowed { drop } 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 oid"
+ALTER TABLE regtest_table SET (fillfactor = 75);
+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"
+ALTER TABLE regtest_table RESET (fillfactor);
+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"
+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;
+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"
+ALTER VIEW regtest_view SET (security_barrier);
+LOG:  SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view"
+ALTER SEQUENCE regtest_seq INCREMENT BY 10 START WITH 1000;
+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_seq"
+--
+-- clean-up objects
+--
+RESET sepgsql.debug_audit;
+RESET client_min_messages;
+DROP DATABASE regtest_sepgsql_test_database;
+DROP SCHEMA regtest_schema CASCADE;
+NOTICE:  drop cascades to 3 other objects
+DETAIL:  drop cascades to table regtest_table_2
+drop cascades to table regtest_table_3
+drop cascades to constraint test_fk on table regtest_table
+DROP SCHEMA regtest_schema_2 CASCADE;
+NOTICE:  drop cascades to 4 other objects
+DETAIL:  drop cascades to table regtest_table
+drop cascades to sequence regtest_seq
+drop cascades to view regtest_view
+drop cascades to function regtest_func(text)
+DROP USER regtest_sepgsql_test_user;
index 1f7ea886b00227b103680d427c14da12f082ef80..d60c65bdb1b1543fd559c92ccddc972cc79e4810 100644 (file)
@@ -1,6 +1,11 @@
 --
 -- 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
 SELECT sepgsql_getcon();       -- confirm client privilege
               sepgsql_getcon               
@@ -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 { 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_seq_t:s0 tclass=db_sequence name="sequence regtest_table_x_seq"
 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"
 CREATE TABLE regtest_table_2 (a int) WITH OIDS;
@@ -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 { 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);
+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
           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"
@@ -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 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 { 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;
 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"
@@ -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 { 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;
+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;
 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"
index 7ec72a05632c16cbcdc52af5106c7747842484ea..0715aa8bc6e802d0ad80245cd8c0db41ad86b619 100644 (file)
@@ -188,6 +188,54 @@ sepgsql_object_access(ObjectAccessType access,
                        }
                        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:
                        elog(ERROR, "unexpected object access type: %d", (int) access);
                        break;
index b47c880f54c117a4614fe6cdc8a262fa86efef83..53b941d85583e19976fd53aaead03f7fda9f598b 100644 (file)
@@ -23,6 +23,7 @@
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
 #include "utils/lsyscache.h"
+#include "utils/syscache.h"
 #include "utils/tqual.h"
 
 #include "sepgsql.h"
@@ -43,6 +44,7 @@ sepgsql_proc_post_create(Oid functionId)
        char       *scontext;
        char       *tcontext;
        char       *ncontext;
+       uint32          required;
        int                     i;
        StringInfoData audit_name;
        ObjectAddress object;
@@ -96,7 +98,7 @@ sepgsql_proc_post_create(Oid functionId)
                                                                          SEPG_CLASS_DB_PROCEDURE);
 
        /*
-        * check db_procedure:{create} permission
+        * check db_procedure:{create (install)} permission
         */
        initStringInfo(&audit_name);
        appendStringInfo(&audit_name, "function %s(", NameStr(proForm->proname));
@@ -110,9 +112,13 @@ sepgsql_proc_post_create(Oid functionId)
        }
        appendStringInfoChar(&audit_name, ')');
 
+       required = SEPG_DB_PROCEDURE__CREATE;
+       if (proForm->proleakproof)
+               required |= SEPG_DB_PROCEDURE__INSTALL;
+
        sepgsql_avc_check_perms_label(ncontext,
                                                                  SEPG_CLASS_DB_PROCEDURE,
-                                                                 SEPG_DB_PROCEDURE__CREATE,
+                                                                 required,
                                                                  audit_name.data,
                                                                  true);
 
@@ -214,3 +220,83 @@ sepgsql_proc_relabel(Oid functionId, const char *seclabel)
                                                                  true);
        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);
+}
index a277fab06646f095f4382ff89f0daea65236571c..8bcaa41d312e1e20e0a02d10443562b449159c1f 100644 (file)
@@ -190,6 +190,36 @@ sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
        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
  *
@@ -529,6 +559,13 @@ sepgsql_relation_relabel(Oid relOid, const char *seclabel)
 void
 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;
        char       *audit_name;
        uint16_t        tclass;
@@ -553,26 +590,66 @@ sepgsql_relation_setattr(Oid relOid)
                        return;
        }
 
-       object.classId = RelationRelationId;
-       object.objectId = relOid;
-       object.objectSubId = 0;
-       audit_name = getObjectDescription(&object);
+       /*
+        * Fetch newer catalog
+        */
+       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
-        * object_access_hook get support for ALTER statement.  Right now, there is
-        * no invocation path on ALTER ...  RENAME TO / SET SCHEMA.
+        * Fetch older catalog
+        */
+       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
         */
+       object.classId = RelationRelationId;
+       object.objectId = relOid;
+       object.objectSubId = 0;
+       audit_name = getObjectDescription(&object);
+
        sepgsql_avc_check_perms(&object,
                                                        tclass,
                                                        SEPG_DB_TABLE__SETATTR,
                                                        audit_name,
                                                        true);
        pfree(audit_name);
+
+       ReleaseSysCache(oldtup);
+       systable_endscan(sscan);
+       heap_close(rel, AccessShareLock);
 }
 
 /*
index 75b28261ce625a3d79a654d8ca548951c39a32ce..ecdfd738d911cef23b1d1e9affdaba34b8fb071f 100644 (file)
@@ -162,3 +162,54 @@ sepgsql_schema_relabel(Oid namespaceId, const char *seclabel)
                                                                  true);
        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);
+}
index 5ae51469d724507c19bcb8a5750329e546b2d159..d4ee94be5a08d62e1cfea65fc75952da40b45cf3 100644 (file)
@@ -293,6 +293,7 @@ extern void sepgsql_database_post_create(Oid databaseId,
                                                         const char *dtemplate);
 extern void sepgsql_database_drop(Oid databaseId);
 extern void sepgsql_database_relabel(Oid databaseId, const char *seclabel);
+extern void sepgsql_database_setattr(Oid databaseId);
 
 /*
  * schema.c
@@ -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_drop(Oid namespaceId);
 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
@@ -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_relabel(Oid relOid, AttrNumber attnum,
                                                  const char *seclabel);
+extern void sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum);
 extern void sepgsql_relation_post_create(Oid relOid);
 extern void sepgsql_relation_drop(Oid relOid);
 extern void sepgsql_relation_relabel(Oid relOid, const char *seclabel);
@@ -319,5 +325,6 @@ extern void sepgsql_relation_setattr(Oid relOid);
 extern void sepgsql_proc_post_create(Oid functionId);
 extern void sepgsql_proc_drop(Oid functionId);
 extern void sepgsql_proc_relabel(Oid functionId, const char *seclabel);
+extern void sepgsql_proc_setattr(Oid functionId);
 
 #endif   /* SEPGSQL_H */
diff --git a/contrib/sepgsql/sql/alter.sql b/contrib/sepgsql/sql/alter.sql
new file mode 100644 (file)
index 0000000..4bded7e
--- /dev/null
@@ -0,0 +1,136 @@
+--
+-- 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;
index 5afe1ba193cf4861b6b5786c8fb8020ca9a1118d..c91c4cf572f15c69aa1afa37ec8f17debca4d6c4 100644 (file)
@@ -2,6 +2,12 @@
 -- 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
 -- @SECURITY-CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0
 SET sepgsql.debug_audit = true;
index 473004f6d22e37f0fa1c9968e847021aefab13dd..8d1a35ce8518ee9607f70339c2d74632b84eea8c 100755 (executable)
@@ -162,6 +162,31 @@ if [ "${POLICY_STATUS}" != on ]; then
     echo ""
     exit 1
 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
 echo -n "checking whether we can run psql    ... "
@@ -259,6 +284,6 @@ echo "found ${NUM}"
 echo
 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"
index e7ce8b5d5b3df811ec0e0946c83eaa123837cfd8..5ee08e1dee2b36553c39f9c9af5b9c16ed1bc932 100644 (file)
@@ -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,
     sequences and procedures), <literal>add_name</> will be also checked
     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>
@@ -450,9 +456,19 @@ UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
    </para>
 
    <para>
-    When objects that are subsidiary of other objects (such as a table's indexes
-    or triggers) are created or dropped, <literal>setattr</> permission will be
-    checked on the main object, instead of the subsidiary object itself.
+    When <literal>ALTER</> command is executed, <literal>setattr</> will be
+    checked on the object being modified for each object types. 
+    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>