public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/gvfs] f43: Fix CVE-2026-842{67..70}
@ 2026-09-01 23:09 Adrian Vovk
  0 siblings, 0 replies; only message in thread
From: Adrian Vovk @ 2026-09-01 23:09 UTC (permalink / raw)
  To: git-commits

A new commit has been pushed.

Repo   : rpms/gvfs
Branch : f43
Commit : 7be53a6f52bb35b4086f8bdaa37d480848236e94
Author : Adrian Vovk <avovk@redhat.com>
Date   : 2026-09-01T19:05:57-04:00
Stats  : +630/-0 in 5 file(s)
URL    : https://src.fedoraproject.org/rpms/gvfs/c/7be53a6f52bb35b4086f8bdaa37d480848236e94?branch=f43

Log:
Fix CVE-2026-842{67..70}

---
diff --git a/CVE-2026-84267.patch b/CVE-2026-84267.patch
new file mode 100644
index 0000000..27d5e34
--- /dev/null
+++ b/CVE-2026-84267.patch
@@ -0,0 +1,100 @@
+From 015bf91450370a0717b91742feeb8f22e8b0243e Mon Sep 17 00:00:00 2001
+From: Ondrej Holy <oholy@redhat.com>
+Date: Mon, 27 Jul 2026 12:42:57 +0200
+Subject: [PATCH] sftp: Validate that reads fully complete before using data
+
+Currently, several places in the SFTP backend use `g_input_stream_read_all()`
+without checking that the requested number of bytes was actually read. A short
+read leaves parts of the allocated buffer uninitialised, which can lead to
+use of invalid data. Let's verify that `bytes_read` matches the expected length
+and treat short reads as protocol errors.
+
+Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/861
+
+Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
+---
+ daemon/gvfsbackendsftp.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/daemon/gvfsbackendsftp.c b/daemon/gvfsbackendsftp.c
+index c7e738ae..c834d9af 100644
+--- a/daemon/gvfsbackendsftp.c
++++ b/daemon/gvfsbackendsftp.c
+@@ -741,8 +741,11 @@ read_reply_sync (Connection *conn, gsize *len_out, GError **error)
+ 
+   if (!g_input_stream_read_all (conn->reply_stream,
+ 				array->data, len,
+-				&bytes_read, NULL, error))
++				&bytes_read, NULL, NULL) ||
++      bytes_read != len)
+     {
++      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++                           _("Invalid reply received"));
+       g_byte_array_free (array, TRUE);
+       return NULL;
+     }
+@@ -779,6 +782,7 @@ read_string (GDataInputStream *stream, gsize *len_out)
+   guint32 len;
+   char *data;
+   GError *error;
++  gsize bytes_read;
+ 
+   error = NULL;
+   len = g_data_input_stream_read_uint32 (stream, NULL, &error);
+@@ -790,7 +794,8 @@ read_string (GDataInputStream *stream, gsize *len_out)
+   
+   data = g_malloc (len + 1);
+ 
+-  if (!g_input_stream_read_all (G_INPUT_STREAM (stream), data, len, NULL, NULL, NULL))
++  if (!g_input_stream_read_all (G_INPUT_STREAM (stream), data, len, &bytes_read, NULL, NULL) ||
++      bytes_read != len)
+     {
+       g_free (data);
+       return NULL;
+@@ -2869,7 +2874,8 @@ read_reply (GVfsBackendSftp *backend,
+ {
+   SftpHandle *handle;
+   guint32 count;
+-  
++  gsize bytes_read;
++
+   handle = user_data;
+   
+   if (reply_type == SSH_FXP_STATUS)
+@@ -2890,13 +2896,14 @@ read_reply (GVfsBackendSftp *backend,
+ 
+   if (!g_input_stream_read_all (G_INPUT_STREAM (reply),
+                                 G_VFS_JOB_READ (job)->buffer, count,
+-                                NULL, NULL, NULL))
++                                &bytes_read, NULL, NULL) ||
++      bytes_read != count)
+     {
+       g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+                         _("Invalid reply received"));
+       return;
+     }
+-  
++
+   handle->offset += count;
+ 
+   g_vfs_job_read_set_size (G_VFS_JOB_READ (job), count);
+@@ -6649,12 +6656,15 @@ pull_read_reply (GVfsBackendSftp *backend,
+     }
+   else
+     {
++      gsize bytes_read;
++
+       request->response_len = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+       request->buffer = g_slice_alloc (request->response_len);
+ 
+       if (g_input_stream_read_all (G_INPUT_STREAM (reply),
+                                    request->buffer, request->response_len,
+-                                   NULL, NULL, NULL))
++                                   &bytes_read, NULL, NULL) &&
++          bytes_read == request->response_len)
+         {
+           handle->queued_writes = g_list_append (handle->queued_writes, request);
+           pull_try_start_write (handle);
+-- 
+GitLab
+

diff --git a/CVE-2026-84268.patch b/CVE-2026-84268.patch
new file mode 100644
index 0000000..e99fa6f
--- /dev/null
+++ b/CVE-2026-84268.patch
@@ -0,0 +1,33 @@
+From ea1322daab1979b30cf96b3e39ed6db5e45fc041 Mon Sep 17 00:00:00 2001
+From: Ondrej Holy <oholy@redhat.com>
+Date: Mon, 22 Jun 2026 16:21:54 +0200
+Subject: [PATCH] sftp: Clamp `read_reply` count to requested buffer size
+
+Currently, the `count` value from the server response is used
+as the read length without checking it against
+`bytes_requested`. A buggy server returning a larger count
+would overflow the job buffer. Let's clamp `count` to
+`bytes_requested`.
+
+Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/862
+
+Made-with: Cursor
+---
+ daemon/gvfsbackendsftp.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/daemon/gvfsbackendsftp.c b/daemon/gvfsbackendsftp.c
+index 5696cf31..cb288b9e 100644
+--- a/daemon/gvfsbackendsftp.c
++++ b/daemon/gvfsbackendsftp.c
+@@ -2862,6 +2862,7 @@ read_reply (GVfsBackendSftp *backend,
+     }
+   
+   count = g_data_input_stream_read_uint32 (reply, NULL, NULL);
++  count = MIN (count, G_VFS_JOB_READ (job)->bytes_requested);
+ 
+   if (!g_input_stream_read_all (G_INPUT_STREAM (reply),
+                                 G_VFS_JOB_READ (job)->buffer, count,
+-- 
+GitLab
+

diff --git a/CVE-2026-84269.patch b/CVE-2026-84269.patch
new file mode 100644
index 0000000..d63713c
--- /dev/null
+++ b/CVE-2026-84269.patch
@@ -0,0 +1,452 @@
+From 81525b2c917950554255784542674222bfee797d Mon Sep 17 00:00:00 2001
+From: Ondrej Holy <oholy@redhat.com>
+Date: Mon, 27 Jul 2026 15:26:42 +0200
+Subject: [PATCH] afp: Validate reply size in DSI read reply handling
+
+Currently, a DSI read reply with `totalDataLength` larger than the
+requested `ReqCount` causes a heap buffer overflow of the pre-sized
+`reply_buf`. Let's validate the reply size and return an "Invalid reply
+received" error. The oversized data is skipped from the stream to
+maintain DSI framing for subsequent operations.
+
+Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/863
+
+Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
+---
+ daemon/gvfsafpconnection.c | 167 +++++++++++++++++++++++++++++++++++--
+ daemon/gvfsafpconnection.h |   1 +
+ daemon/gvfsafpserver.c     |   4 +-
+ daemon/gvfsafpvolume.c     |  35 ++++----
+ 4 files changed, 180 insertions(+), 27 deletions(-)
+
+diff --git a/daemon/gvfsafpconnection.c b/daemon/gvfsafpconnection.c
+index a275038b..2c1e38e9 100644
+--- a/daemon/gvfsafpconnection.c
++++ b/daemon/gvfsafpconnection.c
+@@ -711,6 +711,8 @@ typedef struct
+   
+   GVfsAfpCommand *command;
+   char           *reply_buf;
++  gsize           reply_buf_size;
++  GError         *error;
+   GTask *task;
+ 
+   GVfsAfpConnection *conn;
+@@ -769,6 +771,7 @@ free_request_data (RequestData *req_data)
+ {
+   if (req_data->command)
+     g_object_unref (req_data->command);
++  g_clear_error (&req_data->error);
+   if (req_data->task)
+     g_object_unref (req_data->task);
+ 
+@@ -962,6 +965,97 @@ read_all_finish (GInputStream *stream,
+   return g_task_propagate_boolean (G_TASK (res), error);
+ }
+ 
++typedef struct
++{
++  gsize count;
++  gsize bytes_skipped;
++} SkipAllData;
++
++static void
++free_skip_all_data (SkipAllData *skip_data)
++{
++  g_slice_free (SkipAllData, skip_data);
++}
++
++static void skip_all_async (GInputStream        *stream,
++                            gsize                count,
++                            int                  io_priority,
++                            GCancellable        *cancellable,
++                            GAsyncReadyCallback  callback,
++                            gpointer             user_data);
++
++static void
++skip_all_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
++{
++  GInputStream *stream = G_INPUT_STREAM (source_object);
++  GTask *task = G_TASK (user_data);
++  gssize bytes_skipped;
++  GError *err = NULL;
++  SkipAllData *skip_data = g_task_get_task_data (task);
++
++  bytes_skipped = g_input_stream_skip_finish (stream, res, &err);
++  if (bytes_skipped == -1)
++  {
++    g_task_return_error (task, err);
++    g_object_unref (task);
++    return;
++  }
++  else if (bytes_skipped == 0)
++  {
++    g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CLOSED, _("Got EOS"));
++    g_object_unref (task);
++    return;
++  }
++
++  skip_data->bytes_skipped += bytes_skipped;
++  if (skip_data->bytes_skipped < skip_data->count)
++  {
++    g_input_stream_skip_async (stream,
++                               skip_data->count - skip_data->bytes_skipped,
++                               g_task_get_priority (task), g_task_get_cancellable (task),
++                               skip_all_cb, task);
++    return;
++  }
++
++  g_task_return_boolean (task, TRUE);
++  g_object_unref (task);
++}
++
++static void
++skip_all_async (GInputStream        *stream,
++                gsize                count,
++                int                  io_priority,
++                GCancellable        *cancellable,
++                GAsyncReadyCallback  callback,
++                gpointer             user_data)
++{
++  SkipAllData *skip_data;
++  GTask *task;
++
++  task = g_task_new (stream, cancellable, callback, user_data);
++  g_task_set_source_tag (task, skip_all_async);
++  g_task_set_priority (task, io_priority);
++
++  skip_data = g_slice_new0 (SkipAllData);
++  skip_data->count = count;
++
++  g_task_set_task_data (task, skip_data, (GDestroyNotify)free_skip_all_data);
++
++  g_input_stream_skip_async (stream, count, io_priority, cancellable,
++                             skip_all_cb, task);
++}
++
++static gboolean
++skip_all_finish (GInputStream *stream,
++                 GAsyncResult *res,
++                 GError      **error)
++{
++  g_return_val_if_fail (g_task_is_valid (res, stream), FALSE);
++  g_return_val_if_fail (g_async_result_is_tagged (res, skip_all_async), FALSE);
++
++  return g_task_propagate_boolean (G_TASK (res), error);
++}
++
+ static void
+ dispatch_reply (GVfsAfpConnection *afp_connection)
+ {
+@@ -1017,13 +1111,20 @@ dispatch_reply (GVfsAfpConnection *afp_connection)
+                                       GUINT_TO_POINTER ((guint)dsi_header->requestID));
+       if (req_data)
+       {
+-        GVfsAfpReply *reply;
++        if (req_data->error)
++        {
++          g_task_return_error (req_data->task, g_steal_pointer (&req_data->error));
++        }
++        else
++        {
++          GVfsAfpReply *reply;
+ 
+-        reply = g_vfs_afp_reply_new (dsi_header->errorCode, priv->reply_buf,
+-                                     dsi_header->totalDataLength, priv->free_reply_buf);
+-        priv->free_reply_buf = FALSE;
++          reply = g_vfs_afp_reply_new (dsi_header->errorCode, priv->reply_buf,
++                                       dsi_header->totalDataLength, priv->free_reply_buf);
++          priv->free_reply_buf = FALSE;
+ 
+-        g_task_return_pointer (req_data->task, reply, g_object_unref);
++          g_task_return_pointer (req_data->task, reply, g_object_unref);
++        }
+ 
+         g_hash_table_remove (priv->request_hash,
+                              GUINT_TO_POINTER ((guint)dsi_header->requestID));
+@@ -1036,6 +1137,43 @@ dispatch_reply (GVfsAfpConnection *afp_connection)
+   }
+ }
+     
++static void
++skip_data_cb (GObject *object, GAsyncResult *res, gpointer user_data)
++{
++  GInputStream *input = G_INPUT_STREAM (object);
++  GVfsAfpConnection *afp_connection = G_VFS_AFP_CONNECTION (user_data);
++  GVfsAfpConnectionPrivate *priv = afp_connection->priv;
++
++  gboolean result;
++  GError *err = NULL;
++
++  if (g_atomic_int_get (&priv->atomic_state) == STATE_PENDING_CLOSE)
++  {
++    if (!priv->send_loop_running)
++      close_connection (afp_connection);
++    return;
++  }
++
++  result = skip_all_finish (input, res, &err);
++  if (!result)
++  {
++    if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CLOSED) ||
++        g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
++    {
++      g_message (_("Host closed connection"));
++    }
++    else
++    {
++      g_warning ("FAIL!!! \"%s\"\n", err->message);
++    }
++    exit (0);
++  }
++
++  dispatch_reply (afp_connection);
++
++  read_reply (afp_connection);
++}
++
+ static void
+ read_data_cb (GObject *object, GAsyncResult *res, gpointer user_data)
+ {
+@@ -1124,8 +1262,19 @@ read_dsi_header_cb (GObject *object, GAsyncResult *res, gpointer user_data)
+                                     GUINT_TO_POINTER ((guint)dsi_header->requestID));
+     if (req_data && req_data->reply_buf)
+     {
+-        priv->reply_buf = req_data->reply_buf;
+-        priv->free_reply_buf = FALSE;
++      if (dsi_header->totalDataLength > req_data->reply_buf_size)
++      {
++        g_set_error (&req_data->error,
++                     G_IO_ERROR, G_IO_ERROR_FAILED,
++                     _("Invalid reply received"));
++        skip_all_async (input, dsi_header->totalDataLength, 0,
++                        priv->read_cancellable, skip_data_cb,
++                        afp_conn);
++        return;
++      }
++
++      priv->reply_buf = req_data->reply_buf;
++      priv->free_reply_buf = FALSE;
+     }
+     else
+     {
+@@ -1448,6 +1597,7 @@ void
+ g_vfs_afp_connection_send_command (GVfsAfpConnection   *afp_connection,
+                                    GVfsAfpCommand      *command,
+                                    char                *reply_buf,
++                                   gsize                reply_buf_size,
+                                    GAsyncReadyCallback  callback,
+                                    GCancellable        *cancellable,
+                                    gpointer             user_data)
+@@ -1471,6 +1621,7 @@ g_vfs_afp_connection_send_command (GVfsAfpConnection   *afp_connection,
+   req_data->type = REQUEST_TYPE_COMMAND;
+   req_data->command = g_object_ref (command);
+   req_data->reply_buf = reply_buf;
++  req_data->reply_buf_size = reply_buf_size;
+   req_data->conn = afp_connection;
+   req_data->task = task;
+ 
+@@ -1616,7 +1767,7 @@ g_vfs_afp_connection_send_command_sync (GVfsAfpConnection *afp_connection,
+ 
+   sync_data_init (&sync_data, afp_connection, NULL);
+ 
+-  g_vfs_afp_connection_send_command (afp_connection, command, NULL,
++  g_vfs_afp_connection_send_command (afp_connection, command, NULL, 0,
+                                      send_command_sync_cb, cancellable, &sync_data);
+ 
+   sync_data_wait (&sync_data);
+diff --git a/daemon/gvfsafpconnection.h b/daemon/gvfsafpconnection.h
+index df26e0a7..44d2ffa5 100644
+--- a/daemon/gvfsafpconnection.h
++++ b/daemon/gvfsafpconnection.h
+@@ -364,6 +364,7 @@ GVfsAfpReply*      g_vfs_afp_connection_send_command_finish (GVfsAfpConnection *
+ void               g_vfs_afp_connection_send_command     (GVfsAfpConnection   *afp_connection,
+                                                           GVfsAfpCommand      *command,
+                                                           char                *reply_buf,
++                                                          gsize                reply_buf_size,
+                                                           GAsyncReadyCallback  callback,
+                                                           GCancellable        *cancellable,                                                           
+                                                           gpointer             user_data);
+diff --git a/daemon/gvfsafpserver.c b/daemon/gvfsafpserver.c
+index a3ab24ca..00cdd890 100644
+--- a/daemon/gvfsafpserver.c
++++ b/daemon/gvfsafpserver.c
+@@ -1384,7 +1384,7 @@ g_vfs_afp_server_get_volumes (GVfsAfpServer       *server,
+ 
+   task = g_task_new (server, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_server_get_volumes);
+-  g_vfs_afp_connection_send_command (server->priv->conn, comm, NULL, get_volumes_cb,
++  g_vfs_afp_connection_send_command (server->priv->conn, comm, NULL, 0, get_volumes_cb,
+                                      cancellable, task);
+ }
+ 
+@@ -1778,7 +1778,7 @@ g_vfs_afp_server_map_id (GVfsAfpServer       *server,
+   g_task_set_source_tag (task, g_vfs_afp_server_map_id);
+   g_task_set_task_data (task, GINT_TO_POINTER (map_function), NULL);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0,
+                                      map_id_cb, cancellable, task);
+   g_object_unref (comm);
+ }
+diff --git a/daemon/gvfsafpvolume.c b/daemon/gvfsafpvolume.c
+index c1b3537a..34cf69fa 100644
+--- a/daemon/gvfsafpvolume.c
++++ b/daemon/gvfsafpvolume.c
+@@ -313,7 +313,7 @@ g_vfs_afp_volume_get_parms (GVfsAfpVolume       *volume,
+   task = g_task_new (volume, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_volume_get_parms);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, get_vol_parms_cb,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0, get_vol_parms_cb,
+                                      cancellable, task);
+   g_object_unref (comm);
+ }
+@@ -486,7 +486,7 @@ g_vfs_afp_volume_open_fork (GVfsAfpVolume      *volume,
+   task = g_task_new (volume, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_volume_open_fork);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0,
+                                      open_fork_cb, cancellable, task);
+   g_object_unref (comm);
+ }
+@@ -597,7 +597,7 @@ g_vfs_afp_volume_close_fork (GVfsAfpVolume       *volume,
+   task = g_task_new (volume, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_volume_close_fork);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0,
+                                      close_fork_cb, cancellable, task);
+   g_object_unref (comm);
+ }
+@@ -727,7 +727,7 @@ g_vfs_afp_volume_delete (GVfsAfpVolume       *volume,
+   task = g_task_new (volume, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_volume_delete);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0,
+                                      delete_cb, cancellable, task);
+   g_object_unref (comm);
+ }
+@@ -871,7 +871,7 @@ create_file_get_filedir_parms_cb (GObject *source_object, GAsyncResult *res, gpo
+   g_vfs_afp_command_put_pathname (comm, basename);
+   g_free (basename);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, create_file_cb,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0, create_file_cb,
+                                      g_task_get_cancellable (task), task);
+   g_object_unref (comm);
+ }
+@@ -1050,7 +1050,7 @@ create_directory_get_filedir_parms_cb (GObject *source_object, GAsyncResult *res
+   /* Pathname */
+   g_vfs_afp_command_put_pathname (comm, cdd->basename);
+   
+-  g_vfs_afp_connection_send_command (volume->priv->conn, comm, NULL, make_directory_cb,
++  g_vfs_afp_connection_send_command (volume->priv->conn, comm, NULL, 0, make_directory_cb,
+                                      g_task_get_cancellable (task), task);
+   g_object_unref (comm);
+ }
+@@ -1240,7 +1240,7 @@ rename_get_filedir_parms_cb (GObject      *source_object,
+   /* NewName */
+   g_vfs_afp_command_put_pathname (comm, rd->new_name);
+ 
+-  g_vfs_afp_connection_send_command (volume->priv->conn, comm, NULL, rename_cb,
++  g_vfs_afp_connection_send_command (volume->priv->conn, comm, NULL, 0, rename_cb,
+                                      g_task_get_cancellable (task), task);
+   g_object_unref (comm);
+ }
+@@ -1433,7 +1433,7 @@ g_vfs_afp_volume_move_and_rename (GVfsAfpVolume      *volume,
+   task = g_task_new (volume, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_volume_move_and_rename);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0,
+                                      move_and_rename_cb, cancellable, task);
+   g_object_unref (comm);
+ }
+@@ -1588,7 +1588,7 @@ g_vfs_afp_volume_copy_file (GVfsAfpVolume      *volume,
+   task = g_task_new (volume, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_volume_copy_file);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0,
+                                      copy_file_cb, cancellable, task);
+   g_object_unref (comm);
+ }
+@@ -1735,7 +1735,7 @@ g_vfs_afp_volume_get_filedir_parms (GVfsAfpVolume       *volume,
+   task = g_task_new (volume, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_volume_get_filedir_parms);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0,
+                                      get_filedir_parms_cb, cancellable,
+                                      task);
+   g_object_unref (comm);
+@@ -1855,7 +1855,7 @@ g_vfs_afp_volume_get_fork_parms (GVfsAfpVolume       *volume,
+   task = g_task_new (volume, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_volume_get_fork_parms);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0,
+                                      get_fork_parms_cb, cancellable,
+                                      task);
+   g_object_unref (comm);
+@@ -1978,7 +1978,7 @@ g_vfs_afp_volume_set_fork_size (GVfsAfpVolume       *volume,
+   task = g_task_new (volume, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_volume_set_fork_size);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0,
+                                      set_fork_parms_cb, cancellable, task);
+   g_object_unref (comm);
+ }
+@@ -2117,7 +2117,7 @@ g_vfs_afp_volume_set_unix_privs (GVfsAfpVolume       *volume,
+   task = g_task_new (volume, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_volume_set_unix_privs);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0,
+                                      set_unix_privs_cb, cancellable, task);
+   g_object_unref (comm);
+ }
+@@ -2336,7 +2336,7 @@ g_vfs_afp_volume_enumerate (GVfsAfpVolume       *volume,
+   /* Pathname */
+   g_vfs_afp_command_put_pathname (comm, directory);
+   
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0,
+                                      enumerate_cb, cancellable, task);
+   g_object_unref (comm);
+ }
+@@ -2471,7 +2471,7 @@ g_vfs_afp_volume_exchange_files (GVfsAfpVolume       *volume,
+   task = g_task_new (volume, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_volume_exchange_files);
+ 
+-  g_vfs_afp_connection_send_command (priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (priv->conn, comm, NULL, 0,
+                                      close_replace_exchange_files_cb,
+                                      cancellable, task);
+   g_object_unref (comm);
+@@ -2604,7 +2604,7 @@ g_vfs_afp_volume_write_to_fork (GVfsAfpVolume       *volume,
+   task = g_task_new (volume, cancellable, callback, user_data);
+   g_task_set_source_tag (task, g_vfs_afp_volume_write_to_fork);
+ 
+-  g_vfs_afp_connection_send_command (volume->priv->conn, comm, NULL,
++  g_vfs_afp_connection_send_command (volume->priv->conn, comm, NULL, 0,
+                                      write_ext_cb, cancellable, task);
+   g_object_unref (comm);
+ }
+@@ -2730,7 +2730,8 @@ g_vfs_afp_volume_read_from_fork (GVfsAfpVolume       *volume,
+   g_task_set_source_tag (task, g_vfs_afp_volume_read_from_fork);
+ 
+   g_vfs_afp_connection_send_command (volume->priv->conn, comm, buffer,
+-                                     read_ext_cb, cancellable, task);
++                                     req_count, read_ext_cb, cancellable,
++                                     task);
+   g_object_unref (comm);
+ }
+ 
+-- 
+GitLab
+

diff --git a/CVE-2026-84270.patch b/CVE-2026-84270.patch
new file mode 100644
index 0000000..aa207a0
--- /dev/null
+++ b/CVE-2026-84270.patch
@@ -0,0 +1,40 @@
+From 25add8b5103384c7edc8ad74722ed93eb3f6f077 Mon Sep 17 00:00:00 2001
+From: Ondrej Holy <oholy@redhat.com>
+Date: Mon, 27 Jul 2026 15:38:21 +0200
+Subject: [PATCH] mtp: Validate read size returned by device
+
+Currently, `do_read` copies `actual` bytes from the device response
+into `buffer` without checking that `actual` does not exceed
+`bytes_requested`. If the device returns more data than requested,
+this causes a heap buffer overflow. Let's validate the size and
+return an "Invalid reply received" error instead.
+
+Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/864
+
+Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
+---
+ daemon/gvfsbackendmtp.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/daemon/gvfsbackendmtp.c b/daemon/gvfsbackendmtp.c
+index 9a8ac502..f2a26adf 100644
+--- a/daemon/gvfsbackendmtp.c
++++ b/daemon/gvfsbackendmtp.c
+@@ -2575,6 +2575,14 @@ do_read (GVfsBackend *backend,
+       goto exit;
+     }
+ 
++    if (actual > bytes_requested) {
++      free (temp);
++      g_vfs_job_failed_literal (G_VFS_JOB (job),
++                                G_IO_ERROR, G_IO_ERROR_FAILED,
++                                _("Invalid reply received"));
++      goto exit;
++    }
++
+     memcpy (buffer, temp, actual);
+     free (temp);
+   } else {
+-- 
+GitLab
+

diff --git a/gvfs.spec b/gvfs.spec
index 4f0e8ea..8c6d29f 100644
--- a/gvfs.spec
+++ b/gvfs.spec
@@ -30,6 +30,11 @@ License: LGPL-2.0-or-later AND GPL-3.0-only AND MPL-2.0 AND BSD-3-Clause-Sun
 URL:     https://wiki.gnome.org/Projects/gvfs
 Source0: https://download.gnome.org/sources/gvfs/1.58/gvfs-%{version}.tar.xz
 
+Patch0: CVE-2026-84268.patch
+Patch1: CVE-2026-84270.patch
+Patch2: CVE-2026-84269.patch
+Patch3: CVE-2026-84267.patch
+
 BuildRequires: meson
 BuildRequires: gcc
 BuildRequires: pkgconfig(glib-2.0) >= %{glib2_version}

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-01 23:09 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-01 23:09 [rpms/gvfs] f43: Fix CVE-2026-842{67..70} Adrian Vovk

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox