Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3d2aed6

Browse files
committed
Avoid using unsafe search_path settings during dump and restore.
Historically, pg_dump has "set search_path = foo, pg_catalog" whendumping an object in schema "foo", and has also caused that settingto be used while restoring the object. This is problematic becausefunctions and operators in schema "foo" could capture references meantto refer to pg_catalog entries, both in the queries issued by pg_dumpand those issued during the subsequent restore run. That couldresult in dump/restore misbehavior, or in privilege escalation if anefarious user installs trojan-horse functions or operators.This patch changes pg_dump so that it does not change the search_pathdynamically. The emitted restore script sets the search_path to whatwas used at dump time, and then leaves it alone thereafter. Createdobjects are placed in the correct schema, regardless of the activesearch_path, by dint of schema-qualifying their names in the CREATEcommands, as well as in subsequent ALTER and ALTER-like commands.Since this change requires a change in the behavior of pg_restorewhen processing an archive file made according to this new convention,bump the archive file version number; old versions of pg_restore willtherefore refuse to process files made with new versions of pg_dump.Security:CVE-2018-1058
1 parent3bf05e0 commit3d2aed6

File tree

16 files changed

+1166
-1492
lines changed

16 files changed

+1166
-1492
lines changed

‎src/backend/utils/adt/ruleutils.c

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,17 @@
8686
#definePRETTYINDENT_LIMIT40/* wrap limit */
8787

8888
/* Pretty flags */
89-
#definePRETTYFLAG_PAREN1
90-
#definePRETTYFLAG_INDENT2
89+
#definePRETTYFLAG_PAREN0x0001
90+
#definePRETTYFLAG_INDENT0x0002
91+
#definePRETTYFLAG_SCHEMA0x0004
9192

9293
/* Default line length for pretty-print wrapping: 0 means wrap always */
9394
#defineWRAP_COLUMN_DEFAULT0
9495

95-
/*macro to test if pretty action needed */
96+
/*macros to test if pretty action needed */
9697
#definePRETTY_PAREN(context)((context)->prettyFlags & PRETTYFLAG_PAREN)
9798
#definePRETTY_INDENT(context)((context)->prettyFlags & PRETTYFLAG_INDENT)
99+
#definePRETTY_SCHEMA(context)((context)->prettyFlags & PRETTYFLAG_SCHEMA)
98100

99101

100102
/* ----------
@@ -499,7 +501,7 @@ pg_get_ruledef_ext(PG_FUNCTION_ARGS)
499501
intprettyFlags;
500502
char*res;
501503

502-
prettyFlags=pretty ?PRETTYFLAG_PAREN |PRETTYFLAG_INDENT :PRETTYFLAG_INDENT;
504+
prettyFlags=pretty ?(PRETTYFLAG_PAREN |PRETTYFLAG_INDENT |PRETTYFLAG_SCHEMA) :PRETTYFLAG_INDENT;
503505

504506
res=pg_get_ruledef_worker(ruleoid,prettyFlags);
505507

@@ -620,7 +622,7 @@ pg_get_viewdef_ext(PG_FUNCTION_ARGS)
620622
intprettyFlags;
621623
char*res;
622624

623-
prettyFlags=pretty ?PRETTYFLAG_PAREN |PRETTYFLAG_INDENT :PRETTYFLAG_INDENT;
625+
prettyFlags=pretty ?(PRETTYFLAG_PAREN |PRETTYFLAG_INDENT |PRETTYFLAG_SCHEMA) :PRETTYFLAG_INDENT;
624626

625627
res=pg_get_viewdef_worker(viewoid,prettyFlags,WRAP_COLUMN_DEFAULT);
626628

@@ -640,7 +642,7 @@ pg_get_viewdef_wrap(PG_FUNCTION_ARGS)
640642
char*res;
641643

642644
/* calling this implies we want pretty printing */
643-
prettyFlags=PRETTYFLAG_PAREN |PRETTYFLAG_INDENT;
645+
prettyFlags=PRETTYFLAG_PAREN |PRETTYFLAG_INDENT |PRETTYFLAG_SCHEMA;
644646

