From: Lennart Poettering Date: Wed, 10 Mar 2021 16:41:18 +0000 (+0100) Subject: dissect-image: split DISSECT_IMAGE_REQUIRE_ROOT in two X-Git-Tag: v249-rc1~509^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4b5de5dd6c930276628c84755d33187e2dfca5cc;p=thirdparty%2Fsystemd.git dissect-image: split DISSECT_IMAGE_REQUIRE_ROOT in two Previously, the flag did two things at once: enable support for using generic partitions as root fs if there were only one/allow use of partition-table-less images as root fs. And secondly, insist that there was a rootfs, and fail if not. Let's split these two in two separate options so that they can be used independently of each other. There are cases where one wants to use one without the other (i.e. when inspecting things with systemd-dissect tool it should be OK to do so even if image has no root fs), and it's cleaner anyway. --- diff --git a/src/core/namespace.c b/src/core/namespace.c index c5897c6c944..56385270d86 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -1825,7 +1825,7 @@ int setup_namespace( mount_flags = MS_SHARED; if (root_image) { - dissect_image_flags |= DISSECT_IMAGE_REQUIRE_ROOT; + dissect_image_flags |= DISSECT_IMAGE_GENERIC_ROOT | DISSECT_IMAGE_REQUIRE_ROOT; /* Make the whole image read-only if we can determine that we only access it in a read-only fashion. */ if (root_read_only(read_only_paths, diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index 06808a231e4..10ab834f0d9 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -44,7 +44,13 @@ static const char *arg_image = NULL; static const char *arg_path = NULL; static const char *arg_source = NULL; static const char *arg_target = NULL; -static DissectImageFlags arg_flags = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK|DISSECT_IMAGE_USR_NO_ROOT; +static DissectImageFlags arg_flags = + DISSECT_IMAGE_GENERIC_ROOT | + DISSECT_IMAGE_REQUIRE_ROOT | + DISSECT_IMAGE_DISCARD_ON_LOOP | + DISSECT_IMAGE_RELAX_VAR_CHECK | + DISSECT_IMAGE_FSCK | + DISSECT_IMAGE_USR_NO_ROOT; static VeritySettings arg_verity_settings = VERITY_SETTINGS_DEFAULT; static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; static PagerFlags arg_pager_flags = 0; diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 8e3028717e7..aa7251d1ef2 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -1291,7 +1291,11 @@ static int run(int argc, char *argv[]) { r = mount_image_privately_interactively( arg_image, - DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK, + DISSECT_IMAGE_GENERIC_ROOT | + DISSECT_IMAGE_REQUIRE_ROOT | + DISSECT_IMAGE_VALIDATE_OS | + DISSECT_IMAGE_RELAX_VAR_CHECK | + DISSECT_IMAGE_FSCK, &unlink_dir, &loop_device, &decrypted_image); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 6b06320d782..4b3e697855b 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -2150,7 +2150,10 @@ int main(int argc, char *argv[]) { r = mount_image_privately_interactively( arg_image, - DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK| + DISSECT_IMAGE_GENERIC_ROOT | + DISSECT_IMAGE_REQUIRE_ROOT | + DISSECT_IMAGE_VALIDATE_OS | + DISSECT_IMAGE_RELAX_VAR_CHECK | (arg_action == ACTION_UPDATE_CATALOG ? DISSECT_IMAGE_FSCK : DISSECT_IMAGE_READ_ONLY), &unlink_dir, &loop_device, diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 00e2ba2654a..f89fa1a5738 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -5389,6 +5389,7 @@ static int run(int argc, char *argv[]) { } else { DissectImageFlags dissect_image_flags = + DISSECT_IMAGE_GENERIC_ROOT | DISSECT_IMAGE_REQUIRE_ROOT | DISSECT_IMAGE_RELAX_VAR_CHECK | DISSECT_IMAGE_USR_NO_ROOT; diff --git a/src/portable/portable.c b/src/portable/portable.c index aacc573ef6e..5651db67227 100644 --- a/src/portable/portable.c +++ b/src/portable/portable.c @@ -380,7 +380,16 @@ static int portable_extract_by_path( if (r < 0) return log_debug_errno(r, "Failed to create temporary directory: %m"); - r = dissect_image(d->fd, NULL, NULL, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_USR_NO_ROOT, &m); + r = dissect_image( + d->fd, + NULL, NULL, + DISSECT_IMAGE_READ_ONLY | + DISSECT_IMAGE_GENERIC_ROOT | + DISSECT_IMAGE_REQUIRE_ROOT | + DISSECT_IMAGE_DISCARD_ON_LOOP | + DISSECT_IMAGE_RELAX_VAR_CHECK | + DISSECT_IMAGE_USR_NO_ROOT, + &m); if (r == -ENOPKG) sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Couldn't identify a suitable partition table or file system in '%s'.", path); else if (r == -EADDRNOTAVAIL) diff --git a/src/shared/discover-image.c b/src/shared/discover-image.c index a2f22619807..43138e0a6f6 100644 --- a/src/shared/discover-image.c +++ b/src/shared/discover-image.c @@ -1201,8 +1201,9 @@ int image_read_metadata(Image *i) { r = dissect_image( d->fd, NULL, NULL, - DISSECT_IMAGE_REQUIRE_ROOT| - DISSECT_IMAGE_RELAX_VAR_CHECK| + DISSECT_IMAGE_GENERIC_ROOT | + DISSECT_IMAGE_REQUIRE_ROOT | + DISSECT_IMAGE_RELAX_VAR_CHECK | DISSECT_IMAGE_USR_NO_ROOT, &m); if (r < 0) return r; diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 843fd41bb9d..bdd35703489 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -630,7 +630,7 @@ int dissect_image( } if ((!(flags & DISSECT_IMAGE_GPT_ONLY) && - (flags & DISSECT_IMAGE_REQUIRE_ROOT)) || + (flags & DISSECT_IMAGE_GENERIC_ROOT)) || (flags & DISSECT_IMAGE_NO_PARTITION_TABLE)) { const char *usage = NULL; @@ -1178,45 +1178,47 @@ int dissect_image( } else if (m->partitions[PARTITION_USR_SECONDARY_VERITY].found) return -EADDRNOTAVAIL; /* as above */ - else if (flags & DISSECT_IMAGE_REQUIRE_ROOT) { - _cleanup_free_ char *o = NULL; - const char *options = NULL; + else if ((flags & DISSECT_IMAGE_GENERIC_ROOT) && + (!verity || !verity->root_hash)) { /* OK, we found nothing usable, then check if there's a single generic one distro, and use - * that. */ - - /* If the root hash was set, then we won't fall back to a generic node, because the root hash - * decides. */ - if (verity && verity->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; + * that. If the root hash was set however, then we won't fall back to a generic node, because + * the root hash decides. */ /* 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; - options = mount_options_from_designator(mount_options, PARTITION_ROOT); - if (options) { - o = strdup(options); - if (!o) - return -ENOMEM; - } + /* If we didn't find a generic node, then we can't fix this up either */ + if (generic_node) { + _cleanup_free_ char *o = NULL; + const char *options; + + options = mount_options_from_designator(mount_options, PARTITION_ROOT); + if (options) { + o = strdup(options); + if (!o) + return -ENOMEM; + } - m->partitions[PARTITION_ROOT] = (DissectedPartition) { - .found = true, - .rw = generic_rw, - .partno = generic_nr, - .architecture = _ARCHITECTURE_INVALID, - .node = TAKE_PTR(generic_node), - .uuid = generic_uuid, - .mount_options = TAKE_PTR(o), - }; + m->partitions[PARTITION_ROOT] = (DissectedPartition) { + .found = true, + .rw = generic_rw, + .partno = generic_nr, + .architecture = _ARCHITECTURE_INVALID, + .node = TAKE_PTR(generic_node), + .uuid = generic_uuid, + .mount_options = TAKE_PTR(o), + }; + } } + /* Check if we have a root fs if we are told to do check. /usr alone is fine too, but only if appropriate flag for that is set too */ + if (FLAGS_SET(flags, DISSECT_IMAGE_REQUIRE_ROOT) && + !(m->partitions[PARTITION_ROOT].found || (m->partitions[PARTITION_USR].found && FLAGS_SET(flags, DISSECT_IMAGE_USR_NO_ROOT)))) + return -ENXIO; + /* Refuse if we found a verity partition for /usr but no matching file system partition */ if (!m->partitions[PARTITION_USR].found && m->partitions[PARTITION_USR_VERITY].found) return -EADDRNOTAVAIL; diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index 0e01c5e403b..f07955230ba 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -95,7 +95,7 @@ typedef enum DissectImageFlags { DISSECT_IMAGE_DISCARD | DISSECT_IMAGE_DISCARD_ON_CRYPTO, DISSECT_IMAGE_GPT_ONLY = 1 << 4, /* Only recognize images with GPT partition tables */ - DISSECT_IMAGE_REQUIRE_ROOT = 1 << 5, /* Don't accept disks without root partition (and if no partition table or only single generic partition, assume it's root) */ + DISSECT_IMAGE_GENERIC_ROOT = 1 << 5, /* If no partition table or only single generic partition, assume it's the root fs */ DISSECT_IMAGE_MOUNT_ROOT_ONLY = 1 << 6, /* Mount only the root and /usr partitions */ DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7, /* Mount only the non-root and non-/usr partitions */ DISSECT_IMAGE_VALIDATE_OS = 1 << 8, /* Refuse mounting images that aren't identifiable as OS images */ @@ -106,6 +106,7 @@ typedef enum DissectImageFlags { DISSECT_IMAGE_VERITY_SHARE = 1 << 13, /* When activating a verity device, reuse existing one if already open */ DISSECT_IMAGE_MKDIR = 1 << 14, /* Make top-level directory to mount right before mounting, if missing */ DISSECT_IMAGE_USR_NO_ROOT = 1 << 15, /* If no root fs is in the image, but /usr is, then allow this (so that we can mount the rootfs as tmpfs or so */ + DISSECT_IMAGE_REQUIRE_ROOT = 1 << 16, /* Don't accept disks without root partition (or at least /usr partition if DISSECT_IMAGE_USR_NO_ROOT is set) */ } DissectImageFlags; struct DissectedImage { diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index 2ebb96c3978..49ec23d9343 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -510,9 +510,10 @@ static int merge_subprocess(Hashmap *images, const char *workspace) { _cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL; _cleanup_(verity_settings_done) VeritySettings verity_settings = VERITY_SETTINGS_DEFAULT; DissectImageFlags flags = - DISSECT_IMAGE_READ_ONLY| - DISSECT_IMAGE_REQUIRE_ROOT| - DISSECT_IMAGE_MOUNT_ROOT_ONLY| + DISSECT_IMAGE_READ_ONLY | + DISSECT_IMAGE_GENERIC_ROOT | + DISSECT_IMAGE_REQUIRE_ROOT | + DISSECT_IMAGE_MOUNT_ROOT_ONLY | DISSECT_IMAGE_USR_NO_ROOT; r = verity_settings_load(&verity_settings, img->path, NULL, NULL); diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index b098eb27cd4..27573b74e6d 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -1946,7 +1946,11 @@ static int run(int argc, char *argv[]) { r = mount_image_privately_interactively( arg_image, - DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK, + DISSECT_IMAGE_GENERIC_ROOT | + DISSECT_IMAGE_REQUIRE_ROOT | + DISSECT_IMAGE_VALIDATE_OS | + DISSECT_IMAGE_RELAX_VAR_CHECK | + DISSECT_IMAGE_FSCK, &unlink_dir, &loop_device, &decrypted_image); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 846e456551e..f11b4eed7cc 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -3431,7 +3431,11 @@ static int run(int argc, char *argv[]) { r = mount_image_privately_interactively( arg_image, - DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK, + DISSECT_IMAGE_GENERIC_ROOT | + DISSECT_IMAGE_REQUIRE_ROOT | + DISSECT_IMAGE_VALIDATE_OS | + DISSECT_IMAGE_RELAX_VAR_CHECK | + DISSECT_IMAGE_FSCK, &unlink_dir, &loop_device, &decrypted_image);