Blame SOURCES/0072-Ticket-48338-SimplePagedResults-abandon-could-happen.patch

246821
From 24129b41820b87d613e721f8530e1955f1cce0ff Mon Sep 17 00:00:00 2001
246821
From: Noriko Hosoi <nhosoi@redhat.com>
246821
Date: Thu, 5 Nov 2015 10:44:08 -0800
246821
Subject: [PATCH 72/75] Ticket #48338 - SimplePagedResults -- abandon could
246821
 happen between the abandon check and sending results
246821
246821
Description: An abandon request for a SimplePagedResults request could
246821
happened between the abandon check and the code for sending the search
246821
results.  The abandon frees the search results although sending result
246821
code still refers it.
246821
246821
Fix description: The code (from getting search results through sending
246821
the search results) in op_shared_search is protected by c_mutex locking.
246821
246821
https://fedorahosted.org/389/ticket/48338
246821
246821
Reviewed by rmeggins@redhat.com (Thank you, Rich!!)
246821
246821
(cherry picked from commit 390b8bd9076e8976facc0858e60985d6b4fac05c)
246821
(cherry picked from commit 8f49d33d30fade7b579062414250a0ddb1a66c62)
246821
---
246821
 ldap/servers/slapd/opshared.c     | 13 ++++++++-----
246821
 ldap/servers/slapd/pagedresults.c | 28 ++++++++++++++++++----------
246821
 ldap/servers/slapd/proto-slap.h   |  5 ++---
246821
 3 files changed, 28 insertions(+), 18 deletions(-)
246821
246821
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
246821
index dcdbb04..586ca1f 100644
246821
--- a/ldap/servers/slapd/opshared.c
246821
+++ b/ldap/servers/slapd/opshared.c
246821
@@ -500,7 +500,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
246821
                       be = be_list[index];
246821
                   }
246821
               }
246821
-              pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, pr_idx);
246821
+              pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, 0/*not locked*/, pr_idx);
246821
               estimate = pagedresults_get_search_result_set_size_estimate(pb->pb_conn, operation, pr_idx);
246821
               if (pagedresults_get_unindexed(pb->pb_conn, operation, pr_idx)) {
246821
                   opnote |= SLAPI_OP_NOTE_UNINDEXED;
246821
@@ -675,13 +675,15 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
246821
        * In async paged result case, the search result might be released
246821
        * by other theads.  We need to double check it in the locked region.
246821
        */
246821
-      pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, pr_idx);
246821
+      PR_Lock(pb->pb_conn->c_mutex);
246821
+      pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, 1/*locked*/, pr_idx);
246821
       if (pr_search_result) {
246821
-        if (pagedresults_is_abandoned_or_notavailable(pb->pb_conn, pr_idx)) {
246821
+        if (pagedresults_is_abandoned_or_notavailable(pb->pb_conn, 1/*locked*/, pr_idx)) {
246821
           pagedresults_unlock(pb->pb_conn, pr_idx);
246821
           /* Previous operation was abandoned and the simplepaged object is not in use. */
246821
           send_ldap_result(pb, 0, NULL, "Simple Paged Results Search abandoned", 0, NULL);
246821
           rc = LDAP_SUCCESS;
246821
+          PR_Unlock(pb->pb_conn->c_mutex);
246821
           goto free_and_return;
246821
         } else {
246821
           slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result );
246821
@@ -689,7 +691,8 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
246821
 
246821
           /* search result could be reset in the backend/dse */
246821
           slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
246821
-          pagedresults_set_search_result(pb->pb_conn, operation, sr, 0, pr_idx);
246821
+          pagedresults_set_search_result(pb->pb_conn, operation, sr, 1/*locked*/, pr_idx);
246821
+          PR_Unlock(pb->pb_conn->c_mutex);
246821
         }
246821
       } else {
246821
         pr_stat = PAGEDRESULTS_SEARCH_END;
246821
@@ -720,7 +723,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
246821
       if (PAGEDRESULTS_SEARCH_END == pr_stat) {
246821
         pagedresults_lock(pb->pb_conn, pr_idx);
246821
         slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
246821
-        if (!pagedresults_is_abandoned_or_notavailable(pb->pb_conn, pr_idx)) {
246821
+        if (!pagedresults_is_abandoned_or_notavailable(pb->pb_conn, 0/*not locked*/, pr_idx)) {
246821
           pagedresults_free_one(pb->pb_conn, operation, pr_idx);
246821
         }
246821
         pagedresults_unlock(pb->pb_conn, pr_idx);
246821
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
246821
index 87447c4..4458cfb 100644
246821
--- a/ldap/servers/slapd/pagedresults.c
246821
+++ b/ldap/servers/slapd/pagedresults.c
246821
@@ -395,20 +395,25 @@ pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index, int
246821
 }
246821
 
246821
 void *
246821
-pagedresults_get_search_result(Connection *conn, Operation *op, int index)
246821
+pagedresults_get_search_result(Connection *conn, Operation *op, int locked, int index)
246821
 {
246821
     void *sr = NULL;
246821
     if (!op_is_pagedresults(op)) {
246821
         return sr; /* noop */
246821
     }
246821
-    LDAPDebug1Arg(LDAP_DEBUG_TRACE,
246821
-                  "--> pagedresults_get_search_result: idx=%d\n", index);
246821
+    LDAPDebug2Args(LDAP_DEBUG_TRACE,
246821
+                   "--> pagedresults_get_search_result(%s): idx=%d\n",
246821
+                   locked?"locked":"not locked", index);
246821
     if (conn && (index > -1)) {
246821
-        PR_Lock(conn->c_mutex);
246821
+        if (!locked) {
246821
+            PR_Lock(conn->c_mutex);
246821
+        }
246821
         if (index < conn->c_pagedresults.prl_maxlen) {
246821
             sr = conn->c_pagedresults.prl_list[index].pr_search_result_set;
246821
         }
246821
-        PR_Unlock(conn->c_mutex);
246821
+        if (!locked) {
246821
+            PR_Unlock(conn->c_mutex);
246821
+        }
246821
     }
246821
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
246821
                   "<-- pagedresults_get_search_result: %p\n", sr);
246821
@@ -416,8 +421,7 @@ pagedresults_get_search_result(Connection *conn, Operation *op, int index)
246821
 }
246821
 
246821
 int
246821
-pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, 
246821
-                               int locked, int index)
246821
+pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, int locked, int index)
246821
 {
246821
     int rc = -1;
246821
     if (!op_is_pagedresults(op)) {
246821
@@ -1003,15 +1007,19 @@ pagedresults_unlock( Connection *conn, int index )
246821
 }
246821
 
246821
 int
246821
-pagedresults_is_abandoned_or_notavailable( Connection *conn, int index )
246821
+pagedresults_is_abandoned_or_notavailable(Connection *conn, int locked, int index)
246821
 {
246821
     PagedResults *prp;
246821
     if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
246821
         return 1; /* not abandoned, but do not want to proceed paged results op. */
246821
     }
246821
-    PR_Lock(conn->c_mutex);
246821
+    if (!locked) {
246821
+        PR_Lock(conn->c_mutex);
246821
+    }
246821
     prp = conn->c_pagedresults.prl_list + index;
246821
-    PR_Unlock(conn->c_mutex);
246821
+    if (!locked) {
246821
+        PR_Unlock(conn->c_mutex);
246821
+    }
246821
     return prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED;
246821
 }
246821
 
246821
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
246821
index b10c1eb..e1cb53e 100644
246821
--- a/ldap/servers/slapd/proto-slap.h
246821
+++ b/ldap/servers/slapd/proto-slap.h
246821
@@ -1445,8 +1445,7 @@ void pagedresults_set_response_control(Slapi_PBlock *pb, int iscritical,
246821
                                        int curr_search_count, int index);
246821
 Slapi_Backend *pagedresults_get_current_be(Connection *conn, int index);
246821
 int pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index, int nolock);
246821
-void *pagedresults_get_search_result(Connection *conn, Operation *op,
246821
-                                     int index);
246821
+void *pagedresults_get_search_result(Connection *conn, Operation *op, int locked, int index);
246821
 int pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, 
246821
                                    int locked, int index);
246821
 int pagedresults_get_search_result_count(Connection *conn, Operation *op,
246821
@@ -1487,7 +1486,7 @@ int pagedresults_cleanup_all(Connection *conn, int needlock);
246821
 void op_set_pagedresults(Operation *op);
246821
 void pagedresults_lock(Connection *conn, int index);
246821
 void pagedresults_unlock(Connection *conn, int index);
246821
-int pagedresults_is_abandoned_or_notavailable(Connection *conn, int index);
246821
+int pagedresults_is_abandoned_or_notavailable(Connection *conn, int locked, int index);
246821
 int pagedresults_set_search_result_pb(Slapi_PBlock *pb, void *sr, int locked);
246821
 
246821
 /*
246821
-- 
246821
2.4.3
246821