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.
This commit is contained in:
Lennart Poettering
2022-12-01 22:09:30 +01:00
parent 59a4c0d7e3
commit c80c9079c8
2 changed files with 32 additions and 14 deletions
+30 -12
View File
@@ -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
+2 -2
View 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,