lib: use quote-aware tokenizer for mount option parsing

The strtok_r(opts, ",", ...) based option splitter does not understand
double-quoted values.  SELinux MLS labels can contain commas inside
quotes (e.g., context="system_u:object_r:root_t:s0:c0,c1"), which
would be incorrectly split into separate tokens.

Replace strtok_r with a quote-aware next_mount_opt() helper that skips
commas inside double-quoted regions.

Signed-off-by: Jingbo Xu <jingbo.xu@linux.alibaba.com>
Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
This commit is contained in:
Jingbo Xu
2026-06-16 10:06:11 +08:00
committed by Bernd Schubert
parent 24d40b2a7c
commit 9e22f4e59e
+38 -4
View File
@@ -263,11 +263,44 @@ static int is_mtab_only_opt(const char *opt)
strcmp(opt, "rw") == 0;
}
/*
* Example: parsing rw,fd=7,context="u:r:t,s0"
*
* call 3 -> "context=\"u:r:t,s0\"" (comma inside quotes kept, not split)
* call 4 -> NULL
*/
static char *next_mount_opt(char **cursor)
{
char *opt_start;
char *scan;
int in_quote = 0;
if (!*cursor || !**cursor)
return NULL;
opt_start = *cursor;
for (scan = opt_start; *scan; scan++) {
if (*scan == '"')
in_quote = !in_quote;
else if (*scan == ',' && !in_quote)
break;
}
if (*scan == ',') {
*scan = '\0';
*cursor = scan + 1;
} else {
*cursor = scan;
}
return opt_start;
}
int apply_fsconfig_mount_opts(int fsfd, const char *opts)
{
char *opts_copy;
char *pos;
char *opt;
char *saveptr;
int res;
if (!opts || !*opts)
@@ -279,8 +312,10 @@ int apply_fsconfig_mount_opts(int fsfd, const char *opts)
return -ENOMEM;
}
opt = strtok_r(opts_copy, ",", &saveptr);
while (opt) {
pos = opts_copy;
while ((opt = next_mount_opt(&pos)) != NULL) {
if (!*opt)
continue;
/*
* Skip mount attributes, they're handled by fsmount()
* not fsconfig().
@@ -303,7 +338,6 @@ int apply_fsconfig_mount_opts(int fsfd, const char *opts)
return res;
}
}
opt = strtok_r(NULL, ",", &saveptr);
}
free(opts_copy);