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

Commit17fe279

Browse files
committed
Fix insecure parsing of server command-line switches.
An oversight in commite710b65 alloweddatabase names beginning with "-" to be treated as though they were securecommand-line switches; and this switch processing occurs before clientauthentication, so that even an unprivileged remote attacker could exploitthe bug, needing only connectivity to the postmaster's port. Assortedexploits for this are possible, some requiring a valid database login,some not. The worst known problem is that the "-r" switch can be invokedto redirect the process's stderr output, so that subsequent error messageswill be appended to any file the server can write. This can for example beused to corrupt the server's configuration files, so that it will fail whennext restarted. Complete destruction of database tables is also possible.Fix by keeping the database name extracted from a startup packet fullyseparate from command-line switches, as had already been done with theuser name field.The Postgres project thanks Mitsumasa Kondo for discovering this bug,Kyotaro Horiguchi for drafting the fix, and Noah Misch for recognizingthe full extent of the danger.Security:CVE-2013-1899
1 parentce9ab88 commit17fe279

File tree

5 files changed

+32
-32
lines changed

5 files changed

+32
-32
lines changed

‎src/backend/main/main.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,9 @@ main(int argc, char *argv[])
189189
elseif (argc>1&&strcmp(argv[1],"--describe-config")==0)
190190
GucInfoMain();/* does not return */
191191
elseif (argc>1&&strcmp(argv[1],"--single")==0)
192-
PostgresMain(argc,argv,get_current_username(progname));/* does not return */
192+
PostgresMain(argc,argv,
193+
NULL,/* no dbname */
194+
get_current_username(progname));/* does not return */
193195
else
194196
PostmasterMain(argc,argv);/* does not return */
195197
abort();/* should not get here */

‎src/backend/postmaster/postmaster.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3943,7 +3943,7 @@ BackendRun(Port *port)
39433943
* from ExtraOptions is (strlen(ExtraOptions) + 1) / 2; see
39443944
* pg_split_opts().
39453945
*/
3946-
maxac=5;/* for fixed args supplied below */
3946+
maxac=2;/* for fixed args supplied below */
39473947
maxac+= (strlen(ExtraOptions)+1) /2;
39483948

39493949
av= (char**)MemoryContextAlloc(TopMemoryContext,
@@ -3959,11 +3959,6 @@ BackendRun(Port *port)
39593959
*/
39603960
pg_split_opts(av,&ac,ExtraOptions);
39613961

3962-
/*
3963-
* Tell the backend which database to use.
3964-
*/
3965-
av[ac++]=port->database_name;
3966-
39673962
av[ac]=NULL;
39683963

39693964
Assert(ac<maxac);
@@ -3986,7 +3981,7 @@ BackendRun(Port *port)
39863981
*/
39873982
MemoryContextSwitchTo(TopMemoryContext);
39883983

3989-
PostgresMain(ac,av,port->user_name);
3984+
PostgresMain(ac,av,port->database_name,port->user_name);
39903985
}
39913986

39923987

‎src/backend/tcop/postgres.c

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3247,13 +3247,14 @@ get_stats_option_name(const char *arg)
32473247
* coming from the client, or PGC_SUSET for insecure options coming from
32483248
* a superuser client.
32493249
*
3250-
* Returns the database name extracted from the command line, if any.
3250+
* If a database name is present in the command line arguments, it's
3251+
* returned into *dbname (this is allowed only if *dbname is initially NULL).
32513252
* ----------------------------------------------------------------
32523253
*/
3253-
constchar*
3254-
process_postgres_switches(intargc,char*argv[],GucContextctx)
3254+
void
3255+
process_postgres_switches(intargc,char*argv[],GucContextctx,
3256+
constchar**dbname)
32553257
{
3256-
constchar*dbname;
32573258
boolsecure= (ctx==PGC_POSTMASTER);
32583259
interrs=0;
32593260
GucSourcegucsource;
@@ -3304,7 +3305,8 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx)
33043305

33053306
case'b':
33063307
/* Undocumented flag used for binary upgrades */
3307-
IsBinaryUpgrade= true;
3308+
if (secure)
3309+
IsBinaryUpgrade= true;
33083310
break;
33093311

