]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: make rootfs lookup by parent-id more robust
authorKarel Zak <kzak@redhat.com>
Wed, 1 Feb 2017 15:12:55 +0000 (16:12 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 1 Feb 2017 15:20:12 +0000 (16:20 +0100)
The root FS id really does not have to be the smallest one.

Reported-by: Michal Soltys <soltys@ziu.info>
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/tab.c
tests/expected/findmnt/outputs-messy-mountinfo [new file with mode: 0644]
tests/ts/findmnt/files/mountinfo-messy [new file with mode: 0644]
tests/ts/findmnt/outputs

index 85fd427b54d85daba075105c86de60b1e911d571..0eeefe76d69fae779346827319dc12c7f1b76160 100644 (file)
@@ -438,15 +438,31 @@ int mnt_table_remove_fs(struct libmnt_table *tb, struct libmnt_fs *fs)
        return 0;
 }
 
+static inline struct libmnt_fs *get_parent_fs(struct libmnt_table *tb, struct libmnt_fs *fs)
+{
+       struct libmnt_iter itr;
+       struct libmnt_fs *x;
+       int parent_id = mnt_fs_get_parent_id(fs);
+
+       mnt_reset_iter(&itr, MNT_ITER_FORWARD);
+       while (mnt_table_next_fs(tb, &itr, &x) == 0) {
+               if (mnt_fs_get_id(x) == parent_id)
+                       return x;
+       }
+
+       return NULL;
+}
+
 /**
  * mnt_table_get_root_fs:
  * @tb: mountinfo file (/proc/self/mountinfo)
  * @root: returns pointer to the root filesystem (/)
  *
- * The function uses the parent ID from the mountinfo file to determine the root filesystem
- * (the filesystem with the smallest ID). The function is designed mostly for
- * applications where it is necessary to sort mountpoints by IDs to get the tree
- * of the mountpoints (e.g. findmnt default output).
+ * The function uses the parent ID from the mountinfo file to determine the
+ * root filesystem (the filesystem with the smallest ID with parent ID missing
+ * in the table). The function is designed mostly for applications where it is
+ * necessary to sort mountpoints by IDs to get the tree of the mountpoints
+ * (e.g. findmnt default output).
  *
  * If you're not sure, then use
  *
@@ -469,6 +485,7 @@ int mnt_table_get_root_fs(struct libmnt_table *tb, struct libmnt_fs **root)
 
        *root = NULL;
 
+       /* get smallest possible ID from the table */
        mnt_reset_iter(&itr, MNT_ITER_FORWARD);
        while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
                int id = mnt_fs_get_parent_id(fs);
@@ -479,6 +496,15 @@ int mnt_table_get_root_fs(struct libmnt_table *tb, struct libmnt_fs **root)
                }
        }
 
+       /* go to the root node by "parent_id -> id" relation */
+       while (*root) {
+               struct libmnt_fs *x = get_parent_fs(tb, *root);
+               if (!x || x == *root)
+                       break;
+               DBG(TAB, ul_debugobj(tb, " messy mountinfo, walk to %s", mnt_fs_get_target(x)));
+               *root = x;
+       }
+
        return *root ? 0 : -EINVAL;
 }
 
