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 | |
| 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>
| -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 | ||
