From 626eca697cf4470c44cb76f0603302201538c47e Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 29 Aug 2002 21:02:12 +0000 Subject: [PATCH] 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 --- src/backend/postmaster/postmaster.c | 20 +++++++++++- src/backend/storage/ipc/sinval.c | 26 +++++++++++++++- src/backend/storage/ipc/sinvaladt.c | 31 +++++++++++-------- src/backend/utils/init/postinit.c | 12 ++++++- src/backend/utils/misc/guc.c | 11 +++++-- src/backend/utils/misc/postgresql.conf.sample | 1 + src/include/miscadmin.h | 3 +- src/include/storage/sinval.h | 4 ++- src/include/storage/sinvaladt.h | 3 +- 9 files changed, 90 insertions(+), 21 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index bc8b859f30..bbec926434 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -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. diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c index 940ab32b33..745a9c068d 100644 --- a/src/backend/storage/ipc/sinval.c +++ b/src/backend/storage/ipc/sinval.c @@ -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; +} diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index c88055c07b..b4ab1689f9 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -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); } diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index f36c1d981f..b02e371a81 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -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"); } /* diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 5114fcc38f..e88882def4 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -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 . @@ -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 diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index c3e065ecdb..11e9caaabc 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -31,6 +31,7 @@ #ssl = false #max_connections = 32 +#superuser_reserved_connections = 2 #port = 5432 #hostname_lookup = false diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index f2f6f5c676..fce4fea4b4 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -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; diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h index 7af8f44447..1188c68c95 100644 --- a/src/include/storage/sinval.h +++ b/src/include/storage/sinval.h @@ -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 */ diff --git a/src/include/storage/sinvaladt.h b/src/include/storage/sinvaladt.h index 3e95342c9f..39c895026b 100644 --- a/src/include/storage/sinvaladt.h +++ b/src/include/storage/sinvaladt.h @@ -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