From c7a4890ce42b6c074ba622c4b82bfd3f738df736 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 30 Nov 2016 18:57:42 +0100 Subject: [PATCH] nspawn: optionally, automatically allocated --bind=/--overlay source from /var/tmp This extends the --bind= and --overlay= syntax so that an empty string as source/upper directory is taken as request to automatically allocate a temporary directory below /var/tmp, whose lifetime is bound to the nspawn runtime. In combination with the "+" path extension this permits a switch "--overlay=+/var::/var" in order to use the container's shipped /var, combine it with a writable temporary directory and mount it to the runtime /var of the container. --- man/systemd-nspawn.xml | 27 ++++++++++++++--------- src/nspawn/nspawn-mount.c | 45 +++++++++++++++++++++++++++++++++------ src/nspawn/nspawn-mount.h | 1 + 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index 84fa9cadef..cd0a90d82f 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -741,16 +741,18 @@ Bind mount a file or directory from the host into the container. Takes one of: a path - argument — in which case the specified path will be mounted from the host to the same path in the container —, - or a colon-separated pair of paths — in which case the first specified path is the source in the host, and the - second path is the destination in the container —, or a colon-separated triple of source path, destination path + argument — in which case the specified path will be mounted from the host to the same path in the container, or + a colon-separated pair of paths — in which case the first specified path is the source in the host, and the + second path is the destination in the container, or a colon-separated triple of source path, destination path and mount options. The source path may optionally be prefixed with a + character. If so, the - source path is taken relative to the images root directory. This permits setting up bind mounts within the - container image. Mount options are comma-separated and currently, only "rbind" and "norbind" are allowed, - controlling whether to create a recursive or a regular bind mount. Defaults to "rbind". Backslash escapes are - interpreted, so \: may be used to embed colons in either path. This option may be specified - multiple times for creating multiple independent bind mount points. The option - creates read-only bind mounts. + source path is taken relative to the image's root directory. This permits setting up bind mounts within the + container image. The source path may be specified as empty string, in which case a temporary directory below + the host's /var/tmp directory is used. It is automatically removed when the container is + shut down. Mount options are comma-separated and currently, only and + are allowed, controlling whether to create a recursive or a regular bind + mount. Defaults to "rbind". Backslash escapes are interpreted, so \: may be used to embed + colons in either path. This option may be specified multiple times for creating multiple independent bind + mount points. The option creates read-only bind mounts. @@ -805,7 +807,12 @@ two paths have to be specified. The source paths may optionally be prefixed with + character. If so they are taken - relative to the image's root directory. + relative to the image's root directory. The uppermost source path may also be specified as empty string, in + which case a temporary directory below the host's /var/tmp is used. The directory is + removed automatically when the container is shut down. This behaviour is useful in order to make read-only + container directories writable while the container is running. For example, use the + --overlay=+/var::/var option in order to automatically overlay a writable temporary + directory on a read-only /var directory. For details about overlay file systems, see overlayfs.txt. Note diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 291a88a9ac..3a069cf0e0 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -75,6 +75,11 @@ void custom_mount_free_all(CustomMount *l, unsigned n) { free(m->work_dir); } + if (m->rm_rf_tmpdir) { + (void) rm_rf(m->rm_rf_tmpdir, REMOVE_ROOT|REMOVE_PHYSICAL); + free(m->rm_rf_tmpdir); + } + strv_free(m->lower); } @@ -142,6 +147,24 @@ int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) { free(m->source); m->source = s; + } else { + /* No source specified? In that case, use a throw-away temporary directory in /var/tmp */ + + m->rm_rf_tmpdir = strdup("/var/tmp/nspawn-temp-XXXXXX"); + if (!m->rm_rf_tmpdir) + return log_oom(); + + if (!mkdtemp(m->rm_rf_tmpdir)) { + m->rm_rf_tmpdir = mfree(m->rm_rf_tmpdir); + return log_error_errno(errno, "Failed to acquire temporary directory: %m"); + } + + m->source = strjoin(m->rm_rf_tmpdir, "/src"); + if (!m->source) + return log_oom(); + + if (mkdir(m->source, 0755) < 0) + return log_error_errno(errno, "Failed to create %s: %m", m->source); } if (m->type == CUSTOM_MOUNT_OVERLAY) { @@ -207,8 +230,11 @@ int bind_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only return -ENOMEM; } - if (!source_path_is_valid(source)) + if (isempty(source)) + source = NULL; + else if (!source_path_is_valid(source)) return -EINVAL; + if (!path_is_absolute(destination)) return -EINVAL; @@ -288,19 +314,26 @@ int overlay_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_o if (!destination) return -ENOMEM; } else { - int i; + char **i; /* If more than two parameters are specified, the last one is the destination, the second to last one * the "upper", and all before that the "lower" directories. */ - for (i = 0; i < k - 1; i++) - if (!source_path_is_valid(lower[i])) - return -EINVAL; - destination = lower[k - 1]; upper = lower[k - 2]; lower[k - 2] = NULL; + STRV_FOREACH(i, lower) + if (!source_path_is_valid(*i)) + return -EINVAL; + + /* If the upper directory is unspecified, then let's create it automatically as a throw-away directory + * in /var/tmp */ + if (isempty(upper)) + upper = NULL; + else if (!source_path_is_valid(upper)) + return -EINVAL; + if (!path_is_absolute(destination)) return -EINVAL; } diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h index dc8be438ac..467082a737 100644 --- a/src/nspawn/nspawn-mount.h +++ b/src/nspawn/nspawn-mount.h @@ -56,6 +56,7 @@ typedef struct CustomMount { char *options; char *work_dir; char **lower; + char *rm_rf_tmpdir; } CustomMount; CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t);