sysupdate: refuse reboot/pending logic when a component is selected

The `pending` and `reboot` verbs, as well as the `--reboot` switch, compare
the newest installed version against the booted OS version (IMAGE_VERSION= from
os-release). When a component is selected via --component=, this compares the
component's version against the unrelated host OS version, which by design live
in separate version spaces. The result is arbitrary reboot decisions: depending
on the relative version strings sysupdate would either always or never reboot.

Refuse the combination with a clear error instead of silently performing a
bogus comparison. Correctly tracking a per-component booted version is left as a
future feature.

Fixes: https://github.com/systemd/systemd/issues/42330
This commit is contained in:
Armaan Sandhu
2026-06-19 19:52:24 +01:00
committed by Luca Boccassi
parent d6aed1dca8
commit 095e677436
3 changed files with 22 additions and 2 deletions
+5 -2
View File
@@ -239,7 +239,9 @@
updated together in a synchronous fashion. Simply define multiple transfer files within the same
<filename>sysupdate.d/</filename> directory for these cases.</para>
<para>This option may not be combined with <option>--definitions=</option>.</para>
<para>This option may not be combined with <option>--definitions=</option>, nor with the
<command>pending</command> and <command>reboot</command> commands or the <option>--reboot</option>
switch, which only apply to the booted OS version.</para>
<xi:include href="version-info.xml" xpointer="v251"/></listitem>
</varlistentry>
@@ -314,7 +316,8 @@
<term><option>--reboot</option></term>
<listitem><para>When used in combination with the <command>update</command> commands and a new version is
installed, automatically reboots the system immediately afterwards.</para>
installed, automatically reboots the system immediately afterwards. This switch may not be combined with
<option>--component=</option>, as it only applies to the booted OS version.</para>
<xi:include href="version-info.xml" xpointer="v251"/></listitem>
</varlistentry>
+8
View File
@@ -1555,6 +1555,10 @@ static int verb_update_impl(int argc, char **argv, UpdateActionFlags action_flag
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"The --instances-max argument must be >= 2 while updating");
if (arg_reboot && arg_component)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"The --reboot switch may not be combined with --component=, as automatic reboots only apply to the booted OS version.");
if (arg_reboot) {
/* If automatic reboot on completion is requested, let's first determine the currently booted image */
@@ -1664,6 +1668,10 @@ static int verb_pending_or_reboot(int argc, char *argv[], uintptr_t _data, void
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"The --root=/--image= switches may not be combined with the '%s' operation.", argv[0]);
if (arg_component)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"The --component= switch may not be combined with the '%s' operation, which only applies to the booted OS version.", argv[0]);
r = context_make_offline(&context, /* node= */ NULL,
READ_DEFINITIONS_REQUIRES_ENABLED_TRANSFERS | READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS);
if (r < 0)
+9
View File
@@ -579,6 +579,15 @@ EOF
mkdir /run/sysupdate.d
"$SYSUPDATE" --json=short components | grep -F '{"default":false,"components":["some-component"]}' >/dev/null
# Regression test for https://github.com/systemd/systemd/issues/42330 — the
# 'pending'/'reboot' verbs and the '--reboot' switch compare the newest installed
# version against the booted OS version (IMAGE_VERSION= from os-release), which is
# unrelated to component versions. Selecting a component must therefore be refused
# rather than silently performing a bogus comparison.
(! "$SYSUPDATE" --component=some-component pending)
(! "$SYSUPDATE" --component=some-component reboot)
(! "$SYSUPDATE" --component=some-component update --reboot)
# Clean up regression test
rmdir /run/sysupdate.d
rm -rf /run/sysupdate.some-component.d