From: Luca Boccassi Date: Wed, 10 Sep 2025 17:13:37 +0000 (+0100) Subject: dissect: use blkid_probe filters to restrict probing to supported FSes and no raid X-Git-Tag: v259-rc1~561 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=72bf86663c2c9a4443457fdd6bd69714a234903d;p=thirdparty%2Fsystemd.git dissect: use blkid_probe filters to restrict probing to supported FSes and no raid We only support a subset of filesystems, and no RAID, for DDIs. blkid spends a lot of time trying to probe for the filesystem type, so cut it short by using the filtering options to restrict it to the filesystems we support, and to exclude raid probing. --- diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 26c218e90e4..bd648d84b05 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -74,33 +74,47 @@ /* how many times to wait for the device nodes to appear */ #define N_DEVICE_NODE_LIST_ATTEMPTS 10 -int dissect_fstype_ok(const char *fstype) { +static int allowed_fstypes(char ***ret_strv) { + _cleanup_strv_free_ char **l = NULL; const char *e; - bool b; - /* When we automatically mount file systems, be a bit conservative by default what we are willing to - * mount, just as an extra safety net to not mount with badly maintained legacy file system - * drivers. */ + assert(ret_strv); e = secure_getenv("SYSTEMD_DISSECT_FILE_SYSTEMS"); if (e) { - _cleanup_strv_free_ char **l = NULL; - l = strv_split(e, ":"); if (!l) return -ENOMEM; + } else { + l = strv_new("btrfs", + "erofs", + "ext4", + "f2fs", + "squashfs", + "vfat", + "xfs"); + if (!l) + return -ENOMEM; + } - b = strv_contains(l, fstype); - } else - b = STR_IN_SET(fstype, - "btrfs", - "erofs", - "ext4", - "f2fs", - "squashfs", - "vfat", - "xfs"); - if (b) + *ret_strv = TAKE_PTR(l); + + return 0; +} + +int dissect_fstype_ok(const char *fstype) { + _cleanup_strv_free_ char **l = NULL; + int r; + + /* When we automatically mount file systems, be a bit conservative by default what we are willing to + * mount, just as an extra safety net to not mount with badly maintained legacy file system + * drivers. */ + + r = allowed_fstypes(&l); + if (r < 0) + return r; + + if (strv_contains(l, fstype)) return true; log_debug("File system type '%s' is not allowed to be mounted as result of automatic dissection.", fstype); @@ -177,11 +191,37 @@ int probe_sector_size_prefer_ioctl(int fd, uint32_t *ret) { return probe_sector_size(fd, ret); } +#if HAVE_BLKID +static int probe_blkid_filter(blkid_probe p) { + _cleanup_strv_free_ char **fstypes = NULL; + int r; + + assert(p); + + r = allowed_fstypes(&fstypes); + if (r < 0) + return r; + + errno = 0; + r = blkid_probe_filter_superblocks_type(p, BLKID_FLTR_ONLYIN, fstypes); + if (r != 0) + return errno_or_else(EINVAL); + + errno = 0; + r = blkid_probe_filter_superblocks_usage(p, BLKID_FLTR_NOTIN, BLKID_USAGE_RAID); + if (r != 0) + return errno_or_else(EINVAL); + + return 0; +} +#endif + int probe_filesystem_full( int fd, const char *path, uint64_t offset, uint64_t size, + bool restrict_fstypes, char **ret_fstype) { /* Try to find device content type and return it in *ret_fstype. If nothing is found, @@ -221,6 +261,12 @@ int probe_filesystem_full( if (!b) return -ENOMEM; + if (restrict_fstypes) { + r = probe_blkid_filter(b); + if (r < 0) + return r; + } + /* The Linux kernel maintains separate block device caches for main ("whole") and partition block * devices, which means making a change to one might not be reflected immediately when reading via * the other. That's massively confusing when mixing accesses to such devices. Let's address this in @@ -387,9 +433,9 @@ static int dissected_image_probe_filesystems( /* 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); + r = probe_filesystem_full(p->mount_node_fd, p->node, 0, UINT64_MAX, /* bool restrict_fstypes= */ true, &p->fstype); else - r = probe_filesystem_full(fd, p->node, p->offset, p->size, &p->fstype); + r = probe_filesystem_full(fd, p->node, p->offset, p->size, /* bool restrict_fstypes= */ true, &p->fstype); if (r < 0) return r; } @@ -751,6 +797,10 @@ static int dissect_image( if (!b) return -ENOMEM; + r = probe_blkid_filter(b); + if (r < 0) + return r; + errno = 0; r = blkid_probe_set_device(b, fd, 0, 0); if (r != 0) @@ -3053,7 +3103,7 @@ int dissected_image_decrypt( } if (!p->decrypted_fstype && p->mount_node_fd >= 0 && p->decrypted_node) { - r = probe_filesystem_full(p->mount_node_fd, p->decrypted_node, 0, UINT64_MAX, &p->decrypted_fstype); + r = probe_filesystem_full(p->mount_node_fd, p->decrypted_node, 0, UINT64_MAX, /* bool restrict_fstypes= */ true, &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 97431bca673..2be4c342953 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -156,9 +156,9 @@ 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_full(int fd, const char *path, uint64_t offset, uint64_t size, char **ret_fstype); +int probe_filesystem_full(int fd, const char *path, uint64_t offset, uint64_t size, bool restrict_fstypes, char **ret_fstype); static inline int probe_filesystem(const char *path, char **ret_fstype) { - return probe_filesystem_full(-1, path, 0, UINT64_MAX, ret_fstype); + return probe_filesystem_full(-1, path, 0, UINT64_MAX, /* bool restrict_fstypes= */ false, ret_fstype); } int dissect_log_error(int log_level, int r, const char *name, const VeritySettings *verity);