From ab93cd9b053446dfb64f66bfac97787eb74c1172 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Mon, 26 Apr 2010 10:52:00 +0000
Subject: [PATCH] When we're restricting who can connect, don't allow new
 walsenders.

Normal superuser processes are allowed to connect even when the database
system is shutting down, or when fewer than superuser_reserved_connection
slots remain.  This is intended to make sure an administrator can log in
and troubleshoot, so don't extend these same courtesies to users connecting
for replication.
---
 doc/src/sgml/config.sgml          |  5 +--
 src/backend/utils/init/postinit.c | 53 +++++++++++++++++++------------
 2 files changed, 35 insertions(+), 23 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index e1372bf4a89..71bab707da8 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.269 2010/04/20 11:15:06 rhaas Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.270 2010/04/26 10:51:59 rhaas Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -401,7 +401,8 @@ SET ENABLE_SEQSCAN TO OFF;
         number of active concurrent connections is at least
         <varname>max_connections</> minus
         <varname>superuser_reserved_connections</varname>, new
-        connections will be accepted only for superusers.
+        connections will be accepted only for superusers, and no
+        new replication connections will be accepted.
        </para>
 
        <para>
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index b812c40ac0e..dab7694f700 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.211 2010/04/21 00:51:57 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.212 2010/04/26 10:52:00 rhaas Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -617,6 +617,37 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 		am_superuser = superuser();
 	}
 
+	/*
+	 * If we're trying to shut down, only superusers can connect, and
+	 * new replication connections are not allowed.
+	 */
+	if ((!am_superuser || am_walsender) &&
+		MyProcPort != NULL &&
+		MyProcPort->canAcceptConnections == CAC_WAITBACKUP)
+	{
+		if (am_walsender)
+			ereport(FATAL,
+					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+		     	errmsg("new replication connections are not allowed during database shutdown")));
+		else
+			ereport(FATAL,
+					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				errmsg("must be superuser to connect during database shutdown")));
+	}
+
+	/*
+	 * The last few connections slots are reserved for superusers.
+	 * Although replication connections currently require superuser
+	 * privileges, we don't allow them to consume the reserved slots,
+	 * which are intended for interactive use.
+	 */
+	if ((!am_superuser || am_walsender) &&
+		ReservedBackends > 0 &&
+		!HaveNFreeProcs(ReservedBackends))
+		ereport(FATAL,
+				(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
+				 errmsg("remaining connection slots are reserved for non-replication superuser connections")));
+
 	/*
 	 * If walsender, we're done here --- we don't want to connect to any
 	 * particular database.
@@ -778,26 +809,6 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 	if (!bootstrap)
 		CheckMyDatabase(dbname, am_superuser);
 
-	/*
-	 * If we're trying to shut down, only superusers can connect.
-	 */
-	if (!am_superuser &&
-		MyProcPort != NULL &&
-		MyProcPort->canAcceptConnections == CAC_WAITBACKUP)
-		ereport(FATAL,
-				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-		   errmsg("must be superuser to connect during database shutdown")));
-
-	/*
-	 * Check a normal user hasn't connected to a superuser reserved slot.
-	 */
-	if (!am_superuser &&
-		ReservedBackends > 0 &&
-		!HaveNFreeProcs(ReservedBackends))
-		ereport(FATAL,
-				(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
-				 errmsg("connection limit exceeded for non-superusers")));
-
 	/*
 	 * Now process any command-line switches that were included in the startup
 	 * packet, if we are in a regular backend.	We couldn't do this before
-- 
GitLab