[gvfs] sftp: Limit writes to 32768 bytes



commit 1482097a0dd8aecd93958aab5fc601568b4cfa3b
Author: Ondrej Holy <oholy redhat com>
Date:   Wed Jan 4 10:33:23 2017 +0100

    sftp: Limit writes to 32768 bytes
    
    Write buffer is not limited in the backend and thus it might happen
    that it tries to send data, which are too length. Unfortunatelly, in
    that case the underlying SSH process may exit with "The connection is
    closed (the underlying SSH process exited)" error and the backend is
    force unmounted consequently.
    
    It seems that there isn't any way to determine maximal allowed buffer
    size for the server. The draft-ietf-secsh-filexfer-02.txt just says:
    
    All servers SHOULD support packets of at least 34000 bytes (where the
    packet size refers to the full length, including the header above).
    This should allow for reads and writes of at most 32768 bytes.
    
    Thus the maximal buffer size has to be limited to 32768. It will
    probably cause some slowdown, but better than force unmount.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=776824

 daemon/gvfsbackendsftp.c |   19 +++++++++++++++----
 1 files changed, 15 insertions(+), 4 deletions(-)
---
diff --git a/daemon/gvfsbackendsftp.c b/daemon/gvfsbackendsftp.c
index 45c0009..6a65302 100644
--- a/daemon/gvfsbackendsftp.c
+++ b/daemon/gvfsbackendsftp.c
@@ -84,6 +84,14 @@
 
 #define SFTP_READ_TIMEOUT 40   /* seconds */
 
+/*
+ * All servers SHOULD support packets of at least 34000 bytes (where the packet
+ * size refers to the full length, including the header above). This should
+ * allow for reads and writes of at most 32768 bytes. For more details, see
+ * draft-ietf-secsh-filexfer-02.txt.
+ */
+#define MAX_BUFFER_SIZE 32768
+
 static GQuark id_q;
 
 typedef enum {
@@ -3928,7 +3936,7 @@ write_reply (GVfsBackendSftp *backend,
     {
       if (result_from_status (job, reply, -1, -1))
         {
-          handle->offset += G_VFS_JOB_WRITE (job)->data_size;
+          handle->offset += G_VFS_JOB_WRITE (job)->written_size;
         }
     }
   else
@@ -3946,16 +3954,19 @@ try_write (GVfsBackend *backend,
   SftpHandle *handle = _handle;
   GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
   GDataOutputStream *command;
+  gsize size;
+
+  size = MIN (buffer_size, MAX_BUFFER_SIZE);
 
   command = new_command_stream (op_backend,
                                 SSH_FXP_WRITE);
   put_data_buffer (command, handle->raw_handle);
   g_data_output_stream_put_uint64 (command, handle->offset, NULL, NULL);
-  g_data_output_stream_put_uint32 (command, buffer_size, NULL, NULL);
+  g_data_output_stream_put_uint32 (command, size, NULL, NULL);
   /* Ideally we shouldn't do this copy, but doing the writes as multiple writes
      caused problems on the read side in openssh */
   g_output_stream_write_all (G_OUTPUT_STREAM (command),
-                             buffer, buffer_size,
+                             buffer, size,
                              NULL, NULL, NULL);
   
   queue_command_stream_and_free (&op_backend->command_connection, command,
@@ -3963,7 +3974,7 @@ try_write (GVfsBackend *backend,
                                  G_VFS_JOB (job), handle);
 
   /* We always write the full size (on success) */
-  g_vfs_job_write_set_written_size (job, buffer_size);
+  g_vfs_job_write_set_written_size (job, size);
 
   return TRUE;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]