/* how many times to wait for the device nodes to appear */
#define N_DEVICE_NODE_LIST_ATTEMPTS 10
-int probe_filesystem_full(int fd, const char *path, char **ret_fstype) {
+int probe_filesystem_full(
+ int fd,
+ const char *path,
+ uint64_t offset,
+ uint64_t size,
+ char **ret_fstype) {
+
/* Try to find device content type and return it in *ret_fstype. If nothing is found,
- * 0/NULL will be returned. -EUCLEAN will be returned for ambiguous results, and an
+ * 0/NULL will be returned. -EUCLEAN will be returned for ambiguous results, and a
* different error otherwise. */
#if HAVE_BLKID
_cleanup_(blkid_free_probep) blkid_probe b = NULL;
_cleanup_free_ char *path_by_fd = NULL;
- _cleanup_close_ int fd_close = -1;
+ _cleanup_close_ int fd_close = -EBADF;
const char *fstype;
int r;
path = path_by_fd;
}
+ if (size == 0) /* empty size? nothing found! */
+ goto not_found;
+
b = blkid_new_probe();
if (!b)
return -ENOMEM;
errno = 0;
- r = blkid_probe_set_device(b, fd, 0, 0);
+ r = blkid_probe_set_device(
+ b,
+ fd,
+ offset,
+ size == UINT64_MAX ? 0 : size); /* when blkid sees size=0 it understands "everything". We prefer using UINT64_MAX for that */
if (r != 0)
return errno_or_else(ENOMEM);
errno = 0;
r = blkid_do_safeprobe(b);
- if (r == 1)
+ if (r == _BLKID_SAFEPROBE_NOT_FOUND)
goto not_found;
- if (r == -2)
+ if (r == _BLKID_SAFEPROBE_AMBIGUOUS)
return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
"Results ambiguous for partition %s", path);
- if (r != 0)
+ if (r == _BLKID_SAFEPROBE_ERROR)
return log_debug_errno(errno_or_else(EIO), "Failed to probe partition %s: %m", path);
+ assert(r == _BLKID_SAFEPROBE_FOUND);
+
(void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
if (fstype) {
}
#if HAVE_BLKID
-static int dissected_image_probe_filesystem(DissectedImage *m) {
+static int dissected_image_probe_filesystems(DissectedImage *m, int fd) {
int r;
assert(m);
if (!p->found)
continue;
- if (!p->fstype && p->mount_node_fd >= 0 && !p->decrypted_node) {
- r = probe_filesystem_full(p->mount_node_fd, p->node, &p->fstype);
- if (r < 0 && r != -EUCLEAN)
+ if (!p->fstype) {
+ /* If we have an fd referring to the partition block device, use that. Otherwise go
+ * via the whole block device or backing regular file, and read via offset. */
+ if (p->mount_node_fd >= 0)
+ r = probe_filesystem_full(p->mount_node_fd, p->node, 0, UINT64_MAX, &p->fstype);
+ else
+ r = probe_filesystem_full(fd, p->node, p->offset, p->size, &p->fstype);
+ if (r < 0)
return r;
}
static int open_partition(const char *node, bool is_partition, const LoopDevice *loop) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
- _cleanup_close_ int fd = -1;
+ _cleanup_close_ int fd = -EBADF;
dev_t devnum;
int r;
return TAKE_FD(fd);
}
+static int compare_arch(Architecture a, Architecture b) {
+ if (a == b)
+ return 0;
+
+ if (a == native_architecture())
+ return 1;
+
+ if (b == native_architecture())
+ return -1;
+
+#ifdef ARCHITECTURE_SECONDARY
+ if (a == ARCHITECTURE_SECONDARY)
+ return 1;
+
+ if (b == ARCHITECTURE_SECONDARY)
+ return -1;
+#endif
+
+ return 0;
+}
+
static int dissect_image(
DissectedImage *m,
int fd,
_cleanup_(blkid_free_probep) blkid_probe b = NULL;
_cleanup_free_ char *generic_node = NULL;
sd_id128_t generic_uuid = SD_ID128_NULL;
- const char *pttype = NULL;
+ const char *pttype = NULL, *sptuuid = NULL;
blkid_partlist pl;
int r, generic_nr = -1, n_partitions;
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_set_superblocks_flags(b, BLKID_SUBLKS_TYPE|BLKID_SUBLKS_USAGE|BLKID_SUBLKS_UUID);
}
blkid_probe_enable_partitions(b, 1);
errno = 0;
r = blkid_do_safeprobe(b);
- if (IN_SET(r, -2, 1))
- return log_debug_errno(SYNTHETIC_ERRNO(ENOPKG), "Failed to identify any partition table.");
- if (r != 0)
+ if (r == _BLKID_SAFEPROBE_ERROR)
return errno_or_else(EIO);
+ if (IN_SET(r, _BLKID_SAFEPROBE_AMBIGUOUS, _BLKID_SAFEPROBE_NOT_FOUND))
+ return log_debug_errno(SYNTHETIC_ERRNO(ENOPKG), "Failed to identify any partition table.");
+
+ assert(r == _BLKID_SAFEPROBE_FOUND);
if ((!(flags & DISSECT_IMAGE_GPT_ONLY) &&
(flags & DISSECT_IMAGE_GENERIC_ROOT)) ||
(void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL);
if (STRPTR_IN_SET(usage, "filesystem", "crypto")) {
_cleanup_free_ char *t = NULL, *n = NULL, *o = NULL;
- const char *fstype = NULL, *options = NULL;
- _cleanup_close_ int mount_node_fd = -1;
+ const char *fstype = NULL, *options = NULL, *suuid = NULL;
+ _cleanup_close_ int mount_node_fd = -EBADF;
+ sd_id128_t uuid = SD_ID128_NULL;
- if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) {
+ if (FLAGS_SET(flags, DISSECT_IMAGE_PIN_PARTITION_DEVICES)) {
mount_node_fd = open_partition(devname, /* is_partition = */ false, m->loop);
if (mount_node_fd < 0)
return mount_node_fd;
/* 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, "UUID", &suuid, NULL);
if (fstype) {
t = strdup(fstype);
return -ENOMEM;
}
+ if (suuid) {
+ /* blkid will return FAT's serial number as UUID, hence it is quite possible
+ * that parsing this will fail. We'll ignore the ID, since it's just too
+ * short to be useful as tru identifier. */
+ r = sd_id128_from_string(suuid, &uuid);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse file system UUID '%s', ignoring: %m", suuid);
+ }
+
n = strdup(devname);
if (!n)
return -ENOMEM;
m->encrypted = streq_ptr(fstype, "crypto_LUKS");
m->has_verity = verity && verity->data_path;
- m->verity_ready = m->has_verity &&
- verity->root_hash &&
- (verity->designator < 0 || verity->designator == PARTITION_ROOT);
+ m->verity_ready = verity_settings_data_covers(verity, PARTITION_ROOT);
m->has_verity_sig = false; /* signature not embedded, must be specified */
- m->verity_sig_ready = m->verity_ready &&
- verity->root_hash_sig;
+ m->verity_sig_ready = m->verity_ready && verity->root_hash_sig;
+
+ m->image_uuid = uuid;
options = mount_options_from_designator(mount_options, PARTITION_ROOT);
if (options) {
if (verity && verity->data_path)
return -EBADR;
- if (FLAGS_SET(flags, DISSECT_IMAGE_MANAGE_PARTITION_DEVICES)) {
+ if (FLAGS_SET(flags, DISSECT_IMAGE_ADD_PARTITION_DEVICES)) {
/* Safety check: refuse block devices that carry a partition table but for which the kernel doesn't
* do partition scanning. */
r = blockdev_partscan_enabled(fd);
return -EPROTONOSUPPORT;
}
+ (void) blkid_probe_lookup_value(b, "PTUUID", &sptuuid, NULL);
+ if (sptuuid) {
+ r = sd_id128_from_string(sptuuid, &m->image_uuid);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse partition table UUID '%s', ignoring: %m", sptuuid);
+ }
+
errno = 0;
pl = blkid_probe_get_partitions(b);
if (!pl)
* Kernel returns EBUSY if there's already a partition by that number or an overlapping
* partition already existent. */
- if (FLAGS_SET(flags, DISSECT_IMAGE_MANAGE_PARTITION_DEVICES)) {
+ if (FLAGS_SET(flags, DISSECT_IMAGE_ADD_PARTITION_DEVICES)) {
r = block_device_add_partition(fd, node, nr, (uint64_t) start * 512, (uint64_t) size * 512);
if (r < 0) {
if (r != -EBUSY)
}
if (is_gpt) {
- PartitionDesignator designator = _PARTITION_DESIGNATOR_INVALID;
- Architecture architecture = _ARCHITECTURE_INVALID;
- const char *stype, *sid, *fstype = NULL, *label;
+ const char *fstype = NULL, *label;
sd_id128_t type_id, id;
+ GptPartitionType type;
bool rw = true, growfs = false;
- sid = blkid_partition_get_uuid(pp);
- if (!sid)
- continue;
- if (sd_id128_from_string(sid, &id) < 0)
+ r = blkid_partition_get_uuid_id128(pp, &id);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read partition UUID, ignoring: %m");
continue;
+ }
- stype = blkid_partition_get_type_string(pp);
- if (!stype)
- continue;
- if (sd_id128_from_string(stype, &type_id) < 0)
+ r = blkid_partition_get_type_id128(pp, &type_id);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read partition type UUID, ignoring: %m");
continue;
+ }
- label = blkid_partition_get_name(pp); /* libblkid returns NULL here if empty */
-
- if (sd_id128_equal(type_id, SD_GPT_HOME)) {
-
- check_partition_flags(node, pflags,
- SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
-
- if (pflags & SD_GPT_FLAG_NO_AUTO)
- continue;
+ type = gpt_partition_type_from_uuid(type_id);
- designator = PARTITION_HOME;
- rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
- growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
+ label = blkid_partition_get_name(pp); /* libblkid returns NULL here if empty */
- } else if (sd_id128_equal(type_id, SD_GPT_SRV)) {
+ if (IN_SET(type.designator,
+ PARTITION_HOME,
+ PARTITION_SRV,
+ PARTITION_XBOOTLDR,
+ PARTITION_TMP)) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
if (pflags & SD_GPT_FLAG_NO_AUTO)
continue;
- designator = PARTITION_SRV;
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
- } else if (sd_id128_equal(type_id, SD_GPT_ESP)) {
+ } else if (type.designator == PARTITION_ESP) {
/* Note that we don't check the SD_GPT_FLAG_NO_AUTO flag for the ESP, as it is
* not defined there. We instead check the SD_GPT_FLAG_NO_BLOCK_IO_PROTOCOL, as
if (pflags & SD_GPT_FLAG_NO_BLOCK_IO_PROTOCOL)
continue;
- designator = PARTITION_ESP;
fstype = "vfat";
- } else if (sd_id128_equal(type_id, SD_GPT_XBOOTLDR)) {
-
- check_partition_flags(node, pflags,
- SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
-
- if (pflags & SD_GPT_FLAG_NO_AUTO)
- continue;
-
- designator = PARTITION_XBOOTLDR;
- rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
- growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
-
- } else if (gpt_partition_type_is_root(type_id)) {
+ } else if (type.designator == PARTITION_ROOT) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id))
continue;
- assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
- designator = PARTITION_ROOT_OF_ARCH(architecture);
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
- } else if (gpt_partition_type_is_root_verity(type_id)) {
+ } else if (type.designator == PARTITION_ROOT_VERITY) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY);
if (!sd_id128_is_null(root_verity_uuid) && !sd_id128_equal(root_verity_uuid, id))
continue;
- assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
- designator = PARTITION_VERITY_OF(PARTITION_ROOT_OF_ARCH(architecture));
fstype = "DM_verity_hash";
rw = false;
- } else if (gpt_partition_type_is_root_verity_sig(type_id)) {
+ } else if (type.designator == PARTITION_ROOT_VERITY_SIG) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY);
if (verity->designator >= 0 && verity->designator != PARTITION_ROOT)
continue;
- assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
- designator = PARTITION_VERITY_SIG_OF(PARTITION_ROOT_OF_ARCH(architecture));
fstype = "verity_hash_signature";
rw = false;
- } else if (gpt_partition_type_is_usr(type_id)) {
+ } else if (type.designator == PARTITION_USR) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
if (!sd_id128_is_null(usr_uuid) && !sd_id128_equal(usr_uuid, id))
continue;
- assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
- designator = PARTITION_USR_OF_ARCH(architecture);
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
- } else if (gpt_partition_type_is_usr_verity(type_id)) {
+ } else if (type.designator == PARTITION_USR_VERITY) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY);
if (!sd_id128_is_null(usr_verity_uuid) && !sd_id128_equal(usr_verity_uuid, id))
continue;
- assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
- designator = PARTITION_VERITY_OF(PARTITION_USR_OF_ARCH(architecture));
fstype = "DM_verity_hash";
rw = false;
- } else if (gpt_partition_type_is_usr_verity_sig(type_id)) {
+ } else if (type.designator == PARTITION_USR_VERITY_SIG) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY);
if (verity->designator >= 0 && verity->designator != PARTITION_USR)
continue;
- assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
- designator = PARTITION_VERITY_SIG_OF(PARTITION_USR_OF_ARCH(architecture));
fstype = "verity_hash_signature";
rw = false;
- } else if (sd_id128_equal(type_id, SD_GPT_SWAP)) {
+ } else if (type.designator == PARTITION_SWAP) {
check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO);
if (pflags & SD_GPT_FLAG_NO_AUTO)
continue;
- designator = PARTITION_SWAP;
+ fstype = "swap";
- } else if (sd_id128_equal(type_id, SD_GPT_LINUX_GENERIC)) {
+ /* We don't have a designator for SD_GPT_LINUX_GENERIC so check the UUID instead. */
+ } else if (sd_id128_equal(type.uuid, SD_GPT_LINUX_GENERIC)) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
return -ENOMEM;
}
- } else if (sd_id128_equal(type_id, SD_GPT_TMP)) {
-
- check_partition_flags(node, pflags,
- SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
-
- if (pflags & SD_GPT_FLAG_NO_AUTO)
- continue;
-
- designator = PARTITION_TMP;
- rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
- growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
-
- } else if (sd_id128_equal(type_id, SD_GPT_VAR)) {
+ } else if (type.designator == PARTITION_VAR) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
return r;
if (!sd_id128_equal(var_uuid, id)) {
- log_debug("Found a /var/ partition, but its UUID didn't match our expectations, ignoring.");
+ log_debug("Found a /var/ partition, but its UUID didn't match our expectations "
+ "(found: " SD_ID128_UUID_FORMAT_STR ", expected: " SD_ID128_UUID_FORMAT_STR "), ignoring.",
+ SD_ID128_FORMAT_VAL(id), SD_ID128_FORMAT_VAL(var_uuid));
continue;
}
}
- designator = PARTITION_VAR;
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
}
- if (designator != _PARTITION_DESIGNATOR_INVALID) {
+ if (type.designator != _PARTITION_DESIGNATOR_INVALID) {
_cleanup_free_ char *t = NULL, *o = NULL, *l = NULL;
- _cleanup_close_ int mount_node_fd = -1;
+ _cleanup_close_ int mount_node_fd = -EBADF;
const char *options = NULL;
- if (m->partitions[designator].found) {
+ if (m->partitions[type.designator].found) {
/* For most partition types the first one we see wins. Except for the
* rootfs and /usr, where we do a version compare of the label, and
* let the newest version win. This permits a simple A/B versioning
* scheme in OS images. */
- if (!PARTITION_DESIGNATOR_VERSIONED(designator) ||
- strverscmp_improved(m->partitions[designator].label, label) >= 0)
+ if (compare_arch(type.arch, m->partitions[type.designator].architecture) <= 0)
+ continue;
+
+ if (!partition_designator_is_versioned(type.designator) ||
+ strverscmp_improved(m->partitions[type.designator].label, label) >= 0)
continue;
- dissected_partition_done(m->partitions + designator);
+ dissected_partition_done(m->partitions + type.designator);
}
- if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) {
+ if (FLAGS_SET(flags, DISSECT_IMAGE_PIN_PARTITION_DEVICES) &&
+ type.designator != PARTITION_SWAP) {
mount_node_fd = open_partition(node, /* is_partition = */ true, m->loop);
if (mount_node_fd < 0)
return mount_node_fd;
return -ENOMEM;
}
- options = mount_options_from_designator(mount_options, designator);
+ options = mount_options_from_designator(mount_options, type.designator);
if (options) {
o = strdup(options);
if (!o)
return -ENOMEM;
}
- m->partitions[designator] = (DissectedPartition) {
+ m->partitions[type.designator] = (DissectedPartition) {
.found = true,
.partno = nr,
.rw = rw,
.growfs = growfs,
- .architecture = architecture,
+ .architecture = type.arch,
.node = TAKE_PTR(node),
.fstype = TAKE_PTR(t),
.label = TAKE_PTR(l),
.mount_node_fd = TAKE_FD(mount_node_fd),
.offset = (uint64_t) start * 512,
.size = (uint64_t) size * 512,
+ .gpt_flags = pflags,
};
}
break;
case 0xEA: { /* Boot Loader Spec extended $BOOT partition */
- _cleanup_close_ int mount_node_fd = -1;
+ _cleanup_close_ int mount_node_fd = -EBADF;
_cleanup_free_ char *o = NULL;
sd_id128_t id = SD_ID128_NULL;
- const char *sid, *options = NULL;
+ const char *options = NULL;
/* First one wins */
if (m->partitions[PARTITION_XBOOTLDR].found)
continue;
- if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) {
+ if (FLAGS_SET(flags, DISSECT_IMAGE_PIN_PARTITION_DEVICES)) {
mount_node_fd = open_partition(node, /* is_partition = */ true, m->loop);
if (mount_node_fd < 0)
return mount_node_fd;
}
- sid = blkid_partition_get_uuid(pp);
- if (sid)
- (void) sd_id128_from_string(sid, &id);
+ (void) blkid_partition_get_uuid_id128(pp, &id);
options = mount_options_from_designator(mount_options, PARTITION_XBOOTLDR);
if (options) {
}
}
- if (m->partitions[PARTITION_ROOT].found) {
- /* If we found the primary arch, then invalidate the secondary and other arch to avoid any
- * ambiguities, since we never want to mount the secondary or other arch in this case. */
- m->partitions[PARTITION_ROOT_SECONDARY].found = false;
- m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found = false;
- m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG].found = false;
- m->partitions[PARTITION_USR_SECONDARY].found = false;
- m->partitions[PARTITION_USR_SECONDARY_VERITY].found = false;
- m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG].found = false;
-
- m->partitions[PARTITION_ROOT_OTHER].found = false;
- m->partitions[PARTITION_ROOT_OTHER_VERITY].found = false;
- m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG].found = false;
- m->partitions[PARTITION_USR_OTHER].found = false;
- m->partitions[PARTITION_USR_OTHER_VERITY].found = false;
- m->partitions[PARTITION_USR_OTHER_VERITY_SIG].found = false;
-
- } else if (m->partitions[PARTITION_ROOT_VERITY].found ||
- m->partitions[PARTITION_ROOT_VERITY_SIG].found)
- return -EADDRNOTAVAIL; /* Verity found but no matching rootfs? Something is off, refuse. */
-
- else if (m->partitions[PARTITION_ROOT_SECONDARY].found) {
-
- /* No root partition found but there's one for the secondary architecture? Then upgrade
- * secondary arch to first and invalidate the other arch. */
-
- log_debug("No root partition found of the native architecture, falling back to a root "
- "partition of the secondary architecture.");
-
- m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_SECONDARY];
- zero(m->partitions[PARTITION_ROOT_SECONDARY]);
- m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY];
- zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]);
- m->partitions[PARTITION_ROOT_VERITY_SIG] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG];
- zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG]);
-
- m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_SECONDARY];
- zero(m->partitions[PARTITION_USR_SECONDARY]);
- m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_SECONDARY_VERITY];
- zero(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
- m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG];
- zero(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
-
- m->partitions[PARTITION_ROOT_OTHER].found = false;
- m->partitions[PARTITION_ROOT_OTHER_VERITY].found = false;
- m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG].found = false;
- m->partitions[PARTITION_USR_OTHER].found = false;
- m->partitions[PARTITION_USR_OTHER_VERITY].found = false;
- m->partitions[PARTITION_USR_OTHER_VERITY_SIG].found = false;
-
- } else if (m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found ||
- m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG].found)
- return -EADDRNOTAVAIL; /* as above */
-
- else if (m->partitions[PARTITION_ROOT_OTHER].found) {
-
- /* No root or secondary partition found but there's one for another architecture? Then
- * upgrade the other architecture to first. */
-
- log_debug("No root partition found of the native architecture or the secondary architecture, "
- "falling back to a root partition of a non-native architecture (%s).",
- architecture_to_string(m->partitions[PARTITION_ROOT_OTHER].architecture));
-
- m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_OTHER];
- zero(m->partitions[PARTITION_ROOT_OTHER]);
- m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_OTHER_VERITY];
- zero(m->partitions[PARTITION_ROOT_OTHER_VERITY]);
- m->partitions[PARTITION_ROOT_VERITY_SIG] = m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG];
- zero(m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG]);
-
- m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_OTHER];
- zero(m->partitions[PARTITION_USR_OTHER]);
- m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_OTHER_VERITY];
- zero(m->partitions[PARTITION_USR_OTHER_VERITY]);
- m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_OTHER_VERITY_SIG];
- zero(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
- }
+ if (!m->partitions[PARTITION_ROOT].found &&
+ (m->partitions[PARTITION_ROOT_VERITY].found ||
+ m->partitions[PARTITION_ROOT_VERITY_SIG].found))
+ return -EADDRNOTAVAIL; /* Verity found but no matching rootfs? Something is off, refuse. */
/* Hmm, we found a signature partition but no Verity data? Something is off. */
if (m->partitions[PARTITION_ROOT_VERITY_SIG].found && !m->partitions[PARTITION_ROOT_VERITY].found)
return -EADDRNOTAVAIL;
- if (m->partitions[PARTITION_USR].found) {
- /* Invalidate secondary and other arch /usr/ if we found the primary arch */
- m->partitions[PARTITION_USR_SECONDARY].found = false;
- m->partitions[PARTITION_USR_SECONDARY_VERITY].found = false;
- m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG].found = false;
-
- m->partitions[PARTITION_USR_OTHER].found = false;
- m->partitions[PARTITION_USR_OTHER_VERITY].found = false;
- m->partitions[PARTITION_USR_OTHER_VERITY_SIG].found = false;
-
- } else if (m->partitions[PARTITION_USR_VERITY].found ||
- m->partitions[PARTITION_USR_VERITY_SIG].found)
- return -EADDRNOTAVAIL; /* as above */
-
- else if (m->partitions[PARTITION_USR_SECONDARY].found) {
-
- log_debug("No usr partition found of the native architecture, falling back to a usr "
- "partition of the secondary architecture.");
-
- /* Upgrade secondary arch to primary */
- m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_SECONDARY];
- zero(m->partitions[PARTITION_USR_SECONDARY]);
- m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_SECONDARY_VERITY];
- zero(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
- m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG];
- zero(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
-
- m->partitions[PARTITION_USR_OTHER].found = false;
- m->partitions[PARTITION_USR_OTHER_VERITY].found = false;
- m->partitions[PARTITION_USR_OTHER_VERITY_SIG].found = false;
-
- } else if (m->partitions[PARTITION_USR_SECONDARY_VERITY].found ||
- m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG].found)
- return -EADDRNOTAVAIL; /* as above */
-
- else if (m->partitions[PARTITION_USR_OTHER].found) {
-
- log_debug("No usr partition found of the native architecture or the secondary architecture, "
- "falling back to a usr partition of a non-native architecture (%s).",
- architecture_to_string(m->partitions[PARTITION_ROOT_OTHER].architecture));
-
- /* Upgrade other arch to primary */
- m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_OTHER];
- zero(m->partitions[PARTITION_USR_OTHER]);
- m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_OTHER_VERITY];
- zero(m->partitions[PARTITION_USR_OTHER_VERITY]);
- m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_OTHER_VERITY_SIG];
- zero(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
- }
+ if (!m->partitions[PARTITION_USR].found &&
+ (m->partitions[PARTITION_USR_VERITY].found ||
+ m->partitions[PARTITION_USR_VERITY_SIG].found))
+ return -EADDRNOTAVAIL; /* as above */
- /* Hmm, we found a signature partition but no Verity data? Something is off. */
+ /* as above */
if (m->partitions[PARTITION_USR_VERITY_SIG].found && !m->partitions[PARTITION_USR_VERITY].found)
return -EADDRNOTAVAIL;
/* If we didn't find a generic node, then we can't fix this up either */
if (generic_node) {
- _cleanup_close_ int mount_node_fd = -1;
+ _cleanup_close_ int mount_node_fd = -EBADF;
_cleanup_free_ char *o = NULL;
const char *options;
- if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) {
+ if (FLAGS_SET(flags, DISSECT_IMAGE_PIN_PARTITION_DEVICES)) {
mount_node_fd = open_partition(generic_node, /* is_partition = */ true, m->loop);
if (mount_node_fd < 0)
return mount_node_fd;
}
}
+ r = dissected_image_probe_filesystems(m, fd);
+ if (r < 0)
+ return r;
+
return 0;
}
#endif
#if HAVE_BLKID
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
- _cleanup_close_ int fd = -1;
+ _cleanup_close_ int fd = -EBADF;
int r;
assert(path);
- assert((flags & DISSECT_IMAGE_BLOCK_DEVICE) == 0);
assert(ret);
fd = open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
free(m->hostname);
strv_free(m->machine_info);
strv_free(m->os_release);
+ strv_free(m->initrd_release);
strv_free(m->extension_release);
return mfree(m);
}
static int fs_grow(const char *node_path, const char *mount_path) {
- _cleanup_close_ int mount_fd = -1, node_fd = -1;
+ _cleanup_close_ int mount_fd = -EBADF, node_fd = -EBADF;
uint64_t size, newsize;
int r;
_cleanup_free_ char *node = NULL, *name = NULL;
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
- _cleanup_close_ int fd = -1;
+ _cleanup_close_ int fd = -EBADF;
int r;
assert(m);
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
_cleanup_(dm_deferred_remove_cleanp) char *restore_deferred_remove = NULL;
_cleanup_free_ char *node = NULL, *name = NULL;
- _cleanup_close_ int mount_node_fd = -1;
+ _cleanup_close_ int mount_node_fd = -EBADF;
int r;
assert(m);
* retry a few times before giving up. */
for (unsigned i = 0; i < N_DEVICE_NODE_LIST_ATTEMPTS; i++) {
_cleanup_(sym_crypt_freep) struct crypt_device *existing_cd = NULL;
- _cleanup_close_ int fd = -1;
+ _cleanup_close_ int fd = -EBADF;
/* First, check if the device already exists. */
fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
if (r < 0)
return r;
- k = PARTITION_VERITY_OF(i);
+ k = partition_verity_of(i);
if (k >= 0) {
r = verity_partition(i, p, m->partitions + k, verity, flags | DISSECT_IMAGE_VERITY_SHARE, d);
if (r < 0)
}
if (!p->decrypted_fstype && p->mount_node_fd >= 0 && p->decrypted_node) {
- r = probe_filesystem_full(p->mount_node_fd, p->decrypted_node, &p->decrypted_fstype);
+ r = probe_filesystem_full(p->mount_node_fd, p->decrypted_node, 0, UINT64_MAX, &p->decrypted_fstype);
if (r < 0 && r != -EUCLEAN)
return r;
}
if (r == 0)
return 0;
- d = PARTITION_VERITY_SIG_OF(verity->designator < 0 ? PARTITION_ROOT : verity->designator);
+ d = partition_verity_sig_of(verity->designator < 0 ? PARTITION_ROOT : verity->designator);
assert(d >= 0);
p = m->partitions + d;
META_MACHINE_ID,
META_MACHINE_INFO,
META_OS_RELEASE,
+ META_INITRD_RELEASE,
META_EXTENSION_RELEASE,
META_HAS_INIT_SYSTEM,
_META_MAX,
[META_MACHINE_INFO] = "/etc/machine-info\0",
[META_OS_RELEASE] = ("/etc/os-release\0"
"/usr/lib/os-release\0"),
+ [META_INITRD_RELEASE] = ("/etc/initrd-release\0"
+ "/usr/lib/initrd-release\0"),
[META_EXTENSION_RELEASE] = "extension-release\0", /* Used only for logging. */
[META_HAS_INIT_SYSTEM] = "has-init-system\0", /* ditto */
};
- _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **extension_release = NULL;
- _cleanup_close_pair_ int error_pipe[2] = { -1, -1 };
+ _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **initrd_release = NULL, **extension_release = NULL;
+ _cleanup_close_pair_ int error_pipe[2] = PIPE_EBADF;
_cleanup_(rmdir_and_freep) char *t = NULL;
_cleanup_(sigkill_waitp) pid_t child = 0;
sd_id128_t machine_id = SD_ID128_NULL;
for (; n_meta_initialized < _META_MAX; n_meta_initialized ++) {
if (!paths[n_meta_initialized]) {
- fds[2*n_meta_initialized] = fds[2*n_meta_initialized+1] = -1;
+ fds[2*n_meta_initialized] = fds[2*n_meta_initialized+1] = -EBADF;
continue;
}
for (unsigned k = 0; k < _META_MAX; k++) {
_cleanup_close_ int fd = -ENOENT;
- const char *p;
if (!paths[k])
continue;
break;
+ case META_INITRD_RELEASE:
+ r = load_env_file_pairs(f, "initrd-release", &initrd_release);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read initrd release file of image: %m");
+
+ break;
+
case META_EXTENSION_RELEASE:
r = load_env_file_pairs(f, "extension-release", &extension_release);
if (r < 0)
m->machine_id = machine_id;
strv_free_and_replace(m->machine_info, machine_info);
strv_free_and_replace(m->os_release, os_release);
+ strv_free_and_replace(m->initrd_release, initrd_release);
strv_free_and_replace(m->extension_release, extension_release);
m->has_init_system = has_init_system;
m->loop = loop_device_ref(loop);
- r = dissect_image(m, loop->fd, loop->node, verity, mount_options, flags | DISSECT_IMAGE_BLOCK_DEVICE);
- if (r < 0)
- return r;
-
- r = dissected_image_probe_filesystem(m);
+ r = dissect_image(m, loop->fd, loop->node, verity, mount_options, flags);
if (r < 0)
return r;
if (image->single_file_system)
return partition_designator == PARTITION_ROOT && image->has_verity;
- return PARTITION_VERITY_OF(partition_designator) >= 0;
+ return partition_verity_of(partition_designator) >= 0;
}
bool dissected_image_verity_ready(const DissectedImage *image, PartitionDesignator partition_designator) {
if (image->single_file_system)
return partition_designator == PARTITION_ROOT;
- k = PARTITION_VERITY_OF(partition_designator);
+ k = partition_verity_of(partition_designator);
return k >= 0 && image->partitions[k].found;
}
if (image->single_file_system)
return partition_designator == PARTITION_ROOT;
- k = PARTITION_VERITY_SIG_OF(partition_designator);
+ k = partition_verity_sig_of(partition_designator);
return k >= 0 && image->partitions[k].found;
}
assert(ret_directory);
assert(ret_loop_device);
+ /* We intend to mount this right-away, hence add the partitions if needed and pin them*/
+ flags |= DISSECT_IMAGE_ADD_PARTITION_DEVICES |
+ DISSECT_IMAGE_PIN_PARTITION_DEVICES;
+
r = verity_settings_load(&verity, image, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to load root hash data: %m");
return 0;
}
-static const char *const partition_designator_table[] = {
- [PARTITION_ROOT] = "root",
- [PARTITION_ROOT_SECONDARY] = "root-secondary",
- [PARTITION_ROOT_OTHER] = "root-other",
- [PARTITION_USR] = "usr",
- [PARTITION_USR_SECONDARY] = "usr-secondary",
- [PARTITION_USR_OTHER] = "usr-other",
- [PARTITION_HOME] = "home",
- [PARTITION_SRV] = "srv",
- [PARTITION_ESP] = "esp",
- [PARTITION_XBOOTLDR] = "xbootldr",
- [PARTITION_SWAP] = "swap",
- [PARTITION_ROOT_VERITY] = "root-verity",
- [PARTITION_ROOT_SECONDARY_VERITY] = "root-secondary-verity",
- [PARTITION_ROOT_OTHER_VERITY] = "root-other-verity",
- [PARTITION_USR_VERITY] = "usr-verity",
- [PARTITION_USR_SECONDARY_VERITY] = "usr-secondary-verity",
- [PARTITION_USR_OTHER_VERITY] = "usr-other-verity",
- [PARTITION_ROOT_VERITY_SIG] = "root-verity-sig",
- [PARTITION_ROOT_SECONDARY_VERITY_SIG] = "root-secondary-verity-sig",
- [PARTITION_ROOT_OTHER_VERITY_SIG] = "root-other-verity-sig",
- [PARTITION_USR_VERITY_SIG] = "usr-verity-sig",
- [PARTITION_USR_SECONDARY_VERITY_SIG] = "usr-secondary-verity-sig",
- [PARTITION_USR_OTHER_VERITY_SIG] = "usr-other-verity-sig",
- [PARTITION_TMP] = "tmp",
- [PARTITION_VAR] = "var",
-};
-
static bool mount_options_relax_extension_release_checks(const MountOptions *options) {
if (!options)
return false;
return log_debug_errno(r, "Failed to load root hash: %m");
dissect_image_flags = (verity.data_path ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0) |
- (relax_extension_release_check ? DISSECT_IMAGE_RELAX_SYSEXT_CHECK : 0);
+ (relax_extension_release_check ? DISSECT_IMAGE_RELAX_SYSEXT_CHECK : 0) |
+ DISSECT_IMAGE_ADD_PARTITION_DEVICES |
+ DISSECT_IMAGE_PIN_PARTITION_DEVICES;
/* Note that we don't use loop_device_make here, as the FD is most likely O_PATH which would not be
* accepted by LOOP_CONFIGURE, so just let loop_device_make_by_path reopen it as a regular FD. */
return 0;
}
-
-DEFINE_STRING_TABLE_LOOKUP(partition_designator, PartitionDesignator);