645647
res=pg_get_viewdef_worker(viewoid,prettyFlags,wrap);
646648

@@ -686,7 +688,7 @@ pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
686688
Oidviewoid;
687689
char*res;
688690

689-
prettyFlags=pretty ?PRETTYFLAG_PAREN |PRETTYFLAG_INDENT :PRETTYFLAG_INDENT;
691+
prettyFlags=pretty ?(PRETTYFLAG_PAREN |PRETTYFLAG_INDENT |PRETTYFLAG_SCHEMA) :PRETTYFLAG_INDENT;
690692

691693
/* Look up view name. Can't lock it - we might not have privileges. */
692694
viewrel=makeRangeVarFromNameList(textToQualifiedNameList(viewname));
@@ -922,8 +924,15 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
922924
appendStringInfoString(&buf," TRUNCATE");
923925
findx++;
924926
}
927+
928+
/*
929+
* In non-pretty mode, always schema-qualify the target table name for
930+
* safety. In pretty mode, schema-qualify only if not visible.
931+
*/
925932
appendStringInfo(&buf," ON %s ",
926-
generate_relation_name(trigrec->tgrelid,NIL));
933+
pretty ?
934+
generate_relation_name(trigrec->tgrelid,NIL) :
935+
generate_qualified_relation_name(trigrec->tgrelid));
927936