diff --git a/tests/expected/findmnt/outputs-messy-mountinfo b/tests/expected/findmnt/outputs-messy-mountinfo
new file mode 100644 (file)
index 0000000..c7225a1
--- /dev/null
@@ -0,0 +1,31 @@
+TARGET                                SOURCE                                          FSTYPE    OPTIONS
+/                                     /dev/sda3[/arch]                                ext4      rw,relatime
+|-/sys                                sysfs                                           sysfs     ro,nosuid,nodev,noexec,relatime
+| `-/sys/fs/cgroup                    tmpfs                                           tmpfs     ro,nosuid,nodev,noexec,mode=755
+|   |-/sys/fs/cgroup/perf_event       cgroup                                          cgroup    ro,nosuid,nodev,noexec,relatime,perf_event
+|   |-/sys/fs/cgroup/net_cls          cgroup                                          cgroup    ro,nosuid,nodev,noexec,relatime,net_cls
+|   |-/sys/fs/cgroup/blkio            cgroup                                          cgroup    ro,nosuid,nodev,noexec,relatime,blkio
+|   |-/sys/fs/cgroup/memory           cgroup                                          cgroup    ro,nosuid,nodev,noexec,relatime,memory
+|   |-/sys/fs/cgroup/pids             cgroup                                          cgroup    ro,nosuid,nodev,noexec,relatime,pids
+|   |-/sys/fs/cgroup/cpuset           cgroup                                          cgroup    ro,nosuid,nodev,noexec,relatime,cpuset
+|   |-/sys/fs/cgroup/freezer          cgroup                                          cgroup    ro,nosuid,nodev,noexec,relatime,freezer
+|   |-/sys/fs/cgroup/cpu,cpuacct      cgroup                                          cgroup    ro,nosuid,nodev,noexec,relatime,cpu,cpuacct
+|   |-/sys/fs/cgroup/devices          cgroup                                          cgroup    ro,nosuid,nodev,noexec,relatime,devices
+|   `-/sys/fs/cgroup/systemd          cgroup                                          cgroup    rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd
+|-/dev                                tmpfs                                           tmpfs     rw,nosuid,mode=755
+| |-/dev/mqueue                       mqueue                                          mqueue    rw,relatime
+| |-/dev/hugepages                    hugetlbfs                                       hugetlbfs rw,relatime
+| |-/dev/shm                          tmpfs                                           tmpfs     rw,nosuid,nodev
+| |-/dev/pts                          devpts                                          devpts    rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666
+| `-/dev/console                      devpts[/5]                                      devpts    rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000
+|-/run                                tmpfs                                           tmpfs     rw,nosuid,nodev,mode=755
+| |-/run/user/0                       tmpfs                                           tmpfs     rw,nosuid,nodev,relatime,size=1634120k,mode=700
+| `-/run/systemd/nspawn/incoming      run[/systemd/nspawn/propagate/arch]             tmpfs     ro,relatime,mode=755
+|-/tmp                                tmpfs                                           tmpfs     rw
+`-/proc                               proc                                            proc      rw,nosuid,nodev,noexec,relatime
+  |-/proc/sys/kernel/random/boot_id   tmpfs[/proc-sys-kernel-random-boot-id//deleted] tmpfs     rw,nosuid,nodev,mode=755
+  |-/proc/kmsg                        tmpfs[/kmsg//deleted]                           tmpfs     rw,nosuid,nodev,mode=755
+  |-/proc/sys                         proc[/sys]                                      proc      ro,nosuid,nodev,noexec,relatime
+  | `-/proc/sys/kernel/random/boot_id tmpfs[/proc-sys-kernel-random-boot-id//deleted] tmpfs     ro,nosuid,nodev,mode=755
+  `-/proc/sysrq-trigger               proc[/sysrq-trigger]                            proc      ro,nosuid,nodev,noexec,relatime
+rc=0
diff --git a/tests/ts/findmnt/files/mountinfo-messy b/tests/ts/findmnt/files/mountinfo-messy
new file mode 100644 (file)
index 0000000..6e2ac9d
--- /dev/null
@@ -0,0 +1,29 @@
+220 189 8:3 /arch / rw,relatime shared:50 - ext4 /dev/sda3 rw
+221 220 0:17 / /sys ro,nosuid,nodev,noexec,relatime shared:51 - sysfs sysfs rw
+222 220 0:52 / /dev rw,nosuid shared:52 - tmpfs tmpfs rw,mode=755
+223 222 0:53 / /dev/shm rw,nosuid,nodev shared:53 - tmpfs tmpfs rw
+224 222 0:56 / /dev/pts rw,nosuid,noexec,relatime shared:56 - devpts devpts rw,gid=5,mode=620,ptmxmode=666
+225 222 0:21 /5 /dev/console rw,nosuid,noexec,relatime shared:57 master:4 - devpts devpts rw,gid=5,mode=620,ptmxmode=000
+226 220 0:54 / /run rw,nosuid,nodev shared:54 - tmpfs tmpfs rw,mode=755
+227 226 0:18 /systemd/nspawn/propagate/arch /run/systemd/nspawn/incoming ro,relatime master:11 - tmpfs run rw,mode=755
+228 220 0:55 / /tmp rw shared:55 - tmpfs tmpfs rw
+231 220 0:58 / /proc rw,nosuid,nodev,noexec,relatime shared:58 - proc proc rw
+232 231 0:58 /sys /proc/sys ro,nosuid,nodev,noexec,relatime shared:58 - proc proc rw
+233 231 0:58 /sysrq-trigger /proc/sysrq-trigger ro,nosuid,nodev,noexec,relatime shared:58 - proc proc rw
+93 221 0:59 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:59 - tmpfs tmpfs ro,mode=755
+94 93 0:29 / /sys/fs/cgroup/perf_event ro,nosuid,nodev,noexec,relatime shared:60 - cgroup cgroup rw,perf_event
+95 93 0:31 / /sys/fs/cgroup/net_cls ro,nosuid,nodev,noexec,relatime shared:61 - cgroup cgroup rw,net_cls
+96 93 0:30 / /sys/fs/cgroup/blkio ro,nosuid,nodev,noexec,relatime shared:62 - cgroup cgroup rw,blkio
+98 93 0:33 / /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime shared:63 - cgroup cgroup rw,memory
+99 93 0:32 / /sys/fs/cgroup/pids ro,nosuid,nodev,noexec,relatime shared:64 - cgroup cgroup rw,pids
+100 93 0:27 / /sys/fs/cgroup/cpuset ro,nosuid,nodev,noexec,relatime shared:65 - cgroup cgroup rw,cpuset
+101 93 0:25 / /sys/fs/cgroup/freezer ro,nosuid,nodev,noexec,relatime shared:66 - cgroup cgroup rw,freezer
+102 93 0:28 / /sys/fs/cgroup/cpu,cpuacct ro,nosuid,nodev,noexec,relatime shared:67 - cgroup cgroup rw,cpu,cpuacct
+103 93 0:26 / /sys/fs/cgroup/devices ro,nosuid,nodev,noexec,relatime shared:68 - cgroup cgroup rw,devices
+104 93 0:23 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:69 - cgroup cgroup rw,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd
+105 232 0:54 /proc-sys-kernel-random-boot-id//deleted /proc/sys/kernel/random/boot_id ro,nosuid,nodev shared:54 - tmpfs tmpfs rw,mode=755
+106 231 0:54 /proc-sys-kernel-random-boot-id//deleted /proc/sys/kernel/random/boot_id rw,nosuid,nodev shared:54 - tmpfs tmpfs rw,mode=755
+107 231 0:54 /kmsg//deleted /proc/kmsg rw,nosuid,nodev shared:54 - tmpfs tmpfs rw,mode=755
+97 222 0:57 / /dev/mqueue rw,relatime shared:70 - mqueue mqueue rw
+108 222 0:60 / /dev/hugepages rw,relatime shared:71 - hugetlbfs hugetlbfs rw
+109 226 0:61 / /run/user/0 rw,nosuid,nodev,relatime shared:72 - tmpfs tmpfs rw,size=1634120k,mode=700
index 818d7194ae3ffeb5a204fe17e14e5bb29c14398b..3a4422b37c298112ef99cf7bc360f6211f99a1e4 100755 (executable)
@@ -41,4 +41,9 @@ $TS_CMD_FINDMNT /sys --submounts --kernel --tab-file "$TS_SELF/files/mountinfo"
 echo rc=$? >> $TS_OUTPUT
 ts_finalize_subtest
 
+ts_init_subtest "messy-mountinfo"
+$TS_CMD_FINDMNT --tab-file "$TS_SELF/files/mountinfo-messy" &> $TS_OUTPUT
+echo rc=$? >> $TS_OUTPUT
+ts_finalize_subtest
+
 ts_finalize