From: Zbigniew Jędrzejewski-Szmek Date: Thu, 24 Sep 2020 12:55:57 +0000 (+0200) Subject: fstab,crypttab: allow escaping of commas X-Git-Tag: v247-rc1~138^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7bb553bb98a57b4e03804f8192bdc5a534325582;p=thirdparty%2Fsystemd.git fstab,crypttab: allow escaping of commas Fixes #17035. We use "," as the separator between arguments in fstab and crypttab options field, but the kernel started using "," within arguments. Users will need to escape those nested commas. --- diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 78efe19f238..10472bde266 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -294,7 +294,7 @@ static int parse_options(const char *options) { _cleanup_free_ char *word = NULL; int r; - r = extract_first_word(&options, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS); + r = extract_first_word(&options, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS | EXTRACT_UNESCAPE_SEPARATORS); if (r < 0) return log_error_errno(r, "Failed to parse options: %m"); if (r == 0) @@ -874,6 +874,9 @@ static int run(int argc, char *argv[]) { return r; } + log_debug("%s %s ← %s type=%s cipher=%s", __func__, + argv[2], argv[3], strempty(arg_type), strempty(arg_cipher)); + /* A delicious drop of snake oil */ (void) mlockall(MCL_FUTURE); diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c index d883eca5c78..ca888136023 100644 --- a/src/shared/fstab-util.c +++ b/src/shared/fstab-util.c @@ -95,7 +95,19 @@ int fstab_filter_options(const char *opts, const char *names, if (!ret_filtered) { for (const char *word = opts;;) { - const char *end = word + strcspn(word, ","); + const char *end = word; + + /* Look for an *non-escaped* comma separator. Only commas can be escaped, so "\," is + * the only valid escape sequence, so we can do a very simple test here. */ + for (;;) { + size_t n = strcspn(end, ","); + + end += n; + if (n > 0 && end[-1] == '\\') + end++; + else + break; + } NULSTR_FOREACH(name, names) { if (end < word + strlen(name)) @@ -128,9 +140,10 @@ int fstab_filter_options(const char *opts, const char *names, break; } } else { - stor = strv_split(opts, ","); - if (!stor) - return -ENOMEM; + r = strv_split_full(&stor, opts, ",", EXTRACT_DONT_COALESCE_SEPARATORS | EXTRACT_UNESCAPE_SEPARATORS); + if (r < 0) + return r; + strv = memdup(stor, sizeof(char*) * (strv_length(stor) + 1)); if (!strv) return -ENOMEM; @@ -165,7 +178,7 @@ answer: if (ret_filtered) { char *f; - f = strv_join(strv, ","); + f = strv_join_full(strv, ",", NULL, true); if (!f) return -ENOMEM; diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c index 187be69d15e..f3506045a1f 100644 --- a/src/test/test-fstab-util.c +++ b/src/test/test-fstab-util.c @@ -13,12 +13,11 @@ int fstab_filter_options(const char *opts, const char *names, */ static void do_fstab_filter_options(const char *opts, - const char *remove, - int r_expected, - const char *name_expected, - const char *value_expected, - const char *filtered_expected) { - + const char *remove, + int r_expected, + const char *name_expected, + const char *value_expected, + const char *filtered_expected) { int r; const char *name; _cleanup_free_ char *value = NULL, *filtered = NULL; @@ -34,7 +33,7 @@ static void do_fstab_filter_options(const char *opts, /* also test the malloc-less mode */ r = fstab_filter_options(opts, remove, &name, NULL, NULL); - log_info("\"%s\" → %d, \"%s\", expected %d, \"%s\"", + log_info("\"%s\" → %d, \"%s\", expected %d, \"%s\"\n-", opts, r, name, r_expected, name_expected); assert_se(r == r_expected); @@ -54,6 +53,12 @@ static void test_fstab_filter_options(void) { do_fstab_filter_options("opt,other", "x-opt\0opt\0", 1, "opt", NULL, "other"); do_fstab_filter_options("x-opt,other", "opt\0x-opt\0", 1, "x-opt", NULL, "other"); + do_fstab_filter_options("opt=0\\,1,other", "opt\0x-opt\0", 1, "opt", "0,1", "other"); + do_fstab_filter_options("opt=0,other,x-opt\\,foobar", "x-opt\0opt\0", 1, "opt", "0", "other,x-opt\\,foobar"); + do_fstab_filter_options("opt,other,x-opt\\,part", "opt\0x-opt\0", 1, "opt", NULL, "other,x-opt\\,part"); + do_fstab_filter_options("opt,other,part\\,x-opt", "x-opt\0opt\0", 1, "opt", NULL, "other,part\\,x-opt"); + do_fstab_filter_options("opt,other\\,\\,\\,opt,x-part", "opt\0x-opt\0", 1, "opt", NULL, "other\\,\\,\\,opt,x-part"); + do_fstab_filter_options("opto=0,other", "opt\0x-opt\0", 0, NULL, NULL, NULL); do_fstab_filter_options("opto,other", "opt\0x-opt\0", 0, NULL, NULL, NULL); do_fstab_filter_options("x-opto,other", "opt\0x-opt\0", 0, NULL, NULL, NULL);