Skip to content

Commit 35b7601

Browse files
committed
Add an overall timeout on the client authentication cycle, so that
a hung client or lost connection can't indefinitely block a postmaster child (not to mention the possibility of deliberate DoS attacks). Timeout is controlled by new authentication_timeout GUC variable, which I set to 60 seconds by default ... does that seem reasonable?
1 parent e3f5bc3 commit 35b7601

File tree

8 files changed

+136
-63
lines changed

8 files changed

+136
-63
lines changed

doc/src/sgml/runtime.sgml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.82 2001/09/21 03:32:35 tgl Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.83 2001/09/21 17:06:12 tgl Exp $
33
-->
44

55
<Chapter Id="runtime">
@@ -1018,6 +1018,20 @@ env PGOPTIONS='-c geqo=off' psql
10181018
</listitem>
10191019
</varlistentry>
10201020

1021+
<varlistentry>
1022+
<term><varname>AUTHENTICATION_TIMEOUT</varname> (<type>integer</type>)</term>
1023+
<listitem>
1024+
<para>
1025+
Maximum time to complete client authentication, in seconds.
1026+
If a would-be client has not completed the authentication protocol
1027+
in this much time, the server unceremoniously breaks the connection.
1028+
This prevents hung clients from occupying a connection indefinitely.
1029+
This option can only be set at server start or in the
1030+
<filename>postgresql.conf</filename> file.
1031+
</para>
1032+
</listitem>
1033+
</varlistentry>
1034+
10211035
<varlistentry>
10221036
<indexterm>
10231037
<primary>deadlock</primary>

src/backend/libpq/pqsignal.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/libpq/pqsignal.c,v 1.23 2001/09/08 01:10:20 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/libpq/pqsignal.c,v 1.24 2001/09/21 17:06:12 tgl Exp $
1313
*
1414
* NOTES
1515
* This shouldn't be in libpq, but the monitor and some other
@@ -53,7 +53,7 @@
5353
* signals that should never be turned off.
5454
*
5555
* AuthBlockSig is the set of signals to block during authentication;
56-
* it's essentially BlockSig minus SIGTERM and SIGQUIT.
56+
* it's essentially BlockSig minus SIGTERM, SIGQUIT, SIGALRM.
5757
*
5858
* UnBlockSig is the set of signals to block when we don't want to block
5959
* signals (is this ever nonzero??)
@@ -109,14 +109,17 @@ pqinitmask(void)
109109
#ifdef SIGQUIT
110110
sigdelset(&AuthBlockSig, SIGQUIT);
111111
#endif
112+
#ifdef SIGALRM
113+
sigdelset(&AuthBlockSig, SIGALRM);
114+
#endif
112115
#else
113116
UnBlockSig = 0;
114117
BlockSig = sigmask(SIGHUP) | sigmask(SIGQUIT) |
115118
sigmask(SIGTERM) | sigmask(SIGALRM) |
116119
sigmask(SIGINT) | sigmask(SIGUSR1) |
117120
sigmask(SIGUSR2) | sigmask(SIGCHLD) |
118121
sigmask(SIGWINCH) | sigmask(SIGFPE);
119-
AuthBlockSig = sigmask(SIGHUP) | sigmask(SIGALRM) |
122+
AuthBlockSig = sigmask(SIGHUP) |
120123
sigmask(SIGINT) | sigmask(SIGUSR1) |
121124
sigmask(SIGUSR2) | sigmask(SIGCHLD) |
122125
sigmask(SIGWINCH) | sigmask(SIGFPE);

src/backend/postmaster/postmaster.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
*
3838
*
3939
* IDENTIFICATION
40-
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.241 2001/09/08 01:10:20 tgl Exp $
40+
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.242 2001/09/21 17:06:12 tgl Exp $
4141
*
4242
* NOTES
4343
*
@@ -190,6 +190,8 @@ bool NetServer = false; /* listen on TCP/IP */
190190
bool EnableSSL = false;
191191
bool SilentMode = false; /* silent mode (-S) */
192192

193+
int PreAuthDelay = 0;
194+
int AuthenticationTimeout = 60;
193195
int CheckPointTimeout = 300;
194196

195197
/* Startup/shutdown state */
@@ -1941,16 +1943,38 @@ DoBackend(Port *port)
19411943
/* Reset MyProcPid to new backend's pid */
19421944
MyProcPid = getpid();
19431945

1946+
/*
1947+
* Initialize libpq and enable reporting of elog errors to the client.
1948+
* Must do this now because authentication uses libpq to send messages.
1949+
*/
1950+
pq_init(); /* initialize libpq to talk to client */
1951+
whereToSendOutput = Remote; /* now safe to elog to client */
1952+
19441953
/*
19451954
* We arrange for a simple exit(0) if we receive SIGTERM or SIGQUIT
19461955
* during any client authentication related communication. Otherwise
19471956
* the postmaster cannot shutdown the database FAST or IMMED cleanly
1948-
* if a buggy client blocks a backend during authentication.
1957+
* if a buggy client blocks a backend during authentication. We also
1958+
* will exit(0) after a time delay, so that a broken client can't hog
1959+
* a connection indefinitely.
1960+
*
1961+
* PreAuthDelay is a debugging aid for investigating problems in the
1962+
* authentication cycle: it can be set in postgresql.conf to allow
1963+
* time to attach to the newly-forked backend with a debugger.
1964+
* (See also the -W backend switch, which we allow clients to pass
1965+
* through PGOPTIONS, but it is not honored until after authentication.)
19491966
*/
19501967
pqsignal(SIGTERM, authdie);
19511968
pqsignal(SIGQUIT, authdie);
1969+
pqsignal(SIGALRM, authdie);
19521970
PG_SETMASK(&AuthBlockSig);
19531971

1972+
if (PreAuthDelay > 0)
1973+
sleep(PreAuthDelay);
1974+
1975+
if (! enable_sigalrm_interrupt(AuthenticationTimeout * 1000))
1976+
elog(FATAL, "DoBackend: Unable to set timer for auth timeout");
1977+
19541978
/*
19551979
* Receive the startup packet (which might turn out to be a cancel
19561980
* request packet); then perform client authentication.
@@ -1963,9 +1987,11 @@ DoBackend(Port *port)
19631987
ClientAuthentication(MyProcPort); /* might not return, if failure */
19641988

19651989
/*
1966-
* Done with authentication. Prevent SIGTERM/SIGQUIT again until
1967-
* backend startup is complete.
1990+
* Done with authentication. Disable timeout, and prevent SIGTERM/SIGQUIT
1991+
* again until backend startup is complete.
19681992
*/
1993+
if (! disable_sigalrm_interrupt())
1994+
elog(FATAL, "DoBackend: Unable to disable timer for auth timeout");
19691995
PG_SETMASK(&BlockSig);
19701996

19711997
/*

src/backend/storage/lmgr/proc.c

Lines changed: 67 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.107 2001/09/07 00:27:29 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.108 2001/09/21 17:06:12 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -327,18 +327,7 @@ LockWaitCancel(void)
327327
waitingForLock = false;
328328

329329
/* Turn off the deadlock timer, if it's still running (see ProcSleep) */
330-
#ifndef __BEOS__
331-
{
332-
struct itimerval timeval,
333-
dummy;
334-
335-
MemSet(&timeval, 0, sizeof(struct itimerval));
336-
setitimer(ITIMER_REAL, &timeval, &dummy);
337-
}
338-
#else
339-
/* BeOS doesn't have setitimer, but has set_alarm */
340-
set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM);
341-
#endif /* __BEOS__ */
330+
disable_sigalrm_interrupt();
342331

343332
/* Unlink myself from the wait queue, if on it (might not be anymore!) */
344333
LockLockTable();
@@ -501,12 +490,6 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
501490
bool early_deadlock = false;
502491
PROC *proc;
503492
int i;
504-
#ifndef __BEOS__
505-
struct itimerval timeval,
506-
dummy;
507-
#else
508-
bigtime_t time_interval;
509-
#endif
510493

