]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: accept '\' as escape for options separator
authorKarel Zak <kzak@redhat.com>
Tue, 28 Nov 2023 13:40:48 +0000 (14:40 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 28 Nov 2023 14:25:46 +0000 (15:25 +0100)
The libmount library can accept any characters as an option value when
the value is quoted (e.g., foo="b,a,r"). However, overlayfs users have
been using '\' as an escape character (e.g., lowerdir=foo\,bar).

Although this escaping mechanism was never officially supported by
libmount/mount, it worked for the old mount(2) API because it kept the
options string unparsed for the mount(2) syscall.

The introduction of the new mount API, which utilizes fsconfig(2) per
option, has brought attention to this issue.

This patch addresses the problem by introducing official support for
'\' as an escape character for options separator.

Suggested-by: Miklos Szeredi <miklos@szeredi.hu>
References: https://lore.kernel.org/all/CAOQ4uxhgUSPkYAV8SJu-SFszkJcVO3-M4DXf46nJUtXODrPk2g@mail.gmail.com/T/#ma8e6cfc1ce7229abc089e03eed99b23b90d701e5
Signed-off-by: Karel Zak <kzak@redhat.com>
(cherry picked from commit f6c29efa929cb8c741591ab38061e7921d53a997)

lib/strutils.c
libmount/src/hook_mount.c

index 21751fd89e9179df65d2f301c11b047890c6967e..6229a6e6765d33996f117cd3b447acf0ffcc277c 100644 (file)
@@ -1190,7 +1190,7 @@ int ul_optstr_next(char **optstr, char **name, size_t *namesz,
                        continue;               /* still in quoted block */
                if (!sep && p > start && *p == '=')
                        sep = p;                /* name and value separator */
-               if (*p == ',')
+               if (*p == ',' && (p == optstr0 || *(p - 1) != '\\'))
                        stop = p;               /* terminate the option item */
                else if (*(p + 1) == '\0')
                        stop = p + 1;           /* end of optstr */
index 4b2a534f74e280e0dab27acf6cb80bab25634500..dc3dfa71ad3190d2bb9d3d84a8da7ca660e3a037 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "mountP.h"
 #include "fileutils.h" /* statx() fallback */
+#include "strutils.h"
 #include "mount-api-utils.h"
 #include "linux_version.h"
 
@@ -121,12 +122,23 @@ static inline int fsconfig_set_value(
                        const char *name, const char *value)
 {
        int rc;
+       char *p = NULL;
 
-       DBG(HOOK, ul_debugobj(hs, "  fsconfig(name=%s,value=%s)", name,
+       if (value && strstr(value, "\\,")) {
+               p = strdup(value);
+               if (!p)
+                       return -EINVAL;
+
+               strrem(p, '\\');
+               value = p;
+       }
+
+       DBG(HOOK, ul_debugobj(hs, "  fsconfig(name=\"%s\" value=\"%s\")", name,
                                value ? : ""));
-       if (value)
+       if (value) {
                rc = fsconfig(fd, FSCONFIG_SET_STRING, name, value, 0);
-       else
+               free(p);
+       } else
                rc = fsconfig(fd, FSCONFIG_SET_FLAG, name, NULL, 0);
 
        set_syscall_status(cxt, "fsconfig", rc == 0);