Skip to content

Commit 05e1737

Browse files
committed
Fix search_path to a safe value during maintenance operations.
While executing maintenance operations (ANALYZE, CLUSTER, REFRESH MATERIALIZED VIEW, REINDEX, or VACUUM), set search_path to 'pg_catalog, pg_temp' to prevent inconsistent behavior. Functions that are used for functional indexes, in index expressions, or in materialized views and depend on a different search path must be declared with CREATE FUNCTION ... SET search_path='...'. This change addresses a security risk introduced in commit 60684dd, where a role with MAINTAIN privileges on a table may be able to escalate privileges to the table owner. That commit is not yet part of any release, so no need to backpatch. Discussion: https://postgr.es/m/e44327179e5c9015c8dda67351c04da552066017.camel%40j-davis.com Reviewed-by: Greg Stark Reviewed-by: Nathan Bossart
1 parent 9aee26a commit 05e1737

File tree

15 files changed

+48
-16
lines changed

15 files changed

+48
-16
lines changed

contrib/amcheck/verify_nbtree.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@ bt_index_check_internal(Oid indrelid, bool parentcheck, bool heapallindexed,
282282
SetUserIdAndSecContext(heaprel->rd_rel->relowner,
283283
save_sec_context | SECURITY_RESTRICTED_OPERATION);
284284
save_nestlevel = NewGUCNestLevel();
285+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
286+
PGC_S_SESSION);
285287
}
286288
else
287289
{

src/backend/access/brin/brin.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,8 @@ brin_summarize_range(PG_FUNCTION_ARGS)
10661066
SetUserIdAndSecContext(heapRel->rd_rel->relowner,
10671067
save_sec_context | SECURITY_RESTRICTED_OPERATION);
10681068
save_nestlevel = NewGUCNestLevel();
1069+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
1070+
PGC_S_SESSION);
10691071
}
10701072
else
10711073
{

src/backend/catalog/index.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,8 @@ index_concurrently_build(Oid heapRelationId,
14751475
SetUserIdAndSecContext(heapRel->rd_rel->relowner,
14761476
save_sec_context | SECURITY_RESTRICTED_OPERATION);
14771477
save_nestlevel = NewGUCNestLevel();
1478+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
1479+
PGC_S_SESSION);
14781480

14791481
indexRelation = index_open(indexRelationId, RowExclusiveLock);
14801482

@@ -3006,6 +3008,8 @@ index_build(Relation heapRelation,
30063008
SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
30073009
save_sec_context | SECURITY_RESTRICTED_OPERATION);
30083010
save_nestlevel = NewGUCNestLevel();
3011+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
3012+
PGC_S_SESSION);
30093013

30103014
/* Set up initial progress report status */
30113015
{
@@ -3341,6 +3345,8 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
33413345
SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
33423346
save_sec_context | SECURITY_RESTRICTED_OPERATION);
33433347
save_nestlevel = NewGUCNestLevel();
3348+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
3349+
PGC_S_SESSION);
33443350

33453351
indexRelation = index_open(indexId, RowExclusiveLock);
33463352

@@ -3601,6 +3607,8 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
36013607
SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
36023608
save_sec_context | SECURITY_RESTRICTED_OPERATION);
36033609
save_nestlevel = NewGUCNestLevel();
3610+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
3611+
PGC_S_SESSION);
36043612

36053613
if (progress)
36063614
{

src/backend/commands/analyze.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
348348
SetUserIdAndSecContext(onerel->rd_rel->relowner,
349349
save_sec_context | SECURITY_RESTRICTED_OPERATION);
350350
save_nestlevel = NewGUCNestLevel();
351+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
352+
PGC_S_SESSION);
351353

352354
/* measure elapsed time iff autovacuum logging requires it */
353355
if (IsAutoVacuumWorkerProcess() && params->log_min_duration >= 0)

