Skip to content

Commit 52994e9

Browse files
committed
Fix unsafe order of operations in foreign-table DDL commands.
When updating or deleting a system catalog tuple, it's necessary to acquire RowExclusiveLock on the catalog before looking up the tuple; otherwise a concurrent VACUUM FULL on the catalog might move the tuple to a different TID before we can apply the update. Coding patterns that find the tuple via a table scan aren't at risk here, but when obtaining the tuple from a catalog cache, correct ordering is important; and several routines in foreigncmds.c got it wrong. Noted while running the regression tests in parallel with VACUUM FULL of assorted system catalogs. For consistency I moved all the heap_open calls to the starts of their functions, including a couple for which there was no actual bug. Back-patch to 8.4 where foreigncmds.c was added.
1 parent 8561203 commit 52994e9

File tree

1 file changed

+18
-21
lines changed

1 file changed

+18
-21
lines changed

src/backend/commands/foreigncmds.c

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId)
215215
Oid fdwId;
216216
Form_pg_foreign_data_wrapper form;
217217

218+
rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
219+
218220
/* Must be a superuser to change a FDW owner */
219221
if (!superuser())
220222
ereport(ERROR,
@@ -231,8 +233,6 @@ AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId)
231233
name),
232234
errhint("The owner of a foreign-data wrapper must be a superuser.")));
233235

234-
rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
235-
236236
tup = SearchSysCacheCopy1(FOREIGNDATAWRAPPERNAME, CStringGetDatum(name));
237237

238238
if (!HeapTupleIsValid(tup))
@@ -432,6 +432,8 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
432432
ObjectAddress myself;
433433
ObjectAddress referenced;
434434

435+
rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
436+
435437
/* Must be super user */
436438
if (!superuser())
437439
ereport(ERROR,
@@ -455,8 +457,6 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
455457
/*
456458
* Insert tuple into pg_foreign_data_wrapper.
457459
*/
458-
rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
459-
460460
memset(values, 0, sizeof(values));
461461
memset(nulls, false, sizeof(nulls));
462462

@@ -545,6 +545,8 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
545545
Oid fdwhandler;
546546
Oid fdwvalidator;
547547

548+
rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
549+
548550
/* Must be super user */
549551
if (!superuser())
550552
ereport(ERROR,
@@ -635,9 +637,6 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
635637
}
636638

637639
/* Everything looks good - update the tuple */
638-
639-
rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
640-
641640
tp = heap_modify_tuple(tp, RelationGetDescr(rel),
642641
repl_val, repl_null, repl_repl);
643642

@@ -773,6 +772,8 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
773772
ObjectAddress referenced;
774773
ForeignDataWrapper *fdw;
775774

775+
rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
776+
776777
/* For now the owner cannot be specified on create. Use effective user ID. */
777778
ownerId = GetUserId();
778779

@@ -798,8 +799,6 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
798799
/*
799800
* Insert tuple into pg_foreign_server.
800801
*/
801-
rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
802-
803802
memset(values, 0, sizeof(values));
804803
memset(nulls, false, sizeof(nulls));
805804

@@ -880,6 +879,8 @@ AlterForeignServer(AlterForeignServerStmt *stmt)
880879
Oid srvId;
881880
Form_pg_foreign_server srvForm;
882881

882+
rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
883+
883884
tp = SearchSysCacheCopy1(FOREIGNSERVERNAME,
884885
CStringGetDatum(stmt->servername));
885886

@@ -945,9 +946,6 @@ AlterForeignServer(AlterForeignServerStmt *stmt)
945946
}
946947

947948
/* Everything looks good - update the tuple */
948-
949-
rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
950-
951949
tp = heap_modify_tuple(tp, RelationGetDescr(rel),
952950
repl_val, repl_null, repl_repl);
953951

@@ -1068,6 +1066,8 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
10681066
ForeignServer *srv;
10691067
ForeignDataWrapper *fdw;
10701068

1069+
rel = heap_open(UserMappingRelationId, RowExclusiveLock);
1070+
10711071
useId = GetUserOidFromMapping(stmt->username, false);
10721072

10731073
/* Check that the server exists. */
@@ -1093,8 +1093,6 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
10931093
/*
10941094
* Insert tuple into pg_user_mapping.
10951095
*/
1096-
rel = heap_open(UserMappingRelationId, RowExclusiveLock);
1097-
10981096
memset(values, 0, sizeof(values));
10991097
memset(nulls, false, sizeof(nulls));
11001098

@@ -1161,6 +1159,8 @@ AlterUserMapping(AlterUserMappingStmt *stmt)
11611159
Oid umId;
11621160
ForeignServer *srv;
11631161

1162+
rel = heap_open(UserMappingRelationId, RowExclusiveLock);
1163+
11641164
useId = GetUserOidFromMapping(stmt->username, false);
11651165
srv = GetForeignServerByName(stmt->servername, false);
11661166

@@ -1218,9 +1218,6 @@ AlterUserMapping(AlterUserMappingStmt *stmt)
12181218
}
12191219

12201220
/* Everything looks good - update the tuple */
1221-
1222-
rel = heap_open(UserMappingRelationId, RowExclusiveLock);
1223-
12241221
tp = heap_modify_tuple(tp, RelationGetDescr(rel),
12251222
repl_val, repl_null, repl_repl);
12261223

@@ -1344,11 +1341,13 @@ CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid)
13441341
ForeignServer *server;
13451342

13461343
/*
1347-
* Advance command counter to ensure the pg_attribute tuple visible; the
1348-
* tuple might be updated to add constraints in previous step.
1344+
* Advance command counter to ensure the pg_attribute tuple is visible;
1345+
* the tuple might be updated to add constraints in previous step.
13491346
*/
13501347
CommandCounterIncrement();
13511348

1349+
ftrel = heap_open(ForeignTableRelationId, RowExclusiveLock);
1350+
13521351
/*
13531352
* For now the owner cannot be specified on create. Use effective user ID.
13541353
*/
@@ -1368,8 +1367,6 @@ CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid)
13681367
/*
13691368
* Insert tuple into pg_foreign_table.
13701369
*/
1371-
ftrel = heap_open(ForeignTableRelationId, RowExclusiveLock);
1372-
13731370
memset(values, 0, sizeof(values));
13741371
memset(nulls, false, sizeof(nulls));
13751372

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy