dissect: optionally allow attaching images that do not qualify as DDIs with --attach

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.
This commit is contained in:
Lennart Poettering
2026-09-22 16:04:26 +02:00
committed by Luca Boccassi
parent efa16c7f31
commit b0edc60661
4 changed files with 58 additions and 19 deletions
+14 -1
View File
@@ -209,7 +209,8 @@
of <command>losetup --find --show --partscan</command>, but will validate the image as DDI before
attaching, and derive the correct sector size to use automatically. Moreover, it ensures the
per-partition block devices are created before returning and attempts to enable direct IO mode, if
possible. Takes a path to a disk image file.</para>
possible. Takes a path to a disk image file. Use <option>--relax</option> to attach images that do
not qualify as DDI.</para>
<para>If combined with <option>--quiet</option> output of the block device name is suppressed.</para>
@@ -541,6 +542,18 @@
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--relax</option></term>
<listitem><para>If combined with <option>--attach</option>, skips validation of the image and
attaches it to the loopback block device as it is, even if it does not qualify as DDI. If this
switch is used, no image dissection takes place, and thus it is not guaranteed that the
per-partition block devices are created before the command returns. May not be combined with any
other command than <option>--attach</option>.</para>
<xi:include href="version-info.xml" xpointer="v263"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--mtree-hash=no</option></term>
+2 -1
View File
@@ -37,7 +37,8 @@ _systemd_dissect() {
-r --read-only
--mkdir
--rmdir
--in-memory'
--in-memory
--relax'
[ARG]='-m --mount -M
-u --umount -U
--attach
+20 -7
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);
@@ -1997,7 +2003,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,6 +2059,12 @@ static int run(int argc, char *argv[]) {
log_warning_errno(r, "Failed to set loop reference string to '%s', ignoring: %m", arg_loop_ref);
}
/* 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,
@@ -2063,9 +2075,10 @@ static int run(int argc, char *argv[]) {
&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,
+12
View File
@@ -1066,6 +1066,18 @@ test ! -e "/dev/disk/by-loop-ref/$name"
systemd-dissect --detach "$MINIMAL_IMAGE.raw"
(! systemd-dissect --detach "$MINIMAL_IMAGE.raw")
# --attach --relax also works on images that do not qualify as DDI, e.g. an entirely blank one
BLANK_IMAGE="$(mktemp /var/tmp/blankXXX.raw)"
truncate -s 16M "$BLANK_IMAGE"
(! systemd-dissect --attach "$BLANK_IMAGE")
LOOP="$(systemd-dissect --attach --relax "$BLANK_IMAGE")"
test -b "$LOOP"
systemd-dissect --detach "$LOOP"
rm -f "$BLANK_IMAGE"
# --relax makes no sense for the other verbs
(! systemd-dissect --relax "$MINIMAL_IMAGE.raw")
# check for confext functionality
mkdir -p /run/confexts/test/etc/extension-release.d
echo "ID=_any" >/run/confexts/test/etc/extension-release.d/extension-release.test