]> granicus.if.org Git - postgresql/commitdiff
This patch reserves the last superuser_reserved_connections slots for
authorBruce Momjian <bruce@momjian.us>
Thu, 29 Aug 2002 21:02:12 +0000 (21:02 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 29 Aug 2002 21:02:12 +0000 (21:02 +0000)
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
src/backend/storage/ipc/sinval.c
src/backend/storage/ipc/sinvaladt.c
src/backend/utils/init/postinit.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/include/miscadmin.h
src/include/storage/sinval.h
src/include/storage/sinvaladt.h

index bc8b859f3001ce4849d29dfa1092f30d900bf059..bbec926434d0c33f529e43ffe00762890b9a6725 100644 (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.
index 940ab32b3311af4fa644849c1e4dfcb08e1ab3d8..745a9c068deb25c80237f8bb768a4ff2ef54537a 100644 (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;
+}
index c88055c07b51e4e6018b408d6fa38a69945955d8..b4ab1689f942de57ccdde5cc43c6b4cc0486265f 100644 (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);
 }
 
index f36c1d981fa08c6a2721b44f7c47b2a9e7737aa8..b02e371a8182f6739d5645b103dcd29f5dcd36a5 100644 (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");
 }
 
 /*
index 5114fcc38f29d5745e0a7067b169eb1f7fac1127..e88882def408f2e5467382e11b8889fee7ddcfeb 100644 (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
index c3e065ecdb857776ffba8f1ea65a187392f161dc..11e9caaabcf97e4059a52dece4322352e2c32d8b 100644 (file)
@@ -31,6 +31,7 @@
 #ssl = false
 
 #max_connections = 32
+#superuser_reserved_connections = 2
 
 #port = 5432 
 #hostname_lookup = false
index f2f6f5c67603f61c4fa45ec1b35da83ad21c3fdb..fce4fea4b402af1e3b4816ec0d634917e87b51a9 100644 (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;
index 7af8f444470bb1c2dcb09cd632adfe8e1e98be69..1188c68c95add98786b8fbb79b2433e468fe3c19 100644 (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 */
index 3e95342c9f8887aaffc9c26584d47a67bd39152e..39c895026b438f5c0583b515ca27c5b84c99b388 100644 (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