summaryrefslogtreecommitdiff
path: root/source3/winbindd
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2020-05-15 15:19:45 +0200
committerStefan Metzmacher <metze@samba.org>2020-05-19 10:45:06 +0000
commit68380ebaa60c64311cc1081f700d571abbf69f4f (patch)
treec90365df4010dd63b021988ab8f54fb120e9cb33 /source3/winbindd
parentdd1f750293ef4361455a5d5b63fc7a89495715b7 (diff)
downloadsamba-68380ebaa60c64311cc1081f700d571abbf69f4f.tar.gz
winbindd: Fix a use-after-free when winbind clients exit
Bug: https://bugzilla.samba.org/show_bug.cgi?id=14382 Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> Signed-off-by: Volker Lendecke <vl@samba.org> Signed-off-by: Stefan Metzmacher <metze@samba.org> Autobuild-User(master): Stefan Metzmacher <metze@samba.org> Autobuild-Date(master): Tue May 19 10:45:06 UTC 2020 on sn-devel-184
Diffstat (limited to 'source3/winbindd')
-rw-r--r--source3/winbindd/winbindd_dual.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index 8ad2485324e..47efe988d65 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -202,7 +202,32 @@ struct tevent_req *wb_child_request_send(TALLOC_CTX *mem_ctx,
state->ev = ev;
state->child = child;
- state->request = request;
+
+ /*
+ * We have to make a copy of "request", because our caller
+ * might drop us via talloc_free().
+ *
+ * The talloc_move() magic in wb_child_request_cleanup() keeps
+ * all the requests, but if we are sitting deep within
+ * writev_send() down to the client, we have given it the
+ * pointer to "request". As our caller lost interest, it will
+ * just free "request", while writev_send still references it.
+ */
+
+ state->request = talloc_memdup(state, request, sizeof(*request));
+ if (tevent_req_nomem(state->request, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ if (request->extra_data.data != NULL) {
+ state->request->extra_data.data = talloc_memdup(
+ state->request,
+ request->extra_data.data,
+ request->extra_len);
+ if (tevent_req_nomem(state->request->extra_data.data, req)) {
+ return tevent_req_post(req, ev);
+ }
+ }
subreq = tevent_queue_wait_send(state, ev, child->queue);
if (tevent_req_nomem(subreq, req)) {
@@ -330,6 +355,7 @@ static void wb_child_request_cleanup(struct tevent_req *req,
subreq = talloc_move(state->child->queue, &state->subreq);
talloc_move(subreq, &state->queue_subreq);
+ talloc_move(subreq, &state->request);
tevent_req_set_callback(subreq,
wb_child_request_orphaned,
state->child);