511494
/*
512495
* Determine where to add myself in the wait queue.
@@ -629,21 +612,9 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
629612
*
630613
* By delaying the check until we've waited for a bit, we can avoid
631614
* running the rather expensive deadlock-check code in most cases.
632-
*
633-
* Need to zero out struct to set the interval and the microseconds
634-
* fields to 0.
635615
*/
636-
#ifndef __BEOS__
637-
MemSet(&timeval, 0, sizeof(struct itimerval));
638-
timeval.it_value.tv_sec = DeadlockTimeout / 1000;
639-
timeval.it_value.tv_usec = (DeadlockTimeout % 1000) * 1000;
640-
if (setitimer(ITIMER_REAL, &timeval, &dummy))
616+
if (! enable_sigalrm_interrupt(DeadlockTimeout))
641617
elog(FATAL, "ProcSleep: Unable to set timer for process wakeup");
642-
#else
643-
time_interval = DeadlockTimeout * 1000000; /* usecs */
644-
if (set_alarm(time_interval, B_ONE_SHOT_RELATIVE_ALARM) < 0)
645-
elog(FATAL, "ProcSleep: Unable to set timer for process wakeup");
646-
#endif
647618

648619
/*
649620
* If someone wakes us between SpinRelease and IpcSemaphoreLock,
@@ -664,14 +635,8 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
664635
/*
665636
* Disable the timer, if it's still running
666637
*/
667-
#ifndef __BEOS__
668-
MemSet(&timeval, 0, sizeof(struct itimerval));
669-
if (setitimer(ITIMER_REAL, &timeval, &dummy))
670-
elog(FATAL, "ProcSleep: Unable to disable timer for process wakeup");
671-
#else
672-
if (set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM) < 0)
638+
if (! disable_sigalrm_interrupt())
673639
elog(FATAL, "ProcSleep: Unable to disable timer for process wakeup");
674-
#endif
675640

676641
/*
677642
* Now there is nothing for LockWaitCancel to do.
@@ -949,6 +914,69 @@ ProcSendSignal(BackendId procId)
949914
}
950915

951916

917+
/*****************************************************************************
918+
* SIGALRM interrupt support
919+
*
920+
* Maybe these should be in pqsignal.c?
921+
*****************************************************************************/
922+
923+
/*
924+
* Enable the SIGALRM interrupt to fire after the specified delay
925+
*
926+
* Delay is given in milliseconds. Caller should be sure a SIGALRM
927+
* signal handler is installed before this is called.
928+
*
929+
* Returns TRUE if okay, FALSE on failure.
930+
*/
931+
bool
932+
enable_sigalrm_interrupt(int delayms)
933+
{
934+
#ifndef __BEOS__
935+
struct itimerval timeval,
936+
dummy;
937+
938+
MemSet(&timeval, 0, sizeof(struct itimerval));
939+
timeval.it_value.tv_sec = delayms / 1000;
940+
timeval.it_value.tv_usec = (delayms % 1000) * 1000;
941+
if (setitimer(ITIMER_REAL, &timeval, &dummy))
942+
return false;
943+
#else
944+
/* BeOS doesn't have setitimer, but has set_alarm */
945+
bigtime_t time_interval;
946+
947+
time_interval = delayms * 1000; /* usecs */
948+
if (set_alarm(time_interval, B_ONE_SHOT_RELATIVE_ALARM) < 0)
949+
return false;
950+
#endif
951+
952+
return true;
953+
}
954+
955+
/*
956+
* Disable the SIGALRM interrupt, if it has not yet fired
957+
*
958+
* Returns TRUE if okay, FALSE on failure.
959+
*/
960+
bool
961+
disable_sigalrm_interrupt(void)
962+
{
963+
#ifndef __BEOS__
964+
struct itimerval timeval,
965+
dummy;
966+
967+
MemSet(&timeval, 0, sizeof(struct itimerval));
968+
if (setitimer(ITIMER_REAL, &timeval, &dummy))
969+
return false;
970+
#else
971+
/* BeOS doesn't have setitimer, but has set_alarm */
972+
if (set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM) < 0)
973+
return false;
974+
#endif
975+
976+
return true;
977+
}
978+
979+
952980
/*****************************************************************************
953981
*
954982
*****************************************************************************/

