]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect-image: probe file system via main block device fd/image file fd 25591/head
authorLennart Poettering <lennart@poettering.net>
Wed, 30 Nov 2022 22:00:37 +0000 (23:00 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 1 Dec 2022 21:09:30 +0000 (22:09 +0100)
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.

src/shared/dissect-image.c
src/shared/dissect-image.h

index cf7fae76d1610b913e0cf9919fe90feb1a8ac639..ddd6c5430a82e866d77a12da77a3133dad114541 100644 (file)
 /* 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
index 52d8a2e5696ba19c053cd9d6da8c3233c745af49..2f77228a1d5a7c29929de921e1d2f697519a9904 100644 (file)
@@ -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,