sysext: provide a cmdline kill switch for the sysext/confext merging logic

While it is possible to disable sysext/confext merging in the main system
with 'systemctl disable', sysext/confext are always merged in the initrd,
both by systemd-{sys,conf}ext-initrd.service and by
systemd-{sys,conf}ext-sysroot.service and especially the latter can be
unexpected. Provide kernel cmdline options systemd.{sys,conf}ext=0 and
rd.systemd.{sys,conf}ext=0 covering all options.
This commit is contained in:
Vitaly Kuznetsov
2026-04-07 09:51:03 +02:00
parent c70b17daad
commit 2299a37e28
9 changed files with 46 additions and 1 deletions
+16
View File
@@ -829,6 +829,22 @@
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.sysext=</varname></term>
<term><varname>systemd.confext=</varname></term>
<term><varname>rd.systemd.sysext=</varname></term>
<term><varname>rd.systemd.confext=</varname></term>
<listitem><para>Take boolean arguments, default to on. Control whether system and configuration
extensions for the initrd (<varname>rd.systemd.sysext=</varname>, <varname>rd.systemd.confext=</varname>)
and for the main system (<varname>systemd.sysext=</varname>, <varname>systemd.confext=</varname>) are
merged automatically on boot. See
<citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for details.</para>
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
</variablelist>
</refsect1>
+7 -1
View File
@@ -150,7 +150,13 @@
<para>Note that there is no concept of enabling/disabling installed system extension images: all
installed extension images are automatically activated at boot. However, you can place an empty directory
named like the extension (no <filename>.raw</filename>) in <filename>/etc/extensions/</filename> to "mask"
an extension with the same name in a system folder with lower precedence.</para>
an extension with the same name in a system folder with lower precedence. It is also possible to disable
automatic merging altogether using the <varname>rd.systemd.sysext=</varname>, <varname>rd.systemd.confext=</varname>,
<varname>systemd.sysext=</varname>, and <varname>systemd.confext=</varname> kernel command line options.
Note that <filename>systemd-sysext-sysroot.service</filename> and
<filename>systemd-confext-sysroot.service</filename> are controlled by the <varname>systemd.sysext=</varname>
and <varname>systemd.confext=</varname> options, as these services merge system and configuration
extensions for the main system, not for the initrd.</para>
<para>A simple mechanism for version compatibility is enforced: a system extension image must carry a
<filename>/usr/lib/extension-release.d/extension-release.<replaceable>NAME</replaceable></filename>
+17
View File
@@ -51,6 +51,7 @@
#include "path-util.h"
#include "pidref.h"
#include "pretty-print.h"
#include "proc-cmdline.h"
#include "process-util.h"
#include "rm-rf.h"
#include "runtime-scope.h"
@@ -3038,6 +3039,22 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
return r;
/* PROC_CMDLINE_STRIP_RD_PREFIX cannot be used here as we need to be able to distinguish between
* rd.systemd.{sysext,confext} and systemd.{sysext,confext} in the initrd where they are both used
* and have different meaning. */
const char *string_class = image_class_to_string(arg_image_class);
const char *cmdline_opt = strjoina(in_initrd() && !arg_root ? "rd." : "", "systemd.", string_class);
bool enabled;
r = proc_cmdline_get_bool(cmdline_opt, PROC_CMDLINE_TRUE_WHEN_MISSING, &enabled);
if (r < 0)
log_debug_errno(r, "Failed to check '%s=' kernel command line option, proceeding: %m", cmdline_opt);
else if (!enabled && invoked_by_systemd()) {
/* Kernel command line option should not affect manual invocation. */
log_notice("Disabled by the kernel command line option '%s=', skipping execution.", cmdline_opt);
return 0;
}
/* Parse configuration file after argv because it needs --root=.
* The config entries will not overwrite values set already by
* env/argv because we track initialization. */
+1
View File
@@ -19,6 +19,7 @@ ConditionDirectoryNotEmpty=|/usr/lib/confexts
ConditionDirectoryNotEmpty=|/.extra/confext
ConditionDirectoryNotEmpty=|/.extra/global_confext
ConditionPathExists=/etc/initrd-release
ConditionKernelCommandLine=!rd.systemd.confext=0
DefaultDependencies=no
Before=local-fs-pre.target cryptsetup-pre.target systemd-tmpfiles-setup.service
+1
View File
@@ -16,6 +16,7 @@ ConditionDirectoryNotEmpty=|/sysroot/var/lib/confexts
ConditionDirectoryNotEmpty=|/sysroot/usr/local/lib/confexts
ConditionDirectoryNotEmpty=|/sysroot/usr/lib/confexts
ConditionPathExists=/etc/initrd-release
ConditionKernelCommandLine=!systemd.confext=0
DefaultDependencies=no
Conflicts=shutdown.target
+1
View File
@@ -17,6 +17,7 @@ ConditionDirectoryNotEmpty=|/var/lib/confexts
ConditionDirectoryNotEmpty=|/usr/local/lib/confexts
ConditionDirectoryNotEmpty=|/usr/lib/confexts
ConditionPathExists=!/etc/initrd-release
ConditionKernelCommandLine=!systemd.confext=0
DefaultDependencies=no
After=local-fs.target
+1
View File
@@ -18,6 +18,7 @@ ConditionDirectoryNotEmpty=|/var/lib/extensions
ConditionDirectoryNotEmpty=|/.extra/sysext
ConditionDirectoryNotEmpty=|/.extra/global_sysext
ConditionPathExists=/etc/initrd-release
ConditionKernelCommandLine=!rd.systemd.sysext=0
DefaultDependencies=no
Before=local-fs-pre.target cryptsetup-pre.target systemd-tmpfiles-setup.service
+1
View File
@@ -15,6 +15,7 @@ ConditionCapability=CAP_SYS_ADMIN
ConditionDirectoryNotEmpty=|/sysroot/etc/extensions
ConditionDirectoryNotEmpty=|/sysroot/var/lib/extensions
ConditionPathExists=/etc/initrd-release
ConditionKernelCommandLine=!systemd.sysext=0
DefaultDependencies=no
Conflicts=shutdown.target
+1
View File
@@ -17,6 +17,7 @@ ConditionDirectoryNotEmpty=|/run/extensions
ConditionDirectoryNotEmpty=|/var/lib/extensions
ConditionDirectoryNotEmpty=|/var/lib/extensions.mutable
ConditionPathExists=!/etc/initrd-release
ConditionKernelCommandLine=!systemd.sysext=0
DefaultDependencies=no
After=local-fs.target