答复: [PATCH v2] e2fsprogs: Check device id in advance to skip fake device name
diff mbox series

Message ID 005F77DB9A260B4E91664DDF22573C66E9D380C7@dggemm512-mbs.china.huawei.com
State New
Headers show
Series
  • 答复: [PATCH v2] e2fsprogs: Check device id in advance to skip fake device name
Related show

Commit Message

Guiyao Nov. 11, 2019, 2:43 p.m. UTC
Hi Theodore,

Thanks for your response and your rewriting.

Actually, we found some insane system administrators, they not only do something like "mount -t tmpfs /dev/sdb /tmp ", but also they do " ln -s /dev/sdb abc ", then "resize2fs abc xxx". :(

So we have to add the fixing code in both sides of "name matched" and "name not matched".

For the compiling issue, it's my fault in previous patch, and added the macro in a wrong line.

So, I rewrote it again, and please give more advise. Thank you in advance.

Comments

Theodore Ts'o Nov. 11, 2019, 5:20 p.m. UTC | #1
On Mon, Nov 11, 2019 at 02:43:46PM +0000, Guiyao wrote:
> 
> Actually, we found some insane system administrators, they not only do something like "mount -t tmpfs /dev/sdb /tmp ", but also they do " ln -s /dev/sdb abc ", then "resize2fs abc xxx". :(

So I don't consider ourselves necessarily obligated to twist ourselves
into knots for insane system administrators.  :-)

Did you test the patch that I sent out?  It handles that case already:

% grep /dev/loop /proc/mounts
/dev/loop0 /mnt2 tmpfs rw,relatime 0 0
/dev/loop0 /mnt ext4 rw,relatime 0 0
% ln -s /dev/loop0 abc
% ./tst_ismounted abc
Device abc reports flags 11
abc is apparently in use.
abc is mounted.
abc is mounted on /mnt2.

> So we have to add the fixing code in both sides of "name matched" and "name not matched".
> 
> For the compiling issue, it's my fault in previous patch, and added the macro in a wrong line.
> 
> So, I rewrote it again, and please give more advise. Thank you in advance.

Given that I have a patch which I've already tested, and which is a
substantial clean up in terms of removing #ifdef cases and number of
lines of code:

 lib/ext2fs/ismounted.c | 39 ++++++++++++---------------------------
  1 file changed, 12 insertions(+), 27 deletions(-)
  
I'm inclined to stick with mine.

But here's the quick review.

>  {
>     struct mntent   *mnt;
> +#ifndef __GNU__
> +   struct stat dir_st_buf;
> +#endif  /* __GNU__ */

Lots of extra #ifdef/#ifndef is undesirable.  As it turns out, it
isn't necessary to have a separate dir_st_buf at all.

> @@ -128,13 +131,32 @@ static errcode_t check_mntent_file(const char *mtab_file, const char *file,
>     while ((mnt = getmntent (f)) != NULL) {
>         if (mnt->mnt_fsname[0] != '/')
>             continue;
> -       if (strcmp(file, mnt->mnt_fsname) == 0)
> +#ifndef __GNU__
> +       if (stat(mnt->mnt_dir, &dir_st_buf) != 0)
> +           continue;
> +#endif
> +       if (strcmp(file, mnt->mnt_fsname) == 0) {
> +#ifndef __GNU__
> +           if (file_rdev && (file_rdev != dir_st_buf.st_dev)) {

This doesn't need to be under #ifndef __GNU__.  In the GNU hurd case,
file_rdev will be zero, so the compiler will remove the if statement
for us, without needing an additional #ifndef __GNU__ test.

>         if (stat(mnt->mnt_fsname, &st_buf) == 0) {
>             if (ext2fsP_is_disk_device(st_buf.st_mode)) {
>  #ifndef __GNU__
> -               if (file_rdev && (file_rdev == st_buf.st_rdev))
> -                   break;
> +               if (file_rdev && (file_rdev == st_buf.st_rdev)) {
> +                   if (file_rdev == dir_st_buf.st_dev)
> +                       break;
> +               }
> +

The reason why this isn't necessary is because we're using stat, and
stat follows symlinks.  So when you do "ln -s /dev/sdb abc", and then
we stat abc, st_buf.st_rdev contains the device node of /dev/sbc, not
the symbolic link of abc.  So adding a check for dir_st_buf.st_dev is
not needed.

Cheers,

					- Ted
Guiyao Nov. 12, 2019, 2:19 p.m. UTC | #2
Hi, Ted,

Yes, I agree with you, let's remove the "#ifdef/#ifndef " code. :)

And I have tested your patch, it can work well in case 1, but cannot work in case 2.

#mount -t tmpfs /dev/sdb tmp
#mount /dev/sdb sdb

Case1:
#resize2fs /dev/sdb 7G
// it can success, and the correct sdb resized.

Case2:
#umount sdb
#ln -s /dev/sdb abc
#resize2fs abc 8G
Filesystem at abc is mounted on /root/tmp; on-line resizing required
old_desc_blocks = 2, new_desc_blocks = 2 
resize2fs: Kernel does not support online resizing

it is the reason I added some code here, and had to add "dir_st_buf ".

>         if (stat(mnt->mnt_fsname, &st_buf) == 0) {
>             if (ext2fsP_is_disk_device(st_buf.st_mode)) {  #ifndef 
> __GNU__
> -               if (file_rdev && (file_rdev == st_buf.st_rdev))
> -                   break;
> +               if (file_rdev && (file_rdev == st_buf.st_rdev)) {
> +                   if (file_rdev == dir_st_buf.st_dev)
> +                       break;
> +               }


To be honest, I think the scene of case 2 is really strange.

Thank you.


On Mon, Nov 11, 2019 at 02:43:46PM +0000, Guiyao wrote:
> 
> Actually, we found some insane system administrators, they not only do 
> something like "mount -t tmpfs /dev/sdb /tmp ", but also they do " ln 
> -s /dev/sdb abc ", then "resize2fs abc xxx". :(

So I don't consider ourselves necessarily obligated to twist ourselves into knots for insane system administrators.  :-)

Did you test the patch that I sent out?  It handles that case already:

% grep /dev/loop /proc/mounts
/dev/loop0 /mnt2 tmpfs rw,relatime 0 0
/dev/loop0 /mnt ext4 rw,relatime 0 0
% ln -s /dev/loop0 abc
% ./tst_ismounted abc
Device abc reports flags 11
abc is apparently in use.
abc is mounted.
abc is mounted on /mnt2.

> So we have to add the fixing code in both sides of "name matched" and "name not matched".
> 
> For the compiling issue, it's my fault in previous patch, and added the macro in a wrong line.
> 
> So, I rewrote it again, and please give more advise. Thank you in advance.

Given that I have a patch which I've already tested, and which is a substantial clean up in terms of removing #ifdef cases and number of lines of code:

 lib/ext2fs/ismounted.c | 39 ++++++++++++---------------------------
  1 file changed, 12 insertions(+), 27 deletions(-)
  
I'm inclined to stick with mine.

But here's the quick review.

>  {
>     struct mntent   *mnt;
> +#ifndef __GNU__
> +   struct stat dir_st_buf;
> +#endif  /* __GNU__ */

Lots of extra #ifdef/#ifndef is undesirable.  As it turns out, it isn't necessary to have a separate dir_st_buf at all.

> @@ -128,13 +131,32 @@ static errcode_t check_mntent_file(const char *mtab_file, const char *file,
>     while ((mnt = getmntent (f)) != NULL) {
>         if (mnt->mnt_fsname[0] != '/')
>             continue;
> -       if (strcmp(file, mnt->mnt_fsname) == 0)
> +#ifndef __GNU__
> +       if (stat(mnt->mnt_dir, &dir_st_buf) != 0)
> +           continue;
> +#endif
> +       if (strcmp(file, mnt->mnt_fsname) == 0) { #ifndef __GNU__
> +           if (file_rdev && (file_rdev != dir_st_buf.st_dev)) {

This doesn't need to be under #ifndef __GNU__.  In the GNU hurd case, file_rdev will be zero, so the compiler will remove the if statement for us, without needing an additional #ifndef __GNU__ test.

>         if (stat(mnt->mnt_fsname, &st_buf) == 0) {
>             if (ext2fsP_is_disk_device(st_buf.st_mode)) {  #ifndef 
> __GNU__
> -               if (file_rdev && (file_rdev == st_buf.st_rdev))
> -                   break;
> +               if (file_rdev && (file_rdev == st_buf.st_rdev)) {
> +                   if (file_rdev == dir_st_buf.st_dev)
> +                       break;
> +               }
> +

The reason why this isn't necessary is because we're using stat, and stat follows symlinks.  So when you do "ln -s /dev/sdb abc", and then we stat abc, st_buf.st_rdev contains the device node of /dev/sbc, not the symbolic link of abc.  So adding a check for dir_st_buf.st_dev is not needed.

Cheers,

					- Ted

Patch
diff mbox series

diff --git a/lib/ext2fs/ismounted.c b/lib/ext2fs/ismounted.c
index 6cd497d..729769e 100644
--- a/lib/ext2fs/ismounted.c
+++ b/lib/ext2fs/ismounted.c
@@ -97,6 +97,9 @@  static errcode_t check_mntent_file(const char *mtab_file, const char *file,
                   int *mount_flags, char *mtpt, int mtlen)
 {
    struct mntent   *mnt;
+#ifndef __GNU__
+   struct stat dir_st_buf;
+#endif  /* __GNU__ */
    struct stat st_buf;
    errcode_t   retval = 0;
    dev_t       file_dev=0, file_rdev=0;
@@ -128,13 +131,32 @@  static errcode_t check_mntent_file(const char *mtab_file, const char *file,
    while ((mnt = getmntent (f)) != NULL) {
        if (mnt->mnt_fsname[0] != '/')
            continue;
-       if (strcmp(file, mnt->mnt_fsname) == 0)
+#ifndef __GNU__
+       if (stat(mnt->mnt_dir, &dir_st_buf) != 0)
+           continue;
+#endif
+       if (strcmp(file, mnt->mnt_fsname) == 0) {
+#ifndef __GNU__
+           if (file_rdev && (file_rdev != dir_st_buf.st_dev)) {
+#ifdef DEBUG
+               printf("Bogus entry in %s!  "
+                      "(%s does not exist)\n",
+                      mtab_file, mnt->mnt_dir);
+#endif /* DEBUG */
+               continue;
+           }
+#endif /* __GNU__ */
            break;
+       }
+
        if (stat(mnt->mnt_fsname, &st_buf) == 0) {
            if (ext2fsP_is_disk_device(st_buf.st_mode)) {
 #ifndef __GNU__
-               if (file_rdev && (file_rdev == st_buf.st_rdev))
-                   break;
+               if (file_rdev && (file_rdev == st_buf.st_rdev)) {
+                   if (file_rdev == dir_st_buf.st_dev)
+                       break;
+               }
+
                if (check_loop_mounted(mnt->mnt_fsname,
                        st_buf.st_rdev, file_dev,
                        file_ino) == 1)
@@ -168,32 +190,6 @@  static errcode_t check_mntent_file(const char *mtab_file, const char *file,
 #endif /* __GNU__ */
        goto errout;
    }
-#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
-   /* Validate the entry in case /etc/mtab is out of date */
-   /*
-    * We need to be paranoid, because some broken distributions
-    * (read: Slackware) don't initialize /etc/mtab before checking
-    * all of the non-root filesystems on the disk.
-    */
-   if (stat(mnt->mnt_dir, &st_buf) < 0) {
-       retval = errno;
-       if (retval == ENOENT) {
-#ifdef DEBUG
-           printf("Bogus entry in %s!  (%s does not exist)\n",
-                  mtab_file, mnt->mnt_dir);
-#endif /* DEBUG */
-           retval = 0;
-       }
-       goto errout;
-   }
-   if (file_rdev && (st_buf.st_dev != file_rdev)) {
-#ifdef DEBUG
-       printf("Bogus entry in %s!  (%s not mounted on %s)\n",
-              mtab_file, file, mnt->mnt_dir);
-#endif /* DEBUG */
-       goto errout;
-   }
-#endif /* __GNU__ */
    *mount_flags = EXT2_MF_MOUNTED;

 #ifdef MNTOPT_RO