diff options
-rw-r--r-- | contrib/sepgsql/expected/truncate.out | 46 | ||||
-rw-r--r-- | contrib/sepgsql/hooks.c | 14 | ||||
-rw-r--r-- | contrib/sepgsql/relation.c | 40 | ||||
-rw-r--r-- | contrib/sepgsql/selinux.c | 3 | ||||
-rw-r--r-- | contrib/sepgsql/sepgsql-regtest.te | 8 | ||||
-rw-r--r-- | contrib/sepgsql/sepgsql.h | 2 | ||||
-rw-r--r-- | contrib/sepgsql/sql/truncate.sql | 24 | ||||
-rwxr-xr-x | contrib/sepgsql/test_sepgsql | 16 |
8 files changed, 152 insertions, 1 deletions
diff --git a/contrib/sepgsql/expected/truncate.out b/contrib/sepgsql/expected/truncate.out new file mode 100644 index 00000000000..e2cabd77b34 --- /dev/null +++ b/contrib/sepgsql/expected/truncate.out @@ -0,0 +1,46 @@ +-- +-- Regression Test for TRUNCATE +-- +-- +-- Setup +-- +CREATE TABLE julio_claudians (name text, birth_date date); +SECURITY LABEL ON TABLE julio_claudians IS 'system_u:object_r:sepgsql_regtest_foo_table_t:s0'; +INSERT INTO julio_claudians VALUES ('Augustus', 'September 23, 63 BC'), ('Tiberius', 'November 16, 42 BC'), ('Caligula', 'August 31, 0012'), ('Claudius', 'August 1, 0010'), ('Nero', 'December 15, 0037'); +CREATE TABLE flavians (name text, birth_date date); +SECURITY LABEL ON TABLE flavians IS 'system_u:object_r:sepgsql_table_t:s0'; +INSERT INTO flavians VALUES ('Vespasian', 'November 17, 0009'), ('Titus', 'December 30, 0039'), ('Domitian', 'October 24, 0051'); +SELECT * from julio_claudians; + name | birth_date +----------+--------------- + Augustus | 09-23-0063 BC + Tiberius | 11-16-0042 BC + Caligula | 08-31-0012 + Claudius | 08-01-0010 + Nero | 12-15-0037 +(5 rows) + +SELECT * from flavians; + name | birth_date +-----------+------------ + Vespasian | 11-17-0009 + Titus | 12-30-0039 + Domitian | 10-24-0051 +(3 rows) + +TRUNCATE TABLE julio_claudians; -- ok +TRUNCATE TABLE flavians; -- failed +ERROR: SELinux: security policy violation +SELECT * from julio_claudians; + name | birth_date +------+------------ +(0 rows) + +SELECT * from flavians; + name | birth_date +-----------+------------ + Vespasian | 11-17-0009 + Titus | 12-30-0039 + Domitian | 10-24-0051 +(3 rows) + diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c index 49f32ac4d33..cdf1452cf57 100644 --- a/contrib/sepgsql/hooks.c +++ b/contrib/sepgsql/hooks.c @@ -188,6 +188,20 @@ sepgsql_object_access(ObjectAccessType access, } break; + case OAT_TRUNCATE: + { + switch (classId) + { + case RelationRelationId: + sepgsql_relation_truncate(objectId); + break; + default: + /* Ignore unsupported object classes */ + break; + } + } + break; + case OAT_POST_ALTER: { ObjectAccessPostAlter *pa_arg = arg; diff --git a/contrib/sepgsql/relation.c b/contrib/sepgsql/relation.c index 714cffed973..fa34221509a 100644 --- a/contrib/sepgsql/relation.c +++ b/contrib/sepgsql/relation.c @@ -517,6 +517,46 @@ sepgsql_relation_drop(Oid relOid) } /* + * sepgsql_relation_truncate + * + * Check privileges to TRUNCATE the supplied relation. + */ +void +sepgsql_relation_truncate(Oid relOid) +{ + ObjectAddress object; + char *audit_name; + uint16_t tclass = 0; + char relkind = get_rel_relkind(relOid); + + switch (relkind) + { + case RELKIND_RELATION: + case RELKIND_PARTITIONED_TABLE: + tclass = SEPG_CLASS_DB_TABLE; + break; + default: + /* ignore other relkinds */ + return; + } + + /* + * check db_table:{truncate} permission + */ + object.classId = RelationRelationId; + object.objectId = relOid; + object.objectSubId = 0; + audit_name = getObjectIdentity(&object); + + sepgsql_avc_check_perms(&object, + tclass, + SEPG_DB_TABLE__TRUNCATE, + audit_name, + true); + pfree(audit_name); +} + +/* * sepgsql_relation_relabel * * It checks privileges to relabel the supplied relation by the `seclabel'. diff --git a/contrib/sepgsql/selinux.c b/contrib/sepgsql/selinux.c index b7c489cc336..5e6189a4c31 100644 --- a/contrib/sepgsql/selinux.c +++ b/contrib/sepgsql/selinux.c @@ -360,6 +360,9 @@ static struct "lock", SEPG_DB_TABLE__LOCK }, { + "truncate", SEPG_DB_TABLE__TRUNCATE + }, + { NULL, 0UL }, } diff --git a/contrib/sepgsql/sepgsql-regtest.te b/contrib/sepgsql/sepgsql-regtest.te index 5d9af1a0ddb..569c4da95b9 100644 --- a/contrib/sepgsql/sepgsql-regtest.te +++ b/contrib/sepgsql/sepgsql-regtest.te @@ -152,6 +152,14 @@ allow sepgsql_regtest_var_t sepgsql_regtest_var_table_t:db_tuple { select update optional_policy(` gen_require(` + class db_table { truncate }; + ') + + allow sepgsql_regtest_superuser_t sepgsql_regtest_foo_table_t:db_table { truncate }; +') + +optional_policy(` + gen_require(` role unconfined_r; ') postgresql_role(unconfined_r, sepgsql_regtest_foo_t) diff --git a/contrib/sepgsql/sepgsql.h b/contrib/sepgsql/sepgsql.h index 4787934650a..31828e9eea5 100644 --- a/contrib/sepgsql/sepgsql.h +++ b/contrib/sepgsql/sepgsql.h @@ -145,6 +145,7 @@ #define SEPG_DB_TABLE__INSERT (1<<8) #define SEPG_DB_TABLE__DELETE (1<<9) #define SEPG_DB_TABLE__LOCK (1<<10) +#define SEPG_DB_TABLE__TRUNCATE (1<<11) #define SEPG_DB_SEQUENCE__CREATE (SEPG_DB_DATABASE__CREATE) #define SEPG_DB_SEQUENCE__DROP (SEPG_DB_DATABASE__DROP) @@ -312,6 +313,7 @@ extern void sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum, 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_truncate(Oid relOid); extern void sepgsql_relation_relabel(Oid relOid, const char *seclabel); extern void sepgsql_relation_setattr(Oid relOid); diff --git a/contrib/sepgsql/sql/truncate.sql b/contrib/sepgsql/sql/truncate.sql new file mode 100644 index 00000000000..3748a1bdbea --- /dev/null +++ b/contrib/sepgsql/sql/truncate.sql @@ -0,0 +1,24 @@ +-- +-- Regression Test for TRUNCATE +-- + +-- +-- Setup +-- +CREATE TABLE julio_claudians (name text, birth_date date); +SECURITY LABEL ON TABLE julio_claudians IS 'system_u:object_r:sepgsql_regtest_foo_table_t:s0'; +INSERT INTO julio_claudians VALUES ('Augustus', 'September 23, 63 BC'), ('Tiberius', 'November 16, 42 BC'), ('Caligula', 'August 31, 0012'), ('Claudius', 'August 1, 0010'), ('Nero', 'December 15, 0037'); + +CREATE TABLE flavians (name text, birth_date date); +SECURITY LABEL ON TABLE flavians IS 'system_u:object_r:sepgsql_table_t:s0'; + +INSERT INTO flavians VALUES ('Vespasian', 'November 17, 0009'), ('Titus', 'December 30, 0039'), ('Domitian', 'October 24, 0051'); + +SELECT * from julio_claudians; +SELECT * from flavians; + +TRUNCATE TABLE julio_claudians; -- ok +TRUNCATE TABLE flavians; -- failed + +SELECT * from julio_claudians; +SELECT * from flavians; diff --git a/contrib/sepgsql/test_sepgsql b/contrib/sepgsql/test_sepgsql index 7530363d2cc..3a29556d1ff 100755 --- a/contrib/sepgsql/test_sepgsql +++ b/contrib/sepgsql/test_sepgsql @@ -287,6 +287,20 @@ echo "found ${NUM}" echo echo "============== running sepgsql regression tests ==============" -make REGRESS="label dml ddl alter misc" REGRESS_OPTS="--launcher ./launcher" installcheck +tests="label dml ddl alter misc" +# Check if the truncate permission exists in the loaded policy, and if so, +# run the truncate test +# +# Testing the TRUNCATE regression test can be done by manually adding +# the permission with CIL if necessary: +# sudo semodule -cE base +# sudo sed -i -E 's/(class db_table.*?) \)/\1 truncate\)/' base.cil +# sudo semodule -i base.cil + +if [ -f /sys/fs/selinux/class/db_table/perms/truncate ]; then + tests+=" truncate" +fi + +make REGRESS="$tests" REGRESS_OPTS="--launcher ./launcher" installcheck # exit with the exit code provided by "make" |