From 6a04b4b3efc2a4322ff88f4e854024283325b6cb Mon Sep 17 00:00:00 2001
From: Yuli Khodorkovskiy <yuli@crunchydata.com>
Date: Mon, 15 Jul 2019 13:58:51 -0400
Subject: [PATCH 1/2] Add a hook to allow MAC check 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.
---
 src/backend/catalog/objectaccess.c | 16 ++++++++++++++++
 src/backend/commands/tablecmds.c   |  2 ++
 src/include/catalog/objectaccess.h | 10 +++++++++-
 3 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/src/backend/catalog/objectaccess.c b/src/backend/catalog/objectaccess.c
index b1619b859f..8f40f8f33d 100644
--- a/src/backend/catalog/objectaccess.c
+++ b/src/backend/catalog/objectaccess.c
@@ -64,6 +64,22 @@ RunObjectDropHook(Oid classId, Oid objectId, int subId,
 						   (void *) &drop_arg);
 }
 
+/*
+ * RunObjectTruncateHook
+ *
+ * It is the entrypoint of a TRUNCATE event
+ */
+void
+RunObjectTruncateHook(Oid classId, Oid objectId, int subId)
+{
+	/* caller should check, but just in case... */
+	Assert(object_access_hook != NULL);
+
+	(*object_access_hook) (OAT_TRUNCATE,
+						   classId, objectId, 0,
+						   NULL);
+}
+
 /*
  * RunObjectPostAlterHook
  *
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index decd1bbeb8..b833a77d15 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1931,6 +1931,8 @@ truncate_check_rel(Oid relid, Form_pg_class reltuple)
 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 				 errmsg("permission denied: \"%s\" is a system catalog",
 						relname)));
+
+	InvokeObjectTruncateHook(RelationRelationId, relid, 0);
 }
 
 /*
diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h
index 0170f1f1e4..079bcec98a 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 classId, Oid objectId, int subId);
 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(classId,objectId,subId)							\
+	do {															\
+		if (object_access_hook)										\
+			RunObjectTruncateHook((classId),(objectId),(subId));						\
+	} while(0)
+
 #define InvokeObjectPostAlterHook(classId,objectId,subId)			\
 	InvokeObjectPostAlterHookArg((classId),(objectId),(subId),		\
 								 InvalidOid,false)
-- 
2.22.0