src/backend/commands/cluster.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ cluster_rel(Oid tableOid, Oid indexOid, ClusterParams *params)
355355
SetUserIdAndSecContext(OldHeap->rd_rel->relowner,
356356
save_sec_context | SECURITY_RESTRICTED_OPERATION);
357357
save_nestlevel = NewGUCNestLevel();
358+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
359+
PGC_S_SESSION);
358360

359361
/*
360362
* Since we may open a new transaction for each relation, we have to check

src/backend/commands/indexcmds.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,8 @@ DefineIndex(Oid relationId,
575575
int root_save_nestlevel;
576576

577577
root_save_nestlevel = NewGUCNestLevel();
578+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
579+
PGC_S_SESSION);
578580

579581
/*
580582
* Some callers need us to run with an empty default_tablespace; this is a
@@ -1300,6 +1302,8 @@ DefineIndex(Oid relationId,
13001302
SetUserIdAndSecContext(childrel->rd_rel->relowner,
13011303
child_save_sec_context | SECURITY_RESTRICTED_OPERATION);
13021304
child_save_nestlevel = NewGUCNestLevel();
1305+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
1306+
PGC_S_SESSION);
13031307

13041308
/*
13051309
* Don't try to create indexes on foreign tables, though. Skip
@@ -3753,6 +3757,8 @@ ReindexRelationConcurrently(Oid relationOid, ReindexParams *params)
37533757
SetUserIdAndSecContext(heapRel->rd_rel->relowner,
37543758
save_sec_context | SECURITY_RESTRICTED_OPERATION);
37553759
save_nestlevel = NewGUCNestLevel();
3760+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
3761+
PGC_S_SESSION);
37563762

37573763
/* determine safety of this index for set_indexsafe_procflags */
37583764
idx->safe = (indexRel->rd_indexprs == NIL &&

src/backend/commands/matview.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
179179
SetUserIdAndSecContext(relowner,
180180
save_sec_context | SECURITY_RESTRICTED_OPERATION);
181181
save_nestlevel = NewGUCNestLevel();
182+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
183+
PGC_S_SESSION);
182184

183185
/* Make sure it is a materialized view. */
184186
if (matviewRel->rd_rel->relkind != RELKIND_MATVIEW)

src/backend/commands/vacuum.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,6 +2172,8 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
21722172
SetUserIdAndSecContext(rel->rd_rel->relowner,
21732173
save_sec_context | SECURITY_RESTRICTED_OPERATION);
21742174
save_nestlevel = NewGUCNestLevel();
2175+
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
2176+
PGC_S_SESSION);
21752177

21762178
/*
21772179
* If PROCESS_MAIN is set (the default), it's time to vacuum the main

src/bin/scripts/t/100_vacuumdb.pl

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,11 @@
109109
CREATE FUNCTION f1(int) RETURNS int LANGUAGE SQL AS 'SELECT f0($1)';
110110
CREATE TABLE funcidx (x int);
111111
INSERT INTO funcidx VALUES (0),(1),(2),(3);
112-
CREATE INDEX i0 ON funcidx ((f1(x)));
113112
CREATE SCHEMA "Foo";
114113
CREATE TABLE "Foo".bar(id int);
115114
|);
116115
$node->command_ok([qw|vacuumdb -Z --table="need""q(uot"(")x") postgres|],
117116
'column list');
118-
$node->command_fails(
119-
[qw|vacuumdb -Zt funcidx postgres|],
120-
'unqualified name via functional index');
121117

122118
$node->command_fails(
123119
[ 'vacuumdb', '--analyze', '--table', 'vactable(c)', 'postgres' ],

src/include/utils/guc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ typedef enum
201201

202202
#define GUC_QUALIFIER_SEPARATOR '.'
203203

204+
/*
205+
* Safe search path when executing code as the table owner, such as during
206+
* maintenance operations.
207+
*/
208+
#define GUC_SAFE_SEARCH_PATH "pg_catalog, pg_temp"
209+
204210
/*
205211
* Bit values in "flags" of a GUC variable. Note that these don't appear
206212
* on disk, so we can reassign their values freely.

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