diff options
author | Lennart Poettering <lennart@poettering.net> | 2016-12-23 14:26:05 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2017-02-07 12:19:42 +0100 |
commit | 915e6d1676cf73c4f927f3bbfa21ee82640b1832 (patch) | |
tree | 7b12ef355276452ec4da4778e7b26c5ee58e8664 /src/core/namespace.c | |
parent | 2eedfd2d8b3441e8cf6dae4bdc9afaefbda19c39 (diff) |
core: add RootImage= setting for using a specific image file as root directory for a service
This is similar to RootDirectory= but mounts the root file system from a
block device or loopback file instead of another directory.
This reuses the image dissector code now used by nspawn and
gpt-auto-discovery.
Diffstat (limited to 'src/core/namespace.c')
-rw-r--r-- | src/core/namespace.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/src/core/namespace.c b/src/core/namespace.c index 10917f7b70..0ae5f704c7 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -30,6 +30,7 @@ #include "dev-setup.h" #include "fd-util.h" #include "fs-util.h" +#include "loop-util.h" #include "loopback-setup.h" #include "missing.h" #include "mkdir.h" @@ -867,6 +868,7 @@ static unsigned namespace_calculate_mounts( int setup_namespace( const char* root_directory, + const char* root_image, const NameSpaceInfo *ns_info, char** read_write_paths, char** read_only_paths, @@ -877,16 +879,46 @@ int setup_namespace( const char* var_tmp_dir, ProtectHome protect_home, ProtectSystem protect_system, - unsigned long mount_flags) { + unsigned long mount_flags, + DissectImageFlags dissect_image_flags) { + _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; + _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL; MountEntry *m, *mounts = NULL; bool make_slave = false; unsigned n_mounts; int r = 0; + assert(ns_info); + if (mount_flags == 0) mount_flags = MS_SHARED; + if (root_image) { + dissect_image_flags |= DISSECT_IMAGE_REQUIRE_ROOT; + + if (protect_system == PROTECT_SYSTEM_STRICT && strv_isempty(read_write_paths)) + dissect_image_flags |= DISSECT_IMAGE_READ_ONLY; + + r = loop_device_make_by_path(root_image, + dissect_image_flags & DISSECT_IMAGE_READ_ONLY ? O_RDONLY : O_RDWR, + &loop_device); + if (r < 0) + return r; + + r = dissect_image(loop_device->fd, NULL, 0, dissect_image_flags, &dissected_image); + if (r < 0) + return r; + + if (!root_directory) { + /* Create a mount point for the image, if it's still missing. We use the same mount point for + * all images, which is safe, since they all live in their own namespaces after all, and hence + * won't see each other. */ + root_directory = "/run/systemd/unit-root"; + (void) mkdir(root_directory, 0700); + } + } + n_mounts = namespace_calculate_mounts( ns_info, read_write_paths, @@ -1001,7 +1033,15 @@ int setup_namespace( } } - if (root_directory) { + if (root_image) { + r = dissected_image_mount(dissected_image, root_directory, dissect_image_flags); + if (r < 0) + goto finish; + + loop_device_relinquish(loop_device); + + } else if (root_directory) { + /* Turn directory into bind mount, if it isn't one yet */ r = path_is_mount_point(root_directory, NULL, AT_SYMLINK_FOLLOW); if (r < 0) |