]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_growfs: ensure target path is an active xfs mountpoint
authorBill O'Donnell <billodo@redhat.com>
Wed, 21 Jun 2017 19:40:35 +0000 (14:40 -0500)
committerEric Sandeen <sandeen@redhat.com>
Wed, 21 Jun 2017 19:40:35 +0000 (14:40 -0500)
xfs_growfs manpage clearly states that the target path must be
an active xfs mountpoint.

Current behavior allows xfs_growfs to proceed if the target path
resides anywhere on a mounted xfs filesystem. This could lead to
unexpected results. Unless the target path is an active xfs
mountpoint, reject it. Create a new fs table lookup function which
matches only active xfs mount points, not any file residing within
those mountpoints.

Signed-off-by: Bill O'Donnell <billodo@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
growfs/xfs_growfs.c
include/path.h
libxcmd/paths.c

index a294e144caf275a0e8cf0b539f46b1663964c8e7..366176b710b8b86dd4bc635275d33cd50c2234ff 100644 (file)
@@ -133,6 +133,7 @@ main(int argc, char **argv)
        int                     spinodes;
        int                     rmapbt_enabled;
        int                     reflink_enabled;
+       char                    rpath[PATH_MAX];
 
        progname = basename(argv[0]);
        setlocale(LC_ALL, "");
@@ -202,7 +203,14 @@ main(int argc, char **argv)
                aflag = 1;
 
        fs_table_initialise(0, NULL, 0, NULL);
-       fs = fs_table_lookup(argv[optind], FS_MOUNT_POINT);
+
+       if (!realpath(argv[optind], rpath)) {
+               fprintf(stderr, _("%s: path resolution failed for %s: %s\n"),
+                       progname, argv[optind], strerror(errno));
+               return 1;
+       }
+
+       fs = fs_table_lookup_mount(rpath);
        if (!fs) {
                fprintf(stderr, _("%s: %s is not a mounted XFS filesystem\n"),
                        progname, argv[optind]);
index d077bac4f9ab8cf22b5a7cc01acdb954a95ba44a..1d3a902e07b6ec0d2f8bf023b39211d177b97132 100644 (file)
@@ -56,6 +56,7 @@ extern void fs_table_insert_project_path(char *__dir, uint __projid);
 
 
 extern fs_path_t *fs_table_lookup(const char *__dir, uint __flags);
+extern fs_path_t *fs_table_lookup_mount(const char *__dir);
 
 typedef struct fs_cursor {
        uint            count;          /* total count of mount entries */
index 816acc22b4ab810a26010b3abb45086b072d60df..b767e9dcee739a1817e7a7ecf5df2be2103c8039 100644 (file)
@@ -65,6 +65,9 @@ fs_device_number(
  * Find the FS table entry for the given path.  The "flags" argument
  * is a mask containing FS_MOUNT_POINT or FS_PROJECT_PATH (or both)
  * to indicate the type of table entry sought.
+ * fs_table_lookup() finds the fs table entry for the filesystem hosting
+ * the file represented in the "dir" argument. To compare against actual
+ * mount point entries, use fs_table_lookup_mount() instead.
  */
 struct fs_path *
 fs_table_lookup(
@@ -86,6 +89,34 @@ fs_table_lookup(
        return NULL;
 }
 
+/*
+ * Find the FS table entry describing an actual mount for the given path.
+ * Unlike fs_table_lookup(), fs_table_lookup_mount() compares the "dir"
+ * argument to actual mount point entries in the table. Accordingly, it
+ * will find matches only if the "dir" argument is indeed mounted.
+ */
+struct fs_path *
+fs_table_lookup_mount(
+       const char      *dir)
+{
+       uint            i;
+       dev_t           dev = 0;
+       char            rpath[PATH_MAX];
+
+       if (fs_device_number(dir, &dev))
+               return NULL;
+
+       for (i = 0; i < fs_count; i++) {
+               if (fs_table[i].fs_flags != FS_MOUNT_POINT)
+                       continue;
+               if (!realpath(fs_table[i].fs_dir, rpath))
+                       continue;
+               if (strcmp(rpath, dir) == 0)
+                       return &fs_table[i];
+       }
+       return NULL;
+}
+
 static int
 fs_table_insert(
        char            *dir,