diff options
author | Richard Maw <richard.maw@codethink.co.uk> | 2015-05-26 16:03:38 +0000 |
---|---|---|
committer | Richard Maw <richard.maw@codethink.co.uk> | 2015-05-26 16:44:38 +0000 |
commit | c6198d8b08587c67ea45cd20207eed97d9e9e3dd (patch) | |
tree | 4c490553d37366fa4a0f117859976b014bbe5a49 | |
parent | 5f1326fb2aa87eddd928bd72d949dfcc2a151240 (diff) | |
download | systemd-c6198d8b08587c67ea45cd20207eed97d9e9e3dd.tar.gz |
nspawn: escape paths in overlay mount options
Overlayfs uses , as an option separator and : as a list separator. These
characters are both valid in file paths, so overlayfs allows file paths
which contain these characters to backslash escape these values.
-rw-r--r-- | src/nspawn/nspawn.c | 63 |
1 files changed, 56 insertions, 7 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index c40d50fc4a..f7580f9ec3 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1237,6 +1237,42 @@ static int mount_tmpfs(const char *dest, CustomMount *m) { return 0; } +static char *escaped_overlay_path(const char *path) { + _cleanup_free_ char *colon_escaped = NULL; + char *comma_escaped = NULL; + + colon_escaped = strreplace(path, ":", "\\:"); + if (!colon_escaped) + return NULL; + + comma_escaped = strreplace(colon_escaped, ",", "\\,"); + + return comma_escaped; +} + +static char *joined_and_escaped_lower_dirs(char * const *lower) { + _cleanup_free_ char *s = NULL; + char *ret = NULL; + char * const *path; + bool first = true; + + STRV_FOREACH_BACKWARDS(path, lower) { + _cleanup_free_ char *escaped_path = NULL; + escaped_path = escaped_overlay_path(*path); + if (first) { + if (!strextend(&s, escaped_path, NULL)) + return NULL; + first = false; + } else + if (!strextend(&s, ":", escaped_path, NULL)) + return NULL; + } + + ret = s; + s = NULL; + return ret; +} + static int mount_overlay(const char *dest, CustomMount *m) { _cleanup_free_ char *lower = NULL; const char *where, *options; @@ -1253,19 +1289,32 @@ static int mount_overlay(const char *dest, CustomMount *m) { (void) mkdir_p_label(m->source, 0755); - strv_reverse(m->lower); - lower = strv_join(m->lower, ":"); - strv_reverse(m->lower); + lower = joined_and_escaped_lower_dirs(m->lower); if (!lower) return log_oom(); - if (m->read_only) - options = strjoina("lowerdir=", m->source, ":", lower); - else { + if (m->read_only) { + _cleanup_free_ char *escaped_source = NULL; + + escaped_source = escaped_overlay_path(m->source); + if (!escaped_source) + return log_oom(); + + options = strjoina("lowerdir=", escaped_source, ":", lower); + } else { + _cleanup_free_ char *escaped_source = NULL, *escaped_work_dir = NULL; + assert(m->work_dir); (void) mkdir_label(m->work_dir, 0700); - options = strjoina("lowerdir=", lower, ",upperdir=", m->source, ",workdir=", m->work_dir); + escaped_source = escaped_overlay_path(m->source); + if (!escaped_source) + return log_oom(); + escaped_work_dir = escaped_overlay_path(m->work_dir); + if (!escaped_work_dir) + return log_oom(); + + options = strjoina("lowerdir=", lower, ",upperdir=", escaped_source, ",workdir=", escaped_work_dir); } if (mount("overlay", where, "overlay", m->read_only ? MS_RDONLY : 0, options) < 0) |