All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Vladimir 'φ-coder/phcoder' Serbinenko" <phcoder@gmail.com>
To: The development of GNU GRUB <grub-devel@gnu.org>
Subject: Re: [PATCH] Ignore symlink traversal failures in grub-mount readdir
Date: Sun, 10 Mar 2013 14:02:52 +0100	[thread overview]
Message-ID: <513C847C.602@gmail.com> (raw)
In-Reply-To: <513C8441.60106@gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 2372 bytes --]

On 10.03.2013 14:01, Vladimir 'φ-coder/phcoder' Serbinenko wrote:

> On 09.03.2013 17:47, Andrey Borzenkov wrote:
> 
>> В Fri, 12 Oct 2012 17:09:54 +0100
>> Colin Watson <cjwatson@ubuntu.com> пишет:
>>
>>> This is very much a temporary hack, so I'm sending it here for
>>> discussion rather than just committing it even though it's quite simple.
>>>
>>> r3036.1.15 introduced support for filling in the attributes of files in
>>> fuse_readdir.  However, symlinks to directories are passed to call_fill
>>> with info.dir unset; call_fill will then try to open them with
>>> grub_file_open, and get GRUB_ERR_BAD_FILE_TYPE because it's ultimately a
>>> directory not a regular file.  It then causes the whole readdir call to
>>> fail.  The net effect is that if you, for example, have a symlink
>>> anywhere in the top level of a filesystem, then the entire filesystem
>>> appears empty in grub-mount.  This is the root cause of
>>> https://bugs.launchpad.net/bugs/1051306.
>>>
>>> I think that the proper solution is to pass the full
>>> grub_fshelp_filetype to dirhook functions, which would permit
>>> implementing true symlink support in grub-mount.  That would be a fairly
>>> large change that I don't have time for at the moment.  As a stopgap, I
>>> suggest that we ignore errors from individual grub_file_open calls
>>> during fuse_readdir.  How does this patch look?
>>>
>>
>> The only reason to call grub_file_open() is to fetch file size, and file
>> size is already available when hooks are called. So what about patch
>> below? It fixes problem for me, and it trivial enough. This allows
>> directory listing to work again. I can extend it with info.is_link to
>> return proper filetype to FUSE, but implementing full support needs
>> adding readlink that is a separate topic.
>>
>> I tested it with ext4 and cpio and it works. Testing on more systems
>> (in particular, NTFS, which is the only one with non-trivial change) is
>> appreciated.
>>
> 
> Some time ago I made a similar patch but for another motivation: current
> code is way too inefficient for large directories as you have to rescan
> directory for every file. The problem with this patch is 10 bytes
> increase of core.img. This may be acceptable given this problem (it
> happens in ls on runtime as well) and inefficency of scanning.
> 



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: size.diff --]
[-- Type: text/x-diff; name="size.diff", Size: 12849 bytes --]

=== modified file 'grub-core/commands/ls.c'
--- grub-core/commands/ls.c	2013-01-21 16:46:24 +0000
+++ grub-core/commands/ls.c	2013-03-10 00:21:42 +0000
@@ -118,34 +118,12 @@
 
   if (! info->dir)
     {
-      grub_file_t file;
-      char *pathname;
-
-      if (ctx->dirname[grub_strlen (ctx->dirname) - 1] == '/')
-	pathname = grub_xasprintf ("%s%s", ctx->dirname, filename);
-      else
-	pathname = grub_xasprintf ("%s/%s", ctx->dirname, filename);
-
-      if (!pathname)
-	return 1;
-
-      /* XXX: For ext2fs symlinks are detected as files while they
-	 should be reported as directories.  */
-      grub_file_filter_disable_compression ();
-      file = grub_file_open (pathname);
-      if (! file)
-	{
-	  grub_errno = 0;
-	  grub_free (pathname);
-	  return 0;
-	}
-
       if (! ctx->human)
-	grub_printf ("%-12llu", (unsigned long long) file->size);
+	grub_printf ("%-12llu", (unsigned long long) info->size);
       else
 	{
-	  grub_uint64_t fsize = file->size * 100ULL;
-	  grub_uint64_t fsz = file->size;
+	  grub_uint64_t fsize = info->size * 100ULL;
+	  grub_uint64_t fsz = info->size;
 	  int units = 0;
 	  char buf[20];
 
@@ -168,11 +146,9 @@
 	      grub_printf ("%-12s", buf);
 	    }
 	  else
-	    grub_printf ("%-12llu", (unsigned long long) file->size);
+	    grub_printf ("%-12llu", (unsigned long long) info->size);
 
 	}
-      grub_file_close (file);
-      grub_free (pathname);
     }
   else
     grub_printf ("%-12s", _("DIR"));

=== modified file 'grub-core/fs/affs.c'
--- grub-core/fs/affs.c	2013-02-27 16:19:15 +0000
+++ grub-core/fs/affs.c	2013-03-10 00:21:07 +0000
@@ -565,6 +565,7 @@
   info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
   info.mtimeset = 1;
   info.mtime = aftime2ctime (&node->di.mtime);
+  info.size = grub_be_to_cpu32 (node->di.size);
   grub_free (node);
   return ctx->hook (filename, &info, ctx->hook_data);
 }

=== modified file 'grub-core/fs/bfs.c'
--- grub-core/fs/bfs.c	2013-02-27 16:19:15 +0000
+++ grub-core/fs/bfs.c	2013-03-10 00:11:14 +0000
@@ -890,6 +890,7 @@
 #else
   info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16;
 #endif
+  info.size = grub_bfs_to_cpu64 (ino.ino.size);
   info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR);
   return ctx->hook (name, &info, ctx->hook_data);
 }

=== modified file 'grub-core/fs/btrfs.c'
--- grub-core/fs/btrfs.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/btrfs.c	2013-03-10 00:05:22 +0000
@@ -1581,6 +1581,7 @@
 	    {
 	      info.mtime = grub_le_to_cpu64 (inode.mtime.sec);
 	      info.mtimeset = 1;
+	      info.size = grub_le_to_cpu64 (inode.size);
 	    }
 	  c = cdirel->name[grub_le_to_cpu16 (cdirel->n)];
 	  cdirel->name[grub_le_to_cpu16 (cdirel->n)] = 0;

=== modified file 'grub-core/fs/cpio.c'
--- grub-core/fs/cpio.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/cpio.c	2013-03-10 00:05:22 +0000
@@ -573,6 +573,7 @@
 	      info.dir = (p != NULL) || ((mode & ATTR_TYPE) == ATTR_DIR);
 	      info.mtime = mtime;
 	      info.mtimeset = 1;
+	      info.size = data->size;
 
 	      if (hook (n, &info, hook_data))
 		{

=== modified file 'grub-core/fs/ext2.c'
--- grub-core/fs/ext2.c	2013-02-27 16:19:15 +0000
+++ grub-core/fs/ext2.c	2013-03-10 12:08:40 +0000
@@ -884,6 +884,8 @@
     {
       info.mtimeset = 1;
       info.mtime = grub_le_to_cpu32 (node->inode.mtime);
+      info.size = grub_le_to_cpu32 (node->inode.size)
+	| (((grub_off_t) grub_le_to_cpu32 (node->inode.size_high)) << 32);
     }
 
   info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);

=== modified file 'grub-core/fs/fat.c'
--- grub-core/fs/fat.c	2013-02-27 16:19:15 +0000
+++ grub-core/fs/fat.c	2013-03-10 12:46:55 +0000
@@ -894,6 +894,7 @@
 
       info.dir = !! (ctxt.dir.attr & GRUB_FAT_ATTR_DIRECTORY);
       info.case_insensitive = 1;
+      info.size = ctxt.dir.file_size;
 
 #ifdef MODE_EXFAT
       if (!ctxt.dir.have_stream)

=== modified file 'grub-core/fs/hfs.c'
--- grub-core/fs/hfs.c	2013-03-02 10:31:00 +0000
+++ grub-core/fs/hfs.c	2013-03-10 00:13:16 +0000
@@ -1225,6 +1225,7 @@
       info.dir = 0;
       info.mtimeset = 1;
       info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800;
+      info.size = grub_be_to_cpu32 (frec->size);
       return ctx->hook (fname, &info, ctx->hook_data);
     }
 

=== modified file 'grub-core/fs/hfsplus.c'
--- grub-core/fs/hfsplus.c	2013-03-01 13:02:27 +0000
+++ grub-core/fs/hfsplus.c	2013-03-10 00:13:52 +0000
@@ -1012,6 +1012,7 @@
   info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
   info.mtimeset = 1;
   info.mtime = node->mtime;
+  info.size = node->size;
   info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE);
   grub_free (node);
   return ctx->hook (filename, &info, ctx->hook_data);

=== modified file 'grub-core/fs/iso9660.c'
--- grub-core/fs/iso9660.c	2013-03-07 08:11:36 +0000
+++ grub-core/fs/iso9660.c	2013-03-10 00:14:17 +0000
@@ -861,6 +861,7 @@
   grub_memset (&info, 0, sizeof (info));
   info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
   info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime);