928937
if (OidIsValid(trigrec->tgconstraint))
929938
{
@@ -1017,7 +1026,7 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
10171026
context.windowClause=NIL;
10181027
context.windowTList=NIL;
10191028
context.varprefix= true;
1020-
context.prettyFlags=pretty ?PRETTYFLAG_PAREN |PRETTYFLAG_INDENT :PRETTYFLAG_INDENT;
1029+
context.prettyFlags=pretty ?(PRETTYFLAG_PAREN |PRETTYFLAG_INDENT |PRETTYFLAG_SCHEMA) :PRETTYFLAG_INDENT;
10211030
context.wrapColumn=WRAP_COLUMN_DEFAULT;
10221031
context.indentLevel=PRETTYINDENT_STD;
10231032
context.special_exprkind=EXPR_KIND_NONE;
@@ -1104,7 +1113,7 @@ pg_get_indexdef_ext(PG_FUNCTION_ARGS)
11041113
intprettyFlags;
11051114
char*res;
11061115

1107-
prettyFlags=pretty ?PRETTYFLAG_PAREN |PRETTYFLAG_INDENT :PRETTYFLAG_INDENT;
1116+
prettyFlags=pretty ?(PRETTYFLAG_PAREN |PRETTYFLAG_INDENT |PRETTYFLAG_SCHEMA) :PRETTYFLAG_INDENT;
11081117

11091118
res=pg_get_indexdef_worker(indexrelid,colno,NULL,colno!=0, false,
11101119
false,prettyFlags, true);
@@ -1132,7 +1141,8 @@ pg_get_indexdef_columns(Oid indexrelid, bool pretty)
11321141
{
11331142
intprettyFlags;
11341143

1135-
prettyFlags=pretty ?PRETTYFLAG_PAREN |PRETTYFLAG_INDENT :PRETTYFLAG_INDENT;
1144+
prettyFlags=pretty ? (PRETTYFLAG_PAREN |PRETTYFLAG_INDENT |PRETTYFLAG_SCHEMA) :PRETTYFLAG_INDENT;
1145+
11361146
returnpg_get_indexdef_worker(indexrelid,0,NULL, true, false, false,
11371147
prettyFlags, false);
11381148
}
@@ -1264,7 +1274,9 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
12641274
quote_identifier(NameStr(idxrelrec->relname)),
12651275
idxrelrec->relkind==RELKIND_PARTITIONED_INDEX
12661276
&& !inherits ?"ONLY " :"",
1267-
generate_relation_name(indrelid,NIL),
1277+
(prettyFlags&PRETTYFLAG_SCHEMA) ?
1278+
generate_relation_name(indrelid,NIL) :
1279+
generate_qualified_relation_name(indrelid),
12681280
quote_identifier(NameStr(amrec->amname)));
12691281
else/* currently, must be EXCLUDE constraint */
12701282
appendStringInfo(&buf,"EXCLUDE USING %s (",
@@ -1575,7 +1587,8 @@ pg_get_partkeydef_columns(Oid relid, bool pretty)
15751587
{
15761588
intprettyFlags;
15771589

1578-
prettyFlags=pretty ?PRETTYFLAG_PAREN |PRETTYFLAG_INDENT :PRETTYFLAG_INDENT;
1590+
prettyFlags=pretty ? (PRETTYFLAG_PAREN |PRETTYFLAG_INDENT |PRETTYFLAG_SCHEMA) :PRETTYFLAG_INDENT;
1591+
15791592
returnpg_get_partkeydef_worker(relid,prettyFlags, true, false);
15801593
}
15811594

@@ -1803,7 +1816,7 @@ pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
18031816
intprettyFlags;
18041817
char*res;
18051818

1806-
prettyFlags=pretty ?PRETTYFLAG_PAREN |PRETTYFLAG_INDENT :PRETTYFLAG_INDENT;
1819+
prettyFlags=pretty ?(PRETTYFLAG_PAREN |PRETTYFLAG_INDENT |PRETTYFLAG_SCHEMA) :PRETTYFLAG_INDENT;
18071820

18081821
res=pg_get_constraintdef_worker(constraintId, false,prettyFlags, true);
18091822

@@ -2258,7 +2271,7 @@ pg_get_expr_ext(PG_FUNCTION_ARGS)
22582271
intprettyFlags;
22592272
char*relname;
22602273

2261-
prettyFlags=pretty ?PRETTYFLAG_PAREN |PRETTYFLAG_INDENT :PRETTYFLAG_INDENT;
2274+
prettyFlags=pretty ?(PRETTYFLAG_PAREN |PRETTYFLAG_INDENT |PRETTYFLAG_SCHEMA) :PRETTYFLAG_INDENT;
22622275

22632276
if (OidIsValid(relid))
22642277
{
@@ -4709,7 +4722,10 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
47094722
}
47104723

47114724
/* The relation the rule is fired on */
4712-
appendStringInfo(buf," TO %s",generate_relation_name(ev_class,NIL));
4725+
appendStringInfo(buf," TO %s",
4726+
(prettyFlags&PRETTYFLAG_SCHEMA) ?
4727+
generate_relation_name(ev_class,NIL) :
4728+
generate_qualified_relation_name(ev_class));
47134729

47144730
/* If the rule has an event qualification, add it */
47154731
if (ev_qual==NULL)

‎src/bin/pg_dump/dumputils.c

Lines changed: 71 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ static void AddAcl(PQExpBuffer aclbuf, const char *keyword,
3232
*
3333
*name: the object name, in the form to use in the commands (already quoted)
3434
*subname: the sub-object name, if any (already quoted); NULL if none
35+
*nspname: the namespace the object is in (NULL if none); not pre-quoted
3536
*type: the object type (as seen in GRANT command: must be one of
3637
*TABLE, SEQUENCE, FUNCTION, PROCEDURE, LANGUAGE, SCHEMA, DATABASE, TABLESPACE,
3738
*FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT)
@@ -52,7 +53,7 @@ static void AddAcl(PQExpBuffer aclbuf, const char *keyword,
5253
* since this routine uses fmtId() internally.
5354
*/
5455
bool
55-
buildACLCommands(constchar*name,constchar*subname,
56+
buildACLCommands(constchar*name,constchar*subname,constchar*nspname,
5657
constchar*type,constchar*acls,constchar*racls,
5758
constchar*owner,constchar*prefix,intremoteVersion,
5859
PQExpBuffersql)
@@ -152,7 +153,10 @@ buildACLCommands(const char *name, const char *subname,
152153
appendPQExpBuffer(firstsql,"%sREVOKE ALL",prefix);
153154
if (subname)
154155
appendPQExpBuffer(firstsql,"(%s)",subname);
155-
appendPQExpBuffer(firstsql," ON %s %s FROM PUBLIC;\n",type,name);
156+
appendPQExpBuffer(firstsql," ON %s ",type);
157+
if (nspname&&*nspname)
158+
appendPQExpBuffer(firstsql,"%s.",fmtId(nspname));
159+
appendPQExpBuffer(firstsql,"%s FROM PUBLIC;\n",name);
156160
}
157161
else
158162
{
@@ -170,8 +174,11 @@ buildACLCommands(const char *name, const char *subname,
170174
{
171175
if (privs->len>0)
172176
{
173-
appendPQExpBuffer(firstsql,"%sREVOKE %s ON %s %s FROM ",
174-
prefix,privs->data,type,name);
177+
appendPQExpBuffer(firstsql,"%sREVOKE %s ON %s ",
178+
prefix,privs->data,type);
179+
if (nspname&&*nspname)
180+
appendPQExpBuffer(firstsql,"%s.",fmtId(nspname));
181+
appendPQExpBuffer(firstsql,"%s FROM ",name);
175182
if (grantee->len==0)
176183
appendPQExpBufferStr(firstsql,"PUBLIC;\n");
177184
elseif (strncmp(grantee->data,"group ",
@@ -185,8 +192,11 @@ buildACLCommands(const char *name, const char *subname,
185192
if (privswgo->len>0)
186193
{
187194
appendPQExpBuffer(firstsql,
188-
"%sREVOKE GRANT OPTION FOR %s ON %s %s FROM ",
189-
prefix,privswgo->data,type,name);
195+
"%sREVOKE GRANT OPTION FOR %s ON %s ",
196+
prefix,privswgo->data,type);
197+
if (nspname&&*nspname)
198+
appendPQExpBuffer(firstsql,"%s.",fmtId(nspname));
199+
appendPQExpBuffer(firstsql,"%s FROM ",name);
190200
if (grantee->len==0)
191201
appendPQExpBufferStr(firstsql,"PUBLIC");
192202
elseif (strncmp(grantee->data,"group ",
@@ -251,18 +261,33 @@ buildACLCommands(const char *name, const char *subname,
251261
appendPQExpBuffer(firstsql,"%sREVOKE ALL",prefix);
252262
if (subname)
253263
appendPQExpBuffer(firstsql,"(%s)",subname);
254-
appendPQExpBuffer(firstsql," ON %s %s FROM %s;\n",
255-
type,name,fmtId(grantee->data));
264+
appendPQExpBuffer(firstsql," ON %s ",type);
265+
if (nspname&&*nspname)
266+
appendPQExpBuffer(firstsql,"%s.",fmtId(nspname));
267+
appendPQExpBuffer(firstsql,"%s FROM %s;\n",
268+
name,fmtId(grantee->data));
256269
if (privs->len>0)
270+
{
257271
appendPQExpBuffer(firstsql,
258-
"%sGRANT %s ON %s %s TO %s;\n",
259-
prefix,privs->data,type,name,
260-
fmtId(grantee->data));
272+
"%sGRANT %s ON %s ",
273+
prefix,privs->data,type);
274+
if (nspname&&*nspname)
275+
appendPQExpBuffer(firstsql,"%s.",fmtId(nspname));
276+
appendPQExpBuffer(firstsql,
277+
"%s TO %s;\n",
278+
name,fmtId(grantee->data));
279+
}
261280
if (privswgo->len>0)
281+
{
262282
appendPQExpBuffer(firstsql,
263-
"%sGRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
264-
prefix,privswgo->data,type,name,
265-
fmtId(grantee->data));
283+
"%sGRANT %s ON %s ",
284+
prefix,privswgo->data,type);
285+
if (nspname&&*nspname)
286+
appendPQExpBuffer(firstsql,"%s.",fmtId(nspname));
287+
appendPQExpBuffer(firstsql,
288+
"%s TO %s WITH GRANT OPTION;\n",
289+
name,fmtId(grantee->data));
290+
}
266291
}
267292
}
268293
else
@@ -284,8 +309,11 @@ buildACLCommands(const char *name, const char *subname,
284309

285310
if (privs->len>0)
286311
{
287-
appendPQExpBuffer(secondsql,"%sGRANT %s ON %s %s TO ",
288-
prefix,privs->data,type,name);
312+
appendPQExpBuffer(secondsql,"%sGRANT %s ON %s ",
313+
prefix,privs->data,type);
314+
if (nspname&&*nspname)
315+
appendPQExpBuffer(secondsql,"%s.",fmtId(nspname));
316+
appendPQExpBuffer(secondsql,"%s TO ",name);
289317
if (grantee->len==0)
290318
appendPQExpBufferStr(secondsql,"PUBLIC;\n");
291319
elseif (strncmp(grantee->data,"group ",
@@ -297,8 +325,11 @@ buildACLCommands(const char *name, const char *subname,
297325
}
298326
if (privswgo->len>0)
299327
{
300-
appendPQExpBuffer(secondsql,"%sGRANT %s ON %s %s TO ",
301-
prefix,privswgo->data,type,name);
328+
appendPQExpBuffer(secondsql,"%sGRANT %s ON %s ",
329+
prefix,privswgo->data,type);
330+
if (nspname&&*nspname)
331+
appendPQExpBuffer(secondsql,"%s.",fmtId(nspname));
332+
appendPQExpBuffer(secondsql,"%s TO ",name);
302333
if (grantee->len==0)
303334
appendPQExpBufferStr(secondsql,"PUBLIC");
304335
elseif (strncmp(grantee->data,"group ",
@@ -328,8 +359,11 @@ buildACLCommands(const char *name, const char *subname,
328359
appendPQExpBuffer(firstsql,"%sREVOKE ALL",prefix);
329360
if (subname)
330361
appendPQExpBuffer(firstsql,"(%s)",subname);
331-
appendPQExpBuffer(firstsql," ON %s %s FROM %s;\n",
332-
type,name,fmtId(owner));
362+
appendPQExpBuffer(firstsql," ON %s ",type);
363+
if (nspname&&*nspname)
364+
appendPQExpBuffer(firstsql,"%s.",fmtId(nspname));
365+
appendPQExpBuffer(firstsql,"%s FROM %s;\n",
366+
name,fmtId(owner));
333367
}
334368

335369
destroyPQExpBuffer(grantee);
@@ -388,7 +422,8 @@ buildDefaultACLCommands(const char *type, const char *nspname,
388422
if (strlen(initacls)!=0||strlen(initracls)!=0)
389423
{
390424
appendPQExpBuffer(sql,"SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
391-
if (!buildACLCommands("",NULL,type,initacls,initracls,owner,
425+
if (!buildACLCommands("",NULL,NULL,type,
426+
initacls,initracls,owner,
392427
prefix->data,remoteVersion,sql))
393428
{
394429
destroyPQExpBuffer(prefix);
@@ -397,7 +432,8 @@ buildDefaultACLCommands(const char *type, const char *nspname,
397432
appendPQExpBuffer(sql,"SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
398433
}
399434

400-
if (!buildACLCommands("",NULL,type,acls,racls,owner,
435+
if (!buildACLCommands("",NULL,NULL,type,
436+
acls,racls,owner,
401437
prefix->data,remoteVersion,sql))
402438
{
403439
destroyPQExpBuffer(prefix);
@@ -641,26 +677,32 @@ AddAcl(PQExpBuffer aclbuf, const char *keyword, const char *subname)
641677
* buildShSecLabelQuery
642678
*
643679
* Build a query to retrieve security labels for a shared object.
680+
* The object is identified by its OID plus the name of the catalog
681+
* it can be found in (e.g., "pg_database" for database names).
682+
* The query is appended to "sql". (We don't execute it here so as to
683+
* keep this file free of assumptions about how to deal with SQL errors.)
644684
*/
645685
void
646-
buildShSecLabelQuery(PGconn*conn,constchar*catalog_name,uint32objectId,
686+
buildShSecLabelQuery(PGconn*conn,constchar*catalog_name,OidobjectId,
647687
PQExpBuffersql)
648688
{
649689
appendPQExpBuffer(sql,
650690
"SELECT provider, label FROM pg_catalog.pg_shseclabel "
651-
"WHERE classoid = '%s'::pg_catalog.regclass AND "
652-
"objoid =%u",catalog_name,objectId);
691+
"WHERE classoid = 'pg_catalog.%s'::pg_catalog.regclass "
692+
"ANDobjoid ='%u'",catalog_name,objectId);
653693
}
654694

655695
/*
656696
* emitShSecLabels
657697
*
658-
* Format security label data retrieved by the query generated in
659-
* buildShSecLabelQuery.
698+
* Construct SECURITY LABEL commands using the data retrieved by the query
699+
* generated by buildShSecLabelQuery, and append them to "buffer".
700+
* Here, the target object is identified by its type name (e.g. "DATABASE")
701+
* and its name (not pre-quoted).
660702
*/
661703
void
662704
emitShSecLabels(PGconn*conn,PGresult*res,PQExpBufferbuffer,
663-
constchar*target,constchar*objname)
705+
constchar*objtype,constchar*objname)
664706
{
665707
inti;
666708

@@ -672,7 +714,7 @@ emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer,
672714
/* must use fmtId result before calling it again */
673715
appendPQExpBuffer(buffer,
674716
"SECURITY LABEL FOR %s ON %s",
675-
fmtId(provider),target);
717+
fmtId(provider),objtype);
676718
appendPQExpBuffer(buffer,
677719
" %s IS ",
678720
fmtId(objname));

‎src/bin/pg_dump/dumputils.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#endif
3737

3838

39-
externboolbuildACLCommands(constchar*name,constchar*subname,
39+
externboolbuildACLCommands(constchar*name,constchar*subname,constchar*nspname,
4040
constchar*type,constchar*acls,constchar*racls,
4141
constchar*owner,constchar*prefix,intremoteVersion,
4242
PQExpBuffersql);
@@ -47,9 +47,9 @@ extern bool buildDefaultACLCommands(const char *type, const char *nspname,
4747
intremoteVersion,
4848
PQExpBuffersql);
4949
externvoidbuildShSecLabelQuery(PGconn*conn,constchar*catalog_name,
50-
uint32objectId,PQExpBuffersql);
50+
OidobjectId,PQExpBuffersql);
5151
externvoidemitShSecLabels(PGconn*conn,PGresult*res,
52-
PQExpBufferbuffer,constchar*target,constchar*objname);
52+
PQExpBufferbuffer,constchar*objtype,constchar*objname);
5353

5454
externvoidbuildACLQueries(PQExpBufferacl_subquery,PQExpBufferracl_subquery,
5555
PQExpBufferinit_acl_subquery,PQExpBufferinit_racl_subquery,

‎src/bin/pg_dump/pg_backup.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ typedef struct Archive
197197
/* info needed for string escaping */
198198
intencoding;/* libpq code for client_encoding */
199199
boolstd_strings;/* standard_conforming_strings */
200+
201+
/* other important stuff */
202+
char*searchpath;/* search_path to set during restore */
200203
char*use_role;/* Issue SET ROLE to this */
201204

202205
/* error handling */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp