andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
dc8c34
From f50e991828321e3e19ac704f0b2e0968a0c6704e Mon Sep 17 00:00:00 2001
dc8c34
From: Noriko Hosoi <nhosoi@redhat.com>
dc8c34
Date: Thu, 5 Nov 2015 10:44:08 -0800
dc8c34
Subject: [PATCH 365/365] Ticket #48338 - SimplePagedResults -- abandon could
dc8c34
 happen between the abandon check and sending results
dc8c34
dc8c34
Description: An abandon request for a SimplePagedResults request could
dc8c34
happened between the abandon check and the code for sending the search
dc8c34
results.  The abandon frees the search results although sending result
dc8c34
code still refers it.
dc8c34
dc8c34
Fix description: The code (from getting search results through sending
dc8c34
the search results) in op_shared_search is protected by c_mutex locking.
dc8c34
dc8c34
https://fedorahosted.org/389/ticket/48338
dc8c34
dc8c34
Reviewed by rmeggins@redhat.com (Thank you, Rich!!)
dc8c34
dc8c34
(cherry picked from commit 390b8bd9076e8976facc0858e60985d6b4fac05c)
dc8c34
(cherry picked from commit 8f49d33d30fade7b579062414250a0ddb1a66c62)
dc8c34
(cherry picked from commit a7a8b2d3cb8452cc629ec5228bea6571d72e6538)
dc8c34
(cherry picked from commit d5ccc06cefa6f423d80c6cc0e527b57c116b0cb8)
dc8c34
---
dc8c34
 ldap/servers/slapd/opshared.c     | 13 ++++++++-----
dc8c34
 ldap/servers/slapd/pagedresults.c | 28 ++++++++++++++++++----------
dc8c34
 ldap/servers/slapd/proto-slap.h   |  5 ++---
dc8c34
 3 files changed, 28 insertions(+), 18 deletions(-)
dc8c34
dc8c34
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
dc8c34
index 31d41e8..391d1c3 100644
dc8c34
--- a/ldap/servers/slapd/opshared.c
dc8c34
+++ b/ldap/servers/slapd/opshared.c
dc8c34
@@ -530,7 +530,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
dc8c34
                       be = be_list[index];
dc8c34
                   }
dc8c34
               }
dc8c34
-              pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, pr_idx);
dc8c34
+              pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, 0/*not locked*/, pr_idx);
dc8c34
               estimate = pagedresults_get_search_result_set_size_estimate(pb->pb_conn, operation, pr_idx);
dc8c34
               if (pagedresults_get_unindexed(pb->pb_conn, operation, pr_idx)) {
dc8c34
                   opnote |= SLAPI_OP_NOTE_UNINDEXED;
dc8c34
@@ -700,13 +700,15 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
dc8c34
        * In async paged result case, the search result might be released
dc8c34
        * by other theads.  We need to double check it in the locked region.
dc8c34
        */
dc8c34
-      pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, pr_idx);
dc8c34
+      PR_Lock(pb->pb_conn->c_mutex);
dc8c34
+      pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, 1/*locked*/, pr_idx);
dc8c34
       if (pr_search_result) {
dc8c34
-        if (pagedresults_is_abandoned_or_notavailable(pb->pb_conn, pr_idx)) {
dc8c34
+        if (pagedresults_is_abandoned_or_notavailable(pb->pb_conn, 1/*locked*/, pr_idx)) {
dc8c34
           pagedresults_unlock(pb->pb_conn, pr_idx);
dc8c34
           /* Previous operation was abandoned and the simplepaged object is not in use. */
dc8c34
           send_ldap_result(pb, 0, NULL, "Simple Paged Results Search abandoned", 0, NULL);
dc8c34
           rc = LDAP_SUCCESS;
dc8c34
+          PR_Unlock(pb->pb_conn->c_mutex);
dc8c34
           goto free_and_return;
dc8c34
         } else {
dc8c34
           slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result );
dc8c34
@@ -714,7 +716,8 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
dc8c34
 
dc8c34
           /* search result could be reset in the backend/dse */
dc8c34
           slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
dc8c34
-          pagedresults_set_search_result(pb->pb_conn, operation, sr, 0, pr_idx);
dc8c34
+          pagedresults_set_search_result(pb->pb_conn, operation, sr, 1/*locked*/, pr_idx);
dc8c34
+          PR_Unlock(pb->pb_conn->c_mutex);
dc8c34
         }
dc8c34
       } else {
dc8c34
         pr_stat = PAGEDRESULTS_SEARCH_END;
dc8c34
@@ -745,7 +748,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
dc8c34
       if (PAGEDRESULTS_SEARCH_END == pr_stat) {
dc8c34
         pagedresults_lock(pb->pb_conn, pr_idx);
dc8c34
         slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
dc8c34
-        if (!pagedresults_is_abandoned_or_notavailable(pb->pb_conn, pr_idx)) {
dc8c34
+        if (!pagedresults_is_abandoned_or_notavailable(pb->pb_conn, 0/*not locked*/, pr_idx)) {
dc8c34
           pagedresults_free_one(pb->pb_conn, operation, pr_idx);
dc8c34
         }
dc8c34
         pagedresults_unlock(pb->pb_conn, pr_idx);
dc8c34
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
dc8c34
index 434e48d..c1947f1 100644
dc8c34
--- a/ldap/servers/slapd/pagedresults.c
dc8c34
+++ b/ldap/servers/slapd/pagedresults.c
dc8c34
@@ -408,20 +408,25 @@ pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index, int
dc8c34
 }
dc8c34
 
dc8c34
 void *
dc8c34
-pagedresults_get_search_result(Connection *conn, Operation *op, int index)
dc8c34
+pagedresults_get_search_result(Connection *conn, Operation *op, int locked, int index)
dc8c34
 {
dc8c34
     void *sr = NULL;
dc8c34
     if (!op_is_pagedresults(op)) {
dc8c34
         return sr; /* noop */
dc8c34
     }
dc8c34
-    LDAPDebug1Arg(LDAP_DEBUG_TRACE,
dc8c34
-                  "--> pagedresults_get_search_result: idx=%d\n", index);
dc8c34
+    LDAPDebug2Args(LDAP_DEBUG_TRACE,
dc8c34
+                   "--> pagedresults_get_search_result(%s): idx=%d\n",
dc8c34
+                   locked?"locked":"not locked", index);
dc8c34
     if (conn && (index > -1)) {
dc8c34
-        PR_Lock(conn->c_mutex);
dc8c34
+        if (!locked) {
dc8c34
+            PR_Lock(conn->c_mutex);
dc8c34
+        }
dc8c34
         if (index < conn->c_pagedresults.prl_maxlen) {
dc8c34
             sr = conn->c_pagedresults.prl_list[index].pr_search_result_set;
dc8c34
         }
dc8c34
-        PR_Unlock(conn->c_mutex);
dc8c34
+        if (!locked) {
dc8c34
+            PR_Unlock(conn->c_mutex);
dc8c34
+        }
dc8c34
     }
dc8c34
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
dc8c34
                   "<-- pagedresults_get_search_result: %p\n", sr);
dc8c34
@@ -429,8 +434,7 @@ pagedresults_get_search_result(Connection *conn, Operation *op, int index)
dc8c34
 }
dc8c34
 
dc8c34
 int
dc8c34
-pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, 
dc8c34
-                               int locked, int index)
dc8c34
+pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, int locked, int index)
dc8c34
 {
dc8c34
     int rc = -1;
dc8c34
     if (!op_is_pagedresults(op)) {
dc8c34
@@ -1016,15 +1020,19 @@ pagedresults_unlock( Connection *conn, int index )
dc8c34
 }
dc8c34
 
dc8c34
 int
dc8c34
-pagedresults_is_abandoned_or_notavailable( Connection *conn, int index )
dc8c34
+pagedresults_is_abandoned_or_notavailable(Connection *conn, int locked, int index)
dc8c34
 {
dc8c34
     PagedResults *prp;
dc8c34
     if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
dc8c34
         return 1; /* not abandoned, but do not want to proceed paged results op. */
dc8c34
     }
dc8c34
-    PR_Lock(conn->c_mutex);
dc8c34
+    if (!locked) {
dc8c34
+        PR_Lock(conn->c_mutex);
dc8c34
+    }
dc8c34
     prp = conn->c_pagedresults.prl_list + index;
dc8c34
-    PR_Unlock(conn->c_mutex);
dc8c34
+    if (!locked) {
dc8c34
+        PR_Unlock(conn->c_mutex);
dc8c34
+    }
dc8c34
     return prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED;
dc8c34
 }
dc8c34
 
dc8c34
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
dc8c34
index 8f86eb7..decc29e 100644
dc8c34
--- a/ldap/servers/slapd/proto-slap.h
dc8c34
+++ b/ldap/servers/slapd/proto-slap.h
dc8c34
@@ -1438,8 +1438,7 @@ void pagedresults_set_response_control(Slapi_PBlock *pb, int iscritical,
dc8c34
                                        int curr_search_count, int index);
dc8c34
 Slapi_Backend *pagedresults_get_current_be(Connection *conn, int index);
dc8c34
 int pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index, int nolock);
dc8c34
-void *pagedresults_get_search_result(Connection *conn, Operation *op,
dc8c34
-                                     int index);
dc8c34
+void *pagedresults_get_search_result(Connection *conn, Operation *op, int locked, int index);
dc8c34
 int pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, 
dc8c34
                                    int locked, int index);
dc8c34
 int pagedresults_get_search_result_count(Connection *conn, Operation *op,
dc8c34
@@ -1480,7 +1479,7 @@ int pagedresults_cleanup_all(Connection *conn, int needlock);
dc8c34
 void op_set_pagedresults(Operation *op);
dc8c34
 void pagedresults_lock(Connection *conn, int index);
dc8c34
 void pagedresults_unlock(Connection *conn, int index);
dc8c34
-int pagedresults_is_abandoned_or_notavailable(Connection *conn, int index);
dc8c34
+int pagedresults_is_abandoned_or_notavailable(Connection *conn, int locked, int index);
dc8c34
 int pagedresults_set_search_result_pb(Slapi_PBlock *pb, void *sr, int locked);
dc8c34
 
dc8c34
 /*
dc8c34
-- 
dc8c34
2.4.3
dc8c34