]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
libext2fs: add extra checks to ext2fs_check_mount_point()
authorzhanchengbin <zhanchengbin1@huawei.com>
Tue, 4 Jan 2022 14:23:52 +0000 (22:23 +0800)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 18 Jan 2023 04:55:18 +0000 (23:55 -0500)
A pseudo-filesystem, such as tmpfs, can have anything at all in its
mnt_fsname entry.  Normally, it is just "tmpfs", like this:

tmpfs /tmp tmpfs rw,relatime,inode64 0 0
^^^^^

but in a pathological or malicious case, a system administrator can
specify a block device as its mnt_fsname which is the same as some
other block device.  For example:

/dev/loop0 /tmp/test-tmpfs tmpfs rw,relatime,inode64 0 0
^^^^^^^^^^
/dev/loop0 /tmp/test-mnt ext4 rw,relatime 0 0

In this case, ext2fs_check_mount_point() may erroneously return that
the mountpoint for the file system on /dev/loop0 is mounted on
/tmp/test-tmpfs, instead of the correct /tmp/test-mnt.  This causes
problems for resize2fs, since in order to do an online resize, it
needs to open the directory where the file system is mounted, and
trigger the online resize ioctl.  If it opens the incorrect directory,
then resize2fs will fail.

So we need to add some additional checking to make sure that
directory's st_dev matches the block device's st_rdev field.

An example shell script which reproduces the problem fixed by this
commit is as follows:

   loop_file=/tmp/foo.img
   tmpfs_dir=/tmp/test-tmpfs
   mnt_dir=/tmp/test-mnt

   mkdir -p $tmpfs_dir $mnt_dir
   dd if=/dev/zero of=$loop_file bs=1k count=65536
   test_dev=$(losetup --show -f $loop_file)
   mke2fs -t ext4 -F -b 1024 $test_dev 32768
   mount -t tmpfs $test_dev $tmpfs_dir  # create the evil /proc/mounts entry
   mount -t ext4 $test_dev $mnt_dir
   ln -f ${test_dev} ${test_dev}-ln
   resize2fs ${test_dev}-ln

[ Fixed up the corrupted patch and rewrote the commit description to
  be more clear -- tytso ]

Signed-off-by: zhanchengbin <zhanchengbin1@huawei.com>
Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
lib/ext2fs/ismounted.c

index aee7d72690a79b30c1c93413ceb430e097608c21..fe64e8bb345a78846ce8a2d320530d43e60011dd 100644 (file)
@@ -97,7 +97,7 @@ static errcode_t check_mntent_file(const char *mtab_file, const char *file,
                                   int *mount_flags, char *mtpt, int mtlen)
 {
        struct mntent   *mnt;
-       struct stat     st_buf;
+       struct stat     st_buf, dir_st_buf;
        errcode_t       retval = 0;
        dev_t           file_dev=0, file_rdev=0;
        ino_t           file_ino=0;
@@ -144,8 +144,14 @@ static errcode_t check_mntent_file(const char *mtab_file, const char *file,
                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 (stat(mnt->mnt_dir,
+                                                &dir_st_buf) != 0)
+                                               continue;
+                                       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)