#49744 Ticket 49736 - Hardening of active connection list
Closed 3 years ago by spichugi. Opened 5 years ago by tbordaz.
tbordaz/389-ds-base Ticket-49736  into  master

@@ -243,6 +243,27 @@ 

      int c_sd; /* for logging */

      /* we always have previous element because list contains a dummy header */;

      PR_ASSERT(c->c_prev);

+     if (c->c_prev == NULL) {

+         /* c->c_prev is set when the connection is moved ON the active list

+          * So this connection is already OUT of the active list

+          *

+          * Not sure how to recover from here.

+          * Considering c->c_prev is NULL we can assume refcnt is now 0

+          * and connection_cleanup was already called.

+          * If it is not the case, then consequences are:

+          *  - Leak some memory (connext, unsent page result entries, various buffers)

+          *  - hanging connection (fd not closed)

+          * A option would be to call connection_cleanup here.

+          *

+          * The logged message helps to know how frequently the problem exists

+          */

+         slapi_log_err(SLAPI_LOG_CRIT,

+                       "connection_table_move_connection_out_of_active_list",

+                       "conn %d is already OUT of the active list (refcnt is %d)\n",

+                       c->c_sd, c->c_refcnt);

+ 

+         return 0;

+     }

  

  #ifdef FOR_DEBUGGING

      slapi_log_err(SLAPI_LOG_DEBUG, "connection_table_move_connection_out_of_active_list", "Moving connection out of active list\n");

Bug Description:
In case of a bug in the management of the connection refcnt
it can happen that there are several attempts to move a connection
out of the active list.

It triggers a crash because when derefencing c->c_prev.
c_prev is never NULL on the active list

Fix Description:
The fix tests if the connection is already out of the active list.
If such case, it just returns.

A potential issue that is not addressed by this fix is:
Thread A and Thread B are using 'c' but c->refcnt=1 (it should be 2)
Thread A "closes" 'c', 'c' is move out of active list (free) because of refcnt=0
A new connection happens selecting the free connection 'c', moving it to the active list.
Thread C is using 'c' from the new connection c->refcnt=1
Thread B "closes" 'c', 'c' is moved out of the active list.
-> new operation coming on 'c' will not be detected
-> Thread C will likely crash when sending result

https://pagure.io/389-ds-base/issue/49736

Reviewed by: ?

Platforms tested: F26

Flag Day: no

Doc impact: no

LGTM, lets get this in for the next respin

So the real issue is that Thread A or B on same connection is not handling the refcnt correctly. One is either: setting it too late, not setting it at all, or lowering it too soon. Do we know which one it is?

thanks for the review Mark. Is it a ack ?

Regarding your question I have no real idea.
I know a corner case that can lead to this crash but it exists other scenario and it is the reason of this hardening.
The corner case was an invalid lowering. It happened if a thread was processing several operations in a raw (turbo mode or more_data).

rebased onto b0e0580

5 years ago

Pull-Request has been merged by tbordaz

5 years ago

389-ds-base is moving from Pagure to Github. This means that new issues and pull requests
will be accepted only in 389-ds-base's github repository.

This pull request has been cloned to Github as issue and is available here:
- https://github.com/389ds/389-ds-base/issues/2803

If you want to continue to work on the PR, please navigate to the github issue,
download the patch from the attachments and file a new pull request.

Thank you for understanding. We apologize for all inconvenience.

Pull-Request has been closed by spichugi

3 years ago
Metadata