dblink: Avoid locking relation before privilege check.
authorNathan Bossart <nathan@postgresql.org>
Tue, 14 Oct 2025 17:20:48 +0000 (12:20 -0500)
committerNathan Bossart <nathan@postgresql.org>
Tue, 14 Oct 2025 17:20:48 +0000 (12:20 -0500)
The present coding of dblink's get_rel_from_relname() predates the
introduction of RangeVarGetRelidExtended(), which provides a way to
check permissions before locking the relation.  This commit adjusts
get_rel_from_relname() to use that function.

Reviewed-by: Jeff Davis <pgsql@j-davis.com>
Discussion: https://postgr.es/m/aOgmi6avE6qMw_6t%40nathan

contrib/dblink/dblink.c

index 0cf4c27f2e967ac31677abf69c1e8e6e7a9b9901..1e7696beb5089a1f0106b6d0beb10c6ff68f55d6 100644 (file)
@@ -2460,6 +2460,21 @@ get_tuple_of_interest(Relation rel, int *pkattnums, int pknumatts, char **src_pk
        return NULL;
 }
 
+static void
+RangeVarCallbackForDblink(const RangeVar *relation,
+                                                 Oid relId, Oid oldRelId, void *arg)
+{
+       AclResult       aclresult;
+
+       if (!OidIsValid(relId))
+               return;
+
+       aclresult = pg_class_aclcheck(relId, GetUserId(), *((AclMode *) arg));
+       if (aclresult != ACLCHECK_OK)
+               aclcheck_error(aclresult, get_relkind_objtype(get_rel_relkind(relId)),
+                                          relation->relname);
+}
+
 /*
  * Open the relation named by relname_text, acquire specified type of lock,
  * verify we have specified permissions.
@@ -2469,19 +2484,13 @@ static Relation
 get_rel_from_relname(text *relname_text, LOCKMODE lockmode, AclMode aclmode)
 {
        RangeVar   *relvar;
-       Relation        rel;
-       AclResult       aclresult;
+       Oid                     relid;
 
        relvar = makeRangeVarFromNameList(textToQualifiedNameList(relname_text));
-       rel = table_openrv(relvar, lockmode);
-
-       aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
-                                                                 aclmode);
-       if (aclresult != ACLCHECK_OK)
-               aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind),
-                                          RelationGetRelationName(rel));
+       relid = RangeVarGetRelidExtended(relvar, lockmode, 0,
+                                                                        RangeVarCallbackForDblink, &aclmode);
 
-       return rel;
+       return table_open(relid, NoLock);
 }
 
 /*