File gvfs-CVE-2026-28295.patch of Package gvfs.43109
commit 20db8173252ea88a4af05dc9a24aad6f29b807ad
Author: Ondrej Holy <oholy@redhat.com>
Date: Thu Feb 19 15:45:53 2026 +0100
ftp: Use control connection address for PASV data
Currently, `PASV` uses the IP from the server reply when creating data
connection. This may allow FTP bounce attacks. Let's always use only the
port from the PASV reply and connect to the control connection address.
Co-Authored-By: Cursor <cursoragent@cursor.com>
Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/832
Part-of: <https://gitlab.gnome.org/GNOME/gvfs/-/merge_requests/298>
--- a/daemon/gvfsbackendftp.c
+++ b/daemon/gvfsbackendftp.c
@@ -63,9 +63,8 @@
* GVfsFtpMethod:
* @G_VFS_FTP_METHOD_UNKNOWN: method has not yet been determined
* @G_VFS_FTP_METHOD_EPSV: use EPSV command
- * @G_VFS_FTP_METHOD_PASV: use PASV command
- * @G_VFS_FTP_METHOD_PASV_ADDR: use PASV command, but ignore the returned
- * address and only use it's port
+ * @G_VFS_FTP_METHOD_PASV: use PASV command, but ignore the returned address
+ * and only use it's port (bounce attack prevention)
* @G_VFS_FTP_METHOD_EPRT: use the EPRT command
* @G_VFS_FTP_METHOD_PORT: use the PORT command
*
--- a/daemon/gvfsbackendftp.h
+++ b/daemon/gvfsbackendftp.h
@@ -61,7 +61,6 @@ typedef enum {
G_VFS_FTP_METHOD_ANY = 0,
G_VFS_FTP_METHOD_EPSV,
G_VFS_FTP_METHOD_PASV,
- G_VFS_FTP_METHOD_PASV_ADDR,
G_VFS_FTP_METHOD_EPRT,
G_VFS_FTP_METHOD_PORT
} GVfsFtpMethod;
--- a/daemon/gvfsftptask.c
+++ b/daemon/gvfsftptask.c
@@ -850,7 +850,7 @@ fail:
static GVfsFtpMethod
g_vfs_ftp_task_setup_data_connection_pasv (GVfsFtpTask *task, GVfsFtpMethod method)
{
- guint ip1, ip2, ip3, ip4, port1, port2;
+ guint port1, port2;
char **reply;
const char *s;
GSocketAddress *addr;
@@ -866,10 +866,8 @@ g_vfs_ftp_task_setup_data_connection_pas
*/
for (s = reply[0]; *s; s++)
{
- if (sscanf (s, "%u,%u,%u,%u,%u,%u",
- &ip1, &ip2, &ip3, &ip4,
- &port1, &port2) == 6)
- break;
+ if (sscanf (s, "%*u,%*u,%*u,%*u,%u,%u", &port1, &port2) == 2)
+ break;
}
if (*s == 0)
{
@@ -880,52 +878,16 @@ g_vfs_ftp_task_setup_data_connection_pas
}
g_strfreev (reply);
- if (method == G_VFS_FTP_METHOD_PASV || method == G_VFS_FTP_METHOD_ANY)
- {
- guint8 ip[4];
- GInetAddress *inet_addr;
-
- ip[0] = ip1;
- ip[1] = ip2;
- ip[2] = ip3;
- ip[3] = ip4;
- inet_addr = g_inet_address_new_from_bytes (ip, G_SOCKET_FAMILY_IPV4);
- addr = g_inet_socket_address_new (inet_addr, port1 << 8 | port2);
- g_object_unref (inet_addr);
-
- success = g_vfs_ftp_connection_open_data_connection (task->conn,
- addr,
- task->cancellable,
- &task->error);
- g_object_unref (addr);
- if (success)
- return G_VFS_FTP_METHOD_PASV;
- if (g_vfs_ftp_task_is_in_error (task) && method != G_VFS_FTP_METHOD_ANY)
- return G_VFS_FTP_METHOD_ANY;
-
- g_vfs_ftp_task_clear_error (task);
- }
-
- if (method == G_VFS_FTP_METHOD_PASV_ADDR || method == G_VFS_FTP_METHOD_ANY)
- {
- /* Workaround code:
- * Various ftp servers aren't setup correctly when behind a NAT. They report
- * their own IP address (like 10.0.0.4) and not the address in front of the
- * NAT. But this is likely the same address that we connected to with our
- * command connetion. So if the address given by PASV fails, we fall back
- * to the address of the command stream.
- */
- addr = g_vfs_ftp_task_create_remote_address (task, port1 << 8 | port2);
- if (addr == NULL)
- return G_VFS_FTP_METHOD_ANY;
- success = g_vfs_ftp_connection_open_data_connection (task->conn,
- addr,
- task->cancellable,
- &task->error);
- g_object_unref (addr);
- if (success)
- return G_VFS_FTP_METHOD_PASV_ADDR;
- }
+ addr = g_vfs_ftp_task_create_remote_address (task, port1 << 8 | port2);
+ if (addr == NULL)
+ return G_VFS_FTP_METHOD_ANY;
+ success = g_vfs_ftp_connection_open_data_connection (task->conn,
+ addr,
+ task->cancellable,
+ &task->error);
+ g_object_unref (addr);
+ if (success)
+ return G_VFS_FTP_METHOD_PASV;
return G_VFS_FTP_METHOD_ANY;
}
@@ -1121,7 +1083,6 @@ g_vfs_ftp_task_setup_data_connection (GV
[G_VFS_FTP_METHOD_ANY] = g_vfs_ftp_task_setup_data_connection_any,
[G_VFS_FTP_METHOD_EPSV] = g_vfs_ftp_task_setup_data_connection_epsv,
[G_VFS_FTP_METHOD_PASV] = g_vfs_ftp_task_setup_data_connection_pasv,
- [G_VFS_FTP_METHOD_PASV_ADDR] = g_vfs_ftp_task_setup_data_connection_pasv,
[G_VFS_FTP_METHOD_EPRT] = g_vfs_ftp_task_setup_data_connection_eprt,
[G_VFS_FTP_METHOD_PORT] = g_vfs_ftp_task_setup_data_connection_port
};
@@ -1152,7 +1113,6 @@ g_vfs_ftp_task_setup_data_connection (GV
[G_VFS_FTP_METHOD_ANY] = "any",
[G_VFS_FTP_METHOD_EPSV] = "EPSV",
[G_VFS_FTP_METHOD_PASV] = "PASV",
- [G_VFS_FTP_METHOD_PASV_ADDR] = "PASV with workaround",
[G_VFS_FTP_METHOD_EPRT] = "EPRT",
[G_VFS_FTP_METHOD_PORT] = "PORT"
};