Blame SOURCES/0072-Ticket-49296-Fix-race-condition-in-connection-code-w.patch

b045b9
From dd12327d1523f3ff9d6ae8b44b640fb9d0d2d53b Mon Sep 17 00:00:00 2001
b045b9
From: Mark Reynolds <mreynolds@redhat.com>
b045b9
Date: Mon, 19 Feb 2018 10:44:36 -0500
b045b9
Subject: [PATCH] Ticket 49296 - Fix race condition in connection code with 
b045b9
 anonymous limits
b045b9
b045b9
Bug Description:  When a connection first comes in we set the anonymous
b045b9
                  resource limits (if set) before we do anything else.  The
b045b9
                  way we check if the connection is "new" was flawed.  It
b045b9
                  assumed the connection was new if no operations were
b045b9
                  completed yet, but there was a small window between sending
b045b9
                  the result and setting that the operation completed in the
b045b9
                  connection struct.
b045b9
b045b9
                  So on a connection that binds and then does a search, when
b045b9
                  the server sends the bind result the client sends the search,
b045b9
                  but the search op/activity can be picked up before we set
b045b9
                  c_opscompleted.  This opens a window where the code thinks
b045b9
                  the search op is the first op(new connection), and it incorrectly
b045b9
                  sets the anonymous limits for the bind dn.
b045b9
b045b9
Fix description:  Do not use c_opscompleted to determine if a connection is new,
b045b9
                  instead use a new flag to set the connection "initialized",
b045b9
                  which prevents the race condition.
b045b9
b045b9
https://pagure.io/389-ds-base/issue/49296
b045b9
b045b9
Reviewed by: firstyear(Thanks!)
b045b9
b045b9
(cherry picked from commit 0d5214d08e6b5b39fb9d5ef5cf3d8834574954f1)
b045b9
---
b045b9
 ldap/servers/slapd/connection.c | 12 +++++++++++-
b045b9
 ldap/servers/slapd/slap.h       |  7 +++----
b045b9
 2 files changed, 14 insertions(+), 5 deletions(-)
b045b9
b045b9
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
b045b9
index 5d2b64ed2..5ca32a333 100644
b045b9
--- a/ldap/servers/slapd/connection.c
b045b9
+++ b/ldap/servers/slapd/connection.c
b045b9
@@ -217,6 +217,7 @@ connection_cleanup(Connection *conn)
b045b9
     conn->c_connid = 0;
b045b9
     conn->c_opsinitiated = 0;
b045b9
     conn->c_opscompleted = 0;
b045b9
+    conn->c_anonlimits_set = 0;
b045b9
     conn->c_threadnumber = 0;
b045b9
     conn->c_refcnt = 0;
b045b9
     conn->c_idlesince = 0;
b045b9
@@ -1549,7 +1550,9 @@ connection_threadmain()
b045b9
                     g_decr_active_threadcnt();
b045b9
                     return;
b045b9
                 }
b045b9
-                if (pb_conn->c_opscompleted == 0) {
b045b9
+
b045b9
+                PR_EnterMonitor(pb_conn->c_mutex);
b045b9
+                if (pb_conn->c_anonlimits_set == 0) {
b045b9
                     /*
b045b9
                      * We have a new connection, set the anonymous reslimit idletimeout
b045b9
                      * if applicable.
b045b9
@@ -1568,7 +1571,14 @@ connection_threadmain()
b045b9
                         }
b045b9
                     }
b045b9
                     slapi_ch_free_string(&anon_dn);
b045b9
+                    /*
b045b9
+                     * Set connection as initialized to avoid setting anonymous limits
b045b9
+                     * multiple times on the same connection
b045b9
+                     */
b045b9
+                    pb_conn->c_anonlimits_set = 1;
b045b9
                 }
b045b9
+                PR_ExitMonitor(pb_conn->c_mutex);
b045b9
+
b045b9
                 if (connection_call_io_layer_callbacks(pb_conn)) {
b045b9
                     slapi_log_err(SLAPI_LOG_ERR, "connection_threadmain",
b045b9
                                   "Could not add/remove IO layers from connection\n");
b045b9
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
b045b9
index 9b10aa19e..03355f5fe 100644
b045b9
--- a/ldap/servers/slapd/slap.h
b045b9
+++ b/ldap/servers/slapd/slap.h
b045b9
@@ -1616,6 +1616,7 @@ typedef struct conn
b045b9
     PRUint64 c_maxthreadsblocked;    /* # of operations blocked by maxthreads */
b045b9
     int c_opsinitiated;              /* # ops initiated/next op id      */
b045b9
     PRInt32 c_opscompleted;          /* # ops completed          */
b045b9
+    uint64_t c_anonlimits_set;       /* default anon limits are set */
b045b9
     PRInt32 c_threadnumber;          /* # threads used in this conn    */
b045b9
     int c_refcnt;                    /* # ops refering to this conn    */
b045b9
     PRMonitor *c_mutex;              /* protect each conn structure; need to be re-entrant */
b045b9
@@ -1623,10 +1624,8 @@ typedef struct conn
b045b9
     time_t c_idlesince;              /* last time of activity on conn  */
b045b9
     int c_idletimeout;               /* local copy of idletimeout */
b045b9
     int c_idletimeout_handle;        /* the resource limits handle */
b045b9
-    Conn_private *c_private;         /* data which is not shared outside*/
b045b9
-                                     /* connection.c           */
b045b9
-    int c_flags;                     /* Misc flags used only for SSL   */
b045b9
-                                     /* status currently               */
b045b9
+    Conn_private *c_private;         /* data which is not shared outside connection.c */
b045b9
+    int c_flags;                     /* Misc flags used only for SSL status currently */
b045b9
     int c_needpw;                    /* need new password           */
b045b9
     CERTCertificate *c_client_cert;  /* Client's Cert          */
b045b9
     PRFileDesc *c_prfd;              /* NSPR 2.1 FileDesc          */
b045b9
-- 
b045b9
2.13.6
b045b9