Compare commits
10 Commits
aa1cbc0b73
...
9b5fbfe78f
Author | SHA1 | Date |
---|---|---|
Adrian Vovk | 9b5fbfe78f | |
Luca Boccassi | 66d044b560 | |
Michele Dionisio | d865abf9eb | |
Luca Boccassi | f72fe2d73c | |
Zbigniew Jędrzejewski-Szmek | 78ed1e973c | |
Zbigniew Jędrzejewski-Szmek | 265488414c | |
Zbigniew Jędrzejewski-Szmek | bc11463e8e | |
Adrian Vovk | 3e2b6fd389 | |
Adrian Vovk | 6f6d29290e | |
Adrian Vovk | 19bac76b1a |
35
NEWS
35
NEWS
|
@ -186,7 +186,7 @@ CHANGES WITH 257 in spe:
|
|||
|
||||
* The systemd.machine_id= kernel command line parameter interpreted by
|
||||
PID 1 now supports an additional special value: if "firmware" is
|
||||
specified the machine ID is initialized from the SMBIOS/Devicetree
|
||||
specified the machine ID is initialized from the SMBIOS/DeviceTree
|
||||
system UUID. (Previously this was already done in VM environments,
|
||||
this extends the concept to any system, but only on explicit request
|
||||
via this option.)
|
||||
|
@ -276,10 +276,10 @@ CHANGES WITH 257 in spe:
|
|||
show up as .device units in systemd.
|
||||
|
||||
* The firmware_node/sun sysfs attribute will now be used (if available)
|
||||
for naming slot-based network interfaces,
|
||||
i.e. ID_NET_NAME_SLOT. Moreover the interface aliases specified in
|
||||
Devicetree are now searched for both on the interfaces parent device
|
||||
(as before) and the device itself (new).
|
||||
for naming slot-based network interfaces, i.e. ID_NET_NAME_SLOT.
|
||||
Moreover the interface aliases specified in DeviceTree are now
|
||||
searched for both on the interface's parent device (as before) and
|
||||
the device itself (new).
|
||||
|
||||
* Various USB hardware wallets have are now recognized by udev via a
|
||||
.hwdb file, and get the ID_HARDWARE_WALLET= property set, which
|
||||
|
@ -384,6 +384,16 @@ CHANGES WITH 257 in spe:
|
|||
reset one, and so on – which only differ in kernel command line, but
|
||||
nothing else).
|
||||
|
||||
* New .dtbauto and .hwids sections are now documented and supported in
|
||||
systemd-measure, ukify, systemd-stub, and systemd-boot. A single UKI
|
||||
can contain multiple .dtbauto sections, and the 'compatible' string
|
||||
therein will be compared with the equivalent field in the DTB
|
||||
provided by the firmware, if present. If absent, SMBIOS will be used
|
||||
to calculate hardware IDs and compare them with the content of
|
||||
.hwids. This allows including multiple DTBs in a single UKI, with
|
||||
the bootloader automatically selecting the correct one for the
|
||||
current hardware.
|
||||
|
||||
* ukify gained an --extend switch to import an existing UKI to
|
||||
be extended, and a --measure-base= switch to support measurement
|
||||
of multi-profile UKIs.
|
||||
|
@ -646,6 +656,9 @@ CHANGES WITH 257 in spe:
|
|||
* systemd-tmpfiles --purge switch now requires specification of at
|
||||
least one tmpfiles.d/ drop-in file.
|
||||
|
||||
* tmpfiles.d gained a new '?' specifier for the 'L' type to create a
|
||||
symlink only if the source exists, and gracefully skip otherwise.
|
||||
|
||||
* The new Linux mseal(), listmount(), statmount() syscalls have been
|
||||
added to relevant system call groups.
|
||||
|
||||
|
@ -2012,7 +2025,7 @@ CHANGES WITH 255:
|
|||
respective SBAT sections, so that they can be revoked individually if
|
||||
needed.
|
||||
|
||||
* systemd-boot will no longer load unverified Devicetree blobs when UEFI
|
||||
* systemd-boot will no longer load unverified DeviceTree blobs when UEFI
|
||||
SecureBoot is enabled. For more details see:
|
||||
https://github.com/systemd/systemd/security/advisories/GHSA-6m6p-rjcq-334c
|
||||
|
||||
|
@ -2033,7 +2046,7 @@ CHANGES WITH 255:
|
|||
command-line addons before measuring them in TPM2 PCR 12, in a single
|
||||
measurement, instead of measuring them individually.
|
||||
|
||||
* systemd-stub will now measure and load Devicetree Blob addons, which
|
||||
* systemd-stub will now measure and load DeviceTree Blob addons, which
|
||||
are searched and loaded following the same model as the existing
|
||||
kernel command-line addons.
|
||||
|
||||
|
@ -2041,7 +2054,7 @@ CHANGES WITH 255:
|
|||
passed from systemd-boot when running inside Confidential VMs with UEFI
|
||||
SecureBoot enabled.
|
||||
|
||||
* systemd-stub will now load a Devicetree blob even if the firmware did
|
||||
* systemd-stub will now load a DeviceTree blob even if the firmware did
|
||||
not load any beforehand (e.g.: for ACPI systems).
|
||||
|
||||
* ukify is no longer considered experimental, and now ships in /usr/bin/.
|
||||
|
@ -2222,6 +2235,10 @@ CHANGES WITH 255:
|
|||
specific devices explicitly. NetworkManager will soon implement a
|
||||
similar logic.
|
||||
|
||||
* .network files gained a new MulticastIGMPVersion= setting in the
|
||||
[Network] section, to control sysctl's
|
||||
/proc/sys/net/ipv4/conf/INTERFACE/force_igmp_version setting.
|
||||
|
||||
systemctl:
|
||||
|
||||
* systemctl is-failed now checks the system state if no unit is
|
||||
|
@ -4355,7 +4372,7 @@ CHANGES WITH 252 🎃:
|
|||
* 'udevadm wait' will now listen to kernel uevents too when called with
|
||||
--initialized=no.
|
||||
|
||||
* When naming network devices udev will now consult the Devicetree
|
||||
* When naming network devices udev will now consult the DeviceTree
|
||||
"alias" fields for the device.
|
||||
|
||||
* systemd-udev will now create infiniband/by-path and
|
||||
|
|
|
@ -41,7 +41,7 @@ used for new, additional measurements.
|
|||
|
||||
## PCR Measurements Made by `systemd-boot` (UEFI)
|
||||
|
||||
### PCS 5, `EV_EVENT_TAG`, "loader.conf"
|
||||
### PCS 5, `EV_EVENT_TAG`, `loader.conf`
|
||||
|
||||
The content of `systemd-boot`'s configuration file, `loader/loader.conf`, is
|
||||
measured as a tagged event.
|
||||
|
@ -52,7 +52,7 @@ measured as a tagged event.
|
|||
|
||||
→ **Measured hash** covers the content of `loader.conf` as it is read from the ESP.
|
||||
|
||||
### PCR 12, `EV_IPL`, "Kernel Command Line"
|
||||
### PCR 12, `EV_IPL`, kernel command line
|
||||
|
||||
If the kernel command line was specified explicitly (by the user or in a Boot
|
||||
Loader Specification Type #1 file), the kernel command line passed to the
|
||||
|
@ -70,7 +70,7 @@ trailing NUL bytes).
|
|||
|
||||
## PCR Measurements Made by `systemd-stub` (UEFI)
|
||||
|
||||
### PCR 11, `EV_IPL`, "PE Section Name"
|
||||
### PCR 11, `EV_IPL`, PE section name
|
||||
|
||||
A measurement is made for each PE section of the UKI that is defined by the
|
||||
[UKI
|
||||
|
@ -87,7 +87,7 @@ both types of records appear interleaved in the event log.
|
|||
|
||||
→ **Measured hash** covers the PE section name in ASCII (*including* a trailing NUL byte!).
|
||||
|
||||
### PCR 11, `EV_IPL`, "PE Section Data"
|
||||
### PCR 11, `EV_IPL`, PE section data
|
||||
|
||||
Happens once for each UKI-defined PE section of the UKI, in the canonical UKI
|
||||
PE section order, as per the UKI specification, see above.
|
||||
|
@ -96,7 +96,7 @@ PE section order, as per the UKI specification, see above.
|
|||
|
||||
→ **Measured hash** covers the (binary) PE section contents.
|
||||
|
||||
### PCR 12, `EV_IPL`, "Kernel Command Line"
|
||||
### PCR 12, `EV_IPL`, kernel command line
|
||||
|
||||
Might happen up to three times, for kernel command lines from:
|
||||
|
||||
|
@ -110,37 +110,37 @@ UTF-16.
|
|||
→ **Measured hash** covers the literal kernel command line in UTF-16 (without any
|
||||
trailing NUL bytes).
|
||||
|
||||
### PCR 12, `EV_EVENT_TAG`, "Devicetrees"
|
||||
### PCR 12, `EV_EVENT_TAG`, DeviceTrees
|
||||
|
||||
Devicetree addons are measured individually as a tagged event.
|
||||
DeviceTree addons are measured individually as a tagged event.
|
||||
|
||||
→ **Event Tag** `0x6c46f751`
|
||||
|
||||
→ **Description** the addon filename.
|
||||
→ **Description** is the addon filename.
|
||||
|
||||
→ **Measured hash** covers the content of the Devicetree.
|
||||
→ **Measured hash** covers the content of the DeviceTree.
|
||||
|
||||
### PCR 12, `EV_EVENT_TAG`, "Initrd addons"
|
||||
### PCR 12, `EV_EVENT_TAG`, initrd addons
|
||||
|
||||
Initrd addons are measured individually as a tagged event.
|
||||
|
||||
→ **Event Tag** `0x49dffe0f`
|
||||
|
||||
→ **Description** the addon filename.
|
||||
→ **Description** is the addon filename.
|
||||
|
||||
→ **Measured hash** covers the contents of the initrd.
|
||||
|
||||
### PCR 12, `EV_EVENT_TAG`, "Ucode addons"
|
||||
### PCR 12, `EV_EVENT_TAG`, ucode addons
|
||||
|
||||
Ucode addons are measured individually as a tagged event.
|
||||
|
||||
→ **Event Tag** `0xdac08e1a`
|
||||
|
||||
→ **Description** the addon filename.
|
||||
→ **Description** is the addon filename.
|
||||
|
||||
→ **Measured hash** covers the contents of the ucode initrd.
|
||||
|
||||
### PCR 12, `EV_IPL`, "Per-UKI Credentials initrd"
|
||||
### PCR 12, `EV_IPL`, per-uki credentials initrd
|
||||
|
||||
→ **Description** in the event log record is the constant string "Credentials
|
||||
initrd" in UTF-16.
|
||||
|
@ -148,7 +148,7 @@ initrd" in UTF-16.
|
|||
→ **Measured hash** covers the per-UKI credentials cpio archive (which is generated
|
||||
on-the-fly by `systemd-stub`).
|
||||
|
||||
### PCR 12, `EV_IPL`, "Global Credentials initrd"
|
||||
### PCR 12, `EV_IPL`, global credentials initrd
|
||||
|
||||
→ **Description** in the event log record is the constant string "Global
|
||||
credentials initrd" in UTF-16.
|
||||
|
@ -156,7 +156,7 @@ credentials initrd" in UTF-16.
|
|||
→ **Measured hash** covers the global credentials cpio archive (which is generated
|
||||
on-the-fly by `systemd-stub`).
|
||||
|
||||
### PCR 13, `EV_IPL`, "sysext initrd"
|
||||
### PCR 13, `EV_IPL`, sysext initrd
|
||||
|
||||
→ **Description** in the event log record is the constant string "System extension
|
||||
initrd" in UTF-16.
|
||||
|
@ -166,7 +166,7 @@ on-the-fly by `systemd-stub`).
|
|||
|
||||
## PCR Measurements Made by `systemd-pcrextend` (Userspace)
|
||||
|
||||
### PCR 11, "Boot Phases"
|
||||
### PCR 11, boot phases
|
||||
|
||||
The `systemd-pcrphase.service`, `systemd-pcrphase-initrd.service`,
|
||||
`systemd-pcrphase-sysinit.service` services will measure the boot phase reached
|
||||
|
@ -178,7 +178,7 @@ choose to define additional/different phases.)
|
|||
→ **Measured hash** covers the phase string (in UTF-8, without trailing NUL
|
||||
bytes).
|
||||
|
||||
### PCR 15, "Machine ID"
|
||||
### PCR 15, machine ID
|
||||
|
||||
The `systemd-pcrmachine.service` service will measure the machine ID (as read
|
||||
from `/etc/machine-id`) during boot.
|
||||
|
@ -187,7 +187,7 @@ from `/etc/machine-id`) during boot.
|
|||
formatted in hexadecimal lowercase characters (in UTF-8, without trailing NUL
|
||||
bytes).
|
||||
|
||||
### PCR 15, "File System"
|
||||
### PCR 15, file system
|
||||
|
||||
The `systemd-pcrfs-root.service` and `systemd-pcrfs@.service` services will
|
||||
measure a string identifying a specific file system, typically covering the
|
||||
|
@ -200,7 +200,7 @@ without trailing NUL bytes).
|
|||
|
||||
## PCR Measurements Made by `systemd-cryptsetup` (Userspace)
|
||||
|
||||
### PCR 15, "Volume Key"
|
||||
### PCR 15, volume key
|
||||
|
||||
The `systemd-cryptsetup@.service` service will measure a key derived from the
|
||||
LUKS volume key of a specific encrypted volume, typically covering the backing
|
||||
|
|
|
@ -59,58 +59,66 @@
|
|||
<!-- Let's keep this in the canonical order we also measure the sections by, i.e. as in
|
||||
src/fundamental/uki.h's UnifiedSection enum -->
|
||||
|
||||
<listitem><para>A <literal>.linux</literal> section with the ELF Linux kernel
|
||||
image. (Required)</para></listitem>
|
||||
<listitem><para>A <literal>.linux</literal> section with the ELF Linux kernel image.
|
||||
This section is required.</para></listitem>
|
||||
|
||||
<listitem><para>An <literal>.osrel</literal> section with OS release information, i.e. the contents of
|
||||
the <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> file
|
||||
of the OS the kernel belongs to.</para></listitem>
|
||||
<listitem><para>An optional <literal>.osrel</literal> section with OS release information, i.e. the
|
||||
contents of the
|
||||
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> file of
|
||||
the OS the kernel belongs to.</para></listitem>
|
||||
|
||||
<listitem><para>A <literal>.cmdline</literal> section with the kernel command line to pass to the
|
||||
invoked kernel.</para></listitem>
|
||||
<listitem><para>An optional <literal>.cmdline</literal> section with the kernel command line to pass to
|
||||
the invoked kernel.</para></listitem>
|
||||
|
||||
<listitem><para>An <literal>.initrd</literal> section with the initrd.</para></listitem>
|
||||
<listitem><para>An optional <literal>.initrd</literal> section with the initrd.</para></listitem>
|
||||
|
||||
<listitem><para>A <literal>.ucode</literal> section with an initrd containing microcode, to be handed
|
||||
to the kernel before any other initrd. This initrd must not be compressed.</para></listitem>
|
||||
<listitem><para>An optional <literal>.ucode</literal> section with an initrd containing microcode, to
|
||||
be handed to the kernel before any other initrd. This initrd must not be compressed.</para></listitem>
|
||||
|
||||
<listitem><para>A <literal>.splash</literal> section with an image (in the Windows
|
||||
<listitem><para>An optional <literal>.splash</literal> section with an image (in the Windows
|
||||
<filename>.BMP</filename> format) to show on screen before invoking the kernel.</para></listitem>
|
||||
|
||||
<listitem><para>A <literal>.dtb</literal> section with a compiled binary DeviceTree.</para></listitem>
|
||||
<listitem><para>An optional <literal>.dtb</literal> section with a compiled binary DeviceTree.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>Zero or more <literal>.dtbauto</literal> sections. Stub will always try to find first matching one.
|
||||
Matching process extracts first <varname>compatible</varname> string from <literal>.dtbauto</literal>
|
||||
section and compares it with the first Devicetree's <varname>compatible</varname> string supplied by
|
||||
the firmware in configuration tables. If firmware does not provide Devicetree, matching with
|
||||
<varname>.hwids</varname> section will be used instead. Stub will use SMBIOS data to calculate hardware
|
||||
IDs of the machine (as per <ulink url="https://learn.microsoft.com/en-us/windows-hardware/drivers/install/specifying-hardware-ids-for-a-computer">specification</ulink>),
|
||||
then it will proceed to trying to find any of them in <literal>.hwids</literal> section and will use first
|
||||
matching entry's <varname>compatible</varname> as a search key among the <literal>.dtbauto</literal>
|
||||
entries, in a similar fashion as the use of <varname>compatible</varname> string read from the firmware
|
||||
provided Devicetree was described before. First matching <literal>.dtbauto</literal> section will be
|
||||
<listitem><para>Zero or more <literal>.dtbauto</literal> sections. <filename>systemd-stub</filename>
|
||||
will always use the first matching one. The match is performed by taking the first DeviceTree's
|
||||
<varname>compatible</varname> string supplied by the firmware in configuration tables and comparing it
|
||||
with the first <varname>compatible</varname> string from each of the <literal>.dtbauto</literal>
|
||||
sections. If the firmware does not provide a DeviceTree, the match is done using the
|
||||
<varname>.hwids</varname> section instead. After selecting a <literal>.hwids</literal> section (see the
|
||||
description below), the <varname>compatible</varname> string from that section will be used to perform
|
||||
the same matching procedure. If a match is found, that <literal>.dtbauto</literal> section will be
|
||||
loaded and will override <varname>.dtb</varname> if present.</para></listitem>
|
||||
|
||||
<listitem><para>A <literal>.hwids</literal> section with hardware IDs of the machines to match Devicetrees (refer to <literal>.dtbauto</literal> section description).</para></listitem>
|
||||
<listitem><para>Zero or more <literal>.hwids</literal> sections with hardware IDs of the machines to
|
||||
match DeviceTrees. <filename>systemd-stub</filename> will use the SMBIOS data to calculate hardware IDs
|
||||
of the machine (as per <ulink
|
||||
url="https://learn.microsoft.com/en-us/windows-hardware/drivers/install/specifying-hardware-ids-for-a-computer">specification</ulink>),
|
||||
and then it will try to find any of them in each of the <literal>.hwids</literal> sections. The first
|
||||
matching section will be used.</para></listitem>
|
||||
|
||||
<listitem><para>A <literal>.uname</literal> section with the kernel version information, i.e. the
|
||||
output of <command>uname -r</command> for the kernel included in the <literal>.linux</literal>
|
||||
<listitem><para>An optional <literal>.uname</literal> section with the kernel version information, i.e.
|
||||
the output of <command>uname -r</command> for the kernel included in the <literal>.linux</literal>
|
||||
section.</para></listitem>
|
||||
|
||||
<listitem><para>An <literal>.sbat</literal> section with
|
||||
<ulink url="https://github.com/rhboot/shim/blob/main/SBAT.md">SBAT</ulink> revocation
|
||||
metadata.</para></listitem>
|
||||
<listitem><para>An optional <literal>.sbat</literal> section with
|
||||
<ulink url="https://github.com/rhboot/shim/blob/main/SBAT.md">SBAT</ulink> revocation metadata.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>A <literal>.pcrsig</literal> section with a set of cryptographic signatures for the
|
||||
expected TPM2 PCR values after the kernel has been booted, in JSON format. This is useful for
|
||||
<listitem><para>An optional <literal>.pcrsig</literal> section with a set of cryptographic signatures
|
||||
for the expected TPM2 PCR values after the kernel has been booted, in JSON format. This is useful for
|
||||
implementing TPM2 policies that bind disk encryption and similar to kernels that are signed by a
|
||||
specific key.</para></listitem>
|
||||
|
||||
<listitem><para>A <literal>.pcrpkey</literal> section with a public key in the PEM format matching the
|
||||
signature data in the <literal>.pcrsig</literal> section.</para></listitem>
|
||||
<listitem><para>An optional <literal>.pcrpkey</literal> section with a public key in the PEM format
|
||||
matching the signature data in the <literal>.pcrsig</literal> section.</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>In a basic UKI, the sections listed above appear at most once. In a multi-profile UKI,
|
||||
<!-- FIXME: how does .dtauto/.hwids matching interact with profiles? -->
|
||||
|
||||
<para>In a basic UKI, the sections listed above appear at most once, with the exception of
|
||||
<literal>.dtbauto</literal> and <literal>.hwids</literal> sections. In a multi-profile UKI,
|
||||
multiple sets of these sections are present in a single file and form "profiles",
|
||||
one of which can be selected at boot. For this, the PE section <literal>.profile</literal> is
|
||||
defined to be used as the separator between sets of sections. The
|
||||
|
@ -206,7 +214,7 @@
|
|||
<listitem><para>Similarly, files
|
||||
<filename><replaceable>foo</replaceable>.efi.extra.d/*.addon.efi</filename> are loaded and verified as
|
||||
PE binaries and specific sections are loaded from them. Addons are used to pass additional kernel
|
||||
command line parameters (<literal>.cmdline</literal> section), or Devicetree blobs
|
||||
command line parameters (<literal>.cmdline</literal> section), or DeviceTree blobs
|
||||
(<literal>.dtb</literal> section), additional initrds (<literal>.initrd</literal> section),
|
||||
and microcode updates (<literal>.ucode</literal> section). Addons allow those resources to be passed
|
||||
regardless of the kernel version being booted, for example allowing platform vendors to ship
|
||||
|
|
|
@ -190,6 +190,17 @@
|
|||
<xi:include href="version-info.xml" xpointer="v251"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>streams</option></term>
|
||||
|
||||
<listitem><para>Lists streams that can be updated. This enumerates the
|
||||
<filename>/var/cache/systemd/sysupdate@*.d/</filename> and <filename>/usr/lib/sysupdate@*.d/</filename>
|
||||
directories that contain transfer definitions. This command is useful to list possible parameters
|
||||
for <option>--stream=</option> (see below).</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
<xi:include href="standard-options.xml" xpointer="version" />
|
||||
</variablelist>
|
||||
|
@ -225,7 +236,8 @@
|
|||
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> or
|
||||
<option>--stream=</option>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v251"/></listitem>
|
||||
</varlistentry>
|
||||
|
@ -237,11 +249,29 @@
|
|||
are read from this directory instead of <filename>/usr/lib/sysupdate.d/*.conf</filename>,
|
||||
<filename>/etc/sysupdate.d/*.conf</filename>, and <filename>/run/sysupdate.d/*.conf</filename>.</para>
|
||||
|
||||
<para>This option may not be combined with <option>--component=</option>.</para>
|
||||
<para>This option may not be combined with <option>--component=</option> or
|
||||
<option>--stream=</option>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v251"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--stream=</option></term>
|
||||
|
||||
<listitem><para>Selects the update stream to use. Takes a stream name as argument. This alters
|
||||
the search logic for transfer definitions to look in
|
||||
<filename>/usr/lib/sysupdate@<replaceable>stream</replaceable>.d/</filename> and
|
||||
<filename>/var/cache/systemd/sysupdate@<replaceable>stream</replaceable>.d/</filename> instead of
|
||||
<filename>/usr/lib/sysupdate.d</filename>.
|
||||
Note that administrator-controlled directories (i.e. <filename>/etc/sysupdate.d/</filename>, etc) are
|
||||
still loaded as usual.</para>
|
||||
|
||||
<para>This option may not be combined with <option>--definitions=</option> or
|
||||
<option>--component=</option>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--root=</option></term>
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@
|
|||
|
||||
<row>
|
||||
<entry><replaceable>prefix</replaceable><constant>d</constant><replaceable>number</replaceable></entry>
|
||||
<entry>Devicetree alias index</entry>
|
||||
<entry>DeviceTree alias index</entry>
|
||||
</row>
|
||||
|
||||
</tbody>
|
||||
|
|
|
@ -1004,6 +1004,27 @@ DuplicateAddressDetection=none</programlisting></para>
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>MulticastIGMPVersion=</varname></term>
|
||||
<listitem>
|
||||
<para>Configures IPv4 Multicast IGMP Version to be used, and controls the value of
|
||||
<filename>/proc/sys/net/ipv4/conf/<replaceable>INTERFACE</replaceable>/force_igmp_version</filename>.
|
||||
Takes one of <literal>no</literal>,
|
||||
<literal>v1</literal>, <literal>v2</literal>, or <literal>v3</literal>.
|
||||
When <literal>no</literal>, no enforcement of an IGMP version will be applied, IGMPv1/v2 fallback are allowed, will back to
|
||||
IGMPv3 mode again if all IGMPv1/v2 Querier Present timer expire.
|
||||
When <literal>v1</literal>, use of IGMP version 1 will be enforced, and IGMPv1 report will be replied even if IGMPv2/v3
|
||||
queries are received.
|
||||
When <literal>v2</literal>, use of IGMP version 2 will be enforced, and IGMPv2 report will be replied if an IGMPv2/v3 query
|
||||
is received, but fallback to IGMPv1 if an IGMPv1 query is received.
|
||||
When <literal>v3</literal>, use of IGMP version 3 will be enforced, and the same reaction will be done as <literal>no</literal>.
|
||||
Defaults to unset, and the sysctl value will be unchanged.
|
||||
</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>IPv4AcceptLocal=</varname></term>
|
||||
<listitem>
|
||||
|
|
|
@ -65,6 +65,52 @@
|
|||
<citerefentry><refentrytitle>sysupdate.features</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
</para>
|
||||
|
||||
<para>Sometimes, distributions need to update certain parts of themselves independently from the normal
|
||||
update cycle.
|
||||
For example, the <ulink url="https://github.com/rhboot/shim">UEFI Shim loader</ulink> (necessary for
|
||||
UEFI Secure Boot support in many cases) has its own release cycle, requires code signatures from a
|
||||
third-party, and in general is not tied to a distribution's update cycle.
|
||||
Support for this scenario is provided by "components", which allow distributions to define transfer
|
||||
definitions that receive updates independently from the base OS.
|
||||
Components are defined in <filename>/usr/lib/sysupdate.<replaceable>component</replaceable>.d/</filename>,
|
||||
and have corresponding override directories for administrators (i.e.
|
||||
<filename>/etc/sysupdate.<replaceable>component</replaceable>.d/</filename>, etc).</para>
|
||||
|
||||
<para>Some distributions may wish to maintain multiple update "streams" at a time, for example to offer
|
||||
a beta/nightly update channel, or to distribute security updates to multiple major versions at a time.
|
||||
Users of such distributions may wish to remain on their current stream, and switch streams at some future
|
||||
point in time.
|
||||
A distribution with multiple update streams should ship the transfer definitions for each stream in the
|
||||
<filename>/usr/lib/sysupdate@<replaceable>stream</replaceable>.d/</filename> or
|
||||
<filename>/var/cache/systemd/sysupdate@<replaceable>stream</replaceable>.d/</filename> directories.
|
||||
For example, a distribution with multiple stable branches can ship the next major release's transfer
|
||||
definitions in the current release's
|
||||
<filename>/usr/lib/sysupdate@foobarOS-<replaceable>next</replaceable>.d/</filename> directory, and users
|
||||
can switch to it by updating the <literal>foobarOS-<replaceable>next</replaceable></literal> stream.
|
||||
How exactly these stream definition directories are delivered is up to distributions: they can stabilize
|
||||
transfer definitions a version in advance and ship the stream definitions from day one, or they can ship
|
||||
these files as part of a regular security patch that users will install anyway, or they can use a
|
||||
component as described above to update the stream definitions under <filename>/var/cache/</filename>
|
||||
independently from the host system.
|
||||
Note that the presence of a stream definition directory does not imply the availability of an upgrade on
|
||||
that stream; it just defines where to look and if an update is found on the remote how to install it.
|
||||
Also note that the normal administrator override files (i.e. transfer definitions, feature definitions,
|
||||
or drop-ins found in <filname>/etc/sysupdate.d/</filname>, <filename>/run/sysupdate.d/</filename>, etc)
|
||||
are applied over top of the definitions found in the stream definition directory.
|
||||
This is done because a the stream definition directory turns into the normal definition directory
|
||||
(<filename>/usr/lib/sysupdate.d/</filename>) when that stream is switched to.</para>
|
||||
|
||||
<para>System Administrators must take <emphasis>extreme</emphasis> care when overriding any transfer or
|
||||
optional feature definitions, other than to turn on or off features!
|
||||
As with any configuration defined in <filename>/usr</filename> and overridden in
|
||||
<filename>/etc</filename>, an update to the host system can break the administrator overrides.
|
||||
However, <command>systemd-sysupdate</command> is uniquely destructive: a broken configuration could
|
||||
prevent the system from updating (best case), or completely destroy an installation by wiping the wrong
|
||||
partition.
|
||||
Distributions must take care to avoid breaking systems where overrides exist only to turn on or off
|
||||
optional features; supporting (or choosing not to) everything else is up to distribution policy.
|
||||
<emphasis>You have been warned.</emphasis></para>
|
||||
|
||||
<para>Each <filename>*.transfer</filename> file contains three sections: [Transfer], [Source] and [Target].</para>
|
||||
</refsect1>
|
||||
|
||||
|
|
|
@ -64,12 +64,18 @@
|
|||
"/usr/local/lib/" n "\0" \
|
||||
"/usr/lib/" n "\0"
|
||||
|
||||
#define CONF_PATHS(n) \
|
||||
#define CONF_PATHS_ADMIN(n) \
|
||||
"/etc/" n, \
|
||||
"/run/" n, \
|
||||
"/run/" n
|
||||
|
||||
#define CONF_PATHS_SYSTEM(n) \
|
||||
"/usr/local/lib/" n, \
|
||||
"/usr/lib/" n
|
||||
|
||||
#define CONF_PATHS(n) \
|
||||
CONF_PATHS_ADMIN(n), \
|
||||
CONF_PATHS_SYSTEM(n)
|
||||
|
||||
#define CONF_PATHS_STRV(n) \
|
||||
STRV_MAKE(CONF_PATHS(n))
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ libraries (such as OpenSSL or gnu-efi) are linked, embedded, or used.
|
|||
|
||||
## Additional Resources
|
||||
BLS Type #1 entries allow the user to load two types of additional resources that can affect the system
|
||||
before `ExitBootServices()` has been called — kernel command line arguments and Devicetree blobs — that are
|
||||
before `ExitBootServices()` has been called — kernel command line arguments and DeviceTree blobs — that are
|
||||
not validated before use, as they do not carry signatures. For this reason, when SecureBoot is enabled,
|
||||
loading these resources is automatically disabled. There is no override for this security mechanism, neither
|
||||
at build time nor at runtime. Note that initrds are also not verified in BLS Type #1 configurations, for
|
||||
|
@ -62,7 +62,7 @@ compatibility with how SecureBoot has been traditionally handled on Linux-based
|
|||
only load them after `ExitBootServices()` has been called.
|
||||
|
||||
Another mechanism is supported by `systemd-boot` and `systemd-stub` to add additional payloads to the boot
|
||||
process: "addons". Addons are PE signed binaries that can carry kernel command line arguments or Devicetree
|
||||
process: "addons". Addons are PE signed binaries that can carry kernel command line arguments or DeviceTree
|
||||
blobs (more payload types might be added in the future).
|
||||
In contrast to the user-specified additions in the Type #1 case
|
||||
described above, these addons are loaded through the UEFI image loading protocol, and thus are subject to
|
||||
|
|
|
@ -178,8 +178,8 @@ bool firmware_devicetree_exists(void) {
|
|||
return !!find_configuration_table(MAKE_GUID_PTR(EFI_DTB_TABLE));
|
||||
}
|
||||
|
||||
/* This function checks if the firmware provided Devicetree
|
||||
* and a UKI provided Devicetree contain the same first entry
|
||||
/* This function checks if the firmware provided DeviceTree
|
||||
* and a UKI provided DeviceTree contain the same first entry
|
||||
* on their respective "compatible" fields (which usually defines
|
||||
* the actual device model). More specifically, given the FW/UKI
|
||||
* "compatible" property pair:
|
||||
|
|
|
@ -98,7 +98,7 @@ static int help(int argc, char *argv[], void *userdata) {
|
|||
" --initrd=PATH Path to initrd image file %7$s .initrd\n"
|
||||
" --ucode=PATH Path to microcode image file %7$s .ucode\n"
|
||||
" --splash=PATH Path to splash bitmap file %7$s .splash\n"
|
||||
" --dtb=PATH Path to Devicetree file %7$s .dtb\n"
|
||||
" --dtb=PATH Path to DeviceTree file %7$s .dtb\n"
|
||||
" --uname=PATH Path to 'uname -r' file %7$s .uname\n"
|
||||
" --sbat=PATH Path to SBAT file %7$s .sbat\n"
|
||||
" --pcrpkey=PATH Path to public key for PCR signatures %7$s .pcrpkey\n"
|
||||
|
|
|
@ -47,7 +47,7 @@ enum {
|
|||
/* The tag used for EV_EVENT_TAG event log records covering the boot loader config */
|
||||
#define LOADER_CONF_EVENT_TAG_ID UINT32_C(0xf5bc582a)
|
||||
|
||||
/* The tag used for EV_EVENT_TAG event log records covering Devicetree blobs */
|
||||
/* The tag used for EV_EVENT_TAG event log records covering DeviceTree blobs */
|
||||
#define DEVICETREE_ADDON_EVENT_TAG_ID UINT32_C(0x6c46f751)
|
||||
|
||||
/* The tag used for EV_EVENT_TAG event log records covering initrd addons */
|
||||
|
|
|
@ -502,7 +502,7 @@ try_devicetree:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Note that the Devicetree specification uses the very same vocabulary
|
||||
/* Note that the DeviceTree specification uses the very same vocabulary
|
||||
* of chassis types as we do, hence we do not need to translate these types:
|
||||
*
|
||||
* https://github.com/devicetree-org/devicetree-specification/blob/master/source/chapter3-devicenodes.rst */
|
||||
|
|
|
@ -150,6 +150,7 @@ Network.IPv4ProxyARPPrivateVLAN, config_parse_tristate,
|
|||
Network.ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
|
||||
Network.IPv6ProxyNDPAddress, config_parse_ipv6_proxy_ndp_address, 0, 0
|
||||
Network.IPv4ReversePathFilter, config_parse_ip_reverse_path_filter, 0, offsetof(Network, ipv4_rp_filter)
|
||||
Network.MulticastIGMPVersion, config_parse_ipv4_force_igmp_version, 0, offsetof(Network, ipv4_force_igmp_version)
|
||||
Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier)
|
||||
Network.ConfigureWithoutCarrier, config_parse_bool, 0, offsetof(Network, configure_without_carrier)
|
||||
Network.IgnoreCarrierLoss, config_parse_ignore_carrier_loss, 0, 0
|
||||
|
|
|
@ -481,6 +481,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
|||
.proxy_arp = -1,
|
||||
.proxy_arp_pvlan = -1,
|
||||
.ipv4_rp_filter = _IP_REVERSE_PATH_FILTER_INVALID,
|
||||
.ipv4_force_igmp_version = _IPV4_FORCE_IGMP_VERSION_INVALID,
|
||||
|
||||
.ndisc = -1,
|
||||
.ndisc_use_redirect = true,
|
||||
|
|
|
@ -340,6 +340,7 @@ struct Network {
|
|||
uint32_t ipv6_mtu;
|
||||
IPv6PrivacyExtensions ipv6_privacy_extensions;
|
||||
IPReversePathFilter ipv4_rp_filter;
|
||||
IPv4ForceIgmpVersion ipv4_force_igmp_version;
|
||||
int ipv6_proxy_ndp;
|
||||
Set *ipv6_proxy_ndp_addresses;
|
||||
|
||||
|
|
|
@ -408,6 +408,18 @@ static int link_set_ipv4_rp_filter(Link *link) {
|
|||
return sysctl_write_ip_property_int(AF_INET, link->ifname, "rp_filter", link->network->ipv4_rp_filter, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv4_force_igmp_version(Link *link) {
|
||||
assert(link);
|
||||
|
||||
if (!link_is_configured_for_family(link, AF_INET))
|
||||
return 0;
|
||||
|
||||
if (link->network->ipv4_force_igmp_version < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_int(AF_INET, link->ifname, "force_igmp_version", link->network->ipv4_force_igmp_version, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv6_privacy_extensions(Link *link) {
|
||||
IPv6PrivacyExtensions val;
|
||||
|
||||
|
@ -723,6 +735,10 @@ int link_set_sysctl(Link *link) {
|
|||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Cannot set IPv4 reverse path filtering for interface, ignoring: %m");
|
||||
|
||||
r = link_set_ipv4_force_igmp_version(link);
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Cannot set IPv4 force igmp version, ignoring: %m");
|
||||
|
||||
r = link_set_ipv4_promote_secondaries(link);
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Cannot enable promote_secondaries for interface, ignoring: %m");
|
||||
|
@ -770,3 +786,13 @@ int config_parse_ip_forward_deprecated(
|
|||
"and the same settings in .network files for per-interface setting.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const ipv4_force_igmp_version_table[_IPV4_FORCE_IGMP_VERSION_MAX] = {
|
||||
[IPV4_FORCE_IGMP_VERSION_NO] = "no",
|
||||
[IPV4_FORCE_IGMP_VERSION_1] = "v1",
|
||||
[IPV4_FORCE_IGMP_VERSION_2] = "v2",
|
||||
[IPV4_FORCE_IGMP_VERSION_3] = "v3",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(ipv4_force_igmp_version, IPv4ForceIgmpVersion);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv4_force_igmp_version, ipv4_force_igmp_version, IPv4ForceIgmpVersion);
|
||||
|
|
|
@ -53,3 +53,18 @@ IPReversePathFilter ip_reverse_path_filter_from_string(const char *s) _pure_;
|
|||
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ip_reverse_path_filter);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ip_forward_deprecated);
|
||||
|
||||
typedef enum IPv4ForceIgmpVersion {
|
||||
/* These values map to the kernel's /proc/sys/net/ipv4/conf/INTERFACE/force_igmp_version values. Do not reorder! */
|
||||
IPV4_FORCE_IGMP_VERSION_NO = 0,
|
||||
IPV4_FORCE_IGMP_VERSION_1 = 1,
|
||||
IPV4_FORCE_IGMP_VERSION_2 = 2,
|
||||
IPV4_FORCE_IGMP_VERSION_3 = 3,
|
||||
_IPV4_FORCE_IGMP_VERSION_MAX,
|
||||
_IPV4_FORCE_IGMP_VERSION_INVALID = -EINVAL,
|
||||
} IPv4ForceIgmpVersion;
|
||||
|
||||
const char* ipv4_force_igmp_version_to_string(IPv4ForceIgmpVersion i) _const_;
|
||||
IPv4ForceIgmpVersion ipv4_force_igmp_version_from_string(const char *s) _pure_;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ipv4_force_igmp_version);
|
||||
|
|
|
@ -47,6 +47,7 @@ char *arg_root = NULL;
|
|||
static char *arg_image = NULL;
|
||||
static bool arg_reboot = false;
|
||||
static char *arg_component = NULL;
|
||||
static char *arg_stream = NULL;
|
||||
static int arg_verify = -1;
|
||||
static ImagePolicy *arg_image_policy = NULL;
|
||||
static bool arg_offline = false;
|
||||
|
@ -56,6 +57,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_definitions, freep);
|
|||
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_component, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_stream, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_transfer_source, freep);
|
||||
|
||||
|
@ -180,7 +182,54 @@ static int context_read_definitions(Context *c, const char* node) {
|
|||
|
||||
if (arg_definitions)
|
||||
dirs = strv_new(arg_definitions);
|
||||
else if (arg_component) {
|
||||
else if (arg_stream) {
|
||||
/* Ultimately we end up with a search path along the lines of: /etc/sysupdate.d/,
|
||||
* /run/sysupdate.d/, /var/cache/systemd/sysupdate@<stream>.d, /usr/lib/sysupdate@<stream>.d.
|
||||
* This is very unusual! It seems wrong! But this is the correct behavior. When a
|
||||
* `systemd-sysupdate --stream=` update is completed, /usr/lib/sysupdate@<stream>.d (or its
|
||||
* /var/cache alternative) turns into /usr/lib/sysupdate.d, but the admin overrides remain
|
||||
* untouched. So if we did this any differently, we'd end up in a situation where the admin's
|
||||
* settings are ignored when first installing a major upgrade but then suddenly considered
|
||||
* again once the update is completed. In my opinion, that behavior would be more unexpected
|
||||
* and dangerous than what is implemented here!
|
||||
*
|
||||
* Is this a big and surprising footgun for the admin? Yes. But frankly, so is overriding
|
||||
* anything relating to sysupdate. If an admin has overrides that do anything other than
|
||||
* turning on/off optional features, they've already aimed a ballistic missile at their
|
||||
* installation. It'll detonate either immediately when trying to switch streams (as
|
||||
* implemented now), or when updating to the first patch of the new stream (the alternative);
|
||||
* the installation is doomed either way. And failing immediately during a major OS upgrade
|
||||
* seems a lot more preferable, and something that admins will be more prepared for, than a
|
||||
* subsequent security patch suddenly bricking installations. */
|
||||
|
||||
char **admin = STRV_MAKE(CONF_PATHS_ADMIN("sysupdate.d"));
|
||||
char **system = STRV_MAKE("/var/cache/systemd/", CONF_PATHS_SYSTEM(""));
|
||||
size_t i = 0;
|
||||
|
||||
dirs = new0(char*, strv_length(admin) + strv_length(system) + 1);
|
||||
if (!dirs)
|
||||
return log_oom();
|
||||
|
||||
STRV_FOREACH(dir, admin) {
|
||||
char *d;
|
||||
|
||||
d = strdup(*dir);
|
||||
if (!d)
|
||||
return log_oom();
|
||||
|
||||
dirs[i++] = d;
|
||||
}
|
||||
|
||||
STRV_FOREACH(dir, system) {
|
||||
char *j;
|
||||
|
||||
j = strjoin(*dir, "sysupdate@", arg_stream, ".d");
|
||||
if (!j)
|
||||
return log_oom();
|
||||
|
||||
dirs[i++] = j;
|
||||
}
|
||||
} else if (arg_component) {
|
||||
char **l = CONF_PATHS_STRV("");
|
||||
size_t i = 0;
|
||||
|
||||
|
@ -247,6 +296,11 @@ static int context_read_definitions(Context *c, const char* node) {
|
|||
"No transfer definitions for component '%s' found.",
|
||||
arg_component);
|
||||
|
||||
if (arg_stream)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
|
||||
"No transfer definitions for stream '%s' found.",
|
||||
arg_stream);
|
||||
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
|
||||
"No transfer definitions found.");
|
||||
}
|
||||
|
@ -1532,22 +1586,45 @@ static int component_name_valid(const char *c) {
|
|||
return filename_is_valid(j);
|
||||
}
|
||||
|
||||
static int verb_components(int argc, char **argv, void *userdata) {
|
||||
static int stream_name_valid(const char *s) {
|
||||
_cleanup_free_ char *j = NULL;
|
||||
|
||||
/* See if the specified string enclosed in the directory prefix+suffix would be a valid file name */
|
||||
|
||||
if (isempty(s))
|
||||
return false;
|
||||
|
||||
if (string_has_cc(s, NULL))
|
||||
return false;
|
||||
|
||||
if (!utf8_is_valid(s))
|
||||
return false;
|
||||
|
||||
j = strjoin("sysupdate@", s, ".d");
|
||||
if (!j)
|
||||
return -ENOMEM;
|
||||
|
||||
return filename_is_valid(j);
|
||||
}
|
||||
|
||||
static int walk_search_paths(char **paths, bool component, char ***ret, bool *ret_has_default) {
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
||||
_cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL;
|
||||
_cleanup_set_free_ Set *names = NULL;
|
||||
_cleanup_free_ char **z = NULL; /* We use simple free() rather than strv_free() here, since set_free() will free the strings for us */
|
||||
char **l = CONF_PATHS_STRV("");
|
||||
bool has_default_component = false;
|
||||
_cleanup_free_ char **names_strv = NULL; /* free() b/c the set still owns the values */
|
||||
_cleanup_strv_free_ char **names_dup = NULL;
|
||||
bool has_default = false;
|
||||
int r;
|
||||
|
||||
assert(argc <= 1);
|
||||
assert(paths);
|
||||
assert(ret);
|
||||
assert(ret_has_default);
|
||||
|
||||
r = process_image(/* ro= */ false, &mounted_dir, &loop_device);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(i, l) {
|
||||
STRV_FOREACH(i, paths) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
|
@ -1577,11 +1654,11 @@ static int verb_components(int argc, char **argv, void *userdata) {
|
|||
continue;
|
||||
|
||||
if (streq(de->d_name, "sysupdate.d")) {
|
||||
has_default_component = true;
|
||||
has_default = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
e = startswith(de->d_name, "sysupdate.");
|
||||
e = startswith(de->d_name, component ? "sysupdate." : "sysupdate@");
|
||||
if (!e)
|
||||
continue;
|
||||
|
||||
|
@ -1593,26 +1670,51 @@ static int verb_components(int argc, char **argv, void *userdata) {
|
|||
if (!n)
|
||||
return log_oom();
|
||||
|
||||
r = component_name_valid(n);
|
||||
if (component)
|
||||
r = component_name_valid(n);
|
||||
else
|
||||
r = stream_name_valid(n);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Unable to validate component name: %m");
|
||||
return log_error_errno(r, "Unable to validate %s name: %m",
|
||||
component ? "component" : "stream");
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
r = set_ensure_consume(&names, &string_hash_ops_free, TAKE_PTR(n));
|
||||
if (r < 0 && r != -EEXIST)
|
||||
return log_error_errno(r, "Failed to add component to set: %m");
|
||||
return log_error_errno(r, "Failed to add %s to set: %m",
|
||||
component ? "component" : "stream");
|
||||
}
|
||||
}
|
||||
|
||||
z = set_get_strv(names);
|
||||
if (!z)
|
||||
names_strv = set_get_strv(names);
|
||||
if (!names_strv)
|
||||
return log_oom();
|
||||
|
||||
strv_sort(z);
|
||||
names_dup = strv_copy(names_strv);
|
||||
if (!names_dup)
|
||||
return log_oom();
|
||||
|
||||
strv_sort(names_dup);
|
||||
|
||||
*ret = TAKE_PTR(names_dup);
|
||||
*ret_has_default = has_default;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verb_components(int argc, char **argv, void *userdata) {
|
||||
_cleanup_strv_free_ char **names = NULL;
|
||||
bool has_default_component = false;
|
||||
int r;
|
||||
|
||||
assert(argc <= 1);
|
||||
|
||||
r = walk_search_paths(CONF_PATHS_STRV(""), true, &names, &has_default_component);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!sd_json_format_enabled(arg_json_format_flags)) {
|
||||
if (!has_default_component && set_isempty(names)) {
|
||||
if (!has_default_component && strv_isempty(names)) {
|
||||
log_info("No components defined.");
|
||||
return 0;
|
||||
}
|
||||
|
@ -1621,13 +1723,53 @@ static int verb_components(int argc, char **argv, void *userdata) {
|
|||
printf("%s<default>%s\n",
|
||||
ansi_highlight(), ansi_normal());
|
||||
|
||||
STRV_FOREACH(i, z)
|
||||
STRV_FOREACH(i, names)
|
||||
puts(*i);
|
||||
} else {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *json = NULL;
|
||||
|
||||
r = sd_json_buildo(&json, SD_JSON_BUILD_PAIR_BOOLEAN("default", has_default_component),
|
||||
SD_JSON_BUILD_PAIR_STRV("components", z));
|
||||
SD_JSON_BUILD_PAIR_STRV("components", names));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create JSON: %m");
|
||||
|
||||
r = sd_json_variant_dump(json, arg_json_format_flags, stdout, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to print JSON: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verb_streams(int argc, char **argv, void *userdata) {
|
||||
char **dirs = STRV_MAKE("/var/cache/systemd/", CONF_PATHS_SYSTEM(""));
|
||||
_cleanup_strv_free_ char **names = NULL;
|
||||
bool has_default_stream = false;
|
||||
int r;
|
||||
|
||||
assert(argc <= 1);
|
||||
|
||||
r = walk_search_paths(dirs, false, &names, &has_default_stream);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)) {
|
||||
if (!has_default_stream && strv_isempty(names)) {
|
||||
log_info("No streams defined.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (has_default_stream)
|
||||
printf("%s<default>%s\n",
|
||||
ansi_highlight(), ansi_normal());
|
||||
|
||||
STRV_FOREACH(i, names)
|
||||
puts(*i);
|
||||
} else {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *json = NULL;
|
||||
|
||||
r = sd_json_buildo(&json, SD_JSON_BUILD_PAIR_BOOLEAN("default", has_default_stream),
|
||||
SD_JSON_BUILD_PAIR_STRV("streams", names));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create JSON: %m");
|
||||
|
||||
|
@ -1659,11 +1801,13 @@ static int verb_help(int argc, char **argv, void *userdata) {
|
|||
" currently booted\n"
|
||||
" reboot Reboot if a newer version is installed than booted\n"
|
||||
" components Show list of components\n"
|
||||
" streams Show list of streams\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
" -C --component=NAME Select component to update\n"
|
||||
" --definitions=DIR Find transfer definitions in specified directory\n"
|
||||
" --stream=STREAM Select stream to switch to\n"
|
||||
" --root=PATH Operate on an alternate filesystem root\n"
|
||||
" --image=PATH Operate on disk image as filesystem root\n"
|
||||
" --image-policy=POLICY\n"
|
||||
|
@ -1698,6 +1842,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
ARG_NO_LEGEND,
|
||||
ARG_SYNC,
|
||||
ARG_DEFINITIONS,
|
||||
ARG_STREAM,
|
||||
ARG_JSON,
|
||||
ARG_ROOT,
|
||||
ARG_IMAGE,
|
||||
|
@ -1714,6 +1859,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
||||
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
|
||||
{ "definitions", required_argument, NULL, ARG_DEFINITIONS },
|
||||
{ "stream", required_argument, NULL, ARG_STREAM },
|
||||
{ "instances-max", required_argument, NULL, 'm' },
|
||||
{ "sync", required_argument, NULL, ARG_SYNC },
|
||||
{ "json", required_argument, NULL, ARG_JSON },
|
||||
|
@ -1770,6 +1916,24 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
return r;
|
||||
break;
|
||||
|
||||
case ARG_STREAM:
|
||||
if (isempty(optarg)) {
|
||||
arg_stream = mfree(arg_stream);
|
||||
break;
|
||||
}
|
||||
|
||||
r = stream_name_valid(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine if stream name is valid: %m");
|
||||
if (r == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Stream name invalid: %s", optarg);
|
||||
|
||||
r = free_and_strdup_warn(&arg_stream, optarg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_JSON:
|
||||
r = parse_json_argument(optarg, &arg_json_format_flags);
|
||||
if (r <= 0)
|
||||
|
@ -1856,6 +2020,12 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
if (arg_definitions && arg_component)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The --definitions= and --component= switches may not be combined.");
|
||||
|
||||
if (arg_definitions && arg_stream)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The --definitions= and --stream= switches may not be combined.");
|
||||
|
||||
if (arg_component && arg_stream)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The --component= and --stream= switches may not be combined.");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1864,6 +2034,7 @@ static int sysupdate_main(int argc, char *argv[]) {
|
|||
static const Verb verbs[] = {
|
||||
{ "list", VERB_ANY, 2, VERB_DEFAULT, verb_list },
|
||||
{ "components", VERB_ANY, 1, 0, verb_components },
|
||||
{ "streams", VERB_ANY, 1, 0, verb_streams },
|
||||
{ "features", VERB_ANY, 2, 0, verb_features },
|
||||
{ "check-new", VERB_ANY, 1, 0, verb_check_new },
|
||||
{ "update", VERB_ANY, 2, 0, verb_update },
|
||||
|
|
|
@ -924,7 +924,7 @@ static int names_devicetree(sd_device *dev, const char *prefix, EventMode mode)
|
|||
char str[ALTIFNAMSIZ];
|
||||
if (snprintf_ok(str, sizeof str, "%sd%u", prefix, i))
|
||||
udev_builtin_add_property(dev, mode, "ID_NET_NAME_ONBOARD", str);
|
||||
log_device_debug(dev, "Devicetree identifier: alias_index=%u %s \"%s\"",
|
||||
log_device_debug(dev, "DeviceTree identifier: alias_index=%u %s \"%s\"",
|
||||
i, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), str + strlen(prefix));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -13,3 +13,4 @@ IPv6ProxyNDP=yes
|
|||
IPv6AcceptRA=no
|
||||
IPv4AcceptLocal=yes
|
||||
IPv4ReversePathFilter=no
|
||||
MulticastIGMPVersion=v1
|
||||
|
|
|
@ -4381,6 +4381,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
|||
self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp_pvlan', '1')
|
||||
self.check_ipv4_sysctl_attr('dummy98', 'accept_local', '1')
|
||||
self.check_ipv4_sysctl_attr('dummy98', 'rp_filter', '0')
|
||||
self.check_ipv4_sysctl_attr('dummy98', 'force_igmp_version', '1')
|
||||
|
||||
copy_network_unit('25-sysctl.network.d/25-ipv6-privacy-extensions.conf')
|
||||
networkctl_reload()
|
||||
|
|
Loading…
Reference in New Issue