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:
+14
-1
@@ -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>
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<citerefentry><refentrytitle>systemd-escape</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||
<option>--path</option> to properly escape a file system path.</para>
|
||||
|
||||
<para>This unit invokes <command>systemd-dissect --attach --quiet --loop-ref-auto</command> on the
|
||||
<para>This unit invokes <command>systemd-dissect --attach --relax --quiet --loop-ref-auto</command> on the
|
||||
specified files, see
|
||||
<citerefentry><refentrytitle>systemd-dissect</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
|
||||
details.</para>
|
||||
|
||||
@@ -37,7 +37,8 @@ _systemd_dissect() {
|
||||
-r --read-only
|
||||
--mkdir
|
||||
--rmdir
|
||||
--in-memory'
|
||||
--in-memory
|
||||
--relax'
|
||||
[ARG]='-m --mount -M
|
||||
-u --umount -U
|
||||
--attach
|
||||
|
||||
+46
-19
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -20,5 +20,5 @@ After=modprobe@loop.service
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
TimeoutSec=infinity
|
||||
ExecStart=systemd-dissect --attach --loop-ref-auto --quiet %f
|
||||
ExecStart=systemd-dissect --attach --relax --loop-ref-auto --quiet %f
|
||||
ExecStop=systemd-dissect --detach %f
|
||||
|
||||
Reference in New Issue
Block a user