Blame SOURCES/0066-Ticket-48299-pagedresults-when-timed-out-search-resu.patch

a2f18f
From 695f06f02f6285bad4c494fda98f8f17ace2d1aa Mon Sep 17 00:00:00 2001
a2f18f
From: Noriko Hosoi <nhosoi@redhat.com>
a2f18f
Date: Wed, 30 Sep 2015 13:32:05 -0700
a2f18f
Subject: [PATCH 66/68] Ticket #48299 - pagedresults - when timed out, search
a2f18f
 results could have been already freed.
a2f18f
a2f18f
Description: When a search results object is freed, there is a window
a2f18f
until the information is set to the pagedresults handle.  If the paged-
a2f18f
results handle is released due to a timeout in the window, double free
a2f18f
occurs.
a2f18f
a2f18f
This patch sets NULL just before the search results object is freed
a2f18f
in the backend as well as in dse.
a2f18f
a2f18f
Plus, fixed a minor memory leak in pagedresults_parse_control_value.
a2f18f
a2f18f
https://fedorahosted.org/389/ticket/48299
a2f18f
a2f18f
Reviewed and a bug found by tbordaz@redhat.com (Thank you, Thierry!!)
a2f18f
a2f18f
(cherry picked from commit f90c3a6e1933b9cc19a51b17a038f26652c4b2bc)
a2f18f
(cherry picked from commit 56151ed75bbd63af80932fe73a512df835b17593)
a2f18f
---
a2f18f
 ldap/servers/slapd/back-ldbm/ldbm_search.c |  1 +
a2f18f
 ldap/servers/slapd/dse.c                   |  1 +
a2f18f
 ldap/servers/slapd/pagedresults.c          | 33 +++++++++++++++++++++++++++++-
a2f18f
 ldap/servers/slapd/proto-slap.h            |  1 +
a2f18f
 4 files changed, 35 insertions(+), 1 deletion(-)
a2f18f
a2f18f
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c
a2f18f
index 73c54d3..8ed6b4d 100644
a2f18f
--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c
a2f18f
+++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c
a2f18f
@@ -1890,6 +1890,7 @@ delete_search_result_set( Slapi_PBlock *pb, back_search_result_set **sr )
a2f18f
             /* If the op is pagedresults, let the module clean up sr. */
a2f18f
             return;
a2f18f
         }
a2f18f
+        pagedresults_set_search_result_pb(pb, NULL, 0);
a2f18f
         slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
a2f18f
     }
a2f18f
     if ( NULL != (*sr)->sr_candidates )
a2f18f
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
a2f18f
index e8e393b..68ce751 100644
a2f18f
--- a/ldap/servers/slapd/dse.c
a2f18f
+++ b/ldap/servers/slapd/dse.c
a2f18f
@@ -2830,6 +2830,7 @@ dse_next_search_entry (Slapi_PBlock *pb)
a2f18f
 	/* we reached the end of the list */
a2f18f
 	if (e == NULL)
a2f18f
 	{
a2f18f
+		pagedresults_set_search_result_pb(pb, NULL, 0);
a2f18f
 		dse_search_set_delete (ss);
a2f18f
 		slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
a2f18f
 	}
a2f18f
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
a2f18f
index d0c93cd..6dd6432 100644
a2f18f
--- a/ldap/servers/slapd/pagedresults.c
a2f18f
+++ b/ldap/servers/slapd/pagedresults.c
a2f18f
@@ -172,7 +172,6 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
a2f18f
     }
a2f18f
     /* reset sizelimit */
a2f18f
     op->o_pagedresults_sizelimit = -1;
a2f18f
-    slapi_ch_free((void **)&cookie.bv_val);
a2f18f
 
a2f18f
     if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) {
a2f18f
         if (conn->c_pagedresults.prl_list[*index].pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED) {
a2f18f
@@ -189,6 +188,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
a2f18f
         LDAPDebug1Arg(LDAP_DEBUG_ANY, "pagedresults_parse_control_value: invalid cookie: %d\n", *index);
a2f18f
     }
a2f18f
 bail:
a2f18f
+    slapi_ch_free((void **)&cookie.bv_val);
a2f18f
     /* cleaning up the rest of the timedout or abandoned if any */
a2f18f
     prp = conn->c_pagedresults.prl_list;
a2f18f
     for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++, prp++) {
a2f18f
@@ -1010,3 +1010,34 @@ pagedresults_is_abandoned_or_notavailable( Connection *conn, int index )
a2f18f
     PR_Unlock(conn->c_mutex);
a2f18f
     return prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED;
a2f18f
 }
a2f18f
+
a2f18f
+int
a2f18f
+pagedresults_set_search_result_pb(Slapi_PBlock *pb, void *sr, int locked)
a2f18f
+{
a2f18f
+    int rc = -1;
a2f18f
+    Connection *conn = NULL;
a2f18f
+    Operation *op = NULL;
a2f18f
+    int index = -1;
a2f18f
+    if (!pb) {
a2f18f
+        return 0;
a2f18f
+    }
a2f18f
+    slapi_pblock_get(pb, SLAPI_OPERATION, &op);
a2f18f
+    if (!op_is_pagedresults(op)) {
a2f18f
+        return 0; /* noop */
a2f18f
+    }
a2f18f
+    slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);
a2f18f
+    slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &index);
a2f18f
+    LDAPDebug2Args(LDAP_DEBUG_TRACE,
a2f18f
+                   "--> pagedresults_set_search_result_pb: idx=%d, sr=%p\n", index, sr);
a2f18f
+    if (conn && (index > -1)) {
a2f18f
+        if (!locked) PR_Lock(conn->c_mutex);
a2f18f
+        if (index < conn->c_pagedresults.prl_maxlen) {
a2f18f
+            conn->c_pagedresults.prl_list[index].pr_search_result_set = sr;
a2f18f
+            rc = 0;
a2f18f
+        }
a2f18f
+        if (!locked) PR_Unlock(conn->c_mutex);
a2f18f
+    }
a2f18f
+    LDAPDebug1Arg(LDAP_DEBUG_TRACE,
a2f18f
+                  "<-- pagedresults_set_search_result_pb: %d\n", rc);
a2f18f
+    return rc;
a2f18f
+}
a2f18f
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
a2f18f
index e8673e1..b10c1eb 100644
a2f18f
--- a/ldap/servers/slapd/proto-slap.h
a2f18f
+++ b/ldap/servers/slapd/proto-slap.h
a2f18f
@@ -1488,6 +1488,7 @@ void op_set_pagedresults(Operation *op);
a2f18f
 void pagedresults_lock(Connection *conn, int index);
a2f18f
 void pagedresults_unlock(Connection *conn, int index);
a2f18f
 int pagedresults_is_abandoned_or_notavailable(Connection *conn, int index);
a2f18f
+int pagedresults_set_search_result_pb(Slapi_PBlock *pb, void *sr, int locked);
a2f18f
 
a2f18f
 /*
a2f18f
  * sort.c
a2f18f
-- 
a2f18f
1.9.3
a2f18f