>From 0a498b17d137189762dd4c85ad400c71955832bb Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Tue, 6 Sep 2011 00:07:15 +0200 Subject: [PATCH] Keep deref controls until the whole request is finished https://fedorahosted.org/sssd/ticket/989 John Hodrien found out that when paging is used while dereferencing an entry, sssd_be may segfault on the second page. This was because paging returned the control to sdap_generic_search multiple times but sssd was freeing dereference control after the first search invocation. The subsequend sdap searched accessed memory that was already freed. --- src/providers/ldap/sdap_async.c | 55 +++++++++++++++++++++++++++++++++----- 1 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c index 5594dd5..e5a4f67 100644 --- a/src/providers/ldap/sdap_async.c +++ b/src/providers/ldap/sdap_async.c @@ -1292,6 +1292,7 @@ static int sdap_x_deref_create_control(struct sdap_handle *sh, LDAPControl **ctrl); static void sdap_x_deref_search_done(struct tevent_req *subreq); +static int sdap_x_deref_search_ctrls_destructor(void *ptr); static errno_t sdap_x_deref_parse_entry(struct sdap_handle *sh, struct sdap_msg *msg, @@ -1300,6 +1301,7 @@ struct sdap_x_deref_search_state { struct sdap_handle *sh; struct sdap_op *op; struct sdap_attr_map_info *maps; + LDAPControl **ctrls; struct sdap_deref_reply dreply; int num_maps; @@ -1315,7 +1317,6 @@ sdap_x_deref_search_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct tevent_req *req = NULL; struct tevent_req *subreq = NULL; struct sdap_x_deref_search_state *state; - LDAPControl *ctrls[2] = { NULL, NULL }; int ret; req = tevent_req_create(memctx, &state, struct sdap_x_deref_search_state); @@ -1325,21 +1326,29 @@ sdap_x_deref_search_send(TALLOC_CTX *memctx, struct tevent_context *ev, state->maps = maps; state->op = NULL; state->num_maps = num_maps; + state->ctrls = talloc_array(state, LDAPControl *, 2); + if (state->ctrls == NULL) { + talloc_zfree(req); + return NULL; + } + talloc_set_destructor((TALLOC_CTX *) state->ctrls, + sdap_x_deref_search_ctrls_destructor); - ret = sdap_x_deref_create_control(sh, deref_attr, attrs, &ctrls[0]); + ret = sdap_x_deref_create_control(sh, deref_attr, + attrs, &state->ctrls[0]); if (ret != EOK) { DEBUG(1, ("Could not create OpenLDAP deref control\n")); talloc_zfree(req); return NULL; } + state->ctrls[1] = NULL; DEBUG(6, ("Dereferencing entry [%s] using OpenLDAP deref\n", base_dn)); subreq = sdap_get_generic_ext_send(state, ev, opts, sh, base_dn, LDAP_SCOPE_BASE, NULL, attrs, - false, ctrls, NULL, 0, timeout, + false, state->ctrls, NULL, 0, timeout, sdap_x_deref_parse_entry, state); - ldap_control_free(ctrls[0]); if (!subreq) { talloc_zfree(req); return NULL; @@ -1478,6 +1487,17 @@ static void sdap_x_deref_search_done(struct tevent_req *subreq) tevent_req_done(req); } +static int sdap_x_deref_search_ctrls_destructor(void *ptr) +{ + LDAPControl **ctrls = talloc_get_type(ptr, LDAPControl *);; + + if (ctrls && ctrls[0]) { + ldap_control_free(ctrls[0]); + } + + return 0; +} + static int sdap_x_deref_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, @@ -1499,6 +1519,7 @@ sdap_x_deref_search_recv(struct tevent_req *req, struct sdap_asq_search_state { struct sdap_attr_map_info *maps; int num_maps; + LDAPControl **ctrls; struct sdap_deref_reply dreply; }; @@ -1506,6 +1527,7 @@ struct sdap_asq_search_state { static int sdap_asq_search_create_control(struct sdap_handle *sh, const char *attr, LDAPControl **ctrl); +static int sdap_asq_search_ctrls_destructor(void *ptr); static errno_t sdap_asq_search_parse_entry(struct sdap_handle *sh, struct sdap_msg *msg, void *pvt); @@ -1522,28 +1544,34 @@ sdap_asq_search_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct tevent_req *subreq = NULL; struct sdap_asq_search_state *state; int ret; - LDAPControl *ctrls[2] = { NULL, NULL }; req = tevent_req_create(memctx, &state, struct sdap_asq_search_state); if (!req) return NULL; state->maps = maps; state->num_maps = num_maps; + state->ctrls = talloc_array(state, LDAPControl *, 2); + if (state->ctrls == NULL) { + talloc_zfree(req); + return NULL; + } + talloc_set_destructor((TALLOC_CTX *) state->ctrls, + sdap_asq_search_ctrls_destructor); - ret = sdap_asq_search_create_control(sh, deref_attr, &ctrls[0]); + ret = sdap_asq_search_create_control(sh, deref_attr, &state->ctrls[0]); if (ret != EOK) { talloc_zfree(req); DEBUG(1, ("Could not create ASQ control\n")); return NULL; } + state->ctrls[1] = NULL; DEBUG(6, ("Dereferencing entry [%s] using ASQ\n", base_dn)); subreq = sdap_get_generic_ext_send(state, ev, opts, sh, base_dn, LDAP_SCOPE_BASE, NULL, attrs, - false, ctrls, NULL, 0, timeout, + false, state->ctrls, NULL, 0, timeout, sdap_asq_search_parse_entry, state); - ldap_control_free(ctrls[0]); if (!subreq) { talloc_zfree(req); return NULL; @@ -1684,6 +1712,17 @@ static void sdap_asq_search_done(struct tevent_req *subreq) tevent_req_done(req); } +static int sdap_asq_search_ctrls_destructor(void *ptr) +{ + LDAPControl **ctrls = talloc_get_type(ptr, LDAPControl *);; + + if (ctrls && ctrls[0]) { + ldap_control_free(ctrls[0]); + } + + return 0; +} + int sdap_asq_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, size_t *reply_count, -- 1.7.6