diff options
author | Ondrej Holy <oholy@redhat.com> | 2017-01-04 10:33:23 +0100 |
---|---|---|
committer | Ondrej Holy <oholy@redhat.com> | 2017-01-16 15:53:10 +0100 |
commit | 1482097a0dd8aecd93958aab5fc601568b4cfa3b (patch) | |
tree | cf25cfc9ff3121518504e38491d31681dbb8a3aa | |
parent | 7a8cf1243d479296d5d925fefd25e765c792560d (diff) | |
download | gvfs-1482097a0dd8aecd93958aab5fc601568b4cfa3b.tar.gz |
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
-rw-r--r-- | daemon/gvfsbackendsftp.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/daemon/gvfsbackendsftp.c b/daemon/gvfsbackendsftp.c index 45c0009c..6a653024 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; } |