andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
dc8c34
From 3120dbe2653c143a445f35b46929d5f63c8aa5c6 Mon Sep 17 00:00:00 2001
dc8c34
From: Noriko Hosoi <nhosoi@redhat.com>
dc8c34
Date: Wed, 30 Sep 2015 13:32:05 -0700
dc8c34
Subject: [PATCH 343/344] Ticket #48299 - pagedresults - when timed out, search
dc8c34
 results could have been already freed.
dc8c34
dc8c34
Description: When a search results object is freed, there is a window
dc8c34
until the information is set to the pagedresults handle.  If the paged-
dc8c34
results handle is released due to a timeout in the window, double free
dc8c34
occurs.
dc8c34
dc8c34
This patch sets NULL just before the search results object is freed
dc8c34
in the backend as well as in dse.
dc8c34
dc8c34
Plus, fixed a minor memory leak in pagedresults_parse_control_value.
dc8c34
dc8c34
https://fedorahosted.org/389/ticket/48299
dc8c34
dc8c34
Reviewed and a bug found by tbordaz@redhat.com (Thank you, Thierry!!)
dc8c34
dc8c34
(cherry picked from commit f90c3a6e1933b9cc19a51b17a038f26652c4b2bc)
dc8c34
(cherry picked from commit 56151ed75bbd63af80932fe73a512df835b17593)
dc8c34
(cherry picked from commit 10ed80cf265fbfbec0c8dda005dcb84b6f39762b)
dc8c34
(cherry picked from commit 54e574ad5334fc9c0e27be0a57551add38d84d1e)
dc8c34
---
dc8c34
 ldap/servers/slapd/back-ldbm/ldbm_search.c |  1 +
dc8c34
 ldap/servers/slapd/dse.c                   |  1 +
dc8c34
 ldap/servers/slapd/pagedresults.c          | 33 +++++++++++++++++++++++++++++-
dc8c34
 ldap/servers/slapd/proto-slap.h            |  1 +
dc8c34
 4 files changed, 35 insertions(+), 1 deletion(-)
dc8c34
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c
dc8c34
index 92ae691..bbcbe0e 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c
dc8c34
@@ -1890,6 +1890,7 @@ delete_search_result_set( Slapi_PBlock *pb, back_search_result_set **sr )
dc8c34
             /* If the op is pagedresults, let the module clean up sr. */
dc8c34
             return;
dc8c34
         }
dc8c34
+        pagedresults_set_search_result_pb(pb, NULL, 0);
dc8c34
         slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
dc8c34
     }
dc8c34
     if ( NULL != (*sr)->sr_candidates )
dc8c34
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
dc8c34
index 22cbff1..8080ec9 100644
dc8c34
--- a/ldap/servers/slapd/dse.c
dc8c34
+++ b/ldap/servers/slapd/dse.c
dc8c34
@@ -2578,6 +2578,7 @@ dse_next_search_entry (Slapi_PBlock *pb)
dc8c34
 	/* we reached the end of the list */
dc8c34
 	if (e == NULL)
dc8c34
 	{
dc8c34
+		pagedresults_set_search_result_pb(pb, NULL, 0);
dc8c34
 		dse_search_set_delete (ss);
dc8c34
 		slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
dc8c34
 	}
dc8c34
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
dc8c34
index 010e5c1..9e183ec 100644
dc8c34
--- a/ldap/servers/slapd/pagedresults.c
dc8c34
+++ b/ldap/servers/slapd/pagedresults.c
dc8c34
@@ -185,7 +185,6 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
dc8c34
     }
dc8c34
     /* reset sizelimit */
dc8c34
     op->o_pagedresults_sizelimit = -1;
dc8c34
-    slapi_ch_free((void **)&cookie.bv_val);
dc8c34
 
dc8c34
     if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) {
dc8c34
         if (conn->c_pagedresults.prl_list[*index].pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED) {
dc8c34
@@ -202,6 +201,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
dc8c34
         LDAPDebug1Arg(LDAP_DEBUG_ANY, "pagedresults_parse_control_value: invalid cookie: %d\n", *index);
dc8c34
     }
dc8c34
 bail:
dc8c34
+    slapi_ch_free((void **)&cookie.bv_val);
dc8c34
     /* cleaning up the rest of the timedout or abandoned if any */
dc8c34
     prp = conn->c_pagedresults.prl_list;
dc8c34
     for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++, prp++) {
dc8c34
@@ -1023,3 +1023,34 @@ pagedresults_is_abandoned_or_notavailable( Connection *conn, int index )
dc8c34
     PR_Unlock(conn->c_mutex);
dc8c34
     return prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED;
dc8c34
 }
dc8c34
+
dc8c34
+int
dc8c34
+pagedresults_set_search_result_pb(Slapi_PBlock *pb, void *sr, int locked)
dc8c34
+{
dc8c34
+    int rc = -1;
dc8c34
+    Connection *conn = NULL;
dc8c34
+    Operation *op = NULL;
dc8c34
+    int index = -1;
dc8c34
+    if (!pb) {
dc8c34
+        return 0;
dc8c34
+    }
dc8c34
+    slapi_pblock_get(pb, SLAPI_OPERATION, &op);
dc8c34
+    if (!op_is_pagedresults(op)) {
dc8c34
+        return 0; /* noop */
dc8c34
+    }
dc8c34
+    slapi_pblock_get(pb, SLAPI_CONNECTION, &conn;;
dc8c34
+    slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &index);
dc8c34
+    LDAPDebug2Args(LDAP_DEBUG_TRACE,
dc8c34
+                   "--> pagedresults_set_search_result_pb: idx=%d, sr=%p\n", index, sr);
dc8c34
+    if (conn && (index > -1)) {
dc8c34
+        if (!locked) PR_Lock(conn->c_mutex);
dc8c34
+        if (index < conn->c_pagedresults.prl_maxlen) {
dc8c34
+            conn->c_pagedresults.prl_list[index].pr_search_result_set = sr;
dc8c34
+            rc = 0;
dc8c34
+        }
dc8c34
+        if (!locked) PR_Unlock(conn->c_mutex);
dc8c34
+    }
dc8c34
+    LDAPDebug1Arg(LDAP_DEBUG_TRACE,
dc8c34
+                  "<-- pagedresults_set_search_result_pb: %d\n", rc);
dc8c34
+    return rc;
dc8c34
+}
dc8c34
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
dc8c34
index 7a1ab46..8f86eb7 100644
dc8c34
--- a/ldap/servers/slapd/proto-slap.h
dc8c34
+++ b/ldap/servers/slapd/proto-slap.h
dc8c34
@@ -1481,6 +1481,7 @@ 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_set_search_result_pb(Slapi_PBlock *pb, void *sr, int locked);
dc8c34
 
dc8c34
 /*
dc8c34
  * sort.c
dc8c34
-- 
dc8c34
1.9.3
dc8c34