Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)