+  info.size = get_node_size (node);
 
   grub_free (node);
   return ctx->hook (filename, &info, ctx->hook_data);

=== modified file 'grub-core/fs/jfs.c'
--- grub-core/fs/jfs.c	2013-02-28 09:51:32 +0000
+++ grub-core/fs/jfs.c	2013-03-10 00:14:41 +0000
@@ -832,6 +832,7 @@
 		  & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR;
       info.mtimeset = 1;
       info.mtime = grub_le_to_cpu32 (inode.mtime.sec);
+      info.size = grub_le_to_cpu64 (inode.size);
       if (hook (diro->name, &info, hook_data))
 	goto fail;
     }

=== modified file 'grub-core/fs/minix.c'
--- grub-core/fs/minix.c	2013-02-28 09:50:01 +0000
+++ grub-core/fs/minix.c	2013-03-10 00:05:22 +0000
@@ -587,6 +587,7 @@
 		   & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR);
       info.mtimeset = 1;
       info.mtime = grub_minix_to_cpu32 (data->inode.mtime);
+      info.size = GRUB_MINIX_INODE_SIZE (data);
 
       if (hook (filename, &info, hook_data) ? 1 : 0)
 	break;

=== modified file 'grub-core/fs/nilfs2.c'
--- grub-core/fs/nilfs2.c	2013-02-27 16:19:15 +0000
+++ grub-core/fs/nilfs2.c	2013-03-10 00:15:05 +0000
@@ -1056,6 +1056,7 @@
     {
       info.mtimeset = 1;
       info.mtime = grub_le_to_cpu64 (node->inode.i_mtime);
+      info.size = grub_le_to_cpu64 (node->inode.i_size);
     }
 
   info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);

=== modified file 'grub-core/fs/ntfs.c'
--- grub-core/fs/ntfs.c	2013-02-27 16:19:15 +0000
+++ grub-core/fs/ntfs.c	2013-03-10 00:15:49 +0000
@@ -1019,10 +1019,13 @@
 
   grub_memset (&info, 0, sizeof (info));
   info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+  init_file (node, node->ino);
   info.mtimeset = 1;
   info.mtime = grub_divmod64 (node->mtime, 10000000, 0) 
     - 86400ULL * 365 * (1970 - 1601)
     - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100);
+  info.size = node->size;
+  free_file (node);
   grub_free (node);
   return ctx->hook (filename, &info, ctx->hook_data);
 }

=== modified file 'grub-core/fs/reiserfs.c'
--- grub-core/fs/reiserfs.c	2013-02-27 16:19:15 +0000
+++ grub-core/fs/reiserfs.c	2013-03-10 00:05:22 +0000
@@ -875,6 +875,7 @@
 				    entry_v1_stat.rdev,
 				    entry_v1_stat.first_direct_byte);
 #endif
+		      entry_item->size = (grub_off_t) grub_le_to_cpu64 (entry_v1_stat.size);
 		      entry_item->mtime = grub_le_to_cpu32 (entry_v1_stat.mtime);
 		      if ((grub_le_to_cpu16 (entry_v1_stat.mode) & S_IFLNK)
 			  == S_IFLNK)
@@ -923,6 +924,7 @@
 				    entry_v2_stat.blocks,
 				    entry_v2_stat.first_direct_byte);
 #endif
+		      entry_item->size = (grub_off_t) grub_le_to_cpu64 (entry_v2_stat.size);
 		      entry_item->mtime = grub_le_to_cpu32 (entry_v2_stat.mtime);
 		      entry_item->size = (grub_off_t) grub_le_to_cpu64 (entry_v2_stat.size);
 		      if ((grub_le_to_cpu16 (entry_v2_stat.mode) & S_IFLNK)

=== modified file 'grub-core/fs/romfs.c'
--- grub-core/fs/romfs.c	2013-02-27 16:19:15 +0000
+++ grub-core/fs/romfs.c	2013-03-10 00:16:08 +0000
@@ -331,6 +331,7 @@
   grub_memset (&info, 0, sizeof (info));
 
   info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+  info.size = grub_be_to_cpu32 (node->file.size);
   grub_free (node);
   return ctx->hook (filename, &info, ctx->hook_data);
 }

=== modified file 'grub-core/fs/sfs.c'
--- grub-core/fs/sfs.c	2013-02-27 16:19:15 +0000
+++ grub-core/fs/sfs.c	2013-03-10 00:16:47 +0000
@@ -671,6 +671,7 @@
   info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
   info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2;
   info.mtimeset = 1;
