hi.

just came to my mind.

If you're the table owner, you should be allowed to use get_raw_page (and other
pageinspect module functions)?
We can use RangeVarGetRelidExtended with
RangeVarCallbackOwnsRelation to perform the ownership check.

Attached is a draft POC.
Am I missing anything obvious?
diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c
index aef442b5db3..144e33c8f26 100644
--- a/contrib/pageinspect/rawpage.c
+++ b/contrib/pageinspect/rawpage.c
@@ -19,6 +19,7 @@
 #include "access/relation.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_type.h"
+#include "commands/tablecmds.h"
 #include "funcapi.h"
 #include "miscadmin.h"
 #include "pageinspect.h"
@@ -145,18 +146,21 @@ static bytea *
 get_raw_page_internal(text *relname, ForkNumber forknum, BlockNumber blkno)
 {
 	bytea	   *raw_page;
+	Oid			relid;
 	RangeVar   *relrv;
 	Relation	rel;
 	char	   *raw_page_data;
 	Buffer		buf;
 
-	if (!superuser())
-		ereport(ERROR,
-				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				 errmsg("must be superuser to use raw page functions")));
-
 	relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
-	rel = relation_openrv(relrv, AccessShareLock);
+
+	/* Open and lock sequence, and check for ownership along the way. */
+	relid = RangeVarGetRelidExtended(relrv,
+									 AccessShareLock,
+									 0,
+									 RangeVarCallbackOwnsRelation,
+									 NULL);
+	rel = relation_open(relid, NoLock);
 
 	if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
 		ereport(ERROR,
@@ -196,7 +200,7 @@ get_raw_page_internal(text *relname, ForkNumber forknum, BlockNumber blkno)
 	LockBuffer(buf, BUFFER_LOCK_UNLOCK);
 	ReleaseBuffer(buf);
 
-	relation_close(rel, AccessShareLock);
+	relation_close(rel, NoLock);
 
 	return raw_page;
 }

Reply via email to