diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2014-11-20 16:40:00 +0100 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2014-11-20 16:40:00 +0100 |
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 b92bd1829cf..eee7a62e1c0 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -462,11 +462,34 @@ static const match_table_t ovl_tokens = { {OPT_ERR, NULL} }; +static char *ovl_next_opt(char **s) +{ + char *sbegin = *s; + char *p; + + if (sbegin == NULL) + return NULL; + + for (p = sbegin; *p; p++) { + if (*p == '\\') { + p++; + if (!*p) + break; + } else if (*p == ',') { + *p = '\0'; + *s = p + 1; + return sbegin; + } + } + *s = NULL; + return sbegin; +} + static int ovl_parse_opt(char *opt, struct ovl_config *config) { char *p; - while ((p = strsep(&opt, ",")) != NULL) { + while ((p = ovl_next_opt(&opt)) != NULL) { int token; substring_t args[MAX_OPT_ARGS]; @@ -554,15 +577,34 @@ out_dput: goto out_unlock; } +static void ovl_unescape(char *s) +{ + char *d = s; + + for (;; s++, d++) { + if (*s == '\\') + s++; + *d = *s; + if (!*s) + break; + } +} + static int ovl_mount_dir(const char *name, struct path *path) { int err; + char *tmp = kstrdup(name, GFP_KERNEL); + + if (!tmp) + return -ENOMEM; - err = kern_path(name, LOOKUP_FOLLOW, path); + ovl_unescape(tmp); + err = kern_path(tmp, LOOKUP_FOLLOW, path); if (err) { - pr_err("overlayfs: failed to resolve '%s': %i\n", name, err); + pr_err("overlayfs: failed to resolve '%s': %i\n", tmp, err); err = -EINVAL; } + kfree(tmp); return err; } |