summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2017-10-28 17:02:03 -0400
committerLuke Shumaker <lukeshu@lukeshu.com>2017-10-28 17:02:03 -0400
commitf54f8e2b14d85ee250509b51562d990a5d7d40a6 (patch)
treea850e77c8c64c9f2829f51be884295f3c42571b2
parent1127e1c6e5d4fad15022bcd4a3eaf9a7618d5f92 (diff)
a
-rw-r--r--src/nspawn/nspawn-mount.c422
-rw-r--r--src/nspawn/nspawn-mount.h27
2 files changed, 0 insertions, 449 deletions
diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c
index a47eb31922..051eacb3ba 100644
--- a/src/nspawn/nspawn-mount.c
+++ b/src/nspawn/nspawn-mount.c
@@ -39,199 +39,6 @@
#include "user-util.h"
#include "util.h"
-CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t) {
- CustomMount *c, *ret;
-
- assert(l);
- assert(n);
- assert(t >= 0);
- assert(t < _CUSTOM_MOUNT_TYPE_MAX);
-
- c = realloc_multiply(*l, (*n + 1), sizeof(CustomMount));
- if (!c)
- return NULL;
-
- *l = c;
- ret = *l + *n;
- (*n)++;
-
- *ret = (CustomMount) { .type = t };
-
- return ret;
-}
-
-void custom_mount_free_all(CustomMount *l, unsigned n) {
- unsigned i;
-
- for (i = 0; i < n; i++) {
- CustomMount *m = l + i;
-
- free(m->source);
- free(m->destination);
- free(m->options);
-
- if (m->work_dir) {
- (void) rm_rf(m->work_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
- 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);
- }
-
- free(l);
-}
-
-static int custom_mount_compare(const void *a, const void *b) {
- const CustomMount *x = a, *y = b;
- int r;
-
- r = path_compare(x->destination, y->destination);
- if (r != 0)
- return r;
-
- if (x->type < y->type)
- return -1;
- if (x->type > y->type)
- return 1;
-
- return 0;
-}
-
-static char *resolve_source_path(const char *dest, const char *source) {
-
- if (!source)
- return NULL;
-
- if (source[0] == '+')
- return prefix_root(dest, source + 1);
-
- return strdup(source);
-}
-
-int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) {
- unsigned i;
- int r;
-
- /* Prepare all custom mounts. This will make source we know all temporary directories. This is called in the
- * parent process, so that we know the temporary directories to remove on exit before we fork off the
- * children. */
-
- assert(l || n == 0);
-
- /* Order the custom mounts, and make sure we have a working directory */
- qsort_safe(l, n, sizeof(CustomMount), custom_mount_compare);
-
- for (i = 0; i < n; i++) {
- CustomMount *m = l + i;
-
- if (m->source) {
- char *s;
-
- s = resolve_source_path(dest, m->source);
- if (!s)
- return log_oom();
-
- 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) {
- char **j;
-
- STRV_FOREACH(j, m->lower) {
- char *s;
-
- s = resolve_source_path(dest, *j);
- if (!s)
- return log_oom();
-
- free(*j);
- *j = s;
- }
-
- if (m->work_dir) {
- char *s;
-
- s = resolve_source_path(dest, m->work_dir);
- if (!s)
- return log_oom();
-
- free(m->work_dir);
- m->work_dir = s;
- } else {
- assert(m->source);
-
- r = tempfn_random(m->source, NULL, &m->work_dir);
- if (r < 0)
- return log_error_errno(r, "Failed to acquire working directory: %m");
- }
-
- (void) mkdir_label(m->work_dir, 0700);
- }
- }
-
- return 0;
-}
-
-int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s) {
- _cleanup_free_ char *path = NULL, *opts = NULL;
- const char *p = s;
- CustomMount *m;
- int r;
-
- assert(l);
- assert(n);
- assert(s);
-
- r = extract_first_word(&p, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
- if (r < 0)
- return r;
- if (r == 0)
- return -EINVAL;
-
- if (isempty(p))
- opts = strdup("mode=0755");
- else
- opts = strdup(p);
- if (!opts)
- return -ENOMEM;
-
- if (!path_is_absolute(path))
- return -EINVAL;
-
- m = custom_mount_add(l, n, CUSTOM_MOUNT_TMPFS);
- if (!m)
- return -ENOMEM;
-
- m->destination = path;
- m->options = opts;
-
- path = opts = NULL;
- return 0;
-}
static int tmpfs_patch_options(
const char *options,
@@ -505,235 +312,6 @@ int mount_all(const char *dest,
return 0;
}
-static int parse_mount_bind_options(const char *options, unsigned long *mount_flags, char **mount_opts) {
- const char *p = options;
- unsigned long flags = *mount_flags;
- char *opts = NULL;
- int r;
-
- assert(options);
-
- for (;;) {
- _cleanup_free_ char *word = NULL;
-
- r = extract_first_word(&p, &word, ",", 0);
- if (r < 0)
- return log_error_errno(r, "Failed to extract mount option: %m");
- if (r == 0)
- break;
-
- if (streq(word, "rbind"))
- flags |= MS_REC;
- else if (streq(word, "norbind"))
- flags &= ~MS_REC;
- else {
- log_error("Invalid bind mount option: %s", word);
- return -EINVAL;
- }
- }
-
- *mount_flags = flags;
- /* in the future mount_opts will hold string options for mount(2) */
- *mount_opts = opts;
-
- return 0;
-}
-
-static int mount_bind(const char *dest, CustomMount *m) {
-
- _cleanup_free_ char *mount_opts = NULL, *where = NULL;
- unsigned long mount_flags = MS_BIND | MS_REC;
- struct stat source_st, dest_st;
- int r;
-
- assert(dest);
- assert(m);
-
- if (m->options) {
- r = parse_mount_bind_options(m->options, &mount_flags, &mount_opts);
- if (r < 0)
- return r;
- }
-
- if (stat(m->source, &source_st) < 0)
- return log_error_errno(errno, "Failed to stat %s: %m", m->source);
-
- r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
- if (r < 0)
- return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
- if (r > 0) { /* Path exists already? */
-
- if (stat(where, &dest_st) < 0)
- return log_error_errno(errno, "Failed to stat %s: %m", where);
-
- if (S_ISDIR(source_st.st_mode) && !S_ISDIR(dest_st.st_mode)) {
- log_error("Cannot bind mount directory %s on file %s.", m->source, where);
- return -EINVAL;
- }
-
- if (!S_ISDIR(source_st.st_mode) && S_ISDIR(dest_st.st_mode)) {
- log_error("Cannot bind mount file %s on directory %s.", m->source, where);
- return -EINVAL;
- }
-
- } else { /* Path doesn't exist yet? */
- r = mkdir_parents_label(where, 0755);
- if (r < 0)
- return log_error_errno(r, "Failed to make parents of %s: %m", where);
-
- /* Create the mount point. Any non-directory file can be
- * mounted on any non-directory file (regular, fifo, socket,
- * char, block).
- */
- if (S_ISDIR(source_st.st_mode))
- r = mkdir_label(where, 0755);
- else
- r = touch(where);
- if (r < 0)
- return log_error_errno(r, "Failed to create mount point %s: %m", where);
-
- }
-
- r = mount_verbose(LOG_ERR, m->source, where, NULL, mount_flags, mount_opts);
- if (r < 0)
- return r;
-
- if (m->read_only) {
- r = bind_remount_recursive(where, true, NULL);
- if (r < 0)
- return log_error_errno(r, "Read-only bind mount failed: %m");
- }
-
- return 0;
-}
-
-static int mount_tmpfs(
- const char *dest,
- CustomMount *m,
- bool userns, uid_t uid_shift, uid_t uid_range,
- const char *selinux_apifs_context) {
-
- const char *options;
- _cleanup_free_ char *buf = NULL, *where = NULL;
- int r;
-
- assert(dest);
- assert(m);
-
- r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
- if (r < 0)
- return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
- if (r == 0) { /* Doesn't exist yet? */
- r = mkdir_p_label(where, 0755);
- if (r < 0)
- return log_error_errno(r, "Creating mount point for tmpfs %s failed: %m", where);
- }
-
- r = tmpfs_patch_options(m->options, userns, uid_shift, uid_range, false, selinux_apifs_context, &buf);
- if (r < 0)
- return log_oom();
- options = r > 0 ? buf : m->options;
-
- return mount_verbose(LOG_ERR, "tmpfs", where, "tmpfs", MS_NODEV|MS_STRICTATIME, options);
-}
-
-static char *joined_and_escaped_lower_dirs(char **lower) {
- _cleanup_strv_free_ char **sv = NULL;
-
- sv = strv_copy(lower);
- if (!sv)
- return NULL;
-
- strv_reverse(sv);
-
- if (!strv_shell_escape(sv, ",:"))
- return NULL;
-
- return strv_join(sv, ":");
-}
-
-static int mount_overlay(const char *dest, CustomMount *m) {
-
- _cleanup_free_ char *lower = NULL, *where = NULL, *escaped_source = NULL;
- const char *options;
- int r;
-
- assert(dest);
- assert(m);
-
- r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
- if (r < 0)
- return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
- if (r == 0) { /* Doesn't exist yet? */
- r = mkdir_label(where, 0755);
- if (r < 0)
- return log_error_errno(r, "Creating mount point for overlay %s failed: %m", where);
- }
-
- (void) mkdir_p_label(m->source, 0755);
-
- lower = joined_and_escaped_lower_dirs(m->lower);
- if (!lower)
- return log_oom();
-
- escaped_source = shell_escape(m->source, ",:");
- if (!escaped_source)
- return log_oom();
-
- if (m->read_only)
- options = strjoina("lowerdir=", escaped_source, ":", lower);
- else {
- _cleanup_free_ char *escaped_work_dir = NULL;
-
- escaped_work_dir = shell_escape(m->work_dir, ",:");
- if (!escaped_work_dir)
- return log_oom();
-
- options = strjoina("lowerdir=", lower, ",upperdir=", escaped_source, ",workdir=", escaped_work_dir);
- }
-
- return mount_verbose(LOG_ERR, "overlay", where, "overlay", m->read_only ? MS_RDONLY : 0, options);
-}
-
-int mount_custom(
- const char *dest,
- CustomMount *mounts, unsigned n,
- bool userns, uid_t uid_shift, uid_t uid_range,
- const char *selinux_apifs_context) {
-
- unsigned i;
- int r;
-
- assert(dest);
-
- for (i = 0; i < n; i++) {
- CustomMount *m = mounts + i;
-
- switch (m->type) {
-
- case CUSTOM_MOUNT_BIND:
- r = mount_bind(dest, m);
- break;
-
- case CUSTOM_MOUNT_TMPFS:
- r = mount_tmpfs(dest, m, userns, uid_shift, uid_range, selinux_apifs_context);
- break;
-
- case CUSTOM_MOUNT_OVERLAY:
- r = mount_overlay(dest, m);
- break;
-
- default:
- assert_not_reached("Unknown custom mount type");
- }
-
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
int setup_volatile_state(
const char *directory,
VolatileMode mode,
diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h
index 6549a32dd5..7712e867d2 100644
--- a/src/nspawn/nspawn-mount.h
+++ b/src/nspawn/nspawn-mount.h
@@ -32,36 +32,9 @@ typedef enum MountSettingsMask {
Works only if MOUNT_APPLY_APIVFS_RO is also set. */
} MountSettingsMask;
-typedef enum CustomMountType {
- CUSTOM_MOUNT_BIND,
- CUSTOM_MOUNT_TMPFS,
- CUSTOM_MOUNT_OVERLAY,
- _CUSTOM_MOUNT_TYPE_MAX,
- _CUSTOM_MOUNT_TYPE_INVALID = -1
-} CustomMountType;
-
-typedef struct CustomMount {
- CustomMountType type;
- bool read_only;
- char *source; /* for overlayfs this is the upper directory */
- char *destination;
- char *options;
- char *work_dir;
- char **lower;
- char *rm_rf_tmpdir;
-} CustomMount;
-
-CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t);
-void custom_mount_free_all(CustomMount *l, unsigned n);
-int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n);
-
-int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s);
-
int mount_all(const char *dest, MountSettingsMask mount_settings, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
int mount_sysfs(const char *dest, MountSettingsMask mount_settings);
-int mount_custom(const char *dest, CustomMount *mounts, unsigned n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
-
int setup_volatile(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
int setup_volatile_state(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);