+  info.size = node->size;
   grub_free (node->cache);
   grub_free (node);
   return ctx->hook (filename, &info, ctx->hook_data);

=== modified file 'grub-core/fs/squash4.c'
--- grub-core/fs/squash4.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/squash4.c	2013-03-10 00:17:17 +0000
@@ -656,6 +656,16 @@
   info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
   info.mtimeset = 1;
   info.mtime = grub_le_to_cpu32 (node->ino.mtime);
+  switch (node->ino.type)
+    {
+    case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR):
+      info.size = grub_le_to_cpu64 (node->ino.long_file.size);
+      break;
+    case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR):
+      info.size = grub_le_to_cpu32 (node->ino.file.size);
+      break;
+    }
+
   grub_free (node);
   return ctx->hook (filename, &info, ctx->hook_data);
 }

=== modified file 'grub-core/fs/udf.c'
--- grub-core/fs/udf.c	2013-02-27 16:19:15 +0000
+++ grub-core/fs/udf.c	2013-03-10 00:17:39 +0000
@@ -1026,6 +1026,7 @@
 
   grub_memset (&info, 0, sizeof (info));
   info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+  info.size = U64 (node->block.fe.file_size);
   if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
     tstamp = &node->block.fe.modification_time;
   else if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE)

=== modified file 'grub-core/fs/ufs.c'
--- grub-core/fs/ufs.c	2013-02-27 16:19:15 +0000
+++ grub-core/fs/ufs.c	2013-03-10 00:17:58 +0000
@@ -696,6 +696,12 @@
 #endif
 	info.mtimeset = 1;
 
+#ifdef MODE_UFS2
+	info.size = grub_le_to_cpu64 (inode.size);
+#else
+	info.size = grub_le_to_cpu32 (inode.size);
+#endif
+
 	if (hook (filename, &info, hook_data))
 	  break;
       }

=== modified file 'grub-core/fs/xfs.c'
--- grub-core/fs/xfs.c	2013-02-27 16:19:15 +0000
+++ grub-core/fs/xfs.c	2013-03-10 00:18:18 +0000
@@ -731,6 +731,7 @@
     {
       info.mtimeset = 1;
       info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec);
+      info.size = grub_be_to_cpu64 (node->inode.size);
     }
   info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
   grub_free (node);

=== modified file 'grub-core/fs/zfs/zfs.c'
--- grub-core/fs/zfs/zfs.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/zfs/zfs.c	2013-03-10 00:05:22 +0000
@@ -3768,12 +3768,14 @@
       hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
       info->mtimeset = 1;
       info->mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
+      info->size = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), dn.endian);
     }
 
   if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
     {
       info->mtimeset = 1;
       info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian);
+      info->size = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&data->dnode.dn))->zp_size, dn.endian);
     }
   return;
 }

=== modified file 'include/grub/fs.h'
--- include/grub/fs.h	2013-01-21 01:33:46 +0000
+++ include/grub/fs.h	2013-03-10 00:05:22 +0000
@@ -39,6 +39,7 @@
   unsigned mtimeset:1;
   unsigned case_insensitive:1;
   grub_int32_t mtime;
+  grub_off_t size;
 };
 
 typedef int (*grub_fs_dir_hook_t) (const char *filename,

=== modified file 'util/grub-mount.c'
--- util/grub-mount.c	2013-01-21 01:33:46 +0000
+++ util/grub-mount.c	2013-03-10 00:10:49 +0000
@@ -206,14 +206,7 @@
   st->st_gid = 0;
   st->st_rdev = 0;
   if (!ctx.file_info.dir)
-    {
-      grub_file_t file;
-      file = grub_file_open (path);
-      if (! file)
-	return translate_error ();
-      st->st_size = file->size;
-      grub_file_close (file);
-    }
+    st->st_size = ctx.file_info.size;
   else
     st->st_size = 0;
   st->st_blksize = 512;


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]

  reply	other threads:[~2013-03-10 13:03 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-12 16:09 [PATCH] Ignore symlink traversal failures in grub-mount readdir Colin Watson
2012-10-15 15:08 ` Dave Vasilevsky
2013-03-09 16:47 ` Andrey Borzenkov
2013-03-10 13:01   ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-03-10 13:02     ` Vladimir 'φ-coder/phcoder' Serbinenko [this message]
2013-11-28 13:30     ` Andrey Borzenkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=513C847C.602@gmail.com \
    --to=phcoder@gmail.com \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.