src/backend/tcop/postgres.c

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.232 2001/09/08 01:10:20 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.233 2001/09/21 17:06:12 tgl Exp $
1212
*
1313
* NOTES
1414
* this is the "main" module of the postgres backend and
@@ -967,12 +967,12 @@ die(SIGNAL_ARGS)
967967
}
968968

969969
/*
970-
* Shutdown signal from postmaster during client authentication.
970+
* Timeout or shutdown signal from postmaster during client authentication.
971971
* Simply exit(0).
972972
*
973973
* XXX: possible future improvement: try to send a message indicating
974974
* why we are disconnecting. Problem is to be sure we don't block while
975-
* doing so nor mess up the authentication message exchange.
975+
* doing so, nor mess up the authentication message exchange.
976976
*/
977977
void
978978
authdie(SIGNAL_ARGS)
@@ -1168,16 +1168,6 @@ PostgresMain(int argc, char *argv[],
11681168

11691169
SetProcessingMode(InitProcessing);
11701170

1171-
/*
1172-
* If under postmaster, initialize libpq and enable reporting of
1173-
* elog errors to the client.
1174-
*/
1175-
if (IsUnderPostmaster)
1176-
{
1177-
pq_init(); /* initialize libpq at backend startup */
1178-
whereToSendOutput = Remote; /* now safe to elog to client */
1179-
}
1180-
11811171
/*
11821172
* Set default values for command-line options.
11831173
*/
@@ -1736,7 +1726,7 @@ PostgresMain(int argc, char *argv[],
17361726
if (!IsUnderPostmaster)
17371727
{
17381728
puts("\nPOSTGRES backend interactive interface ");
1739-
puts("$Revision: 1.232 $ $Date: 2001/09/08 01:10:20 $\n");
1729+
puts("$Revision: 1.233 $ $Date: 2001/09/21 17:06:12 $\n");
17401730
}
17411731

17421732
/*

src/backend/utils/misc/guc.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Support for grand unified configuration scheme, including SET
55
* command, configuration file, and command line options.
66
*
7-
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.50 2001/09/21 03:32:35 tgl Exp $
7+
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.51 2001/09/21 17:06:12 tgl Exp $
88
*
99
* Copyright 2000 by PostgreSQL Global Development Group
1010
* Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -41,6 +41,8 @@
4141

4242
/* XXX these should be in other modules' header files */
4343
extern bool Log_connections;
44+
extern int PreAuthDelay;
45+
extern int AuthenticationTimeout;
4446
extern int CheckPointTimeout;
4547
extern int CommitDelay;
4648
extern int CommitSiblings;
@@ -320,6 +322,12 @@ static struct config_int
320322
{"max_locks_per_transaction", PGC_POSTMASTER, &max_locks_per_xact,
321323
64, 10, INT_MAX, NULL, NULL},
322324

325+
{"authentication_timeout", PGC_SIGHUP, &AuthenticationTimeout,
326+
60, 1, 600, NULL, NULL},
327+
328+
{"pre_auth_delay", PGC_SIGHUP, &PreAuthDelay,
329+
0, 0, 60, NULL, NULL},
330+
323331
{"checkpoint_segments", PGC_SIGHUP, &CheckPointSegments,
324332
3, 1, INT_MAX, NULL, NULL},
325333

src/backend/utils/misc/postgresql.conf.sample

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@
176176
#
177177
#dynamic_library_path = '$libdir'
178178
#australian_timezones = false
179+
#authentication_timeout = 60 # min 1, max 600
179180
#deadlock_timeout = 1000
180181
#default_transaction_isolation = 'read committed'
181182
#max_expr_depth = 10000 # min 10

src/include/storage/proc.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: proc.h,v 1.46 2001/09/07 00:27:30 tgl Exp $
10+
* $Id: proc.h,v 1.47 2001/09/21 17:06:12 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -154,4 +154,7 @@ extern void ProcWaitForSignal(void);
154154
extern void ProcCancelWaitForSignal(void);
155155
extern void ProcSendSignal(BackendId procId);
156156

157+
extern bool enable_sigalrm_interrupt(int delayms);
158+
extern bool disable_sigalrm_interrupt(void);
159+
157160
#endif /* PROC_H */

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