]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3: smbd: Make sure we correctly reply to outstanding aio requests with an error...
authorJeremy Allison <jra@samba.org>
Mon, 2 Mar 2020 21:11:06 +0000 (13:11 -0800)
committerJeremy Allison <jra@samba.org>
Sun, 8 Mar 2020 18:07:44 +0000 (18:07 +0000)
SHUTDOWN_CLOSE can be called when smbcontrol close-share
is used to terminate active connections.

Previously we just called talloc_free()
on the outstanding request, but this
caused crashes (before the async callback
functions were fixed not to reference req
directly) and also leaves the SMB2 request
outstanding on the processing queue.

Using tevent_req_error() instead
causes the outstanding SMB1/2/3 request to
return with NT_STATUS_INVALID_HANDLE
and removes it from the processing queue.

The callback function called from this
calls talloc_free(req). The destructor will remove
itself from the fsp and the aio_requests array.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14301

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
source3/smbd/close.c

index f45371e656c70887c51caf3a32dd5be4fb574b03..c7be0c8d4471c52817634a79e3e7850cf305c747 100644 (file)
@@ -652,6 +652,7 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
        bool is_durable = false;
 
        if (fsp->num_aio_requests != 0) {
+               unsigned num_requests = fsp->num_aio_requests;
 
                if (close_type != SHUTDOWN_CLOSE) {
                        /*
@@ -681,13 +682,30 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
 
                while (fsp->num_aio_requests != 0) {
                        /*
-                        * The destructor of the req will remove
-                        * itself from the fsp.
-                        * Don't use TALLOC_FREE here, this will overwrite
-                        * what the destructor just wrote into
-                        * aio_requests[0].
+                        * Previously we just called talloc_free()
+                        * on the outstanding request, but this
+                        * caused crashes (before the async callback
+                        * functions were fixed not to reference req
+                        * directly) and also leaves the SMB2 request
+                        * outstanding on the processing queue.
+                        *
+                        * Using tevent_req_error() instead
+                        * causes the outstanding SMB1/2/3 request to
+                        * return with NT_STATUS_INVALID_HANDLE
+                        * and removes it from the processing queue.
+                        *
+                        * The callback function called from this
+                        * calls talloc_free(req). The destructor will remove
+                        * itself from the fsp and the aio_requests array.
                         */
-                       talloc_free(fsp->aio_requests[0]);
+                       tevent_req_error(fsp->aio_requests[0], EBADF);
+
+                       /* Paranoia to ensure we don't spin. */
+                       num_requests--;
+                       if (fsp->num_aio_requests != num_requests) {
+                               smb_panic("cannot cancel outstanding aio "
+                                       "requests");
+                       }
                }
        }