From 1d369d78b3cdb801c5758880b04cc10f997e2b0c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 17 Sep 2022 03:30:13 +0900 Subject: [PATCH 1/5] dissect-image: reduce indentation No functional change, just refactoring. --- src/shared/dissect-image.c | 87 +++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 29d893e03b..77d6101cff 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -2068,8 +2068,11 @@ static int verity_partition( * In case of ENODEV/ENOENT, which can happen if another process is activating at the exact same time, * 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; r = do_crypt_activate_verity(cd, name, verity); + if (r >= 0) + goto success; /* The device is activated. */ /* libdevmapper can return EINVAL when the device is already in the activation stage. * There's no way to distinguish this situation from a genuine error due to invalid * parameters, so immediately fall back to activating the device with a unique name. @@ -2077,50 +2080,56 @@ static int verity_partition( * https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/96 */ if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE)) break; - if (r < 0 && !IN_SET(r, - -EEXIST, /* Volume is already open and ready to be used */ - -EBUSY, /* Volume is being opened but not ready, crypt_init_by_name can fetch details */ - -ENODEV /* Volume is being opened but not ready, crypt_init_by_name would fail, try to open again */)) - return r; - if (IN_SET(r, -EEXIST, -EBUSY)) { - _cleanup_(sym_crypt_freep) struct crypt_device *existing_cd = NULL; + if (r == -ENODEV) /* Volume is being opened but not ready, crypt_init_by_name would fail, try to open again */ + goto try_again; + if (!IN_SET(r, + -EEXIST, /* Volume has already been opened and ready to be used. */ + -EBUSY /* Volume is being opened but not ready, crypt_init_by_name() can fetch details. */)) + return log_debug_errno(r, "Failed to activate verity device %s: %m", node); - if (!restore_deferred_remove){ - /* To avoid races, disable automatic removal on umount while setting up the new device. Restore it on failure. */ - r = dm_deferred_remove_cancel(name); - /* If activation returns EBUSY there might be no deferred removal to cancel, that's fine */ - if (r < 0 && r != -ENXIO) - return log_debug_errno(r, "Disabling automated deferred removal for verity device %s failed: %m", node); - if (r >= 0) { - restore_deferred_remove = strdup(name); - if (!restore_deferred_remove) - return -ENOMEM; - } - } - - r = verity_can_reuse(verity, name, &existing_cd); - /* Same as above, -EINVAL can randomly happen when it actually means -EEXIST */ - if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE)) - break; - if (r < 0 && !IN_SET(r, -ENODEV, -ENOENT, -EBUSY)) - return log_debug_errno(r, "Checking whether existing verity device %s can be reused failed: %m", node); + if (!restore_deferred_remove){ + /* To avoid races, disable automatic removal on umount while setting up the new device. Restore it on failure. */ + r = dm_deferred_remove_cancel(name); + /* If activation returns EBUSY there might be no deferred removal to cancel, that's fine */ + if (r < 0 && r != -ENXIO) + return log_debug_errno(r, "Failed to disable automated deferred removal for verity device %s: %m", node); if (r >= 0) { - /* devmapper might say that the device exists, but the devlink might not yet have been - * created. Check and wait for the udev event in that case. */ - r = device_wait_for_devlink(node, "block", verity_timeout(), NULL); - /* Fallback to activation with a unique device if it's taking too long */ - if (r == -ETIMEDOUT && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE)) - break; - if (r < 0) - return r; - - crypt_free_and_replace(cd, existing_cd); + restore_deferred_remove = strdup(name); + if (!restore_deferred_remove) + return log_oom_debug(); } } - if (r >= 0) - goto success; - /* Device is being opened by another process, but it has not finished yet, yield for 2ms */ + r = verity_can_reuse(verity, name, &existing_cd); + /* Same as above, -EINVAL can randomly happen when it actually means -EEXIST */ + if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE)) + break; + if (IN_SET(r, + -ENOENT, /* Removed?? */ + -EBUSY, /* Volume is being opened but not ready, crypt_init_by_name() can fetch details. */ + -ENODEV /* Volume is being opened but not ready, crypt_init_by_name() would fail, try to open again. */ )) + goto try_again; + if (r < 0) + return log_debug_errno(r, "Failed to check if existing verity device %s can be reused: %m", node); + + if (r >= 0) { /* FIXME: Drop this meaningless condition later. */ + /* devmapper might say that the device exists, but the devlink might not yet have been + * created. Check and wait for the udev event in that case. */ + r = device_wait_for_devlink(node, "block", verity_timeout(), NULL); + /* Fallback to activation with a unique device if it's taking too long */ + if (r == -ETIMEDOUT && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE)) + break; + if (r < 0) + return log_debug_errno(r, "Failed to wait device node symlink %s: %m", node); + } + + if (existing_cd) + crypt_free_and_replace(cd, existing_cd); + + goto success; + + try_again: + /* Device is being removed by another process. Let's wait for a while. */ (void) usleep(2 * USEC_PER_MSEC); } From 12f5fbdf30cbb917760cc1887abd19089d49b0a8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 17 Sep 2022 15:27:15 +0900 Subject: [PATCH 2/5] dissect-image: fix error handling of @cancel_deferred_remove DM command See target_message() in drivers/md/dm-ioctl.c and dm_cancel_deferred_remove() in drivers/md/dm.c. --- src/shared/dissect-image.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 77d6101cff..6bfea815ee 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -2090,14 +2090,17 @@ static int verity_partition( if (!restore_deferred_remove){ /* To avoid races, disable automatic removal on umount while setting up the new device. Restore it on failure. */ r = dm_deferred_remove_cancel(name); - /* If activation returns EBUSY there might be no deferred removal to cancel, that's fine */ - if (r < 0 && r != -ENXIO) + /* -EBUSY and -ENXIO: the device has already been removed or being removed. We cannot + * use the device, try to open again. See target_message() in drivers/md/dm-ioctl.c + * and dm_cancel_deferred_remove() in drivers/md/dm.c */ + if (IN_SET(r, -EBUSY, -ENXIO)) + goto try_again; + if (r < 0) return log_debug_errno(r, "Failed to disable automated deferred removal for verity device %s: %m", node); - if (r >= 0) { - restore_deferred_remove = strdup(name); - if (!restore_deferred_remove) - return log_oom_debug(); - } + + restore_deferred_remove = strdup(name); + if (!restore_deferred_remove) + return log_oom_debug(); } r = verity_can_reuse(verity, name, &existing_cd); From f80015ff40bd6e17eccba3690b45335c5b11fad7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 17 Sep 2022 05:03:24 +0900 Subject: [PATCH 3/5] dissect-image: try to open device node before activating Hopefully decrease the chance that the device is removed soon after it is detected. --- src/shared/dissect-image.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 6bfea815ee..4fa1d4707f 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -2069,7 +2069,16 @@ static int verity_partition( * 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; + /* First, check if the device already exists. */ + fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY); + if (fd < 0 && !ERRNO_IS_DEVICE_ABSENT(errno)) + return log_debug_errno(errno, "Failed to open verity device %s: %m", node); + if (fd >= 0) + goto check; /* The device already exists. Let's check it. */ + + /* The symlink to the device node does not exist yet. Assume not activated, and let's activate it. */ r = do_crypt_activate_verity(cd, name, verity); if (r >= 0) goto success; /* The device is activated. */ @@ -2087,6 +2096,7 @@ static int verity_partition( -EBUSY /* Volume is being opened but not ready, crypt_init_by_name() can fetch details. */)) return log_debug_errno(r, "Failed to activate verity device %s: %m", node); + check: if (!restore_deferred_remove){ /* To avoid races, disable automatic removal on umount while setting up the new device. Restore it on failure. */ r = dm_deferred_remove_cancel(name); @@ -2115,7 +2125,7 @@ static int verity_partition( if (r < 0) return log_debug_errno(r, "Failed to check if existing verity device %s can be reused: %m", node); - if (r >= 0) { /* FIXME: Drop this meaningless condition later. */ + if (fd < 0) { /* devmapper might say that the device exists, but the devlink might not yet have been * created. Check and wait for the udev event in that case. */ r = device_wait_for_devlink(node, "block", verity_timeout(), NULL); From f7725647bb41c3398a867f139efe526efe8aa1b3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 10 Sep 2022 05:44:27 +0900 Subject: [PATCH 4/5] dissect-image: open dissected or decrypted partitions and mount through the file descriptor If multiple services with the same encrypted image are simultaneously starting, one may deactivate the dm device while others using it. Or, similary, after (regular) partitions are dissected, another process may try to remove them before we mount them. To prevent such situations, let's keep the dissected and decrypted partitions opened. Then, use the file descriptors when we mount the partitions. Fixes #24617. --- src/shared/dissect-image.c | 107 +++++++++++++++++++++++++++++++++++-- src/shared/dissect-image.h | 8 ++- 2 files changed, 109 insertions(+), 6 deletions(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 4fa1d4707f..dc85ce9ea5 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -32,6 +32,7 @@ #include "def.h" #include "device-nodes.h" #include "device-util.h" +#include "devnum-util.h" #include "discover-image.h" #include "dissect-image.h" #include "dm-util.h" @@ -236,6 +237,7 @@ static void dissected_partition_done(DissectedPartition *p) { free(p->decrypted_fstype); free(p->decrypted_node); free(p->mount_options); + safe_close(p->mount_node_fd); *p = DISSECTED_PARTITION_NULL; } @@ -264,6 +266,48 @@ static int make_partition_devname( return asprintf(ret, "%s%s%i", whole_devname, need_p ? "p" : "", nr); } +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; + dev_t devnum; + int r; + + assert(node); + assert(loop); + + fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return -errno; + + /* Check if the block device is a child of (or equivalent to) the originally provided one. */ + r = block_device_new_from_fd(fd, is_partition ? BLOCK_DEVICE_LOOKUP_WHOLE_DISK : 0, &dev); + if (r < 0) + return r; + + r = sd_device_get_devnum(dev, &devnum); + if (r < 0) + return r; + + if (loop->devno != devnum) + return -ENXIO; + + /* Also check diskseq. */ + if (loop->diskseq > 0) { + uint64_t diskseq; + + r = fd_get_diskseq(fd, &diskseq); + if (r < 0) + return r; + + if (loop->diskseq != diskseq) + return -ENXIO; + } + + log_debug("Opened %s (fd=%i, whole_block_devnum=" DEVNUM_FORMAT_STR ", diskseq=%" PRIu64 ").", + node, fd, DEVNUM_FORMAT_VAL(loop->devno), loop->diskseq); + return TAKE_FD(fd); +} + static int dissect_image( DissectedImage *m, int fd, @@ -365,6 +409,13 @@ static int dissect_image( 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; + + if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_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); @@ -406,6 +457,7 @@ static int dissect_image( .fstype = TAKE_PTR(t), .node = TAKE_PTR(n), .mount_options = TAKE_PTR(o), + .mount_node_fd = TAKE_FD(mount_node_fd), .offset = 0, .size = UINT64_MAX, }; @@ -778,6 +830,7 @@ static int dissect_image( if (designator != _PARTITION_DESIGNATOR_INVALID) { _cleanup_free_ char *t = NULL, *o = NULL, *l = NULL; + _cleanup_close_ int mount_node_fd = -1; const char *options = NULL; if (m->partitions[designator].found) { @@ -793,6 +846,12 @@ static int dissect_image( dissected_partition_done(m->partitions + designator); } + if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) { + mount_node_fd = open_partition(node, /* is_partition = */ true, m->loop); + if (mount_node_fd < 0) + return mount_node_fd; + } + if (fstype) { t = strdup(fstype); if (!t) @@ -823,6 +882,7 @@ static int dissect_image( .label = TAKE_PTR(l), .uuid = id, .mount_options = TAKE_PTR(o), + .mount_node_fd = TAKE_FD(mount_node_fd), .offset = (uint64_t) start * 512, .size = (uint64_t) size * 512, }; @@ -851,6 +911,7 @@ static int dissect_image( break; case 0xEA: { /* Boot Loader Spec extended $BOOT partition */ + _cleanup_close_ int mount_node_fd = -1; _cleanup_free_ char *o = NULL; sd_id128_t id = SD_ID128_NULL; const char *sid, *options = NULL; @@ -859,6 +920,12 @@ static int dissect_image( if (m->partitions[PARTITION_XBOOTLDR].found) continue; + if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_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); @@ -879,6 +946,7 @@ static int dissect_image( .node = TAKE_PTR(node), .uuid = id, .mount_options = TAKE_PTR(o), + .mount_node_fd = TAKE_FD(mount_node_fd), .offset = (uint64_t) start * 512, .size = (uint64_t) size * 512, }; @@ -1048,9 +1116,16 @@ static int dissect_image( /* 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_free_ char *o = NULL; const char *options; + if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) { + mount_node_fd = open_partition(generic_node, /* is_partition = */ true, m->loop); + if (mount_node_fd < 0) + return mount_node_fd; + } + options = mount_options_from_designator(mount_options, PARTITION_ROOT); if (options) { o = strdup(options); @@ -1068,6 +1143,7 @@ static int dissect_image( .node = TAKE_PTR(generic_node), .uuid = generic_uuid, .mount_options = TAKE_PTR(o), + .mount_node_fd = TAKE_FD(mount_node_fd), .offset = UINT64_MAX, .size = UINT64_MAX, }; @@ -1319,12 +1395,13 @@ static int mount_partition( assert(m); assert(where); + if (m->mount_node_fd < 0) + return 0; + /* Use decrypted node and matching fstype if available, otherwise use the original device */ - node = m->decrypted_node ?: m->node; + node = FORMAT_PROC_FD_PATH(m->mount_node_fd); fstype = m->decrypted_node ? m->decrypted_fstype: m->fstype; - if (!m->found || !node) - return 0; if (!fstype) return -EAFNOSUPPORT; @@ -1724,6 +1801,7 @@ static int decrypt_partition( _cleanup_free_ char *node = NULL, *name = NULL; _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL; + _cleanup_close_ int fd = -1; int r; assert(m); @@ -1767,12 +1845,17 @@ static int decrypt_partition( return r == -EPERM ? -EKEYREJECTED : r; } + fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return log_debug_errno(errno, "Failed to open %s: %m", node); + d->decrypted[d->n_decrypted++] = (DecryptedPartition) { .name = TAKE_PTR(name), .device = TAKE_PTR(cd), }; m->decrypted_node = TAKE_PTR(node); + close_and_replace(m->mount_node_fd, fd); return 0; } @@ -2008,6 +2091,7 @@ static int verity_partition( _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; int r; assert(m); @@ -2081,7 +2165,7 @@ static int verity_partition( /* The symlink to the device node does not exist yet. Assume not activated, and let's activate it. */ r = do_crypt_activate_verity(cd, name, verity); if (r >= 0) - goto success; /* The device is activated. */ + goto try_open; /* The device is activated. Let's open it. */ /* libdevmapper can return EINVAL when the device is already in the activation stage. * There's no way to distinguish this situation from a genuine error due to invalid * parameters, so immediately fall back to activating the device with a unique name. @@ -2136,6 +2220,20 @@ static int verity_partition( return log_debug_errno(r, "Failed to wait device node symlink %s: %m", node); } + try_open: + if (fd < 0) { + /* Now, the device is activated and devlink is created. Let's open it. */ + fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { + if (!ERRNO_IS_DEVICE_ABSENT(errno)) + return log_debug_errno(errno, "Failed to open verity device %s: %m", node); + + /* The device has already been removed?? */ + goto try_again; + } + } + + mount_node_fd = TAKE_FD(fd); if (existing_cd) crypt_free_and_replace(cd, existing_cd); @@ -2171,6 +2269,7 @@ success: }; m->decrypted_node = TAKE_PTR(node); + close_and_replace(m->mount_node_fd, mount_node_fd); return 0; } diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index 581c607e51..cd0f5b6e64 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -29,6 +29,7 @@ struct DissectedPartition { char *decrypted_node; char *decrypted_fstype; char *mount_options; + int mount_node_fd; uint64_t size; uint64_t offset; }; @@ -37,6 +38,7 @@ struct DissectedPartition { ((DissectedPartition) { \ .partno = -1, \ .architecture = _ARCHITECTURE_INVALID, \ + .mount_node_fd = -1, \ }) typedef enum PartitionDesignator { @@ -207,8 +209,10 @@ typedef enum DissectImageFlags { DISSECT_IMAGE_GROWFS = 1 << 18, /* Grow file systems in partitions marked for that to the size of the partitions after mount */ DISSECT_IMAGE_MOUNT_IDMAPPED = 1 << 19, /* Mount mounts with kernel 5.12-style userns ID mapping, if file system type doesn't support uid=/gid= */ DISSECT_IMAGE_MANAGE_PARTITION_DEVICES = 1 << 20, /* Manage partition devices, e.g. probe each partition in more detail */ - DISSECT_IMAGE_BLOCK_DEVICE = DISSECT_IMAGE_MANAGE_PARTITION_DEVICES, - DISSECT_IMAGE_RELAX_SYSEXT_CHECK = 1 << 21, /* Don't insist that the extension-release file name matches the image name */ + DISSECT_IMAGE_OPEN_PARTITION_DEVICES = 1 << 21, /* Open dissected partitions and decrypted partitions */ + DISSECT_IMAGE_BLOCK_DEVICE = DISSECT_IMAGE_MANAGE_PARTITION_DEVICES | + DISSECT_IMAGE_OPEN_PARTITION_DEVICES, + DISSECT_IMAGE_RELAX_SYSEXT_CHECK = 1 << 22, /* Don't insist that the extension-release file name matches the image name */ } DissectImageFlags; struct DissectedImage { From d2c6e79d89ce2f967d7a8a1e9c94492907dfd564 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 1 Oct 2022 11:02:40 +0900 Subject: [PATCH 5/5] dissect-image: introduce probe_filesystem_full() which can take file descriptor of device node In dissect_loop_device(), we have opened the device node. Let's reuse the file descriptor. --- src/shared/dissect-image.c | 47 +++++++++++++++++++++++++++++--------- src/shared/dissect-image.h | 5 +++- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index dc85ce9ea5..2989d31d3c 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -74,19 +74,44 @@ /* how many times to wait for the device nodes to appear */ #define N_DEVICE_NODE_LIST_ATTEMPTS 10 -int probe_filesystem(const char *node, char **ret_fstype) { +int probe_filesystem_full(int fd, const char *path, 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 * 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; const char *fstype; int r; - errno = 0; - b = blkid_new_probe_from_filename(node); + assert(fd >= 0 || path); + assert(ret_fstype); + + if (fd < 0) { + fd_close = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY); + if (fd_close < 0) + return -errno; + + fd = fd_close; + } + + if (!path) { + r = fd_get_path(fd, &path_by_fd); + if (r < 0) + return r; + + path = path_by_fd; + } + + b = blkid_new_probe(); if (!b) + return -ENOMEM; + + errno = 0; + r = blkid_probe_set_device(b, fd, 0, 0); + if (r != 0) return errno_or_else(ENOMEM); blkid_probe_enable_superblocks(b, 1); @@ -98,16 +123,16 @@ int probe_filesystem(const char *node, char **ret_fstype) { goto not_found; if (r == -2) return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN), - "Results ambiguous for partition %s", node); + "Results ambiguous for partition %s", path); if (r != 0) - return log_debug_errno(errno_or_else(EIO), "Failed to probe partition %s: %m", node); + return log_debug_errno(errno_or_else(EIO), "Failed to probe partition %s: %m", path); (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); if (fstype) { char *t; - log_debug("Probed fstype '%s' on partition %s.", fstype, node); + log_debug("Probed fstype '%s' on partition %s.", fstype, path); t = strdup(fstype); if (!t) @@ -118,7 +143,7 @@ int probe_filesystem(const char *node, char **ret_fstype) { } not_found: - log_debug("No type detected on partition %s", node); + log_debug("No type detected on partition %s", path); *ret_fstype = NULL; return 0; #else @@ -140,8 +165,8 @@ static int dissected_image_probe_filesystem(DissectedImage *m) { if (!p->found) continue; - if (!p->fstype && p->node) { - r = probe_filesystem(p->node, &p->fstype); + 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) return r; } @@ -2326,8 +2351,8 @@ int dissected_image_decrypt( return r; } - if (!p->decrypted_fstype && p->decrypted_node) { - r = probe_filesystem(p->decrypted_node, &p->decrypted_fstype); + 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); if (r < 0 && r != -EUCLEAN) return r; } diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index cd0f5b6e64..8007b544e7 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -267,7 +267,10 @@ MountOptions* mount_options_free_all(MountOptions *options); DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all); const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator); -int probe_filesystem(const char *node, char **ret_fstype); +int probe_filesystem_full(int fd, const char *path, char **ret_fstype); +static inline int probe_filesystem(const char *path, char **ret_fstype) { + return probe_filesystem_full(-1, path, ret_fstype); +} int dissect_image_file( const char *path, const VeritySettings *verity,