From a4c35b6b4d8457e15caa3fe18ce8050918932d00 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 8 Dec 2016 00:28:05 +0100 Subject: nspawn: split out VolatileMode definitions This moves the VolatileMode enum and its helper functions to src/shared/. This is useful to then reuse them to implement systemd.volatile= in a later commit. --- src/nspawn/nspawn-mount.c | 18 ------------------ src/nspawn/nspawn-mount.h | 11 +---------- 2 files changed, 1 insertion(+), 28 deletions(-) (limited to 'src/nspawn') diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index aaa64a7ba8..72c007f204 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -1349,21 +1349,3 @@ fail: (void) rmdir(template); return r; } - -VolatileMode volatile_mode_from_string(const char *s) { - int b; - - if (isempty(s)) - return _VOLATILE_MODE_INVALID; - - b = parse_boolean(s); - if (b > 0) - return VOLATILE_YES; - if (b == 0) - return VOLATILE_NO; - - if (streq(s, "state")) - return VOLATILE_STATE; - - return _VOLATILE_MODE_INVALID; -} diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h index 467082a737..6b33fbff57 100644 --- a/src/nspawn/nspawn-mount.h +++ b/src/nspawn/nspawn-mount.h @@ -22,6 +22,7 @@ #include #include "cgroup-util.h" +#include "volatile-util.h" typedef enum MountSettingsMask { MOUNT_FATAL = 1 << 0, /* if set, a mount error is considered fatal */ @@ -32,14 +33,6 @@ typedef enum MountSettingsMask { Works only if MOUNT_APPLY_APIVFS_RO is also set. */ } MountSettingsMask; -typedef enum VolatileMode { - VOLATILE_NO, - VOLATILE_YES, - VOLATILE_STATE, - _VOLATILE_MODE_MAX, - _VOLATILE_MODE_INVALID = -1 -} VolatileMode; - typedef enum CustomMountType { CUSTOM_MOUNT_BIND, CUSTOM_MOUNT_TMPFS, @@ -77,5 +70,3 @@ int mount_custom(const char *dest, CustomMount *mounts, unsigned n, bool userns, 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); - -VolatileMode volatile_mode_from_string(const char *s); -- cgit v1.2.3-54-g00ecf From 9b6deb03fcb358d6987ce86fcad08e2e290ee5d0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Dec 2016 18:39:15 +0100 Subject: dissect: optionally, only look for GPT partition tables, nothing else This is useful for reusing the dissector logic in the gpt-auto-discovery logic: there we really don't want to use MBR or naked file systems as root device. --- src/dissect/dissect.c | 2 +- src/machine/image-dbus.c | 2 +- src/nspawn/nspawn.c | 2 +- src/shared/dissect-image.c | 89 +++++++++++++++++++++++-------------------- src/shared/dissect-image.h | 3 +- src/test/test-dissect-image.c | 2 +- 6 files changed, 54 insertions(+), 46 deletions(-) (limited to 'src/nspawn') diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index f2f1e135ec..aa06894037 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -191,7 +191,7 @@ int main(int argc, char *argv[]) { goto finish; } - r = dissect_image(d->fd, arg_root_hash, arg_root_hash_size, &m); + r = dissect_image(d->fd, arg_root_hash, arg_root_hash_size, 0, &m); if (r == -ENOPKG) { log_error_errno(r, "Couldn't identify a suitable partition table or file system in %s.", arg_image); goto finish; diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c index e2fb882393..2b168b267b 100644 --- a/src/machine/image-dbus.c +++ b/src/machine/image-dbus.c @@ -336,7 +336,7 @@ static int raw_image_get_os_release(Image *image, char ***ret, sd_bus_error *err if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to set up loop block device for %s: %m", image->path); - r = dissect_image(d->fd, NULL, 0, &m); + r = dissect_image(d->fd, NULL, 0, 0, &m); if (r == -ENOPKG) return sd_bus_error_set_errnof(error, r, "Disk image %s not understood: %m", image->path); if (r < 0) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index dcc639f15c..2e879d7d7f 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3743,7 +3743,7 @@ int main(int argc, char *argv[]) { goto finish; } - r = dissect_image(loop->fd, arg_root_hash, arg_root_hash_size, &dissected_image); + r = dissect_image(loop->fd, arg_root_hash, arg_root_hash_size, 0, &dissected_image); if (r == -ENOPKG) { log_error_errno(r, "Could not find a suitable file system or partition table in image: %s", arg_image); diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index d3ba9b9dde..10d53eab45 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -84,7 +84,7 @@ not_found: #endif } -int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectedImage **ret) { +int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DissectedImage **ret) { #ifdef HAVE_BLKID sd_id128_t root_uuid = SD_ID128_NULL, verity_uuid = SD_ID128_NULL; @@ -95,7 +95,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, Dissecte _cleanup_blkid_free_probe_ blkid_probe b = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_free_ char *generic_node = NULL; - const char *pttype = NULL, *usage = NULL; + const char *pttype = NULL; struct udev_list_entry *first, *item; blkid_partlist pl; int r, generic_nr; @@ -147,8 +147,12 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, Dissecte return -errno; } - blkid_probe_enable_superblocks(b, 1); - blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE|BLKID_SUBLKS_USAGE); + if ((flags & DISSECT_IMAGE_GPT_ONLY) == 0) { + /* Look for file system superblocks, unless we only shall look for GPT partition tables */ + blkid_probe_enable_superblocks(b, 1); + blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE|BLKID_SUBLKS_USAGE); + } + blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); @@ -169,40 +173,44 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, Dissecte if (!m) return -ENOMEM; - (void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL); - if (STRPTR_IN_SET(usage, "filesystem", "crypto")) { - _cleanup_free_ char *t = NULL, *n = NULL; - const char *fstype = NULL; + if ((flags & DISSECT_IMAGE_GPT_ONLY) == 0) { + const char *usage = NULL; - /* OK, we have found a file system, that's our root partition then. */ - (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); + (void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL); + if (STRPTR_IN_SET(usage, "filesystem", "crypto")) { + _cleanup_free_ char *t = NULL, *n = NULL; + const char *fstype = NULL; - if (fstype) { - t = strdup(fstype); - if (!t) - return -ENOMEM; - } + /* OK, we have found a file system, that's our root partition then. */ + (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); - if (asprintf(&n, "/dev/block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0) - return -ENOMEM; + if (fstype) { + t = strdup(fstype); + if (!t) + return -ENOMEM; + } - m->partitions[PARTITION_ROOT] = (DissectedPartition) { - .found = true, - .rw = true, - .partno = -1, - .architecture = _ARCHITECTURE_INVALID, - .fstype = t, - .node = n, - }; + if (asprintf(&n, "/dev/block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0) + return -ENOMEM; - t = n = NULL; + m->partitions[PARTITION_ROOT] = (DissectedPartition) { + .found = true, + .rw = true, + .partno = -1, + .architecture = _ARCHITECTURE_INVALID, + .fstype = t, + .node = n, + }; - m->encrypted = streq(fstype, "crypto_LUKS"); + t = n = NULL; - *ret = m; - m = NULL; + m->encrypted = streq(fstype, "crypto_LUKS"); - return 0; + *ret = m; + m = NULL; + + return 0; + } } (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL); @@ -212,7 +220,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, Dissecte is_gpt = streq_ptr(pttype, "gpt"); is_mbr = streq_ptr(pttype, "dos"); - if (!is_gpt && !is_mbr) + if (!is_gpt && ((flags & DISSECT_IMAGE_GPT_ONLY) || !is_mbr)) return -ENOPKG; errno = 0; @@ -300,7 +308,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, Dissecte first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *q; - unsigned long long flags; + unsigned long long pflags; blkid_partition pp; const char *node; dev_t qn; @@ -325,7 +333,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, Dissecte if (!pp) continue; - flags = blkid_partition_get_flags(pp); + pflags = blkid_partition_get_flags(pp); nr = blkid_partition_get_partno(pp); if (nr < 0) @@ -337,7 +345,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, Dissecte sd_id128_t type_id, id; bool rw = true; - if (flags & GPT_FLAG_NO_AUTO) + if (pflags & GPT_FLAG_NO_AUTO) continue; sid = blkid_partition_get_uuid(pp); @@ -354,10 +362,10 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, Dissecte if (sd_id128_equal(type_id, GPT_HOME)) { designator = PARTITION_HOME; - rw = !(flags & GPT_FLAG_READ_ONLY); + rw = !(pflags & GPT_FLAG_READ_ONLY); } else if (sd_id128_equal(type_id, GPT_SRV)) { designator = PARTITION_SRV; - rw = !(flags & GPT_FLAG_READ_ONLY); + rw = !(pflags & GPT_FLAG_READ_ONLY); } else if (sd_id128_equal(type_id, GPT_ESP)) { designator = PARTITION_ESP; fstype = "vfat"; @@ -371,7 +379,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, Dissecte designator = PARTITION_ROOT; architecture = native_architecture(); - rw = !(flags & GPT_FLAG_READ_ONLY); + rw = !(pflags & GPT_FLAG_READ_ONLY); } else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE_VERITY)) { m->can_verity = true; @@ -395,9 +403,8 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, Dissecte designator = PARTITION_ROOT_SECONDARY; architecture = SECONDARY_ARCHITECTURE; - rw = !(flags & GPT_FLAG_READ_ONLY); + rw = !(pflags & GPT_FLAG_READ_ONLY); } else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY_VERITY)) { - m->can_verity = true; /* Ignore verity unless root has is specified */ @@ -419,7 +426,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, Dissecte multiple_generic = true; else { generic_nr = nr; - generic_rw = !(flags & GPT_FLAG_READ_ONLY); + generic_rw = !(pflags & GPT_FLAG_READ_ONLY); generic_node = strdup(node); if (!generic_node) return -ENOMEM; @@ -457,7 +464,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, Dissecte } else if (is_mbr) { - if (flags != 0x80) /* Bootable flag */ + if (pflags != 0x80) /* Bootable flag */ continue; if (blkid_partition_get_type(pp) != 0x83) /* Linux partition */ diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index 175ddd8ea0..b424dac665 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -67,6 +67,7 @@ typedef enum DissectImageFlags { DISSECT_IMAGE_DISCARD_ANY = DISSECT_IMAGE_DISCARD_ON_LOOP | DISSECT_IMAGE_DISCARD | DISSECT_IMAGE_DISCARD_ON_CRYPTO, + DISSECT_IMAGE_GPT_ONLY = 16, /* Only recognize images with GPT partition tables */ } DissectImageFlags; struct DissectedImage { @@ -76,7 +77,7 @@ struct DissectedImage { DissectedPartition partitions[_PARTITION_DESIGNATOR_MAX]; }; -int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectedImage **ret); +int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DissectedImage **ret); DissectedImage* dissected_image_unref(DissectedImage *m); DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref); diff --git a/src/test/test-dissect-image.c b/src/test/test-dissect-image.c index 0512a15e88..ddaf3a0d8b 100644 --- a/src/test/test-dissect-image.c +++ b/src/test/test-dissect-image.c @@ -43,7 +43,7 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } - r = dissect_image(d->fd, NULL, 0, &m); + r = dissect_image(d->fd, NULL, 0, 0, &m); if (r < 0) { log_error_errno(r, "Failed to dissect image: %m"); return EXIT_FAILURE; -- cgit v1.2.3-54-g00ecf From 4ad14eff19f644fe632adf6ecc292a8e88540801 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 12 Dec 2016 19:46:56 +0100 Subject: nspawn: restore --volatile=yes support This was broken by 19caffac75a2590a0c5ebc2a0214960f8188aec7 which remounted the root directory to MS_SHARED before applying the volatile mount logic. This broke things as MS_MOVE is incompatible with MS_SHARED directory trees, and we need MS_MOVE in the volatile mount logic to rearrange the directory tree. Simply swap the order here, apply the volatile logic before we switch to MS_SHARED. --- src/nspawn/nspawn.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/nspawn') diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 2e879d7d7f..01d89df1a4 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -2470,20 +2470,6 @@ static int outer_child( if (r < 0) return r; - /* Mark everything as shared so our mounts get propagated down. This is - * required to make new bind mounts available in systemd services - * inside the containter that create a new mount namespace. - * See https://github.com/systemd/systemd/issues/3860 - * Further submounts (such as /dev) done after this will inherit the - * shared propagation mode.*/ - r = mount_verbose(LOG_ERR, NULL, directory, NULL, MS_SHARED|MS_REC, NULL); - if (r < 0) - return r; - - r = recursive_chown(directory, arg_uid_shift, arg_uid_range); - if (r < 0) - return r; - r = setup_volatile( directory, arg_volatile_mode, @@ -2504,6 +2490,20 @@ static int outer_child( if (r < 0) return r; + /* Mark everything as shared so our mounts get propagated down. This is + * required to make new bind mounts available in systemd services + * inside the containter that create a new mount namespace. + * See https://github.com/systemd/systemd/issues/3860 + * Further submounts (such as /dev) done after this will inherit the + * shared propagation mode.*/ + r = mount_verbose(LOG_ERR, NULL, directory, NULL, MS_SHARED|MS_REC, NULL); + if (r < 0) + return r; + + r = recursive_chown(directory, arg_uid_shift, arg_uid_range); + if (r < 0) + return r; + r = base_filesystem_create(directory, arg_uid_shift, (gid_t) arg_uid_shift); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From e0f9e7bd03eebeb8fdfce7f766c4e254e3586dc8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Dec 2016 17:38:11 +0100 Subject: dissect: make using a generic partition as root partition optional In preparation for reusing the image dissector in the GPT auto-discovery logic, only optionally fail the dissection when we can't identify a root partition. In the GPT auto-discovery we are completely fine with any kind of root, given that we run when it is already mounted and all we do is find some additional auxiliary partitions on the same disk. --- src/dissect/dissect.c | 4 ++-- src/machine/image-dbus.c | 2 +- src/nspawn/nspawn.c | 6 +++++- src/shared/dissect-image.c | 25 +++++++++++++++++-------- src/shared/dissect-image.h | 1 + src/test/test-dissect-image.c | 2 +- 6 files changed, 27 insertions(+), 13 deletions(-) (limited to 'src/nspawn') diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index 78ec88fa35..fd9db5ba87 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -35,7 +35,7 @@ static enum { } arg_action = ACTION_DISSECT; static const char *arg_image = NULL; static const char *arg_path = NULL; -static DissectImageFlags arg_flags = DISSECT_IMAGE_DISCARD_ON_LOOP; +static DissectImageFlags arg_flags = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP; static void *arg_root_hash = NULL; static size_t arg_root_hash_size = 0; @@ -191,7 +191,7 @@ int main(int argc, char *argv[]) { goto finish; } - r = dissect_image(d->fd, arg_root_hash, arg_root_hash_size, 0, &m); + r = dissect_image(d->fd, arg_root_hash, arg_root_hash_size, arg_flags, &m); if (r == -ENOPKG) { log_error_errno(r, "Couldn't identify a suitable partition table or file system in %s.", arg_image); goto finish; diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c index 2b168b267b..1891f07586 100644 --- a/src/machine/image-dbus.c +++ b/src/machine/image-dbus.c @@ -336,7 +336,7 @@ static int raw_image_get_os_release(Image *image, char ***ret, sd_bus_error *err if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to set up loop block device for %s: %m", image->path); - r = dissect_image(d->fd, NULL, 0, 0, &m); + r = dissect_image(d->fd, NULL, 0, DISSECT_IMAGE_REQUIRE_ROOT, &m); if (r == -ENOPKG) return sd_bus_error_set_errnof(error, r, "Disk image %s not understood: %m", image->path); if (r < 0) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 01d89df1a4..224d30fca6 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3743,7 +3743,11 @@ int main(int argc, char *argv[]) { goto finish; } - r = dissect_image(loop->fd, arg_root_hash, arg_root_hash_size, 0, &dissected_image); + r = dissect_image( + loop->fd, + arg_root_hash, arg_root_hash_size, + DISSECT_IMAGE_REQUIRE_ROOT, + &dissected_image); if (r == -ENOPKG) { log_error_errno(r, "Could not find a suitable file system or partition table in image: %s", arg_image); diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 5b6e78dd3d..878cb008aa 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -174,7 +174,8 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI if (!m) return -ENOMEM; - if ((flags & DISSECT_IMAGE_GPT_ONLY) == 0) { + if (!(flags & DISSECT_IMAGE_GPT_ONLY) && + (flags & DISSECT_IMAGE_REQUIRE_ROOT)) { const char *usage = NULL; (void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL); @@ -490,7 +491,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI * either, then check if there's a single generic one, and use that. */ if (m->partitions[PARTITION_ROOT_VERITY].found) - return -ENXIO; + return -EADDRNOTAVAIL; if (m->partitions[PARTITION_ROOT_SECONDARY].found) { m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_SECONDARY]; @@ -499,8 +500,19 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY]; zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]); - } else if (generic_node && !root_hash) { + } else if (flags & DISSECT_IMAGE_REQUIRE_ROOT) { + + /* If the root has was set, then we won't fallback to a generic node, because the root hash + * decides */ + if (root_hash) + return -EADDRNOTAVAIL; + /* If we didn't find a generic node, then we can't fix this up either */ + if (!generic_node) + return -ENXIO; + + /* If we didn't find a properly marked root partition, but we did find a single suitable + * generic Linux partition, then use this as root partition, if the caller asked for it. */ if (multiple_generic) return -ENOTUNIQ; @@ -514,14 +526,11 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI }; generic_node = NULL; - } else - return -ENXIO; + } } - assert(m->partitions[PARTITION_ROOT].found); - if (root_hash) { - if (!m->partitions[PARTITION_ROOT_VERITY].found) + if (!m->partitions[PARTITION_ROOT_VERITY].found || !m->partitions[PARTITION_ROOT].found) return -EADDRNOTAVAIL; /* If we found the primary root with the hash, then we definitely want to suppress any secondary root diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index 76104e5780..26319bd8e7 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -69,6 +69,7 @@ typedef enum DissectImageFlags { DISSECT_IMAGE_DISCARD | DISSECT_IMAGE_DISCARD_ON_CRYPTO, DISSECT_IMAGE_GPT_ONLY = 16, /* Only recognize images with GPT partition tables */ + DISSECT_IMAGE_REQUIRE_ROOT = 32, /* Don't accept disks without root partition */ } DissectImageFlags; struct DissectedImage { diff --git a/src/test/test-dissect-image.c b/src/test/test-dissect-image.c index ddaf3a0d8b..2bb68be0db 100644 --- a/src/test/test-dissect-image.c +++ b/src/test/test-dissect-image.c @@ -43,7 +43,7 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } - r = dissect_image(d->fd, NULL, 0, 0, &m); + r = dissect_image(d->fd, NULL, 0, DISSECT_IMAGE_REQUIRE_ROOT, &m); if (r < 0) { log_error_errno(r, "Failed to dissect image: %m"); return EXIT_FAILURE; -- cgit v1.2.3-54-g00ecf From 8ccf7e9e96ac89f02424c065e39043b5165f8bca Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Dec 2016 00:39:50 +0100 Subject: nspawn: don't complain when we can't fix the timezone of read-only containers There's nothing we can do about it, hence don't complain. --- src/nspawn/nspawn.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/nspawn') diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 224d30fca6..5df00df6ed 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1288,15 +1288,18 @@ static int setup_timezone(const char *dest) { return 0; } - r = unlink(where); - if (r < 0 && errno != ENOENT) { - log_error_errno(errno, "Failed to remove existing timezone info %s in container: %m", where); + if (unlink(where) < 0 && errno != ENOENT) { + log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING, /* Don't complain on read-only images */ + errno, + "Failed to remove existing timezone info %s in container, ignoring: %m", where); return 0; } what = strjoina("../usr/share/zoneinfo/", z); if (symlink(what, where) < 0) { - log_error_errno(errno, "Failed to correct timezone of container: %m"); + log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING, + errno, + "Failed to correct timezone of container, ignoring: %m"); return 0; } -- cgit v1.2.3-54-g00ecf From 87447ae4598d8de5aad557ec746e27e8271a60a7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Dec 2016 00:44:00 +0100 Subject: nspawn: tweaks to /etc/resolv.conf management Handle properly if /etc is a symlink (i.e. make sure we don't follow the symlink outside the image). Also follow /etc/resolv.conf if it is a symlink, and use the resolved path when creating a mount point and mounting (as both of these operations follow symlinks and rally shouldn't). Handle more types of read-only errors as debug-level issues. --- src/nspawn/nspawn.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'src/nspawn') diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 5df00df6ed..6246c6d6fa 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1311,31 +1311,43 @@ static int setup_timezone(const char *dest) { } static int setup_resolv_conf(const char *dest) { - const char *where = NULL; - int r; + _cleanup_free_ char *resolved = NULL, *etc = NULL; + const char *where; + int r, found; assert(dest); if (arg_private_network) return 0; - /* Fix resolv.conf, if possible */ - where = prefix_roota(dest, "/etc/resolv.conf"); + r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc); + if (r < 0) { + log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m"); + return 0; + } + + where = strjoina(etc, "/resolv.conf"); + found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved); + if (found < 0) { + log_warning_errno(found, "Failed to resolve /etc/resolv.conf path in container, ignoring: %m"); + return 0; + } if (access("/run/systemd/resolve/resolv.conf", F_OK) >= 0 && - access("/usr/lib/systemd/resolv.conf", F_OK) >= 0) { + access("/usr/lib/systemd/resolv.conf", F_OK) >= 0) { + /* resolved is enabled on the host. In this, case bind mount its static resolv.conf file into the * container, so that the container can use the host's resolver. Given that network namespacing is * disabled it's only natural of the container also uses the host's resolver. It also has the big * advantage that the container will be able to follow the host's DNS server configuration changes * transparently. */ - (void) touch(where); + if (found == 0) /* missing? */ + (void) touch(resolved); - r = mount_verbose(LOG_WARNING, "/usr/lib/systemd/resolv.conf", where, NULL, MS_BIND, NULL); + r = mount_verbose(LOG_DEBUG, "/usr/lib/systemd/resolv.conf", resolved, NULL, MS_BIND, NULL); if (r >= 0) - return mount_verbose(LOG_ERR, NULL, where, NULL, - MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL); + return mount_verbose(LOG_ERR, NULL, resolved, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL); } /* If that didn't work, let's copy the file */ @@ -1346,7 +1358,7 @@ static int setup_resolv_conf(const char *dest) { * * If the disk image is read-only, there's also no point in complaining. */ - log_full_errno(IN_SET(r, -ELOOP, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(IN_SET(r, -ELOOP, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r, "Failed to copy /etc/resolv.conf to %s, ignoring: %m", where); return 0; } -- cgit v1.2.3-54-g00ecf