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.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2020-09-25 13:36:34 +02:00
parent 48904c8bfd
commit 7bb553bb98
3 changed files with 34 additions and 13 deletions
+4 -1
View File
@@ -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);
+18 -5
View File
@@ -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;
+12 -7
View File
@@ -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);