summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Holy <oholy@redhat.com>2017-01-04 10:33:23 +0100
committerOndrej Holy <oholy@redhat.com>2017-01-16 16:06:48 +0100
commit7b12e8a3cede090043eff78238095d89257daa75 (patch)
treedd772c9a118570ff8dea899cd3d641db7ea50305
parent560cf509ab554ee9d15985e71a090f7d8eccdf37 (diff)
downloadgvfs-7b12e8a3cede090043eff78238095d89257daa75.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.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/daemon/gvfsbackendsftp.c b/daemon/gvfsbackendsftp.c
index 2788646b..78dce928 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 {
@@ -3903,7 +3911,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
@@ -3921,16 +3929,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,
@@ -3938,7 +3949,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;
}