dissect: optionally allow attaching images that do not qualify as DDIs with --attach (#43583)

It's nice to use --attach since it validates our images. So far, it
strictly insisted on checking that the image was a DDI however, which
limits its use for certain usecases.

Add "--relax" to address this limitation.

Fixes: #43605
This commit is contained in:
Yu Watanabe
2026-09-23 08:54:29 +09:00
committed by GitHub
6 changed files with 76 additions and 23 deletions
+46 -19
View File
@@ -109,6 +109,7 @@ static RuntimeScope arg_runtime_scope = _RUNTIME_SCOPE_INVALID;
static bool arg_all = false;
static uid_t arg_uid_base = UID_INVALID;
static bool arg_quiet = false;
static bool arg_relax = false;
static ImageFilter *arg_image_filter = NULL;
static int arg_copy_ownership = -1;
@@ -355,6 +356,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_loop_ref_auto = true;
break;
OPTION_LONG("relax", NULL, "Skip DDI validation, attach image as it is"):
arg_relax = true;
break;
OPTION_LONG("image-policy", "POLICY", "Specify image dissection policy"):
r = parse_image_policy_argument(opts.arg, &arg_image_policy);
if (r < 0)
@@ -707,6 +712,10 @@ static int parse_argv(int argc, char *argv[]) {
return r;
}
if (arg_relax && arg_action != ACTION_ATTACH)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"The --relax switch is only supported in combination with --attach.");
SET_FLAG(arg_flags, DISSECT_IMAGE_ALLOW_INTERACTIVE_AUTH, isatty_safe(STDIN_FILENO));
return 1;
@@ -1809,19 +1818,16 @@ static int action_discover(void) {
return table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
}
static int action_attach(DissectedImage *m, LoopDevice *d) {
static int action_attach(LoopDevice *d) {
int r;
assert(m);
assert(d);
r = loop_device_set_autoclear(d, false);
if (r < 0)
return log_error_errno(r, "Failed to disable auto-clear logic on loopback device: %m");
r = dissected_image_relinquish(m);
if (r < 0)
return log_error_errno(r, "Failed to relinquish DM and loopback block devices: %m");
loop_device_relinquish(d);
if (!arg_quiet)
puts(d->node);
@@ -1849,10 +1855,24 @@ static int action_detach(const char *path) {
if (r < 0)
return log_error_errno(r, "Failed to open '%s' as loopback block device: %m", path);
} else if (S_ISREG(st.st_mode)) {
/* If the specified block device is not a loopback block device itself, it might be the
* backing device of one (this is the case when systemd-loop@.service is instantiated for a
* block device, e.g. a CD-ROM drive, in which case it is passed the backing device on
* ExecStop= too). Hence, in that case search for the loopback block device backed by it
* below, the same way as we do for regular files. */
if (LOOP_DEVICE_IS_FOREIGN(loop))
loop = loop_device_unref(loop);
} else if (!S_ISREG(st.st_mode))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "'%s' is neither a block device nor a regular file, refusing.", path);
if (!loop) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
/* If a regular file is specified, search for a loopback block device that is backed by it */
/* If a regular file (or a block device that is not a loopback block device) is specified,
* search for a loopback block device that is backed by it. Note that the kernel reports
* the backing inode of a loopback device both for regular files and for block device
* nodes, hence we can match by inode in both cases. */
r = sd_device_enumerator_new(&e);
if (r < 0)
@@ -1997,7 +2017,7 @@ static int run(int argc, char *argv[]) {
;
}
if (arg_image) {
if (arg_image && !arg_relax) {
r = verity_settings_load(
&arg_verity_settings,
arg_image,
@@ -2053,19 +2073,26 @@ static int run(int argc, char *argv[]) {
log_warning_errno(r, "Failed to set loop reference string to '%s', ignoring: %m", arg_loop_ref);
}
r = dissect_loop_device_and_warn(
d,
&arg_verity_settings,
/* mount_options= */ NULL,
arg_image_policy,
arg_image_filter,
arg_flags,
&m);
if (r < 0)
return r;
/* Unless --relax is specified we insist that the image qualifies as DDI:
* dissecting it validates it against the image policy and waits until the
* kernel created the per-partition block devices, so that callers may
* access them immediately after we return. With --relax we skip dissection
* entirely, and attach the image as it is. */
if (!arg_relax) {
r = dissect_loop_device_and_warn(
d,
&arg_verity_settings,
/* mount_options= */ NULL,
arg_image_policy,
arg_image_filter,
arg_flags,
&m);
if (r < 0)
return r;
}
if (arg_action == ACTION_ATTACH)
return action_attach(m, d);
return action_attach(d);
r = dissected_image_load_verity_sig_partition(
m,