0001-Use-MAC-in-addition-to-DAC-for-TRUNCATE.patch
application/octet-stream
Filename: 0001-Use-MAC-in-addition-to-DAC-for-TRUNCATE.patch
Type: application/octet-stream
Part: 0
Message:
add a MAC check for TRUNCATE
Patch
Format: format-patch
Series: patch 0001
Subject: Use MAC in addition to DAC for TRUNCATE
| File | + | − |
|---|---|---|
| contrib/sepgsql/hooks.c | 14 | 0 |
| contrib/sepgsql/relation.c | 40 | 0 |
| contrib/sepgsql/selinux.c | 3 | 0 |
| contrib/sepgsql/sepgsql.h | 2 | 0 |
| src/backend/catalog/objectaccess.c | 17 | 0 |
| src/backend/commands/tablecmds.c | 2 | 0 |
| src/include/catalog/objectaccess.h | 9 | 1 |
From ce496c4dbc226a0e1110d368de9f4bf80639e42b Mon Sep 17 00:00:00 2001
From: Yuli Khodorkovskiy <yuli@crunchydata.com>
Date: Mon, 15 Jul 2019 13:58:51 -0400
Subject: [PATCH] Use MAC in addition to DAC for TRUNCATE
All DAC checks need to have corresponding MAC. The command
`TRUNCATE` is missing this check. This patch adds a new hook to
allow extensions to implement an access check for TRUNCATE.
Additionaly, update sepgsql and create a new SELinux permission
check for TRUNCATE. Since refpolicy and Redhat do not currently
have this permission implemented, access checks on TRUNCATE will be
denied unless the system's `/sys/fs/selinux/deny_unknown` flag is
set to 0.
---
contrib/sepgsql/hooks.c | 14 +++++++++++
contrib/sepgsql/relation.c | 40 ++++++++++++++++++++++++++++++
contrib/sepgsql/selinux.c | 3 +++
contrib/sepgsql/sepgsql.h | 2 ++
src/backend/catalog/objectaccess.c | 17 +++++++++++++
src/backend/commands/tablecmds.c | 2 ++
src/include/catalog/objectaccess.h | 10 +++++++-
7 files changed, 87 insertions(+), 1 deletion(-)
diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c
index ebfa441b47..6f6afa2c04 100644
--- a/contrib/sepgsql/hooks.c
+++ b/contrib/sepgsql/hooks.c
@@ -189,6 +189,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 061527559c..d6170c6530 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
*
diff --git a/contrib/sepgsql/selinux.c b/contrib/sepgsql/selinux.c
index fbc044e818..651d13ecff 100644
--- a/contrib/sepgsql/selinux.c
+++ b/contrib/sepgsql/selinux.c
@@ -359,6 +359,9 @@ static struct
{
"lock", SEPG_DB_TABLE__LOCK
},
+ {
+ "truncate", SEPG_DB_TABLE__TRUNCATE
+ },
{
NULL, 0UL
},
diff --git a/contrib/sepgsql/sepgsql.h b/contrib/sepgsql/sepgsql.h
index 7197e3cdf0..5b55299a41 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/src/backend/catalog/objectaccess.c b/src/backend/catalog/objectaccess.c
index b1619b859f..066fe6a37f 100644
--- a/src/backend/catalog/objectaccess.c
+++ b/src/backend/catalog/objectaccess.c
@@ -13,6 +13,7 @@
#include "catalog/objectaccess.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
+#include "catalog/pg_class.h"
/*
* Hook on object accesses. This is intended as infrastructure for security
@@ -64,6 +65,22 @@ RunObjectDropHook(Oid classId, Oid objectId, int subId,
(void *) &drop_arg);
}
+/*
+ * RunObjectTruncateHook
+ *
+ * It is the entrypoint of a TRUNCATE event
+ */
+void
+RunObjectTruncateHook(Oid objectId)
+{
+ /* caller should check, but just in case... */
+ Assert(object_access_hook != NULL);
+
+ (*object_access_hook) (OAT_TRUNCATE,
+ RelationRelationId, objectId, 0,
+ NULL);
+}
+
/*
* RunObjectPostAlterHook
*
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index ba59fc708a..748e7df6e0 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1915,6 +1915,8 @@ truncate_check_rel(Oid relid, Form_pg_class reltuple)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied: \"%s\" is a system catalog",
relname)));
+
+ InvokeObjectTruncateHook(relid);
}
/*
diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h
index 0170f1f1e4..776120343b 100644
--- a/src/include/catalog/objectaccess.h
+++ b/src/include/catalog/objectaccess.h
@@ -45,7 +45,8 @@ typedef enum ObjectAccessType
OAT_DROP,
OAT_POST_ALTER,
OAT_NAMESPACE_SEARCH,
- OAT_FUNCTION_EXECUTE
+ OAT_FUNCTION_EXECUTE,
+ OAT_TRUNCATE
} ObjectAccessType;
/*
@@ -131,6 +132,7 @@ extern void RunObjectPostCreateHook(Oid classId, Oid objectId, int subId,
bool is_internal);
extern void RunObjectDropHook(Oid classId, Oid objectId, int subId,
int dropflags);
+extern void RunObjectTruncateHook(Oid objectId);
extern void RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
Oid auxiliaryId, bool is_internal);
extern bool RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation);
@@ -160,6 +162,12 @@ extern void RunFunctionExecuteHook(Oid objectId);
(dropflags)); \
} while(0)
+#define InvokeObjectTruncateHook(objectId) \
+ do { \
+ if (object_access_hook) \
+ RunObjectTruncateHook(objectId); \
+ } while(0)
+
#define InvokeObjectPostAlterHook(classId,objectId,subId) \
InvokeObjectPostAlterHookArg((classId),(objectId),(subId), \
InvalidOid,false)
--
2.19.0