winbind: protect a pending wb_child_request against a talloc_free()
authorStefan Metzmacher <metze@samba.org>
Fri, 16 Feb 2018 14:05:57 +0000 (15:05 +0100)
committerStefan Metzmacher <metze@samba.org>
Fri, 23 Feb 2018 03:09:18 +0000 (04:09 +0100)
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 <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
source3/winbindd/winbindd_dual.c

index fa5b5b0589eb7aff07c14c2e941ba57449346ff9..d0a40a8bac43b8cea90f4371112a8eeae3d36709 100644 (file)
@@ -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);