diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/namespace.c | 109 |
1 files changed, 62 insertions, 47 deletions
diff --git a/src/core/namespace.c b/src/core/namespace.c index 0ef84794c9..1a4d15a800 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -107,6 +107,7 @@ typedef struct MountEntry { unsigned long flags; /* Mount flags used by EMPTY_DIR and TMPFS. Do not include MS_RDONLY here, but please use read_only. */ unsigned n_followed; LIST_HEAD(MountOptions, image_options_const); + char **overlay_layers; } MountEntry; typedef struct MountList { @@ -336,6 +337,7 @@ static void mount_entry_done(MountEntry *p) { p->unprefixed_path_malloc = mfree(p->unprefixed_path_malloc); p->source_malloc = mfree(p->source_malloc); p->options_malloc = mfree(p->options_malloc); + p->overlay_layers = strv_free(p->overlay_layers); } static void mount_list_done(MountList *ml) { @@ -470,7 +472,8 @@ static int append_extensions( size_t n, char **extension_directories) { - _cleanup_strv_free_ char **overlays = NULL; + char ***overlays = NULL; + size_t n_overlays = 0; int r; assert(ml); @@ -480,21 +483,19 @@ static int append_extensions( assert(extension_dir); - /* Prepare a list of overlays, that will have as each element a string suitable for being - * passed as a lowerdir= parameter, so start with the hierarchy on the root. + n_overlays = strv_length(hierarchies); + if (n_overlays == 0) + return 0; + + /* Prepare a list of overlays, that will have as each element a strv containing all the layers that + * will later be concatenated as a lowerdir= parameter for the mount operation. * The overlays vector will have the same number of elements and will correspond to the * hierarchies vector, so they can be iterated upon together. */ - STRV_FOREACH(hierarchy, hierarchies) { - _cleanup_free_ char *prefixed_hierarchy = NULL; - - prefixed_hierarchy = path_join(root, *hierarchy); - if (!prefixed_hierarchy) - return -ENOMEM; + overlays = new0(char**, n_overlays); + if (!overlays) + return -ENOMEM; - r = strv_consume(&overlays, TAKE_PTR(prefixed_hierarchy)); - if (r < 0) - return r; - } + CLEANUP_ARRAY(overlays, n_overlays, strv_free_many); /* First, prepare a mount for each image, but these won't be visible to the unit, instead * they will be mounted in our propagate directory, and used as a source for the overlay. */ @@ -506,28 +507,18 @@ static int append_extensions( return -ENOMEM; for (size_t j = 0; hierarchies && hierarchies[j]; ++j) { - _cleanup_free_ char *prefixed_hierarchy = NULL, *escaped = NULL, *lowerdir = NULL; - - prefixed_hierarchy = path_join(mount_point, hierarchies[j]); + char *prefixed_hierarchy = path_join(mount_point, hierarchies[j]); if (!prefixed_hierarchy) return -ENOMEM; - escaped = shell_escape(prefixed_hierarchy, ",:"); - if (!escaped) - return -ENOMEM; - - /* Note that lowerdir= parameters are in 'reverse' order, so the - * top-most directory in the overlay comes first in the list. */ - lowerdir = strjoin(escaped, ":", overlays[j]); - if (!lowerdir) - return -ENOMEM; - - free_and_replace(overlays[j], lowerdir); + r = strv_consume(&overlays[j], TAKE_PTR(prefixed_hierarchy)); + if (r < 0) + return r; } MountEntry *me = mount_list_extend(ml); if (!me) - return log_oom_debug(); + return -ENOMEM; *me = (MountEntry) { .path_malloc = TAKE_PTR(mount_point), @@ -565,28 +556,18 @@ static int append_extensions( return -ENOMEM; for (size_t j = 0; hierarchies && hierarchies[j]; ++j) { - _cleanup_free_ char *prefixed_hierarchy = NULL, *escaped = NULL, *lowerdir = NULL; - - prefixed_hierarchy = path_join(mount_point, hierarchies[j]); + char *prefixed_hierarchy = path_join(mount_point, hierarchies[j]); if (!prefixed_hierarchy) return -ENOMEM; - escaped = shell_escape(prefixed_hierarchy, ",:"); - if (!escaped) - return -ENOMEM; - - /* Note that lowerdir= parameters are in 'reverse' order, so the - * top-most directory in the overlay comes first in the list. */ - lowerdir = strjoin(escaped, ":", overlays[j]); - if (!lowerdir) - return -ENOMEM; - - free_and_replace(overlays[j], lowerdir); + r = strv_consume(&overlays[j], TAKE_PTR(prefixed_hierarchy)); + if (r < 0) + return r; } MountEntry *me = mount_list_extend(ml); if (!me) - return log_oom_debug(); + return -ENOMEM; *me = (MountEntry) { .path_malloc = TAKE_PTR(mount_point), @@ -609,11 +590,11 @@ static int append_extensions( MountEntry *me = mount_list_extend(ml); if (!me) - return log_oom_debug(); + return -ENOMEM; *me = (MountEntry) { .path_malloc = TAKE_PTR(prefixed_hierarchy), - .options_malloc = TAKE_PTR(overlays[i]), + .overlay_layers = TAKE_PTR(overlays[i]), .mode = MOUNT_OVERLAY, .has_prefix = true, .ignore = true, /* If the source image doesn't set the ignore bit it will fail earlier. */ @@ -1413,12 +1394,46 @@ static int mount_image( } static int mount_overlay(const MountEntry *m) { - const char *options; + _cleanup_free_ char *options = NULL, *layers = NULL; int r; assert(m); - options = strjoina("lowerdir=", mount_entry_options(m)); + /* Extension hierarchies are optional (e.g.: confext might not have /opt) so check if they actually + * exist in an image before attempting to create an overlay with them, otherwise the mount will + * fail. We can't check before this, as the images will not be mounted until now. */ + + /* Note that lowerdir= parameters are in 'reverse' order, so the top-most directory in the overlay + * comes first in the list. */ + STRV_FOREACH_BACKWARDS(o, m->overlay_layers) { + _cleanup_free_ char *escaped = NULL; + + r = is_dir(*o, /* follow= */ false); + if (r <= 0) { + if (r != -ENOENT) + log_debug_errno(r, + "Failed to check whether overlay layer source path '%s' exists, ignoring: %m", + *o); + continue; + } + + escaped = shell_escape(*o, ",:"); + if (!escaped) + return log_oom_debug(); + + if (!strextend_with_separator(&layers, ":", escaped)) + return log_oom_debug(); + } + + if (!layers) { + log_debug("None of the overlays specified in '%s' exist at the source, skipping.", + mount_entry_options(m)); + return 0; /* Only the root is set? Then there's nothing to overlay */ + } + + options = strjoin("lowerdir=", layers, ":", mount_entry_path(m)); /* The root goes in last */ + if (!options) + return log_oom_debug(); (void) mkdir_p_label(mount_entry_path(m), 0755); |