]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: (mountinfo) parse empty strings in source
authorAlban Crequy <alban@kinvolk.io>
Fri, 22 Jun 2018 11:54:25 +0000 (13:54 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 10 Jul 2018 11:48:38 +0000 (13:48 +0200)
The source of a mount in /proc/self/mountinfo can unfortunately be an
empty string. Before this patch, 'mount' and 'mountpoint' fail as
following:

  $ sudo mount -t tmpfs "" /tmp/bb
  $ mount
  mount: /proc/self/mountinfo: parse error at line 64 -- ignored
  $ mountpoint /tmp/bb
  /tmp/bb is not a mountpoint

This patch fixes the parsing. It is unfortunately more complex because
sscanf() does not handle fields with empty strings easily.

Other projects have their own parser for mountinfo and have similar
issues. I know of runc and runtime-tools (I'll send a patch for those
two) but there are probably others.

Signed-off-by: Alban Crequy <alban@kinvolk.io>
libmount/src/tab_parse.c

index 3ed84ebc288cd19bbd08a534774404948ecc465d..4944d5f8c33794897c45e65073878c1014bcaa6a 100644 (file)
@@ -173,13 +173,36 @@ static int mnt_parse_mountinfo_line(struct libmnt_fs *fs, char *s)
                fs->opt_fields = strndup(s + 1, p - s - 1);
        s = p + 3;
 
-       rc += sscanf(s, UL_SCNsA" "     /* (8) FS type */
-                       UL_SCNsA" "     /* (9) source */
-                       UL_SCNsA,       /* (10) fs options (fs specific) */
+       end = 0;
+       rc += sscanf(s, UL_SCNsA"%n",   /* (8) FS type */
 
                        &fstype,
-                       &src,
-                       &fs->fs_optstr);
+                       &end);
+
+       if (rc >= 8 && end > 0)
+               s += end;
+       if (s[0] == ' ')
+               s++;
+
+       /* (9) source can unfortunately be an empty string "" and scanf does
+        * not work well with empty string. Test with:
+        *     $ sudo mount -t tmpfs "" /tmp/bb
+        *     $ mountpoint /tmp/bb
+        * */
+       if (s[0] == ' ') {
+               src = strdup("");
+               s++;
+               rc++;
+               rc += sscanf(s, UL_SCNsA,       /* (10) fs options (fs specific) */
+
+                               &fs->fs_optstr);
+       } else {
+               rc += sscanf(s, UL_SCNsA" "     /* (9) source */
+                               UL_SCNsA,       /* (10) fs options (fs specific) */
+
+                               &src,
+                               &fs->fs_optstr);
+       }
 
        if (rc >= 10) {
                size_t sz;