diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2014-11-20 10:40:00 -0500 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2014-11-20 10:40:00 -0500 |
commit | 91c77947133f7aef851b625701e182d3f99d14a9 (patch) | |
tree | 9ba1e0db29e4b7e6835d32bae45ec45b62371896 /fs | |
parent | 521484639ec19a6f1ed56de6993feb255f5f676c (diff) |
ovl: allow filenames with comma
Allow option separator (comma) to be escaped with backslash.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/overlayfs/super.c | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index b92bd1829cf7..eee7a62e1c0e 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -462,11 +462,34 @@ static const match_table_t ovl_tokens = { | |||
462 | {OPT_ERR, NULL} | 462 | {OPT_ERR, NULL} |
463 | }; | 463 | }; |
464 | 464 | ||
465 | static char *ovl_next_opt(char **s) | ||
466 | { | ||
467 | char *sbegin = *s; | ||
468 | char *p; | ||
469 | |||
470 | if (sbegin == NULL) | ||
471 | return NULL; | ||
472 | |||
473 | for (p = sbegin; *p; p++) { | ||
474 | if (*p == '\\') { | ||
475 | p++; | ||
476 | if (!*p) | ||
477 | break; | ||
478 | } else if (*p == ',') { | ||
479 | *p = '\0'; | ||
480 | *s = p + 1; | ||
481 | return sbegin; | ||
482 | } | ||
483 | } | ||
484 | *s = NULL; | ||
485 | return sbegin; | ||
486 | } | ||
487 | |||
465 | static int ovl_parse_opt(char *opt, struct ovl_config *config) | 488 | static int ovl_parse_opt(char *opt, struct ovl_config *config) |
466 | { | 489 | { |
467 | char *p; | 490 | char *p; |
468 | 491 | ||
469 | while ((p = strsep(&opt, ",")) != NULL) { | 492 | while ((p = ovl_next_opt(&opt)) != NULL) { |
470 | int token; | 493 | int token; |
471 | substring_t args[MAX_OPT_ARGS]; | 494 | substring_t args[MAX_OPT_ARGS]; |
472 | 495 | ||
@@ -554,15 +577,34 @@ out_dput: | |||
554 | goto out_unlock; | 577 | goto out_unlock; |
555 | } | 578 | } |
556 | 579 | ||
580 | static void ovl_unescape(char *s) | ||
581 | { | ||
582 | char *d = s; | ||
583 | |||
584 | for (;; s++, d++) { | ||
585 | if (*s == '\\') | ||
586 | s++; | ||
587 | *d = *s; | ||
588 | if (!*s) | ||
589 | break; | ||
590 | } | ||
591 | } | ||
592 | |||
557 | static int ovl_mount_dir(const char *name, struct path *path) | 593 | static int ovl_mount_dir(const char *name, struct path *path) |
558 | { | 594 | { |
559 | int err; | 595 | int err; |
596 | char *tmp = kstrdup(name, GFP_KERNEL); | ||
597 | |||
598 | if (!tmp) | ||
599 | return -ENOMEM; | ||
560 | 600 | ||
561 | err = kern_path(name, LOOKUP_FOLLOW, path); | 601 | ovl_unescape(tmp); |
602 | err = kern_path(tmp, LOOKUP_FOLLOW, path); | ||
562 | if (err) { | 603 | if (err) { |
563 | pr_err("overlayfs: failed to resolve '%s': %i\n", name, err); | 604 | pr_err("overlayfs: failed to resolve '%s': %i\n", tmp, err); |
564 | err = -EINVAL; | 605 | err = -EINVAL; |
565 | } | 606 | } |
607 | kfree(tmp); | ||
566 | return err; | 608 | return err; |
567 | } | 609 | } |
568 | 610 | ||