33103312
case'C':
@@ -3321,7 +3323,8 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx)
33213323
break;
33223324

33233325
case'E':
3324-
EchoQuery= true;
3326+
if (secure)
3327+
EchoQuery= true;
33253328
break;
33263329

33273330
case'e':
@@ -3346,7 +3349,8 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx)
33463349
break;
33473350

33483351
case'j':
3349-
UseNewLine=0;
3352+
if (secure)
3353+
UseNewLine=0;
33503354
break;
33513355

33523356
case'k':
@@ -3464,13 +3468,10 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx)
34643468
}
34653469

34663470
/*
3467-
* Should be no more arguments except an optional database name, and
3468-
* that's only in the secure case.
3471+
* Optional database name should be there only if *dbname is NULL.
34693472
*/
3470-
if (!errs&&secure&&argc-optind >=1)
3471-
dbname=strdup(argv[optind++]);
3472-
else
3473-
dbname=NULL;
3473+
if (!errs&&dbname&&*dbname==NULL&&argc-optind >=1)
3474+
*dbname=strdup(argv[optind++]);
34743475

34753476
if (errs||argc!=optind)
34763477
{
@@ -3499,8 +3500,6 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx)
34993500
#ifdefHAVE_INT_OPTRESET
35003501
optreset=1;/* some systems need this too */
35013502
#endif
3502-
3503-
returndbname;
35043503
}
35053504

35063505

@@ -3510,14 +3509,16 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx)
35103509
*
35113510
* argc/argv are the command line arguments to be used. (When being forked
35123511
* by the postmaster, these are not the original argv array of the process.)
3513-
* username is the (possibly authenticated) PostgreSQL user name to be used
3514-
* for the session.
3512+
* dbname is the name of the database to connect to, or NULL if the database
3513+
* name should be extracted from the command line arguments or defaulted.
3514+
* username is the PostgreSQL user name to be used for the session.
35153515
* ----------------------------------------------------------------
35163516
*/
35173517
void
3518-
PostgresMain(intargc,char*argv[],constchar*username)
3518+
PostgresMain(intargc,char*argv[],
3519+
constchar*dbname,
3520+
constchar*username)
35193521
{
3520-
constchar*dbname;
35213522
intfirstchar;
35223523
StringInfoDatainput_message;
35233524
sigjmp_buflocal_sigjmp_buf;
@@ -3564,7 +3565,7 @@ PostgresMain(int argc, char *argv[], const char *username)
35643565
/*
35653566
* Parse command-line options.
35663567
*/
3567-
dbname=process_postgres_switches(argc,argv,PGC_POSTMASTER);
3568+
process_postgres_switches(argc,argv,PGC_POSTMASTER,&dbname);
35683569

35693570
/* Must have gotten a database name, or have a default (the username) */
35703571
if (dbname==NULL)

‎src/backend/utils/init/postinit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ process_startup_options(Port *port, bool am_superuser)
969969

970970
Assert(ac<maxac);
971971

972-
(void)process_postgres_switches(ac,av,gucctx);
972+
(void)process_postgres_switches(ac,av,gucctx,NULL);
973973
}
974974

975975
/*

‎src/include/tcop/tcopprot.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,11 @@ extern void RecoveryConflictInterrupt(ProcSignalReason reason); /* called from S
6969
* handler */
7070
externvoidprepare_for_client_read(void);
7171
externvoidclient_read_ended(void);
72-
externconstchar*process_postgres_switches(intargc,char*argv[],
73-
GucContextctx);
74-
externvoidPostgresMain(intargc,char*argv[],constchar*username) __attribute__((noreturn));
72+
externvoidprocess_postgres_switches(intargc,char*argv[],
73+
GucContextctx,constchar**dbname);
74+
externvoidPostgresMain(intargc,char*argv[],
75+
constchar*dbname,
76+
constchar*username) __attribute__((noreturn));
7577
externlongget_stack_depth_rlimit(void);
7678
externvoidResetUsage(void);
7779
externvoidShowUsage(constchar*title);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp