|
|
3b7e51 |
From 1f3e1ad55f72a885e27db41be28ce1037ff0ce93 Mon Sep 17 00:00:00 2001
|
|
|
3b7e51 |
From: Thierry Bordaz <tbordaz@redhat.com>
|
|
|
3b7e51 |
Date: Fri, 1 Jun 2018 16:12:40 +0200
|
|
|
3b7e51 |
Subject: [PATCH] Ticket 49736 - Hardening of active connection list
|
|
|
3b7e51 |
|
|
|
3b7e51 |
Bug Description:
|
|
|
3b7e51 |
In case of a bug in the management of the connection refcnt
|
|
|
3b7e51 |
it can happen that there are several attempts to move a connection
|
|
|
3b7e51 |
out of the active list.
|
|
|
3b7e51 |
|
|
|
3b7e51 |
It triggers a crash because when derefencing c->c_prev.
|
|
|
3b7e51 |
c_prev is never NULL on the active list
|
|
|
3b7e51 |
|
|
|
3b7e51 |
Fix Description:
|
|
|
3b7e51 |
The fix tests if the connection is already out of the active list.
|
|
|
3b7e51 |
If such case, it just returns.
|
|
|
3b7e51 |
|
|
|
3b7e51 |
A potential issue that is not addressed by this fix is:
|
|
|
3b7e51 |
Thread A and Thread B are using 'c' but c->refcnt=1 (it should be 2)
|
|
|
3b7e51 |
Thread A "closes" 'c', 'c' is move out of active list (free) because of refcnt=0
|
|
|
3b7e51 |
A new connection happens selecting the free connection 'c', moving it to the active list.
|
|
|
3b7e51 |
Thread C is using 'c' from the new connection c->refcnt=1
|
|
|
3b7e51 |
Thread B "closes" 'c', 'c' is moved out of the active list.
|
|
|
3b7e51 |
-> new operation coming on 'c' will not be detected
|
|
|
3b7e51 |
-> Thread C will likely crash when sending result
|
|
|
3b7e51 |
|
|
|
3b7e51 |
https://pagure.io/389-ds-base/issue/49736
|
|
|
3b7e51 |
|
|
|
3b7e51 |
Reviewed by: Mark Reynolds (thanks!)
|
|
|
3b7e51 |
|
|
|
3b7e51 |
Platforms tested: F26
|
|
|
3b7e51 |
|
|
|
3b7e51 |
Flag Day: no
|
|
|
3b7e51 |
|
|
|
3b7e51 |
Doc impact: no
|
|
|
3b7e51 |
|
|
|
3b7e51 |
(cherry picked from commit b0e05806232b781eed3ff102485045a358d7659b)
|
|
|
3b7e51 |
---
|
|
|
3b7e51 |
ldap/servers/slapd/conntable.c | 21 +++++++++++++++++++++
|
|
|
3b7e51 |
1 file changed, 21 insertions(+)
|
|
|
3b7e51 |
|
|
|
3b7e51 |
diff --git a/ldap/servers/slapd/conntable.c b/ldap/servers/slapd/conntable.c
|
|
|
3b7e51 |
index 114871d17..cb68a1119 100644
|
|
|
3b7e51 |
--- a/ldap/servers/slapd/conntable.c
|
|
|
3b7e51 |
+++ b/ldap/servers/slapd/conntable.c
|
|
|
3b7e51 |
@@ -243,6 +243,27 @@ connection_table_move_connection_out_of_active_list(Connection_Table *ct, Connec
|
|
|
3b7e51 |
int c_sd; /* for logging */
|
|
|
3b7e51 |
/* we always have previous element because list contains a dummy header */;
|
|
|
3b7e51 |
PR_ASSERT(c->c_prev);
|
|
|
3b7e51 |
+ if (c->c_prev == NULL) {
|
|
|
3b7e51 |
+ /* c->c_prev is set when the connection is moved ON the active list
|
|
|
3b7e51 |
+ * So this connection is already OUT of the active list
|
|
|
3b7e51 |
+ *
|
|
|
3b7e51 |
+ * Not sure how to recover from here.
|
|
|
3b7e51 |
+ * Considering c->c_prev is NULL we can assume refcnt is now 0
|
|
|
3b7e51 |
+ * and connection_cleanup was already called.
|
|
|
3b7e51 |
+ * If it is not the case, then consequences are:
|
|
|
3b7e51 |
+ * - Leak some memory (connext, unsent page result entries, various buffers)
|
|
|
3b7e51 |
+ * - hanging connection (fd not closed)
|
|
|
3b7e51 |
+ * A option would be to call connection_cleanup here.
|
|
|
3b7e51 |
+ *
|
|
|
3b7e51 |
+ * The logged message helps to know how frequently the problem exists
|
|
|
3b7e51 |
+ */
|
|
|
3b7e51 |
+ slapi_log_err(SLAPI_LOG_CRIT,
|
|
|
3b7e51 |
+ "connection_table_move_connection_out_of_active_list",
|
|
|
3b7e51 |
+ "conn %d is already OUT of the active list (refcnt is %d)\n",
|
|
|
3b7e51 |
+ c->c_sd, c->c_refcnt);
|
|
|
3b7e51 |
+
|
|
|
3b7e51 |
+ return 0;
|
|
|
3b7e51 |
+ }
|
|
|
3b7e51 |
|
|
|
3b7e51 |
#ifdef FOR_DEBUGGING
|
|
|
3b7e51 |
slapi_log_err(SLAPI_LOG_DEBUG, "connection_table_move_connection_out_of_active_list", "Moving connection out of active list\n");
|
|
|
3b7e51 |
--
|
|
|
3b7e51 |
2.17.0
|
|
|
3b7e51 |
|