This patch reserves the last superuser_reserved_connections slots for

connections by the superuser only.

This patch replaces the last patch I sent a couple of days ago.

It closes a connection that has not been authorised by a superuser if it would
leave less than the GUC variable ReservedBackends
(superuser_reserved_connections in postgres.conf) backend process slots free
in the SISeg. This differs to the first patch which only reserved the last
ReservedBackends slots in the procState array. This has made the free slot
test more expensive due to the use of a lock.

After thinking about a comment on the first patch I've also made it a fatal
error if the number of reserved slots is not less than the maximum number of
connections.

Nigel J. Andrews
This commit is contained in:
Bruce Momjian 2002-08-29 21:02:12 +00:00
parent 1761990e38
commit 626eca697c
9 changed files with 90 additions and 21 deletions

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.285 2002/08/18 03:03:25 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.286 2002/08/29 21:02:12 momjian Exp $
*
* NOTES
*
@ -151,6 +151,18 @@ char *VirtualHost;
*/
int MaxBackends = DEF_MAXBACKENDS;
/*
* ReservedBackends is the number of backends reserved for superuser use.
* This number is taken out of the pool size given by MaxBackends so
* number of backend slots available to none super users is
* (MaxBackends - ReservedBackends). Note, existing super user
* connections are not taken into account once this lower limit has
* been reached, i.e. superuser connections made before the lower limit
* is reached always count towards that limit and are not taken from
* ReservedBackends.
*/
int ReservedBackends = 2;
static char *progname = (char *) NULL;
@ -567,6 +579,12 @@ PostmasterMain(int argc, char *argv[])
ProcessConfigFile(PGC_POSTMASTER);
/*
* Force an exit if ReservedBackends is not less than MaxBackends.
*/
if (ReservedBackends >= MaxBackends)
elog(FATAL,"superuser_reserved_connections must be less than max_connections.");
/*
* Now that we are done processing the postmaster arguments, reset
* getopt(3) library so that it will work correctly in subprocesses.

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.49 2002/06/20 20:29:35 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.50 2002/08/29 21:02:12 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -538,3 +538,27 @@ BackendIdGetProc(BackendId procId)
return NULL;
}
/*
* CountEmptyBackendSlots - count empty slots in backend process table
*
* Doesn't count since the procState array could be large and we've already
* allowed for that by running a freeBackends counter in the SI segment.
* Unlike CountActiveBackends() we do not need to interrogate the
* backends to determine the free slot count.
* Goes for a lock despite being a trival look up in case other backends
* are busy starting or exiting since there is scope for confusion.
*/
int
CountEmptyBackendSlots(void)
{
int count;
LWLockAcquire(SInvalLock, LW_SHARED);
count = shmInvalBuffer->freeBackends;
LWLockRelease(SInvalLock);
return count;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.47 2002/06/20 20:29:35 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.48 2002/08/29 21:02:12 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -60,6 +60,7 @@ SIBufferInit(int maxBackends)
segP->maxMsgNum = 0;
segP->lastBackend = 0;
segP->maxBackends = maxBackends;
segP->freeBackends = maxBackends;
/* The buffer[] array is initially all unused, so we need not fill it */
@ -91,6 +92,13 @@ SIBackendInit(SISeg *segP)
int index;
ProcState *stateP = NULL;
if (segP->freeBackends == 0)
{
/* out of procState slots */
MyBackendId = InvalidBackendId;
return 0;
}
/* Look for a free entry in the procState array */
for (index = 0; index < segP->lastBackend; index++)
{
@ -103,18 +111,9 @@ SIBackendInit(SISeg *segP)
if (stateP == NULL)
{
if (segP->lastBackend < segP->maxBackends)
{
stateP = &segP->procState[segP->lastBackend];
Assert(stateP->nextMsgNum < 0);
segP->lastBackend++;
}
else
{
/* out of procState slots */
MyBackendId = InvalidBackendId;
return 0;
}
stateP = &segP->procState[segP->lastBackend];
Assert(stateP->nextMsgNum < 0);
segP->lastBackend++;
}
MyBackendId = (stateP - &segP->procState[0]) + 1;
@ -123,6 +122,9 @@ SIBackendInit(SISeg *segP)
elog(DEBUG1, "SIBackendInit: backend id %d", MyBackendId);
#endif /* INVALIDDEBUG */
/* Reduce free slot count */
segP->freeBackends--;
/* mark myself active, with all extant messages already read */
stateP->nextMsgNum = segP->maxMsgNum;
stateP->resetState = false;
@ -166,6 +168,9 @@ CleanupInvalidationState(int status, Datum arg)
}
segP->lastBackend = i;
/* Adjust free slot count */
segP->freeBackends++;
LWLockRelease(SInvalLock);
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.110 2002/08/29 07:22:28 ishii Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.111 2002/08/29 21:02:12 momjian Exp $
*
*
*-------------------------------------------------------------------------
@ -395,6 +395,16 @@ InitPostgres(const char *dbname, const char *username)
/* close the transaction we started above */
if (!bootstrap)
CommitTransactionCommand();
/*
* Check a normal user hasn't connected to a superuser reserved slot.
* Do this here since we need the user information and that only happens
* after we've started bringing the shared memory online. So we wait
* until we've registered exit handlers and potentially shut an open
* transaction down for an as safety conscious rejection as possible.
*/
if (CountEmptyBackendSlots() < ReservedBackends && !superuser())
elog(ERROR, "Non-superuser connection limit exceeded");
}
/*

View File

@ -5,7 +5,7 @@
* command, configuration file, and command line options.
* See src/backend/utils/misc/README for more information.
*
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.86 2002/08/29 17:14:33 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.87 2002/08/29 21:02:12 momjian Exp $
*
* Copyright 2000 by PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
@ -537,13 +537,20 @@ static struct config_int
/*
* Note: There is some postprocessing done in PostmasterMain() to make
* sure the buffers are at least twice the number of backends, so the
* constraints here are partially unused.
* constraints here are partially unused. Similarly, the superuser
* reserved number is checked to ensure it is less than the max
* backends number.
*/
{
{ "max_connections", PGC_POSTMASTER }, &MaxBackends,
DEF_MAXBACKENDS, 1, INT_MAX, NULL, NULL
},
{
{ "superuser_reserved_connections", PGC_POSTMASTER }, &ReservedBackends,
2, 0, INT_MAX, NULL, NULL
},
{
{ "shared_buffers", PGC_POSTMASTER }, &NBuffers,
DEF_NBUFFERS, 16, INT_MAX, NULL, NULL

View File

@ -31,6 +31,7 @@
#ssl = false
#max_connections = 32
#superuser_reserved_connections = 2
#port = 5432
#hostname_lookup = false

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: miscadmin.h,v 1.106 2002/06/20 20:29:42 momjian Exp $
* $Id: miscadmin.h,v 1.107 2002/08/29 21:02:12 momjian Exp $
*
* NOTES
* some of the information in this file should be moved to
@ -179,6 +179,7 @@ extern bool NetServer;
extern bool EnableSSL;
extern bool SilentMode;
extern int MaxBackends;
extern int ReservedBackends;
extern int NBuffers;
extern int PostPortNumber;
extern int Unix_socket_permissions;

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: sinval.h,v 1.28 2002/06/20 20:29:52 momjian Exp $
* $Id: sinval.h,v 1.29 2002/08/29 21:02:12 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -89,4 +89,6 @@ extern int CountActiveBackends(void);
/* Use "struct PGPROC", not PGPROC, to avoid including proc.h here */
extern struct PGPROC *BackendIdGetProc(BackendId procId);
extern int CountEmptyBackendSlots(void);
#endif /* SINVAL_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: sinvaladt.h,v 1.32 2002/06/20 20:29:52 momjian Exp $
* $Id: sinvaladt.h,v 1.33 2002/08/29 21:02:12 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -85,6 +85,7 @@ typedef struct SISeg
int lastBackend; /* index of last active procState entry,
* +1 */
int maxBackends; /* size of procState array */
int freeBackends; /* number of empty procState slots */
/*
* Circular buffer holding shared-inval messages