From 43af57d8728883c5ddbe169e1483181246fb68a8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Feb 2018 15:05:57 +0100 Subject: [PATCH] winbind: protect a pending wb_child_request against a talloc_free() If the (winbind) client gave up we call TALLOC_FREE(state->mem_ctx) in remove_client(). This triggers a recursive talloc_free() for all in flight requests. In order to maintain the winbindd parent-child protocol, we need to keep the orphaned wb_simple_trans request until the parent got the response from the child. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13290 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke --- source3/winbindd/winbindd_dual.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index fa5b5b0589e..d0a40a8bac4 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -130,6 +130,7 @@ static bool fork_domain_child(struct winbindd_child *child); static void wb_child_request_waited(struct tevent_req *subreq); static void wb_child_request_done(struct tevent_req *subreq); +static void wb_child_request_orphaned(struct tevent_req *subreq); static void wb_child_request_cleanup(struct tevent_req *req, enum tevent_req_state req_state); @@ -220,6 +221,12 @@ static void wb_child_request_done(struct tevent_req *subreq) tevent_req_done(req); } +static void wb_child_request_orphaned(struct tevent_req *subreq) +{ + DBG_WARNING("cleanup orphaned subreq[%p]\n", subreq); + TALLOC_FREE(subreq); +} + int wb_child_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct winbindd_response **presponse, int *err) { @@ -244,6 +251,28 @@ static void wb_child_request_cleanup(struct tevent_req *req, return; } + if (req_state == TEVENT_REQ_RECEIVED) { + struct tevent_req *subreq = NULL; + + /* + * Our caller gave up, but we need to keep + * the low level request (wb_simple_trans) + * in order to maintain the parent child protocol. + * + * We also need to keep the child queue blocked + * until we got the response from the child. + */ + + subreq = talloc_move(state->child->queue, &state->subreq); + talloc_move(subreq, &state->queue_subreq); + tevent_req_set_callback(subreq, + wb_child_request_orphaned, + NULL); + + DBG_WARNING("keep orphaned subreq[%p]\n", subreq); + return; + } + TALLOC_FREE(state->subreq); TALLOC_FREE(state->queue_subreq); -- 2.34.1