Fix threadsafety of closing channels

Fix d-bus messages leaks
Fix /dev symlink checks in gdu volume monitor
This commit is contained in:
Tomas Bzatek 2011-04-18 16:09:46 +02:00
parent 9486d00117
commit 38e3ea2e55
4 changed files with 220 additions and 125 deletions

View File

@ -1,124 +0,0 @@
From 089ba0b1af08f8b7506bd867a415e197f4017ec0 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Thu, 28 Oct 2010 16:25:12 +0000
Subject: Use correct "usb:" address for GPhoto mounts with gudev
gphoto2 expects the usb:X,X addresses to use the dirname and device
names from libusb, which are zero-padded. Given that it's what udev
gives us, just don't transform it to an int before printing.
https://bugzilla.gnome.org/show_bug.cgi?id=631562
---
diff --git a/monitor/gphoto2/ggphoto2volumemonitor.c b/monitor/gphoto2/ggphoto2volumemonitor.c
index 9fefc5d..25affe3 100644
--- a/monitor/gphoto2/ggphoto2volumemonitor.c
+++ b/monitor/gphoto2/ggphoto2volumemonitor.c
@@ -83,7 +83,7 @@ static void update_cameras (GGPhoto2VolumeMonitor *monitor,
GList **removed_volumes);
#endif
-static GList* get_stores_for_camera (int bus_num, int device_num);
+static GList* get_stores_for_camera (const char *bus_num, const char *device_num);
G_DEFINE_TYPE (GGPhoto2VolumeMonitor, g_gphoto2_volume_monitor, G_TYPE_VOLUME_MONITOR)
@@ -195,9 +195,7 @@ gudev_add_camera (GGPhoto2VolumeMonitor *monitor, GUdevDevice *device, gboolean
GGPhoto2Volume *volume;
GList *store_heads, *l;
guint num_store_heads;
- const char *property;
- int usb_bus_num;
- int usb_device_num;
+ const char *usb_bus_num, *usb_device_num;
/* For iPhones and iPod Touches, don't mount gphoto mounts,
* we already have access through AFC */
@@ -209,19 +207,17 @@ gudev_add_camera (GGPhoto2VolumeMonitor *monitor, GUdevDevice *device, gboolean
}
#endif /* HAVE_AFC */
- property = g_udev_device_get_property (device, "BUSNUM");
- if (property == NULL) {
+ usb_bus_num = g_udev_device_get_property (device, "BUSNUM");
+ if (usb_bus_num == NULL) {
g_warning("device %s has no BUSNUM property, ignoring", g_udev_device_get_device_file (device));
return;
}
- usb_bus_num = atoi (property);
- property = g_udev_device_get_property (device, "DEVNUM");
- if (property == NULL) {
+ usb_device_num = g_udev_device_get_property (device, "DEVNUM");
+ if (usb_device_num == NULL) {
g_warning("device %s has no DEVNUM property, ignoring", g_udev_device_get_device_file (device));
return;
}
- usb_device_num = atoi (property);
/* g_debug ("gudev_add_camera: camera device %s (bus: %i, device: %i)",
g_udev_device_get_device_file (device),
@@ -241,11 +237,11 @@ gudev_add_camera (GGPhoto2VolumeMonitor *monitor, GUdevDevice *device, gboolean
*/
if (num_store_heads == 1)
{
- uri = g_strdup_printf ("gphoto2://[usb:%03d,%03d]", usb_bus_num, usb_device_num);
+ uri = g_strdup_printf ("gphoto2://[usb:%s,%s]", usb_bus_num, usb_device_num);
}
else
{
- uri = g_strdup_printf ("gphoto2://[usb:%03d,%03d]/%s", usb_bus_num, usb_device_num,
+ uri = g_strdup_printf ("gphoto2://[usb:%s,%s]/%s", usb_bus_num, usb_device_num,
store_path[0] == '/' ? store_path + 1 : store_path);
}
/* g_debug ("gudev_add_camera: ... adding URI for storage head: %s", uri); */
@@ -608,7 +604,7 @@ update_all (GGPhoto2VolumeMonitor *monitor,
#endif
static GList *
-get_stores_for_camera (int bus_num, int device_num)
+get_stores_for_camera (const char *bus_num, const char *device_num)
{
GList *l;
CameraStorageInformation *storage_info;
@@ -624,7 +620,7 @@ get_stores_for_camera (int bus_num, int device_num)
camera = NULL;
context = NULL;
l = NULL;
- port = g_strdup_printf ("usb:%d,%d", bus_num, device_num);
+ port = g_strdup_printf ("usb:%s,%s", bus_num, device_num);
/* Connect to the camera */
context = gp_context_new ();
@@ -686,6 +682,21 @@ out:
}
#ifndef HAVE_GUDEV
+static GList *
+get_stores_for_camera_int (int bus_num, int device_num)
+{
+ GList *ret;
+ char *bus_num_str, *device_num_str;
+
+ bus_num_str = g_strdup_printf ("%d", bus_num);
+ device_num_str = g_strdup_printf ("%d", device_num);
+ ret = get_stores_for_camera (bus_num_str, device_num_str);
+ g_free (bus_num_str);
+ g_free (device_num_str);
+
+ return ret;
+}
+
static void
update_cameras (GGPhoto2VolumeMonitor *monitor,
GList **added_volumes,
@@ -781,7 +792,7 @@ update_cameras (GGPhoto2VolumeMonitor *monitor,
# error "Need OS specific tweaks"
#endif
- store_heads = get_stores_for_camera (usb_bus_num, usb_device_num);
+ store_heads = get_stores_for_camera_int (usb_bus_num, usb_device_num);
num_store_heads = g_list_length (store_heads);
for (l = store_heads ; l != NULL; l = l->next)
{
--
cgit v0.8.3.1

View File

@ -0,0 +1,23 @@
From 9bfe6ccdf1143c9f5409d17908f40c7544ceb119 Mon Sep 17 00:00:00 2001
From: Alexander Larsson <alexl@redhat.com>
Date: Fri, 15 Apr 2011 12:49:25 +0000
Subject: gdu volume monitor: Fix check for symlinks in /dev, was reversed
Spotted by Emilio Pozuelo Monfort in
https://bugzilla.gnome.org/show_bug.cgi?id=601497
---
diff --git a/monitor/gdu/ggduvolumemonitor.c b/monitor/gdu/ggduvolumemonitor.c
index 794d354..1066f4f 100644
--- a/monitor/gdu/ggduvolumemonitor.c
+++ b/monitor/gdu/ggduvolumemonitor.c
@@ -1427,7 +1427,7 @@ update_fstab_volumes (GGduVolumeMonitor *monitor,
GduDevice *device;
/* doesn't exist */
- if (realpath (device_file, resolved_path) != NULL)
+ if (realpath (device_file, resolved_path) == NULL)
continue;
/* is handled by DKD */
--
cgit v0.9

View File

@ -0,0 +1,183 @@
From 0babec2c24287a8578be488dacb0428998aa5648 Mon Sep 17 00:00:00 2001
From: Alexander Larsson <alexl@redhat.com>
Date: Fri, 15 Apr 2011 10:14:46 +0000
Subject: Fix threadsafety of closing channels
There is a race in g_vfs_job_close_read_finalize vs command_read_cb
where if these run in different threads (the command_read_cb in the main
thread and the close in another thread), such as in the smb case then
we may free the channel early.
We fix this by having the command reading propely ref the channel and
add a cancellable that allows us to cancel the command reading when the
channel is closed.
---
diff --git a/daemon/gvfschannel.c b/daemon/gvfschannel.c
index efe2376..f746f55 100644
--- a/daemon/gvfschannel.c
+++ b/daemon/gvfschannel.c
@@ -61,6 +61,7 @@ typedef struct
{
GVfsChannel *channel;
GInputStream *command_stream;
+ GCancellable *cancellable;
char buffer[G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE];
int buffer_size;
char *data;
@@ -84,6 +85,7 @@ struct _GVfsChannelPrivate
GVfsBackend *backend;
gboolean connection_closed;
GInputStream *command_stream;
+ GCancellable *cancellable;
GOutputStream *reply_stream;
int remote_fd;
GPid actual_consumer;
@@ -94,8 +96,6 @@ struct _GVfsChannelPrivate
GList *queued_requests;
- RequestReader *request_reader;
-
char reply_buffer[G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE];
int reply_buffer_pos;
@@ -130,13 +130,13 @@ g_vfs_channel_finalize (GObject *object)
g_object_unref (channel->priv->reply_stream);
channel->priv->reply_stream = NULL;
- if (channel->priv->request_reader)
- channel->priv->request_reader->channel = NULL;
- channel->priv->request_reader = NULL;
-
if (channel->priv->command_stream)
g_object_unref (channel->priv->command_stream);
channel->priv->command_stream = NULL;
+
+ if (channel->priv->cancellable)
+ g_object_unref (channel->priv->cancellable);
+ channel->priv->cancellable = NULL;
if (channel->priv->remote_fd != -1)
close (channel->priv->remote_fd);
@@ -204,6 +204,7 @@ g_vfs_channel_init (GVfsChannel *channel)
else
{
channel->priv->command_stream = g_unix_input_stream_new (socket_fds[0], TRUE);
+ channel->priv->cancellable = g_cancellable_new ();
channel->priv->reply_stream = g_unix_output_stream_new (socket_fds[0], FALSE);
channel->priv->remote_fd = socket_fds[1];
@@ -284,6 +285,8 @@ static void
request_reader_free (RequestReader *reader)
{
g_object_unref (reader->command_stream);
+ g_object_unref (reader->cancellable);
+ g_object_unref (reader->channel);
g_free (reader->data);
g_free (reader);
}
@@ -426,7 +429,7 @@ finish_request (RequestReader *reader)
g_input_stream_read_async (reader->command_stream,
reader->buffer + reader->buffer_size,
G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE - reader->buffer_size,
- 0, NULL,
+ 0, reader->cancellable,
command_read_cb,
reader);
}
@@ -440,18 +443,10 @@ data_read_cb (GObject *source_object,
GInputStream *stream = G_INPUT_STREAM (source_object);
gssize count_read;
- if (reader->channel == NULL)
- {
- /* Channel was finalized */
- request_reader_free (reader);
- return;
- }
-
count_read = g_input_stream_read_finish (stream, res, NULL);
if (count_read <= 0)
{
- reader->channel->priv->request_reader = NULL;
g_vfs_channel_connection_closed (reader->channel);
request_reader_free (reader);
return;
@@ -464,7 +459,7 @@ data_read_cb (GObject *source_object,
g_input_stream_read_async (reader->command_stream,
reader->data + reader->data_pos,
reader->data_len - reader->data_pos,
- 0, NULL,
+ 0, reader->cancellable,
data_read_cb, reader);
return;
}
@@ -484,18 +479,10 @@ command_read_cb (GObject *source_object,
guint32 data_len;
gssize count_read;
- if (reader->channel == NULL)
- {
- /* Channel was finalized */
- request_reader_free (reader);
- return;
- }
-
count_read = g_input_stream_read_finish (stream, res, NULL);
if (count_read <= 0)
{
- reader->channel->priv->request_reader = NULL;
g_vfs_channel_connection_closed (reader->channel);
request_reader_free (reader);
return;
@@ -508,7 +495,7 @@ command_read_cb (GObject *source_object,
g_input_stream_read_async (reader->command_stream,
reader->buffer + reader->buffer_size,
G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE - reader->buffer_size,
- 0, NULL,
+ 0, reader->cancellable,
command_read_cb, reader);
return;
}
@@ -525,7 +512,7 @@ command_read_cb (GObject *source_object,
g_input_stream_read_async (reader->command_stream,
reader->data + reader->data_pos,
reader->data_len - reader->data_pos,
- 0, NULL,
+ 0, reader->cancellable,
data_read_cb, reader);
return;
}
@@ -539,16 +526,15 @@ start_request_reader (GVfsChannel *channel)
RequestReader *reader;
reader = g_new0 (RequestReader, 1);
- reader->channel = channel;
+ reader->channel = g_object_ref (channel);
+ reader->cancellable = g_object_ref (channel->priv->cancellable);
reader->command_stream = g_object_ref (channel->priv->command_stream);
g_input_stream_read_async (reader->command_stream,
reader->buffer + reader->buffer_size,
G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE - reader->buffer_size,
- 0, NULL,
+ 0, reader->cancellable,
command_read_cb, reader);
-
- channel->priv->request_reader = reader;
}
static void
@@ -615,6 +601,8 @@ send_reply_cb (GObject *source_object,
if (G_VFS_IS_JOB_CLOSE_READ (job) ||
G_VFS_IS_JOB_CLOSE_WRITE (job))
{
+ /* Cancel the reader */
+ g_cancellable_cancel (channel->priv->cancellable);
g_vfs_job_source_closed (G_VFS_JOB_SOURCE (channel));
channel->priv->backend_handle = NULL;
}
--
cgit v0.9

View File

@ -1,7 +1,7 @@
Summary: Backends for the gio framework in GLib
Name: gvfs
Version: 1.8.0
Release: 1%{?dist}
Release: 2%{?dist}
License: LGPLv2+
Group: System Environment/Libraries
URL: http://www.gtk.org
@ -39,6 +39,11 @@ Patch0: gvfs-archive-integration.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=552856
Patch15: gvfs-1.5.1-gphoto2-no-storageinfo-support.patch
# from upstream
Patch16: gvfs-1.8.1-gvfschannel-safety.patch
Patch17: gvfs-1.8.1-dbus-leak.patch
Patch18: gvfs-1.8.1-gdu-volume-monitor-realpath.patch
Obsoletes: gnome-mount <= 0.8
Obsoletes: gnome-mount-nautilus-properties <= 0.8
@ -136,6 +141,9 @@ including phones and music players to applications using gvfs.
%setup -q
%patch0 -p1 -b .archive-integration
%patch15 -p1 -b .gphoto2-storageinfo
%patch16 -p1 -b .channel-safety
%patch17 -p1 -b .dbus-leak
%patch18 -p1 -b .realpath
%build
@ -310,6 +318,11 @@ killall -USR1 gvfsd >&/dev/null || :
%endif
%changelog
* Mon Apr 18 2011 Tomas Bzatek <tbzatek@redhat.com> - 1.8.0-2
- Fix threadsafety of closing channels
- Fix d-bus messages leaks
- Fix /dev symlink checks in gdu volume monitor
* Mon Apr 4 2011 Matthias Clasen <mclasen@redhat.com> - 1.8.0-1
- Update to 1.8.0