From: Lennart Poettering Date: Wed, 30 Nov 2022 22:00:37 +0000 (+0100) Subject: dissect-image: probe file system via main block device fd/image file fd X-Git-Tag: v253-rc1~394^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F25591%2Fhead;p=thirdparty%2Fsystemd.git dissect-image: probe file system via main block device fd/image file fd let's make sure we can probe file systems also when unprivileged: instead of probing the partition block devices for file system signatures, let's go via the original "whole" fd. libblkid makes this easy actually, as it allows us to specify the offset/size of the area to probe. And we have the partition offsets/sizes anyway, so it's trivial for us to make use of. This thus enables fs probing also when lacking privs and operating on naked regular files without loopback devices or anything like this. --- diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index cf7fae76d16..ddd6c5430a8 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -74,9 +74,15 @@ /* 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 @@ -105,12 +111,19 @@ int probe_filesystem_full(int fd, const char *path, char **ret_fstype) { 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); @@ -154,7 +167,7 @@ not_found: } #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); @@ -167,9 +180,14 @@ static int dissected_image_probe_filesystem(DissectedImage *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; } @@ -1117,6 +1135,10 @@ static int dissect_image( } } + r = dissected_image_probe_filesystems(m, fd); + if (r < 0) + return r; + return 0; } #endif @@ -2240,7 +2262,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, &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; } @@ -2952,10 +2974,6 @@ int dissect_loop_device( if (r < 0) return r; - r = dissected_image_probe_filesystem(m); - if (r < 0) - return r; - *ret = TAKE_PTR(m); return 0; #else diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index 52d8a2e5696..2f77228a1d5 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -133,9 +133,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, char **ret_fstype); +int probe_filesystem_full(int fd, const char *path, uint64_t offset, uint64_t size, char **ret_fstype); static inline int probe_filesystem(const char *path, char **ret_fstype) { - return probe_filesystem_full(-1, path, ret_fstype); + return probe_filesystem_full(-1, path, 0, UINT64_MAX, ret_fstype); } int dissect_image_file( const char *path,