From 8bc225e7990a791dadf5f472c01fd9477a80d5db Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 29 Aug 2007 17:24:29 +0000
Subject: [PATCH] Relax permissions checks on dbsize functions, per discussion.
  Revert out all checks for individual-table-size functions, since anyone in
 the database could get approximate values from pg_class.relpages anyway. 
 Allow database-size to users with CONNECT privilege for the target database
 (note that this is granted by default).  Allow tablespace-size if the user
 has CREATE privilege on the tablespace (which is *not* granted by default),
 or if the tablespace is the default tablespace for the current database
 (since we treat that as implicitly allowing use of the tablespace).

---
 src/backend/utils/adt/dbsize.c | 57 +++++++++++++---------------------
 1 file changed, 21 insertions(+), 36 deletions(-)

diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 0681876b3db..3848e8111f1 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2002-2007, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.13 2007/08/27 01:19:14 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.14 2007/08/29 17:24:29 tgl Exp $
  *
  */
 
@@ -79,6 +79,13 @@ calculate_database_size(Oid dbOid)
 	struct dirent *direntry;
 	char		dirpath[MAXPGPATH];
 	char		pathname[MAXPGPATH];
+	AclResult	aclresult;
+
+	/* User must have connect privilege for target database */
+	aclresult = pg_database_aclcheck(dbOid, GetUserId(), ACL_CONNECT);
+	if (aclresult != ACLCHECK_OK)
+		aclcheck_error(aclresult, ACL_KIND_DATABASE,
+					   get_database_name(dbOid));
 
 	/* Shared storage in pg_global is not counted */
 
@@ -122,10 +129,6 @@ pg_database_size_oid(PG_FUNCTION_ARGS)
 {
 	Oid			dbOid = PG_GETARG_OID(0);
 
-	if (!pg_database_ownercheck(dbOid, GetUserId()))
-		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
-					   get_database_name(dbOid));
-
 	PG_RETURN_INT64(calculate_database_size(dbOid));
 }
 
@@ -141,10 +144,6 @@ pg_database_size_name(PG_FUNCTION_ARGS)
 				 errmsg("database \"%s\" does not exist",
 						NameStr(*dbName))));
 
-	if (!pg_database_ownercheck(dbOid, GetUserId()))
-		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
-					   NameStr(*dbName));
-
 	PG_RETURN_INT64(calculate_database_size(dbOid));
 }
 
@@ -160,6 +159,19 @@ calculate_tablespace_size(Oid tblspcOid)
 	int64		totalsize = 0;
 	DIR		   *dirdesc;
 	struct dirent *direntry;
+	AclResult	aclresult;
+
+	/*
+	 * User must have CREATE privilege for target tablespace, either explicitly
+	 * granted or implicitly because it is default for current database.
+	 */
+	if (tblspcOid != MyDatabaseTableSpace)
+	{
+		aclresult = pg_tablespace_aclcheck(tblspcOid, GetUserId(), ACL_CREATE);
+		if (aclresult != ACLCHECK_OK)
+			aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
+						   get_tablespace_name(tblspcOid));
+	}
 
 	if (tblspcOid == DEFAULTTABLESPACE_OID)
 		snprintf(tblspcPath, MAXPGPATH, "base");
@@ -212,11 +224,6 @@ pg_tablespace_size_oid(PG_FUNCTION_ARGS)
 {
 	Oid			tblspcOid = PG_GETARG_OID(0);
 
-	if (!superuser())
-		ereport(ERROR,
-				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				 (errmsg("must be superuser to use pg_tablespace_size"))));
-
 	PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));
 }
 
@@ -226,11 +233,6 @@ pg_tablespace_size_name(PG_FUNCTION_ARGS)
 	Name		tblspcName = PG_GETARG_NAME(0);
 	Oid			tblspcOid = get_tablespace_oid(NameStr(*tblspcName));
 
-	if (!superuser())
-		ereport(ERROR,
-				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				 (errmsg("must be superuser to use pg_tablespace_size"))));
-
 	if (!OidIsValid(tblspcOid))
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -289,10 +291,6 @@ pg_relation_size_oid(PG_FUNCTION_ARGS)
 
 	rel = relation_open(relOid, AccessShareLock);
 
-	if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
-		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
-					   RelationGetRelationName(rel));
-
 	size = calculate_relation_size(&(rel->rd_node));
 
 	relation_close(rel, AccessShareLock);
@@ -311,10 +309,6 @@ pg_relation_size_name(PG_FUNCTION_ARGS)
 	relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
 	rel = relation_openrv(relrv, AccessShareLock);
 
-	if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
-		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
-					   RelationGetRelationName(rel));
-
 	size = calculate_relation_size(&(rel->rd_node));
 
 	relation_close(rel, AccessShareLock);
@@ -336,11 +330,6 @@ calculate_total_relation_size(Oid Relid)
 	ListCell   *cell;
 
 	heapRel = relation_open(Relid, AccessShareLock);
-
-	if (!pg_class_ownercheck(RelationGetRelid(heapRel), GetUserId()))
-		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
-					   RelationGetRelationName(heapRel));
-
 	toastOid = heapRel->rd_rel->reltoastrelid;
 
 	/* Get the heap size */
@@ -380,8 +369,6 @@ pg_total_relation_size_oid(PG_FUNCTION_ARGS)
 {
 	Oid			relid = PG_GETARG_OID(0);
 
-	/* permission check is inside calculate_total_relation_size */
-
 	PG_RETURN_INT64(calculate_total_relation_size(relid));
 }
 
@@ -395,8 +382,6 @@ pg_total_relation_size_name(PG_FUNCTION_ARGS)
 	relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
 	relid = RangeVarGetRelid(relrv, false);
 
-	/* permission check is inside calculate_total_relation_size */
-
 	PG_RETURN_INT64(calculate_total_relation_size(relid));
 }
 
-- 
GitLab