Don't fail LoopSetup() because fstat(2) fails
authorDavid Zeuthen <davidz@redhat.com>
Wed, 7 Dec 2011 21:09:03 +0000 (16:09 -0500)
committerDavid Zeuthen <davidz@redhat.com>
Wed, 7 Dec 2011 21:09:03 +0000 (16:09 -0500)
With this change, this method now works with fds from a GVfs FUSE
mount (where not even uid 0 may open files on).

Signed-off-by: David Zeuthen <davidz@redhat.com>
src/udiskscleanup.c
src/udiskslinuxmanager.c

index cbdfe1d..21cffe0 100644 (file)
  *           (of type <link linkend="G-VARIANT-TYPE-ARRAY:CAPS">'ay'</link>) for the name of the backing file and
  *           <literal>backing-file-device</literal>
  *           (of type <link linkend="G-VARIANT-TYPE-UINT64:CAPS">'t'</link>) for the #dev_t
- *           for of the device holding the backing file and
+ *           for of the device holding the backing file (or 0 if unknown) and
  *           <literal>setup-by-uid</literal>
  *           (of type <link linkend="G-VARIANT-TYPE-UINT32:CAPS">'u'</link>) that is the #uid_t
  *           of the user who set up the loop device.
@@ -1489,7 +1489,7 @@ udisks_cleanup_check_loop_entry (UDisksCleanup  *cleanup,
   /* Check if device exists... */
   if (major (backing_file_device) == 0)
     {
-      /* major==0 -> not regular block device ... could be e.g. NFS ...
+      /* major==0 -> not regular block device or just not known ... could be e.g. NFS ...
        * for now, just assume it's still there and mounted
        */
       has_backing_device = TRUE;
@@ -1677,7 +1677,7 @@ udisks_cleanup_check_loop (UDisksCleanup *cleanup,
  * @cleanup: A #UDisksCleanup.
  * @device_file: The loop device file.
  * @backing_file: The backing file.
- * @backing_file_device: The #dev_t of the backing file.
+ * @backing_file_device: The #dev_t of the backing file or 0 if unknown.
  * @uid: The user id of the process requesting the loop device.
  *
  * Adds a new entry to the <filename>/run/udisks2/loop</filename>
index b3986a1..b539d3c 100644 (file)
@@ -265,7 +265,7 @@ handle_loop_setup (UDisksManager          *object,
   guint64 option_size = 0;
   uid_t caller_uid;
   struct stat fd_statbuf;
-  struct stat path_statbuf;
+  gboolean fd_statbuf_valid = FALSE;
   WaitForLoopData wait_data;
 
   /* we need the uid of the caller for the loop file */
@@ -322,31 +322,11 @@ handle_loop_setup (UDisksManager          *object,
   g_variant_lookup (options, "offset", "t", &option_offset);
   g_variant_lookup (options, "size", "t", &option_size);
 
-  /* Validate that st_ino and st_dev from fstat(fd) are the same as
-   * for stat(path)
+  /* it's not a problem if fstat fails... for example, this can happen if the user
+   * passes a fd to a file on the GVfs fuse mount
    */
-  if (fstat (fd, &fd_statbuf) != 0)
-    {
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR, UDISKS_ERROR_FAILED,
-                                             "Error statting fd: %m");
-      goto out;
-    }
-  if (stat (path, &path_statbuf) != 0)
-    {
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR, UDISKS_ERROR_FAILED,
-                                             "Error statting path: %m");
-      goto out;
-    }
-  if ((fd_statbuf.st_ino != path_statbuf.st_ino) ||
-      (fd_statbuf.st_dev != path_statbuf.st_dev))
-    {
-      g_dbus_method_invocation_return_error (invocation,
-                                             UDISKS_ERROR, UDISKS_ERROR_FAILED,
-                                             "stat(2) info for path and fd does not agree");
-      goto out;
-    }
+  if (fstat (fd, &fd_statbuf) == 0)
+    fd_statbuf_valid = TRUE;
 
   loop_control_fd = open ("/dev/loop-control", O_RDWR);
   if (loop_control_fd == -1)
@@ -420,7 +400,7 @@ handle_loop_setup (UDisksManager          *object,
   udisks_cleanup_add_loop (udisks_daemon_get_cleanup (manager->daemon),
                            loop_device,
                            path,
-                           fd_statbuf.st_dev,
+                           fd_statbuf_valid ? fd_statbuf.st_dev : 0,
                            caller_uid);
 
   udisks_notice ("Set up loop device %s (backed by %s)",