s3: Avoid a race with the async echo handler
authorVolker Lendecke <vl@samba.org>
Thu, 10 Nov 2011 08:39:23 +0000 (09:39 +0100)
committerVolker Lendecke <vl@samba.org>
Thu, 10 Nov 2011 16:18:53 +0000 (17:18 +0100)
We can not read from the echo handler socket when we have the main socket
locked. This leads to the echo responder to lock up sitting in the fcntl lock
while the parent wants to read the remainder of a large packet.

source3/smbd/process.c

index 0ad554228b231e59fa7c5e242da2ba4ab3738de2..82dd51048e4bf02a9e5d48edb2e57124c96cd595 100644 (file)
@@ -2217,46 +2217,41 @@ static void smbd_server_connection_read_handler(
        NTSTATUS status;
        uint32_t seqnum;
 
-       bool from_client = (sconn->sock == fd);
+       bool from_client;
+
+       if (lp_async_smb_echo_handler()
+           && fd_is_readable(sconn->smb1.echo_handler.trusted_fd)) {
+               /*
+                * This is the super-ugly hack to prefer the packets
+                * forwarded by the echo handler over the ones by the
+                * client directly
+                */
+               fd = sconn->smb1.echo_handler.trusted_fd;
+       }
+
+       from_client = (sconn->sock == fd);
 
        if (from_client) {
                smbd_lock_socket(sconn);
 
-               if (lp_async_smb_echo_handler()) {
-
-                       if (fd_is_readable(sconn->smb1.echo_handler.trusted_fd)) {
-                               /*
-                                * This is the super-ugly hack to
-                                * prefer the packets forwarded by the
-                                * echo handler over the ones by the
-                                * client directly
-                                */
-                               fd = sconn->smb1.echo_handler.trusted_fd;
-                       } else if (!fd_is_readable(fd)) {
-                               DEBUG(10,("the echo listener was faster\n"));
-                               smbd_unlock_socket(sconn);
-                               return;
-                       }
+               if (!fd_is_readable(fd)) {
+                       DEBUG(10,("the echo listener was faster\n"));
+                       smbd_unlock_socket(sconn);
+                       return;
                }
+       }
+
+       /* TODO: make this completely nonblocking */
+       status = receive_smb_talloc(mem_ctx, sconn, fd,
+                                   (char **)(void *)&inbuf,
+                                   0, /* timeout */
+                                   &unread_bytes,
+                                   &encrypted,
+                                   &inbuf_len, &seqnum,
+                                   false /* trusted channel */);
 
-               /* TODO: make this completely nonblocking */
-               status = receive_smb_talloc(mem_ctx, sconn, fd,
-                                           (char **)(void *)&inbuf,
-                                           0, /* timeout */
-                                           &unread_bytes,
-                                           &encrypted,
-                                           &inbuf_len, &seqnum,
-                                           false /* trusted channel */);
+       if (from_client) {
                smbd_unlock_socket(sconn);
-       } else {
-               /* TODO: make this completely nonblocking */
-               status = receive_smb_talloc(mem_ctx, sconn, fd,
-                                           (char **)(void *)&inbuf,
-                                           0, /* timeout */
-                                           &unread_bytes,
-                                           &encrypted,
-                                           &inbuf_len, &seqnum,
-                                           true /* trusted channel */);
        }
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {