Merge pull request #24625 from yuwata/dissect-image-open-and-lock-decrypted
dissect-image: open dissected and decrypted partitions
This commit is contained in:
+197
-51
@@ -32,6 +32,7 @@
|
||||
#include "def.h"
|
||||
#include "device-nodes.h"
|
||||
#include "device-util.h"
|
||||
#include "devnum-util.h"
|
||||
#include "discover-image.h"
|
||||
#include "dissect-image.h"
|
||||
#include "dm-util.h"
|
||||
@@ -73,19 +74,44 @@
|
||||
/* how many times to wait for the device nodes to appear */
|
||||
#define N_DEVICE_NODE_LIST_ATTEMPTS 10
|
||||
|
||||
int probe_filesystem(const char *node, char **ret_fstype) {
|
||||
int probe_filesystem_full(int fd, const char *path, 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
|
||||
* different error otherwise. */
|
||||
|
||||
#if HAVE_BLKID
|
||||
_cleanup_(blkid_free_probep) blkid_probe b = NULL;
|
||||
_cleanup_free_ char *path_by_fd = NULL;
|
||||
_cleanup_close_ int fd_close = -1;
|
||||
const char *fstype;
|
||||
int r;
|
||||
|
||||
errno = 0;
|
||||
b = blkid_new_probe_from_filename(node);
|
||||
assert(fd >= 0 || path);
|
||||
assert(ret_fstype);
|
||||
|
||||
if (fd < 0) {
|
||||
fd_close = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd_close < 0)
|
||||
return -errno;
|
||||
|
||||
fd = fd_close;
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
r = fd_get_path(fd, &path_by_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
path = path_by_fd;
|
||||
}
|
||||
|
||||
b = blkid_new_probe();
|
||||
if (!b)
|
||||
return -ENOMEM;
|
||||
|
||||
errno = 0;
|
||||
r = blkid_probe_set_device(b, fd, 0, 0);
|
||||
if (r != 0)
|
||||
return errno_or_else(ENOMEM);
|
||||
|
||||
blkid_probe_enable_superblocks(b, 1);
|
||||
@@ -97,16 +123,16 @@ int probe_filesystem(const char *node, char **ret_fstype) {
|
||||
goto not_found;
|
||||
if (r == -2)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
|
||||
"Results ambiguous for partition %s", node);
|
||||
"Results ambiguous for partition %s", path);
|
||||
if (r != 0)
|
||||
return log_debug_errno(errno_or_else(EIO), "Failed to probe partition %s: %m", node);
|
||||
return log_debug_errno(errno_or_else(EIO), "Failed to probe partition %s: %m", path);
|
||||
|
||||
(void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
|
||||
|
||||
if (fstype) {
|
||||
char *t;
|
||||
|
||||
log_debug("Probed fstype '%s' on partition %s.", fstype, node);
|
||||
log_debug("Probed fstype '%s' on partition %s.", fstype, path);
|
||||
|
||||
t = strdup(fstype);
|
||||
if (!t)
|
||||
@@ -117,7 +143,7 @@ int probe_filesystem(const char *node, char **ret_fstype) {
|
||||
}
|
||||
|
||||
not_found:
|
||||
log_debug("No type detected on partition %s", node);
|
||||
log_debug("No type detected on partition %s", path);
|
||||
*ret_fstype = NULL;
|
||||
return 0;
|
||||
#else
|
||||
@@ -139,8 +165,8 @@ static int dissected_image_probe_filesystem(DissectedImage *m) {
|
||||
if (!p->found)
|
||||
continue;
|
||||
|
||||
if (!p->fstype && p->node) {
|
||||
r = probe_filesystem(p->node, &p->fstype);
|
||||
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)
|
||||
return r;
|
||||
}
|
||||
@@ -236,6 +262,7 @@ static void dissected_partition_done(DissectedPartition *p) {
|
||||
free(p->decrypted_fstype);
|
||||
free(p->decrypted_node);
|
||||
free(p->mount_options);
|
||||
safe_close(p->mount_node_fd);
|
||||
|
||||
*p = DISSECTED_PARTITION_NULL;
|
||||
}
|
||||
@@ -264,6 +291,48 @@ static int make_partition_devname(
|
||||
return asprintf(ret, "%s%s%i", whole_devname, need_p ? "p" : "", nr);
|
||||
}
|
||||
|
||||
static int open_partition(const char *node, bool is_partition, const LoopDevice *loop) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
dev_t devnum;
|
||||
int r;
|
||||
|
||||
assert(node);
|
||||
assert(loop);
|
||||
|
||||
fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
/* Check if the block device is a child of (or equivalent to) the originally provided one. */
|
||||
r = block_device_new_from_fd(fd, is_partition ? BLOCK_DEVICE_LOOKUP_WHOLE_DISK : 0, &dev);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_device_get_devnum(dev, &devnum);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (loop->devno != devnum)
|
||||
return -ENXIO;
|
||||
|
||||
/* Also check diskseq. */
|
||||
if (loop->diskseq > 0) {
|
||||
uint64_t diskseq;
|
||||
|
||||
r = fd_get_diskseq(fd, &diskseq);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (loop->diskseq != diskseq)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
log_debug("Opened %s (fd=%i, whole_block_devnum=" DEVNUM_FORMAT_STR ", diskseq=%" PRIu64 ").",
|
||||
node, fd, DEVNUM_FORMAT_VAL(loop->devno), loop->diskseq);
|
||||
return TAKE_FD(fd);
|
||||
}
|
||||
|
||||
static int dissect_image(
|
||||
DissectedImage *m,
|
||||
int fd,
|
||||
@@ -365,6 +434,13 @@ static int dissect_image(
|
||||
if (STRPTR_IN_SET(usage, "filesystem", "crypto")) {
|
||||
_cleanup_free_ char *t = NULL, *n = NULL, *o = NULL;
|
||||
const char *fstype = NULL, *options = NULL;
|
||||
_cleanup_close_ int mount_node_fd = -1;
|
||||
|
||||
if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) {
|
||||
mount_node_fd = open_partition(devname, /* is_partition = */ false, m->loop);
|
||||
if (mount_node_fd < 0)
|
||||
return mount_node_fd;
|
||||
}
|
||||
|
||||
/* OK, we have found a file system, that's our root partition then. */
|
||||
(void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
|
||||
@@ -406,6 +482,7 @@ static int dissect_image(
|
||||
.fstype = TAKE_PTR(t),
|
||||
.node = TAKE_PTR(n),
|
||||
.mount_options = TAKE_PTR(o),
|
||||
.mount_node_fd = TAKE_FD(mount_node_fd),
|
||||
.offset = 0,
|
||||
.size = UINT64_MAX,
|
||||
};
|
||||
@@ -778,6 +855,7 @@ static int dissect_image(
|
||||
|
||||
if (designator != _PARTITION_DESIGNATOR_INVALID) {
|
||||
_cleanup_free_ char *t = NULL, *o = NULL, *l = NULL;
|
||||
_cleanup_close_ int mount_node_fd = -1;
|
||||
const char *options = NULL;
|
||||
|
||||
if (m->partitions[designator].found) {
|
||||
@@ -793,6 +871,12 @@ static int dissect_image(
|
||||
dissected_partition_done(m->partitions + designator);
|
||||
}
|
||||
|
||||
if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) {
|
||||
mount_node_fd = open_partition(node, /* is_partition = */ true, m->loop);
|
||||
if (mount_node_fd < 0)
|
||||
return mount_node_fd;
|
||||
}
|
||||
|
||||
if (fstype) {
|
||||
t = strdup(fstype);
|
||||
if (!t)
|
||||
@@ -823,6 +907,7 @@ static int dissect_image(
|
||||
.label = TAKE_PTR(l),
|
||||
.uuid = id,
|
||||
.mount_options = TAKE_PTR(o),
|
||||
.mount_node_fd = TAKE_FD(mount_node_fd),
|
||||
.offset = (uint64_t) start * 512,
|
||||
.size = (uint64_t) size * 512,
|
||||
};
|
||||
@@ -851,6 +936,7 @@ static int dissect_image(
|
||||
break;
|
||||
|
||||
case 0xEA: { /* Boot Loader Spec extended $BOOT partition */
|
||||
_cleanup_close_ int mount_node_fd = -1;
|
||||
_cleanup_free_ char *o = NULL;
|
||||
sd_id128_t id = SD_ID128_NULL;
|
||||
const char *sid, *options = NULL;
|
||||
@@ -859,6 +945,12 @@ static int dissect_image(
|
||||
if (m->partitions[PARTITION_XBOOTLDR].found)
|
||||
continue;
|
||||
|
||||
if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) {
|
||||
mount_node_fd = open_partition(node, /* is_partition = */ true, m->loop);
|
||||
if (mount_node_fd < 0)
|
||||
return mount_node_fd;
|
||||
}
|
||||
|
||||
sid = blkid_partition_get_uuid(pp);
|
||||
if (sid)
|
||||
(void) sd_id128_from_string(sid, &id);
|
||||
@@ -879,6 +971,7 @@ static int dissect_image(
|
||||
.node = TAKE_PTR(node),
|
||||
.uuid = id,
|
||||
.mount_options = TAKE_PTR(o),
|
||||
.mount_node_fd = TAKE_FD(mount_node_fd),
|
||||
.offset = (uint64_t) start * 512,
|
||||
.size = (uint64_t) size * 512,
|
||||
};
|
||||
@@ -1048,9 +1141,16 @@ static int dissect_image(
|
||||
|
||||
/* If we didn't find a generic node, then we can't fix this up either */
|
||||
if (generic_node) {
|
||||
_cleanup_close_ int mount_node_fd = -1;
|
||||
_cleanup_free_ char *o = NULL;
|
||||
const char *options;
|
||||
|
||||
if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) {
|
||||
mount_node_fd = open_partition(generic_node, /* is_partition = */ true, m->loop);
|
||||
if (mount_node_fd < 0)
|
||||
return mount_node_fd;
|
||||
}
|
||||
|
||||
options = mount_options_from_designator(mount_options, PARTITION_ROOT);
|
||||
if (options) {
|
||||
o = strdup(options);
|
||||
@@ -1068,6 +1168,7 @@ static int dissect_image(
|
||||
.node = TAKE_PTR(generic_node),
|
||||
.uuid = generic_uuid,
|
||||
.mount_options = TAKE_PTR(o),
|
||||
.mount_node_fd = TAKE_FD(mount_node_fd),
|
||||
.offset = UINT64_MAX,
|
||||
.size = UINT64_MAX,
|
||||
};
|
||||
@@ -1319,12 +1420,13 @@ static int mount_partition(
|
||||
assert(m);
|
||||
assert(where);
|
||||
|
||||
if (m->mount_node_fd < 0)
|
||||
return 0;
|
||||
|
||||
/* Use decrypted node and matching fstype if available, otherwise use the original device */
|
||||
node = m->decrypted_node ?: m->node;
|
||||
node = FORMAT_PROC_FD_PATH(m->mount_node_fd);
|
||||
fstype = m->decrypted_node ? m->decrypted_fstype: m->fstype;
|
||||
|
||||
if (!m->found || !node)
|
||||
return 0;
|
||||
if (!fstype)
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
@@ -1724,6 +1826,7 @@ static int decrypt_partition(
|
||||
|
||||
_cleanup_free_ char *node = NULL, *name = NULL;
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@@ -1767,12 +1870,17 @@ static int decrypt_partition(
|
||||
return r == -EPERM ? -EKEYREJECTED : r;
|
||||
}
|
||||
|
||||
fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
return log_debug_errno(errno, "Failed to open %s: %m", node);
|
||||
|
||||
d->decrypted[d->n_decrypted++] = (DecryptedPartition) {
|
||||
.name = TAKE_PTR(name),
|
||||
.device = TAKE_PTR(cd),
|
||||
};
|
||||
|
||||
m->decrypted_node = TAKE_PTR(node);
|
||||
close_and_replace(m->mount_node_fd, fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2008,6 +2116,7 @@ static int verity_partition(
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(dm_deferred_remove_cleanp) char *restore_deferred_remove = NULL;
|
||||
_cleanup_free_ char *node = NULL, *name = NULL;
|
||||
_cleanup_close_ int mount_node_fd = -1;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@@ -2068,8 +2177,20 @@ static int verity_partition(
|
||||
* In case of ENODEV/ENOENT, which can happen if another process is activating at the exact same time,
|
||||
* retry a few times before giving up. */
|
||||
for (unsigned i = 0; i < N_DEVICE_NODE_LIST_ATTEMPTS; i++) {
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *existing_cd = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
/* First, check if the device already exists. */
|
||||
fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0 && !ERRNO_IS_DEVICE_ABSENT(errno))
|
||||
return log_debug_errno(errno, "Failed to open verity device %s: %m", node);
|
||||
if (fd >= 0)
|
||||
goto check; /* The device already exists. Let's check it. */
|
||||
|
||||
/* The symlink to the device node does not exist yet. Assume not activated, and let's activate it. */
|
||||
r = do_crypt_activate_verity(cd, name, verity);
|
||||
if (r >= 0)
|
||||
goto try_open; /* The device is activated. Let's open it. */
|
||||
/* libdevmapper can return EINVAL when the device is already in the activation stage.
|
||||
* There's no way to distinguish this situation from a genuine error due to invalid
|
||||
* parameters, so immediately fall back to activating the device with a unique name.
|
||||
@@ -2077,50 +2198,74 @@ static int verity_partition(
|
||||
* https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/96 */
|
||||
if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
|
||||
break;
|
||||
if (r < 0 && !IN_SET(r,
|
||||
-EEXIST, /* Volume is already open and ready to be used */
|
||||
-EBUSY, /* Volume is being opened but not ready, crypt_init_by_name can fetch details */
|
||||
-ENODEV /* Volume is being opened but not ready, crypt_init_by_name would fail, try to open again */))
|
||||
return r;
|
||||
if (IN_SET(r, -EEXIST, -EBUSY)) {
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *existing_cd = NULL;
|
||||
if (r == -ENODEV) /* Volume is being opened but not ready, crypt_init_by_name would fail, try to open again */
|
||||
goto try_again;
|
||||
if (!IN_SET(r,
|
||||
-EEXIST, /* Volume has already been opened and ready to be used. */
|
||||
-EBUSY /* Volume is being opened but not ready, crypt_init_by_name() can fetch details. */))
|
||||
return log_debug_errno(r, "Failed to activate verity device %s: %m", node);
|
||||
|
||||
if (!restore_deferred_remove){
|
||||
/* To avoid races, disable automatic removal on umount while setting up the new device. Restore it on failure. */
|
||||
r = dm_deferred_remove_cancel(name);
|
||||
/* If activation returns EBUSY there might be no deferred removal to cancel, that's fine */
|
||||
if (r < 0 && r != -ENXIO)
|
||||
return log_debug_errno(r, "Disabling automated deferred removal for verity device %s failed: %m", node);
|
||||
if (r >= 0) {
|
||||
restore_deferred_remove = strdup(name);
|
||||
if (!restore_deferred_remove)
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
check:
|
||||
if (!restore_deferred_remove){
|
||||
/* To avoid races, disable automatic removal on umount while setting up the new device. Restore it on failure. */
|
||||
r = dm_deferred_remove_cancel(name);
|
||||
/* -EBUSY and -ENXIO: the device has already been removed or being removed. We cannot
|
||||
* use the device, try to open again. See target_message() in drivers/md/dm-ioctl.c
|
||||
* and dm_cancel_deferred_remove() in drivers/md/dm.c */
|
||||
if (IN_SET(r, -EBUSY, -ENXIO))
|
||||
goto try_again;
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to disable automated deferred removal for verity device %s: %m", node);
|
||||
|
||||
r = verity_can_reuse(verity, name, &existing_cd);
|
||||
/* Same as above, -EINVAL can randomly happen when it actually means -EEXIST */
|
||||
if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
|
||||
restore_deferred_remove = strdup(name);
|
||||
if (!restore_deferred_remove)
|
||||
return log_oom_debug();
|
||||
}
|
||||
|
||||
r = verity_can_reuse(verity, name, &existing_cd);
|
||||
/* Same as above, -EINVAL can randomly happen when it actually means -EEXIST */
|
||||
if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
|
||||
break;
|
||||
if (IN_SET(r,
|
||||
-ENOENT, /* Removed?? */
|
||||
-EBUSY, /* Volume is being opened but not ready, crypt_init_by_name() can fetch details. */
|
||||
-ENODEV /* Volume is being opened but not ready, crypt_init_by_name() would fail, try to open again. */ ))
|
||||
goto try_again;
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to check if existing verity device %s can be reused: %m", node);
|
||||
|
||||
if (fd < 0) {
|
||||
/* devmapper might say that the device exists, but the devlink might not yet have been
|
||||
* created. Check and wait for the udev event in that case. */
|
||||
r = device_wait_for_devlink(node, "block", verity_timeout(), NULL);
|
||||
/* Fallback to activation with a unique device if it's taking too long */
|
||||
if (r == -ETIMEDOUT && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
|
||||
break;
|
||||
if (r < 0 && !IN_SET(r, -ENODEV, -ENOENT, -EBUSY))
|
||||
return log_debug_errno(r, "Checking whether existing verity device %s can be reused failed: %m", node);
|
||||
if (r >= 0) {
|
||||
/* devmapper might say that the device exists, but the devlink might not yet have been
|
||||
* created. Check and wait for the udev event in that case. */
|
||||
r = device_wait_for_devlink(node, "block", verity_timeout(), NULL);
|
||||
/* Fallback to activation with a unique device if it's taking too long */
|
||||
if (r == -ETIMEDOUT && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
|
||||
break;
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to wait device node symlink %s: %m", node);
|
||||
}
|
||||
|
||||
crypt_free_and_replace(cd, existing_cd);
|
||||
try_open:
|
||||
if (fd < 0) {
|
||||
/* Now, the device is activated and devlink is created. Let's open it. */
|
||||
fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0) {
|
||||
if (!ERRNO_IS_DEVICE_ABSENT(errno))
|
||||
return log_debug_errno(errno, "Failed to open verity device %s: %m", node);
|
||||
|
||||
/* The device has already been removed?? */
|
||||
goto try_again;
|
||||
}
|
||||
}
|
||||
if (r >= 0)
|
||||
goto success;
|
||||
|
||||
/* Device is being opened by another process, but it has not finished yet, yield for 2ms */
|
||||
mount_node_fd = TAKE_FD(fd);
|
||||
if (existing_cd)
|
||||
crypt_free_and_replace(cd, existing_cd);
|
||||
|
||||
goto success;
|
||||
|
||||
try_again:
|
||||
/* Device is being removed by another process. Let's wait for a while. */
|
||||
(void) usleep(2 * USEC_PER_MSEC);
|
||||
}
|
||||
|
||||
@@ -2149,6 +2294,7 @@ success:
|
||||
};
|
||||
|
||||
m->decrypted_node = TAKE_PTR(node);
|
||||
close_and_replace(m->mount_node_fd, mount_node_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2205,8 +2351,8 @@ int dissected_image_decrypt(
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!p->decrypted_fstype && p->decrypted_node) {
|
||||
r = probe_filesystem(p->decrypted_node, &p->decrypted_fstype);
|
||||
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);
|
||||
if (r < 0 && r != -EUCLEAN)
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ struct DissectedPartition {
|
||||
char *decrypted_node;
|
||||
char *decrypted_fstype;
|
||||
char *mount_options;
|
||||
int mount_node_fd;
|
||||
uint64_t size;
|
||||
uint64_t offset;
|
||||
};
|
||||
@@ -37,6 +38,7 @@ struct DissectedPartition {
|
||||
((DissectedPartition) { \
|
||||
.partno = -1, \
|
||||
.architecture = _ARCHITECTURE_INVALID, \
|
||||
.mount_node_fd = -1, \
|
||||
})
|
||||
|
||||
typedef enum PartitionDesignator {
|
||||
@@ -207,8 +209,10 @@ typedef enum DissectImageFlags {
|
||||
DISSECT_IMAGE_GROWFS = 1 << 18, /* Grow file systems in partitions marked for that to the size of the partitions after mount */
|
||||
DISSECT_IMAGE_MOUNT_IDMAPPED = 1 << 19, /* Mount mounts with kernel 5.12-style userns ID mapping, if file system type doesn't support uid=/gid= */
|
||||
DISSECT_IMAGE_MANAGE_PARTITION_DEVICES = 1 << 20, /* Manage partition devices, e.g. probe each partition in more detail */
|
||||
DISSECT_IMAGE_BLOCK_DEVICE = DISSECT_IMAGE_MANAGE_PARTITION_DEVICES,
|
||||
DISSECT_IMAGE_RELAX_SYSEXT_CHECK = 1 << 21, /* Don't insist that the extension-release file name matches the image name */
|
||||
DISSECT_IMAGE_OPEN_PARTITION_DEVICES = 1 << 21, /* Open dissected partitions and decrypted partitions */
|
||||
DISSECT_IMAGE_BLOCK_DEVICE = DISSECT_IMAGE_MANAGE_PARTITION_DEVICES |
|
||||
DISSECT_IMAGE_OPEN_PARTITION_DEVICES,
|
||||
DISSECT_IMAGE_RELAX_SYSEXT_CHECK = 1 << 22, /* Don't insist that the extension-release file name matches the image name */
|
||||
} DissectImageFlags;
|
||||
|
||||
struct DissectedImage {
|
||||
@@ -263,7 +267,10 @@ 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(const char *node, char **ret_fstype);
|
||||
int probe_filesystem_full(int fd, const char *path, char **ret_fstype);
|
||||
static inline int probe_filesystem(const char *path, char **ret_fstype) {
|
||||
return probe_filesystem_full(-1, path, ret_fstype);
|
||||
}
|
||||
int dissect_image_file(
|
||||
const char *path,
|
||||
const VeritySettings *verity,
|
||||
|
||||
Reference in New Issue
Block a user