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:
+30
-12
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user