Fix a crash bug found by Ira Cooper <samba@ira.wakeful.net>.
authorJeremy Allison <jra@samba.org>
Wed, 2 Jun 2010 23:43:31 +0000 (16:43 -0700)
committerJeremy Allison <jra@samba.org>
Wed, 2 Jun 2010 23:43:31 +0000 (16:43 -0700)
A create call comes in, goes async (on the oplock request).
At a later time (just before a cancel request is received)
it completes, and goes through smbd_smb2_request_reply() to
send the reply to the create call.

However, the output socket queue is full, so when
tstream_writev_queue_send() is called from smbd_smb2_request_reply(),
the smb2req stays on the "being processed" queue on
sconn->smb2.requests, as only when tstream_writev_queue_send() completes
is smbd_smb2_request_writev_done() get called, which will TALLOC_FREE
the smb2req (and thus take if off the queue).

The cancel comes in, gets processed and looks through the
requests on the queue, and BANG - hits the smb2req that
has already been processed and is outgoing....

Remove the request from the queue once
tstream_writev_queue_send() is called and not in the talloc
destructor function.

Jeremy.

source3/smbd/smb2_server.c

index b081b6a25769e3d99baafa182224258ded4c014c..7a2a32a9dce1078e505a44cea27f2a70bf858d1b 100644 (file)
@@ -156,10 +156,6 @@ static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
 
 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
 {
-       if (req->out.vector) {
-               DLIST_REMOVE(req->sconn->smb2.requests, req);
-       }
-
        if (req->parent) {
                *req->parent = NULL;
                talloc_free(req->mem_pool);
@@ -1245,6 +1241,11 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
                return NT_STATUS_NO_MEMORY;
        }
        tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
+       /*
+        * We're done with this request -
+        * move it off the "being processed" queue.
+        */
+       DLIST_REMOVE(req->sconn->smb2.requests, req);
 
        return NT_STATUS_OK;
 }