aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/sepgsql/expected/truncate.out46
-rw-r--r--contrib/sepgsql/hooks.c14
-rw-r--r--contrib/sepgsql/relation.c40
-rw-r--r--contrib/sepgsql/selinux.c3
-rw-r--r--contrib/sepgsql/sepgsql-regtest.te8
-rw-r--r--contrib/sepgsql/sepgsql.h2
-rw-r--r--contrib/sepgsql/sql/truncate.sql24
-rwxr-xr-xcontrib/sepgsql/test_sepgsql16
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"