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.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
+10
-1
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
+31
-29
@@ -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;
|
||||
|
||||
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),
|
||||
};
|
||||
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),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+4
-3
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user