mirror of
https://github.com/systemd/systemd.git
synced 2024-10-27 10:25:37 +03:00
Merge pull request #17576 from gportay/veritysetup-add-support-for-dm-verity-flags
veritysetup: add support for veritytab
This commit is contained in:
commit
3dc536e0c5
@ -49,6 +49,9 @@ All tools:
|
|||||||
* `$SYSTEMD_CRYPTTAB` — if set, use this path instead of /etc/crypttab. Only
|
* `$SYSTEMD_CRYPTTAB` — if set, use this path instead of /etc/crypttab. Only
|
||||||
useful for debugging. Currently only supported by systemd-cryptsetup-generator.
|
useful for debugging. Currently only supported by systemd-cryptsetup-generator.
|
||||||
|
|
||||||
|
* `$SYSTEMD_VERITYTAB` — if set, use this path instead of /etc/veritytab. Only
|
||||||
|
useful for debugging. Currently only supported by systemd-veritysetup-generator.
|
||||||
|
|
||||||
* `$SYSTEMD_EFI_OPTIONS` — if set, used instead of the string in the
|
* `$SYSTEMD_EFI_OPTIONS` — if set, used instead of the string in the
|
||||||
SystemdOptions EFI variable. Analogous to `$SYSTEMD_PROC_CMDLINE`.
|
SystemdOptions EFI variable. Analogous to `$SYSTEMD_PROC_CMDLINE`.
|
||||||
|
|
||||||
|
@ -92,10 +92,10 @@
|
|||||||
|
|
||||||
<!-- note: do not use unicode ellipsis here, because docbook will replace that
|
<!-- note: do not use unicode ellipsis here, because docbook will replace that
|
||||||
with three dots anyway, messing up alignment -->
|
with three dots anyway, messing up alignment -->
|
||||||
<programlisting> cryptsetup-pre.target
|
<programlisting> cryptsetup-pre.target veritysetup-pre.target
|
||||||
|
|
|
|
||||||
(various low-level v
|
(various low-level v
|
||||||
API VFS mounts: (various cryptsetup devices...)
|
API VFS mounts: (various cryptsetup/veritysetup devices...)
|
||||||
mqueue, configfs, | |
|
mqueue, configfs, | |
|
||||||
debugfs, ...) v |
|
debugfs, ...) v |
|
||||||
| cryptsetup.target |
|
| cryptsetup.target |
|
||||||
@ -105,7 +105,7 @@
|
|||||||
| v local-fs-pre.target | | | (network file systems)
|
| v local-fs-pre.target | | | (network file systems)
|
||||||
| swap.target | | v v |
|
| swap.target | | v v |
|
||||||
| | v | remote-cryptsetup.target |
|
| | v | remote-cryptsetup.target |
|
||||||
| | (various low-level (various mounts and | | |
|
| | (various low-level (various mounts and | remote-veritysetup.target |
|
||||||
| | services: udevd, fsck services...) | | remote-fs.target
|
| | services: udevd, fsck services...) | | remote-fs.target
|
||||||
| | tmpfiles, random | | | /
|
| | tmpfiles, random | | | /
|
||||||
| | seed, sysctl, ...) v | | /
|
| | seed, sysctl, ...) v | | /
|
||||||
@ -303,7 +303,8 @@ emergency.service | | |
|
|||||||
<programlisting> (conflicts with (conflicts with
|
<programlisting> (conflicts with (conflicts with
|
||||||
all system all file system
|
all system all file system
|
||||||
services) mounts, swaps,
|
services) mounts, swaps,
|
||||||
| cryptsetup
|
| cryptsetup/
|
||||||
|
| veritysetup
|
||||||
| devices, ...)
|
| devices, ...)
|
||||||
| |
|
| |
|
||||||
v v
|
v v
|
||||||
|
@ -94,7 +94,8 @@
|
|||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title><filename>/etc/crypttab</filename> and
|
<title><filename>/etc/crypttab</filename>,
|
||||||
|
<filename>/etc/veritytab</filename> and
|
||||||
<filename>/etc/fstab</filename> options</title>
|
<filename>/etc/fstab</filename> options</title>
|
||||||
|
|
||||||
<para>Options which influence mounted filesystems and encrypted volumes.</para>
|
<para>Options which influence mounted filesystems and encrypted volumes.</para>
|
||||||
|
@ -356,11 +356,14 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
<term><varname>veritytab=</varname></term>
|
||||||
|
<term><varname>rd.veritytab=</varname></term>
|
||||||
<term><varname>roothash=</varname></term>
|
<term><varname>roothash=</varname></term>
|
||||||
<term><varname>systemd.verity=</varname></term>
|
<term><varname>systemd.verity=</varname></term>
|
||||||
<term><varname>rd.systemd.verity=</varname></term>
|
<term><varname>rd.systemd.verity=</varname></term>
|
||||||
<term><varname>systemd.verity_root_data=</varname></term>
|
<term><varname>systemd.verity_root_data=</varname></term>
|
||||||
<term><varname>systemd.verity_root_hash=</varname></term>
|
<term><varname>systemd.verity_root_hash=</varname></term>
|
||||||
|
<term><varname>systemd.verity.root_options=</varname></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>Configures the integrity protection root hash for the root file system, and other related
|
<para>Configures the integrity protection root hash for the root file system, and other related
|
||||||
parameters. For details, see
|
parameters. For details, see
|
||||||
|
@ -9,6 +9,7 @@ manpages = [
|
|||||||
['coredump.conf', '5', ['coredump.conf.d'], 'ENABLE_COREDUMP'],
|
['coredump.conf', '5', ['coredump.conf.d'], 'ENABLE_COREDUMP'],
|
||||||
['coredumpctl', '1', [], 'ENABLE_COREDUMP'],
|
['coredumpctl', '1', [], 'ENABLE_COREDUMP'],
|
||||||
['crypttab', '5', [], 'HAVE_LIBCRYPTSETUP'],
|
['crypttab', '5', [], 'HAVE_LIBCRYPTSETUP'],
|
||||||
|
['veritytab', '5', [], 'HAVE_LIBCRYPTSETUP'],
|
||||||
['daemon', '7', [], ''],
|
['daemon', '7', [], ''],
|
||||||
['dnssec-trust-anchors.d',
|
['dnssec-trust-anchors.d',
|
||||||
'5',
|
'5',
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
<listitem><para>Takes a boolean argument. Defaults to <literal>yes</literal>. If <literal>no</literal>,
|
<listitem><para>Takes a boolean argument. Defaults to <literal>yes</literal>. If <literal>no</literal>,
|
||||||
disables the generator entirely. <varname>rd.systemd.verity=</varname> is honored only by the initial RAM disk
|
disables the generator entirely. <varname>rd.systemd.verity=</varname> is honored only by the initial RAM disk
|
||||||
(initrd) while <varname>systemd.verity=</varname> is honored by both the host system and the
|
(initrd) while <varname>systemd.verity=</varname> is honored by both the host system and the
|
||||||
initrd. </para></listitem>
|
initrd.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
@ -81,6 +81,17 @@
|
|||||||
(see above).</para></listitem>
|
(see above).</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>systemd.verity_root_options=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a comma-separated list of dm-verity options. Expects the following options
|
||||||
|
<option>ignore-corruption</option>, <option>restart-on-corruption</option>, <option>ignore-zero-blocks</option>,
|
||||||
|
<option>check-at-most-once</option>, <option>panic-on-corruption</option> and
|
||||||
|
<option>root-hash-signature</option>. See
|
||||||
|
<citerefentry><refentrytitle>veritysetup</refentrytitle><manvolnum>8</manvolnum></citerefentry> for more
|
||||||
|
details.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
<filename>bluetooth.target</filename>,
|
<filename>bluetooth.target</filename>,
|
||||||
<filename>cryptsetup-pre.target</filename>,
|
<filename>cryptsetup-pre.target</filename>,
|
||||||
<filename>cryptsetup.target</filename>,
|
<filename>cryptsetup.target</filename>,
|
||||||
|
<filename>veritysetup-pre.target</filename>,
|
||||||
|
<filename>veritysetup.target</filename>,
|
||||||
<filename>ctrl-alt-del.target</filename>,
|
<filename>ctrl-alt-del.target</filename>,
|
||||||
<filename>blockdev@.target</filename>,
|
<filename>blockdev@.target</filename>,
|
||||||
<filename>boot-complete.target</filename>,
|
<filename>boot-complete.target</filename>,
|
||||||
@ -60,6 +62,7 @@
|
|||||||
<filename>printer.target</filename>,
|
<filename>printer.target</filename>,
|
||||||
<filename>reboot.target</filename>,
|
<filename>reboot.target</filename>,
|
||||||
<filename>remote-cryptsetup.target</filename>,
|
<filename>remote-cryptsetup.target</filename>,
|
||||||
|
<filename>remote-veritysetup.target</filename>,
|
||||||
<filename>remote-fs-pre.target</filename>,
|
<filename>remote-fs-pre.target</filename>,
|
||||||
<filename>remote-fs.target</filename>,
|
<filename>remote-fs.target</filename>,
|
||||||
<filename>rescue.target</filename>,
|
<filename>rescue.target</filename>,
|
||||||
@ -186,6 +189,13 @@
|
|||||||
encrypted block devices.</para>
|
encrypted block devices.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><filename>veritysetup.target</filename></term>
|
||||||
|
<listitem>
|
||||||
|
<para>A target that pulls in setup services for all
|
||||||
|
verity integrity protected block devices.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><filename>dbus.service</filename></term>
|
<term><filename>dbus.service</filename></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -552,6 +562,15 @@
|
|||||||
entries marked with <option>_netdev</option>.</para>
|
entries marked with <option>_netdev</option>.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><filename>remote-veritysetup.target</filename></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Similar to <filename>veritysetup.target</filename>, but for verity
|
||||||
|
integrity protected devices which are accessed over the network. It is used for
|
||||||
|
<citerefentry><refentrytitle>veritytab</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
|
entries marked with <option>_netdev</option>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><filename>remote-fs.target</filename></term>
|
<term><filename>remote-fs.target</filename></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -855,7 +874,8 @@
|
|||||||
<listitem><para>This template unit is used to order mount units and other consumers of block
|
<listitem><para>This template unit is used to order mount units and other consumers of block
|
||||||
devices after services that synthesize these block devices. In particular, this is intended to be
|
devices after services that synthesize these block devices. In particular, this is intended to be
|
||||||
used with storage services (such as
|
used with storage services (such as
|
||||||
<citerefentry><refentrytitle>systemd-cryptsetup@.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
|
<citerefentry><refentrytitle>systemd-cryptsetup@.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>/
|
||||||
|
<citerefentry><refentrytitle>systemd-veritysetup@.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
|
||||||
that allocate and manage a virtual block device. Storage services are ordered before an instance of
|
that allocate and manage a virtual block device. Storage services are ordered before an instance of
|
||||||
<filename>blockdev@.target</filename>, and the consumer units after it. The ordering is
|
<filename>blockdev@.target</filename>, and the consumer units after it. The ordering is
|
||||||
particularly relevant during shutdown, as it ensures that the mount is deactivated first and the
|
particularly relevant during shutdown, as it ensures that the mount is deactivated first and the
|
||||||
@ -879,6 +899,19 @@
|
|||||||
stopped.</para>
|
stopped.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><filename>veritysetup-pre.target</filename></term>
|
||||||
|
<listitem>
|
||||||
|
<para>This passive target unit may be pulled in by services
|
||||||
|
that want to run before any verity integrity protected block
|
||||||
|
device is set up. All verity integrity protected block
|
||||||
|
devices are set up after this target has been reached. Since
|
||||||
|
the shutdown order is implicitly the reverse start-up order
|
||||||
|
between units, this target is particularly useful to ensure
|
||||||
|
that a service is shut down only after all verity integrity
|
||||||
|
protected block devices are fully stopped.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><filename>first-boot-complete.target</filename></term>
|
<term><filename>first-boot-complete.target</filename></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -972,7 +1005,7 @@
|
|||||||
<term><filename>remote-fs-pre.target</filename></term>
|
<term><filename>remote-fs-pre.target</filename></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>This target unit is automatically ordered before all
|
<para>This target unit is automatically ordered before all
|
||||||
mount point units (see above) and cryptsetup devices
|
mount point units (see above) and cryptsetup/veritysetup devices
|
||||||
marked with the <option>_netdev</option>. It can be used to run
|
marked with the <option>_netdev</option>. It can be used to run
|
||||||
certain units before remote encrypted devices and mounts are established.
|
certain units before remote encrypted devices and mounts are established.
|
||||||
Note that this unit is generally not part of the initial
|
Note that this unit is generally not part of the initial
|
||||||
|
198
man/veritytab.xml
Normal file
198
man/veritytab.xml
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--*-nxml-*-->
|
||||||
|
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||||
|
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||||
|
<!--
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
This is based on crypttab(5).
|
||||||
|
|
||||||
|
-->
|
||||||
|
<refentry id="veritytab" conditional='HAVE_LIBCRYPTSETUP' xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||||
|
|
||||||
|
<refentryinfo>
|
||||||
|
<title>veritytab</title>
|
||||||
|
<productname>systemd</productname>
|
||||||
|
</refentryinfo>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>veritytab</refentrytitle>
|
||||||
|
<manvolnum>5</manvolnum>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>veritytab</refname>
|
||||||
|
<refpurpose>Configuration for verity block devices</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<para><filename>/etc/veritytab</filename></para>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para>The <filename>/etc/veritytab</filename> file describes
|
||||||
|
verity integrity protected block devices that are set up during
|
||||||
|
system boot.</para>
|
||||||
|
|
||||||
|
<para>Empty lines and lines starting with the <literal>#</literal>
|
||||||
|
character are ignored. Each of the remaining lines describes one
|
||||||
|
verity integrity protected block device. Fields are delimited by
|
||||||
|
white space.</para>
|
||||||
|
|
||||||
|
<para>Each line is in the form<programlisting><replaceable>volume-name</replaceable> <replaceable>data-device</replaceable> <replaceable>hash-device</replaceable> <replaceable>roothash</replaceable> <replaceable>options</replaceable></programlisting>
|
||||||
|
The first four fields are mandatory, the remaining one is optional.</para>
|
||||||
|
|
||||||
|
<para>The first field contains the name of the resulting verity volume; its block device is set up
|
||||||
|
below <filename>/dev/mapper/</filename>.</para>
|
||||||
|
|
||||||
|
<para>The second field contains a path to the underlying block data device, or a specification of a block device via
|
||||||
|
<literal>UUID=</literal> followed by the UUID.</para>
|
||||||
|
|
||||||
|
<para>The third field contains a path to the underlying block hash device, or a specification of a block device via
|
||||||
|
<literal>UUID=</literal> followed by the UUID.</para>
|
||||||
|
|
||||||
|
<para>The fourth field is the <literal>roothash</literal> in hexadecimal.</para>
|
||||||
|
|
||||||
|
<para>The fifth field, if present, is a comma-delimited list of options. The following options are
|
||||||
|
recognized:</para>
|
||||||
|
|
||||||
|
<variablelist class='fstab-options'>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ignore-corruption</option></term>
|
||||||
|
<term><option>restart-on-corruption</option></term>
|
||||||
|
<term><option>panic-on-corruption</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Defines what to do if data integrity problem is detected (data corruption). Without these
|
||||||
|
options kernel fails the IO operation with I/O error. With <literal>--ignore-corruption</literal> option the
|
||||||
|
corruption is only logged. With <literal>--restart-on-corruption</literal> or
|
||||||
|
<literal>--panic-on-corruption</literal> the kernel is restarted (panicked) immediately.
|
||||||
|
|
||||||
|
(You have to provide way how to avoid restart loops.)</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ignore-zero-blocks</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Instruct kernel to not verify blocks that are expected to contain zeroes and always directly
|
||||||
|
return zeroes instead.
|
||||||
|
|
||||||
|
WARNING: Use this option only in very specific cases. This option is available since Linux kernel version 4.5.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>check-at-most-once</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Instruct kernel to verify blocks only the first time they are read from the data device, rather
|
||||||
|
than every time.
|
||||||
|
|
||||||
|
WARNING: It provides a reduced level of security because only offline tampering of the data device's content
|
||||||
|
will be detected, not online tampering. This option is available since Linux kernel version 4.17.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>root-hash-signature=</option></term>
|
||||||
|
|
||||||
|
<listitem><para>A base64 string encoding the root hash signature prefixed by <literal>base64:</literal> or a
|
||||||
|
path to roothash signature file used to verify the root hash (in kernel). This feature requires Linux kernel
|
||||||
|
version 5.4 or more recent.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>_netdev</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Marks this veritysetup device as requiring network. It will be
|
||||||
|
started after the network is available, similarly to
|
||||||
|
<citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||||
|
units marked with <option>_netdev</option>. The service unit to set up this device
|
||||||
|
will be ordered between <filename>remote-fs-pre.target</filename> and
|
||||||
|
<filename>remote-veritysetup.target</filename>, instead of
|
||||||
|
<filename>veritysetup-pre.target</filename> and
|
||||||
|
<filename>veritysetup.target</filename>.</para>
|
||||||
|
|
||||||
|
<para>Hint: if this device is used for a mount point that is specified in
|
||||||
|
<citerefentry project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||||
|
the <option>_netdev</option> option should also be used for the mount
|
||||||
|
point. Otherwise, a dependency loop might be created where the mount point
|
||||||
|
will be pulled in by <filename>local-fs.target</filename>, while the
|
||||||
|
service to configure the network is usually only started <emphasis>after</emphasis>
|
||||||
|
the local file system has been mounted.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>noauto</option></term>
|
||||||
|
|
||||||
|
<listitem><para>This device will not be added to <filename>veritysetup.target</filename>.
|
||||||
|
This means that it will not be automatically enabled on boot, unless something else pulls
|
||||||
|
it in. In particular, if the device is used for a mount point, it'll be enabled
|
||||||
|
automatically during boot, unless the mount point itself is also disabled with
|
||||||
|
<option>noauto</option>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>nofail</option></term>
|
||||||
|
|
||||||
|
<listitem><para>This device will not be a hard dependency of
|
||||||
|
<filename>veritysetup.target</filename>. It'll still be pulled in and started, but the system
|
||||||
|
will not wait for the device to show up and be enabled, and boot will not fail if this is
|
||||||
|
unsuccessful. Note that other units that depend on the enabled device may still fail. In
|
||||||
|
particular, if the device is used for a mount point, the mount point itself also needs to
|
||||||
|
have the <option>nofail</option> option, or the boot will fail if the device is not enabled
|
||||||
|
successfully.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>x-initrd.attach</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Setup this verity integrity protected block device in the initramfs, similarly to
|
||||||
|
<citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||||
|
units marked with <option>x-initrd.mount</option>.</para>
|
||||||
|
|
||||||
|
<para>Although it's not necessary to mark the mount entry for the root file system with
|
||||||
|
<option>x-initrd.mount</option>, <option>x-initrd.attach</option> is still recommended with
|
||||||
|
the verity integrity protected block device containing the root file system as otherwise systemd
|
||||||
|
will attempt to detach the device during the regular system shutdown while it's still in
|
||||||
|
use. With this option the device will still be detached but later after the root file
|
||||||
|
system is unmounted.</para>
|
||||||
|
|
||||||
|
<para>All other verity integrity protected block devices that contain file systems mounted in the
|
||||||
|
initramfs should use this option.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
<para>At early boot and when the system manager configuration is
|
||||||
|
reloaded, this file is translated into native systemd units by
|
||||||
|
<citerefentry><refentrytitle>systemd-veritysetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Examples</title>
|
||||||
|
<example>
|
||||||
|
<title>/etc/veritytab example</title>
|
||||||
|
<para>Set up two verity integrity protected block devices. One using device blocks, another using files.</para>
|
||||||
|
|
||||||
|
<programlisting>usr PARTUUID=783e45ae-7aa3-484a-beef-a80ff9c19cbb PARTUUID=21dc1dfe-4c33-8b48-98a9-918a22eb3e37 36e3f740ad502e2c25e2a23d9c7c17bf0fdad2300b7580842d4b7ec1fb0fa263 auto
|
||||||
|
data /etc/data /etc/hash a5ee4b42f70ae1f46a08a7c92c2e0a20672ad2f514792730f5d49d7606ab8fdf auto
|
||||||
|
</programlisting>
|
||||||
|
</example>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See Also</title>
|
||||||
|
<para>
|
||||||
|
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||||
|
<citerefentry><refentrytitle>systemd-veritysetup@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
|
<citerefentry><refentrytitle>systemd-veritysetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
|
<citerefentry project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||||
|
<citerefentry project='die-net'><refentrytitle>veritysetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
@ -237,6 +237,7 @@ conf.set_quoted('ROOTPREFIX_NOSLASH', rootprefixdir_nosl
|
|||||||
conf.set_quoted('RANDOM_SEED_DIR', randomseeddir)
|
conf.set_quoted('RANDOM_SEED_DIR', randomseeddir)
|
||||||
conf.set_quoted('RANDOM_SEED', join_paths(randomseeddir, 'random-seed'))
|
conf.set_quoted('RANDOM_SEED', join_paths(randomseeddir, 'random-seed'))
|
||||||
conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH', join_paths(rootlibexecdir, 'systemd-cryptsetup'))
|
conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH', join_paths(rootlibexecdir, 'systemd-cryptsetup'))
|
||||||
|
conf.set_quoted('SYSTEMD_VERITYSETUP_PATH', join_paths(rootlibexecdir, 'systemd-veritysetup'))
|
||||||
conf.set_quoted('SYSTEM_GENERATOR_DIR', systemgeneratordir)
|
conf.set_quoted('SYSTEM_GENERATOR_DIR', systemgeneratordir)
|
||||||
conf.set_quoted('USER_GENERATOR_DIR', usergeneratordir)
|
conf.set_quoted('USER_GENERATOR_DIR', usergeneratordir)
|
||||||
conf.set_quoted('SYSTEM_ENV_GENERATOR_DIR', systemenvgeneratordir)
|
conf.set_quoted('SYSTEM_ENV_GENERATOR_DIR', systemenvgeneratordir)
|
||||||
|
@ -620,6 +620,81 @@ int generator_write_cryptsetup_service_section(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int generator_write_veritysetup_unit_section(
|
||||||
|
FILE *f,
|
||||||
|
const char *source) {
|
||||||
|
|
||||||
|
assert(f);
|
||||||
|
|
||||||
|
fprintf(f,
|
||||||
|
"[Unit]\n"
|
||||||
|
"Description=Integrity Protection Setup for %%I\n"
|
||||||
|
"Documentation=man:veritytab(5) man:systemd-veritysetup-generator(8) man:systemd-veritysetup@.service(8)\n");
|
||||||
|
|
||||||
|
if (source)
|
||||||
|
fprintf(f, "SourcePath=%s\n", source);
|
||||||
|
|
||||||
|
fprintf(f,
|
||||||
|
"DefaultDependencies=no\n"
|
||||||
|
"IgnoreOnIsolate=true\n"
|
||||||
|
"After=cryptsetup-pre.target systemd-udevd-kernel.socket\n"
|
||||||
|
"Before=blockdev@dev-mapper-%%i.target\n"
|
||||||
|
"Wants=blockdev@dev-mapper-%%i.target\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int generator_write_veritysetup_service_section(
|
||||||
|
FILE *f,
|
||||||
|
const char *name,
|
||||||
|
const char *data_what,
|
||||||
|
const char *hash_what,
|
||||||
|
const char *roothash,
|
||||||
|
const char *options) {
|
||||||
|
|
||||||
|
_cleanup_free_ char *name_escaped = NULL, *data_what_escaped = NULL, *hash_what_escaped,
|
||||||
|
*roothash_escaped = NULL, *options_escaped = NULL;
|
||||||
|
|
||||||
|
assert(f);
|
||||||
|
assert(name);
|
||||||
|
assert(data_what);
|
||||||
|
assert(hash_what);
|
||||||
|
|
||||||
|
name_escaped = specifier_escape(name);
|
||||||
|
if (!name_escaped)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
data_what_escaped = specifier_escape(data_what);
|
||||||
|
if (!data_what_escaped)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
hash_what_escaped = specifier_escape(hash_what);
|
||||||
|
if (!hash_what_escaped)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
roothash_escaped = specifier_escape(roothash);
|
||||||
|
if (!roothash_escaped)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
if (options) {
|
||||||
|
options_escaped = specifier_escape(options);
|
||||||
|
if (!options_escaped)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(f,
|
||||||
|
"\n"
|
||||||
|
"[Service]\n"
|
||||||
|
"Type=oneshot\n"
|
||||||
|
"RemainAfterExit=yes\n"
|
||||||
|
"ExecStart=" SYSTEMD_VERITYSETUP_PATH " attach '%s' '%s' '%s' '%s' '%s'\n"
|
||||||
|
"ExecStop=" SYSTEMD_VERITYSETUP_PATH " detach '%s'\n",
|
||||||
|
name_escaped, data_what_escaped, hash_what_escaped, roothash_escaped, strempty(options_escaped),
|
||||||
|
name_escaped);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void log_setup_generator(void) {
|
void log_setup_generator(void) {
|
||||||
/* Disable talking to syslog/journal (i.e. the two IPC-based loggers) if we run in system context. */
|
/* Disable talking to syslog/journal (i.e. the two IPC-based loggers) if we run in system context. */
|
||||||
if (cg_pid_get_owner_uid(0, NULL) == -ENXIO /* not running in a per-user slice */)
|
if (cg_pid_get_owner_uid(0, NULL) == -ENXIO /* not running in a per-user slice */)
|
||||||
|
@ -42,6 +42,18 @@ int generator_write_cryptsetup_service_section(
|
|||||||
const char *password,
|
const char *password,
|
||||||
const char *options);
|
const char *options);
|
||||||
|
|
||||||
|
int generator_write_veritysetup_unit_section(
|
||||||
|
FILE *f,
|
||||||
|
const char *source);
|
||||||
|
|
||||||
|
int generator_write_veritysetup_service_section(
|
||||||
|
FILE *f,
|
||||||
|
const char *name,
|
||||||
|
const char *data_what,
|
||||||
|
const char *hash_what,
|
||||||
|
const char *roothash,
|
||||||
|
const char *options);
|
||||||
|
|
||||||
int generator_write_device_deps(
|
int generator_write_device_deps(
|
||||||
const char *dir,
|
const char *dir,
|
||||||
const char *what,
|
const char *what,
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
|
#include "dropin.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "fstab-util.h"
|
#include "fstab-util.h"
|
||||||
@ -24,18 +25,33 @@
|
|||||||
|
|
||||||
#define SYSTEMD_VERITYSETUP_SERVICE "systemd-veritysetup@root.service"
|
#define SYSTEMD_VERITYSETUP_SERVICE "systemd-veritysetup@root.service"
|
||||||
|
|
||||||
|
typedef struct verity_device {
|
||||||
|
char *uuid;
|
||||||
|
char *datadev;
|
||||||
|
char *hashdev;
|
||||||
|
char *roothash;
|
||||||
|
char *name;
|
||||||
|
char *options;
|
||||||
|
bool create;
|
||||||
|
} verity_device;
|
||||||
|
|
||||||
static const char *arg_dest = NULL;
|
static const char *arg_dest = NULL;
|
||||||
static bool arg_enabled = true;
|
static bool arg_enabled = true;
|
||||||
|
static bool arg_read_veritytab = true;
|
||||||
|
static const char *arg_veritytab = NULL;
|
||||||
static char *arg_root_hash = NULL;
|
static char *arg_root_hash = NULL;
|
||||||
static char *arg_data_what = NULL;
|
static char *arg_data_what = NULL;
|
||||||
static char *arg_hash_what = NULL;
|
static char *arg_hash_what = NULL;
|
||||||
|
static char *arg_options = NULL;
|
||||||
|
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep);
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_data_what, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_data_what, freep);
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_hash_what, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_hash_what, freep);
|
||||||
|
STATIC_DESTRUCTOR_REGISTER(arg_options, freep);
|
||||||
|
|
||||||
static int create_device(void) {
|
static int create_device(void) {
|
||||||
_cleanup_free_ char *u = NULL, *v = NULL, *d = NULL, *e = NULL, *u_escaped = NULL, *v_escaped = NULL, *root_hash_escaped = NULL;
|
_cleanup_free_ char *u = NULL, *v = NULL, *d = NULL, *e = NULL, *u_escaped = NULL, *v_escaped = NULL,
|
||||||
|
*root_hash_escaped = NULL, *options_escaped = NULL;
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
const char *to;
|
const char *to;
|
||||||
int r;
|
int r;
|
||||||
@ -57,7 +73,8 @@ static int create_device(void) {
|
|||||||
|
|
||||||
log_debug("Using root verity data device %s,\n"
|
log_debug("Using root verity data device %s,\n"
|
||||||
" hash device %s,\n"
|
" hash device %s,\n"
|
||||||
" and root hash %s.", arg_data_what, arg_hash_what, arg_root_hash);
|
" options %s,\n"
|
||||||
|
" and root hash %s.", arg_data_what, arg_hash_what, arg_options, arg_root_hash);
|
||||||
|
|
||||||
u = fstab_node_to_udev_node(arg_data_what);
|
u = fstab_node_to_udev_node(arg_data_what);
|
||||||
if (!u)
|
if (!u)
|
||||||
@ -80,6 +97,10 @@ static int create_device(void) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to generate unit name: %m");
|
return log_error_errno(r, "Failed to generate unit name: %m");
|
||||||
|
|
||||||
|
options_escaped = specifier_escape(arg_options ?: "");
|
||||||
|
if (!options_escaped)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
root_hash_escaped = specifier_escape(arg_root_hash);
|
root_hash_escaped = specifier_escape(arg_root_hash);
|
||||||
if (!root_hash_escaped)
|
if (!root_hash_escaped)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
@ -97,22 +118,22 @@ static int create_device(void) {
|
|||||||
"Conflicts=umount.target\n"
|
"Conflicts=umount.target\n"
|
||||||
"BindsTo=%s %s\n"
|
"BindsTo=%s %s\n"
|
||||||
"IgnoreOnIsolate=true\n"
|
"IgnoreOnIsolate=true\n"
|
||||||
"After=cryptsetup-pre.target systemd-udevd-kernel.socket %s %s\n"
|
"After=veritysetup-pre.target systemd-udevd-kernel.socket %s %s\n"
|
||||||
"Before=cryptsetup.target umount.target\n"
|
"Before=veritysetup.target umount.target\n"
|
||||||
"\n[Service]\n"
|
"\n[Service]\n"
|
||||||
"Type=oneshot\n"
|
"Type=oneshot\n"
|
||||||
"RemainAfterExit=yes\n"
|
"RemainAfterExit=yes\n"
|
||||||
"ExecStart=" ROOTLIBEXECDIR "/systemd-veritysetup attach root '%s' '%s' '%s'\n"
|
"ExecStart=" ROOTLIBEXECDIR "/systemd-veritysetup attach root '%s' '%s' '%s' '%s'\n"
|
||||||
"ExecStop=" ROOTLIBEXECDIR "/systemd-veritysetup detach root\n",
|
"ExecStop=" ROOTLIBEXECDIR "/systemd-veritysetup detach root\n",
|
||||||
d, e,
|
d, e,
|
||||||
d, e,
|
d, e,
|
||||||
u_escaped, v_escaped, root_hash_escaped);
|
u_escaped, v_escaped, root_hash_escaped, options_escaped);
|
||||||
|
|
||||||
r = fflush_and_check(f);
|
r = fflush_and_check(f);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to write file unit "SYSTEMD_VERITYSETUP_SERVICE": %m");
|
return log_error_errno(r, "Failed to write file unit "SYSTEMD_VERITYSETUP_SERVICE": %m");
|
||||||
|
|
||||||
to = strjoina(arg_dest, "/cryptsetup.target.requires/" SYSTEMD_VERITYSETUP_SERVICE);
|
to = strjoina(arg_dest, "/veritysetup.target.requires/" SYSTEMD_VERITYSETUP_SERVICE);
|
||||||
|
|
||||||
(void) mkdir_parents(to, 0755);
|
(void) mkdir_parents(to, 0755);
|
||||||
if (symlink("../" SYSTEMD_VERITYSETUP_SERVICE, to) < 0)
|
if (symlink("../" SYSTEMD_VERITYSETUP_SERVICE, to) < 0)
|
||||||
@ -132,6 +153,14 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
else
|
else
|
||||||
arg_enabled = r;
|
arg_enabled = r;
|
||||||
|
|
||||||
|
} else if (streq(key, "veritytab")) {
|
||||||
|
|
||||||
|
r = value ? parse_boolean(value) : 1;
|
||||||
|
if (r < 0)
|
||||||
|
log_warning("Failed to parse veritytab= kernel command line switch %s. Ignoring.", value);
|
||||||
|
else
|
||||||
|
arg_read_veritytab = r;
|
||||||
|
|
||||||
} else if (proc_cmdline_key_streq(key, "roothash")) {
|
} else if (proc_cmdline_key_streq(key, "roothash")) {
|
||||||
|
|
||||||
if (proc_cmdline_value_missing(key, value))
|
if (proc_cmdline_value_missing(key, value))
|
||||||
@ -158,6 +187,16 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
r = free_and_strdup(&arg_hash_what, value);
|
r = free_and_strdup(&arg_hash_what, value);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
|
} else if (proc_cmdline_key_streq(key, "systemd.verity_root_options")) {
|
||||||
|
|
||||||
|
if (proc_cmdline_value_missing(key, value))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = free_and_strdup(&arg_options, value);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -205,21 +244,221 @@ static int determine_devices(void) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int create_disk(
|
||||||
|
const char *name,
|
||||||
|
const char *data_device,
|
||||||
|
const char *hash_device,
|
||||||
|
const char *roothash,
|
||||||
|
const char *options,
|
||||||
|
const char *source) {
|
||||||
|
|
||||||
|
_cleanup_free_ char *n = NULL, *dd = NULL, *du = NULL, *hd = NULL, *hu = NULL, *e = NULL,
|
||||||
|
*du_escaped = NULL, *hu_escaped = NULL, *name_escaped = NULL;
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
const char *dmname;
|
||||||
|
bool noauto, nofail, netdev, attach_in_initrd;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(name);
|
||||||
|
assert(data_device);
|
||||||
|
assert(hash_device);
|
||||||
|
assert(roothash);
|
||||||
|
|
||||||
|
noauto = fstab_test_yes_no_option(options, "noauto\0" "auto\0");
|
||||||
|
nofail = fstab_test_yes_no_option(options, "nofail\0" "fail\0");
|
||||||
|
netdev = fstab_test_option(options, "_netdev\0");
|
||||||
|
attach_in_initrd = fstab_test_option(options, "x-initrd.attach\0");
|
||||||
|
|
||||||
|
name_escaped = specifier_escape(name);
|
||||||
|
if (!name_escaped)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
e = unit_name_escape(name);
|
||||||
|
if (!e)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
du = fstab_node_to_udev_node(data_device);
|
||||||
|
if (!du)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
hu = fstab_node_to_udev_node(hash_device);
|
||||||
|
if (!hu)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = unit_name_build("systemd-veritysetup", e, ".service", &n);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to generate unit name: %m");
|
||||||
|
|
||||||
|
du_escaped = specifier_escape(du);
|
||||||
|
if (!du_escaped)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
hu_escaped = specifier_escape(hu);
|
||||||
|
if (!hu_escaped)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = unit_name_from_path(du, ".device", &dd);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to generate unit name: %m");
|
||||||
|
|
||||||
|
r = unit_name_from_path(hu, ".device", &hd);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to generate unit name: %m");
|
||||||
|
|
||||||
|
r = generator_open_unit_file(arg_dest, NULL, n, &f);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = generator_write_veritysetup_unit_section(f, source);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (netdev)
|
||||||
|
fprintf(f, "After=remote-fs-pre.target\n");
|
||||||
|
|
||||||
|
/* If initrd takes care of attaching the disk then it should also detach it during shutdown. */
|
||||||
|
if (!attach_in_initrd)
|
||||||
|
fprintf(f, "Conflicts=umount.target\n");
|
||||||
|
|
||||||
|
if (!nofail)
|
||||||
|
fprintf(f,
|
||||||
|
"Before=%s\n",
|
||||||
|
netdev ? "remote-veritysetup.target" : "veritysetup.target");
|
||||||
|
|
||||||
|
if (path_startswith(du, "/dev/"))
|
||||||
|
fprintf(f,
|
||||||
|
"BindsTo=%s\n"
|
||||||
|
"After=%s\n"
|
||||||
|
"Before=umount.target\n",
|
||||||
|
dd, dd);
|
||||||
|
else
|
||||||
|
/* For loopback devices, add systemd-tmpfiles-setup-dev.service
|
||||||
|
dependency to ensure that loopback support is available in
|
||||||
|
the kernel (/dev/loop-control needs to exist) */
|
||||||
|
fprintf(f,
|
||||||
|
"RequiresMountsFor=%s\n"
|
||||||
|
"Requires=systemd-tmpfiles-setup-dev.service\n"
|
||||||
|
"After=systemd-tmpfiles-setup-dev.service\n",
|
||||||
|
du_escaped);
|
||||||
|
|
||||||
|
if (path_startswith(hu, "/dev/"))
|
||||||
|
fprintf(f,
|
||||||
|
"BindsTo=%s\n"
|
||||||
|
"After=%s\n"
|
||||||
|
"Before=umount.target\n",
|
||||||
|
hd, hd);
|
||||||
|
else
|
||||||
|
/* For loopback devices, add systemd-tmpfiles-setup-dev.service
|
||||||
|
dependency to ensure that loopback support is available in
|
||||||
|
the kernel (/dev/loop-control needs to exist) */
|
||||||
|
fprintf(f,
|
||||||
|
"RequiresMountsFor=%s\n"
|
||||||
|
"Requires=systemd-tmpfiles-setup-dev.service\n"
|
||||||
|
"After=systemd-tmpfiles-setup-dev.service\n",
|
||||||
|
hu_escaped);
|
||||||
|
|
||||||
|
r = generator_write_veritysetup_service_section(f, name, du_escaped, hu_escaped, roothash, options);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = fflush_and_check(f);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to write unit file %s: %m", n);
|
||||||
|
|
||||||
|
if (!noauto) {
|
||||||
|
r = generator_add_symlink(arg_dest,
|
||||||
|
netdev ? "remote-veritysetup.target" : "veritysetup.target",
|
||||||
|
nofail ? "wants" : "requires", n);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
dmname = strjoina("dev-mapper-", e, ".device");
|
||||||
|
return generator_add_symlink(arg_dest, dmname, "requires", n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_veritytab_devices(void) {
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
unsigned veritytab_line = 0;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!arg_read_veritytab)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = fopen_unlocked(arg_veritytab, "re", &f);
|
||||||
|
if (r < 0) {
|
||||||
|
if (errno != ENOENT)
|
||||||
|
log_error_errno(errno, "Failed to open %s: %m", arg_veritytab);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
_cleanup_free_ char *line = NULL, *name = NULL, *data_device = NULL, *hash_device = NULL,
|
||||||
|
*roothash = NULL, *options = NULL;
|
||||||
|
verity_device *d = NULL;
|
||||||
|
char *l, *data_uuid, *hash_uuid;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
r = read_line(f, LONG_LINE_MAX, &line);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to read %s: %m", arg_veritytab);
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
veritytab_line++;
|
||||||
|
|
||||||
|
l = strstrip(line);
|
||||||
|
if (IN_SET(l[0], 0, '#'))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
k = sscanf(l, "%ms %ms %ms %ms %ms", &name, &data_device, &hash_device, &roothash, &options);
|
||||||
|
if (k < 4 || k > 5) {
|
||||||
|
log_error("Failed to parse %s:%u, ignoring.", arg_veritytab, veritytab_line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_uuid = startswith(data_device, "UUID=");
|
||||||
|
if (!data_uuid)
|
||||||
|
data_uuid = path_startswith(data_device, "/dev/disk/by-uuid/");
|
||||||
|
|
||||||
|
hash_uuid = startswith(hash_device, "UUID=");
|
||||||
|
if (!hash_uuid)
|
||||||
|
hash_uuid = path_startswith(hash_device, "/dev/disk/by-uuid/");
|
||||||
|
|
||||||
|
r = create_disk(name,
|
||||||
|
data_device,
|
||||||
|
hash_device,
|
||||||
|
roothash,
|
||||||
|
options,
|
||||||
|
arg_veritytab);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (d)
|
||||||
|
d->create = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int run(const char *dest, const char *dest_early, const char *dest_late) {
|
static int run(const char *dest, const char *dest_early, const char *dest_late) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_se(arg_dest = dest);
|
assert_se(arg_dest = dest);
|
||||||
|
|
||||||
|
arg_veritytab = getenv("SYSTEMD_VERITYTAB") ?: "/etc/veritytab";
|
||||||
|
|
||||||
r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
|
r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_warning_errno(r, "Failed to parse kernel command line: %m");
|
return log_warning_errno(r, "Failed to parse kernel command line: %m");
|
||||||
|
|
||||||
/* For now we only support the root device on verity. Later on we might want to add support for /etc/veritytab
|
|
||||||
* or similar to define additional mappings */
|
|
||||||
|
|
||||||
if (!arg_enabled)
|
if (!arg_enabled)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
r = add_veritytab_devices();
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = determine_devices();
|
r = determine_devices();
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -15,13 +15,10 @@
|
|||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "terminal-util.h"
|
#include "terminal-util.h"
|
||||||
|
|
||||||
static char *arg_root_hash = NULL;
|
static uint32_t arg_activate_flags = CRYPT_ACTIVATE_READONLY;
|
||||||
static char *arg_data_what = NULL;
|
static char *arg_root_hash_signature = NULL;
|
||||||
static char *arg_hash_what = NULL;
|
|
||||||
|
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_root_hash_signature, freep);
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_data_what, freep);
|
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_hash_what, freep);
|
|
||||||
|
|
||||||
static int help(void) {
|
static int help(void) {
|
||||||
_cleanup_free_ char *link = NULL;
|
_cleanup_free_ char *link = NULL;
|
||||||
@ -31,7 +28,7 @@ static int help(void) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
printf("%s attach VOLUME DATADEVICE HASHDEVICE ROOTHASH [ROOTHASHSIG]\n"
|
printf("%s attach VOLUME DATADEVICE HASHDEVICE ROOTHASH [OPTIONS]\n"
|
||||||
"%s detach VOLUME\n\n"
|
"%s detach VOLUME\n\n"
|
||||||
"Attaches or detaches an integrity protected block device.\n"
|
"Attaches or detaches an integrity protected block device.\n"
|
||||||
"\nSee the %s for details.\n"
|
"\nSee the %s for details.\n"
|
||||||
@ -43,6 +40,93 @@ static int help(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int looks_like_roothashsig(const char *option) {
|
||||||
|
const char *val;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (path_is_absolute(option)) {
|
||||||
|
|
||||||
|
r = free_and_strdup(&arg_root_hash_signature, option);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = startswith(option, "base64:");
|
||||||
|
if (val) {
|
||||||
|
|
||||||
|
r = free_and_strdup(&arg_root_hash_signature, val);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_options(const char *options) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* backward compatibility with the obsolete ROOTHASHSIG positional argument */
|
||||||
|
r = looks_like_roothashsig(options);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 1) {
|
||||||
|
log_warning("Usage of ROOTHASHSIG positional argument is deprecated. "
|
||||||
|
"Please use the option root-hash-signature=%s instead.", options);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
_cleanup_free_ char *word = NULL;
|
||||||
|
char *val;
|
||||||
|
|
||||||
|
r = extract_first_word(&options, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS | EXTRACT_UNESCAPE_SEPARATORS);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse options: %m");
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (STR_IN_SET(word, "noauto", "auto", "nofail", "fail", "_netdev"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (isempty(word))
|
||||||
|
continue;
|
||||||
|
else if (streq(word, "ignore-corruption"))
|
||||||
|
arg_activate_flags |= CRYPT_ACTIVATE_IGNORE_CORRUPTION;
|
||||||
|
else if (streq(word, "restart-on-corruption"))
|
||||||
|
arg_activate_flags |= CRYPT_ACTIVATE_RESTART_ON_CORRUPTION;
|
||||||
|
else if (streq(word, "ignore-zero-blocks"))
|
||||||
|
arg_activate_flags |= CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS;
|
||||||
|
#ifdef CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE
|
||||||
|
else if (streq(word, "check-at-most-once"))
|
||||||
|
arg_activate_flags |= CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE;
|
||||||
|
#endif
|
||||||
|
#ifdef CRYPT_ACTIVATE_PANIC_ON_CORRUPTION
|
||||||
|
else if (streq(word, "panic-on-corruption"))
|
||||||
|
arg_activate_flags |= CRYPT_ACTIVATE_PANIC_ON_CORRUPTION;
|
||||||
|
#endif
|
||||||
|
else if ((val = startswith(word, "root-hash-signature="))) {
|
||||||
|
|
||||||
|
r = looks_like_roothashsig(val);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "root-hash-signature expects either full path to signature file or "
|
||||||
|
"base64 string encoding signature prefixed by base64:.");
|
||||||
|
|
||||||
|
r = free_and_strdup(&arg_root_hash_signature, val);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
} else
|
||||||
|
log_warning("Encountered unknown option '%s', ignoring.", word);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static int run(int argc, char *argv[]) {
|
static int run(int argc, char *argv[]) {
|
||||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||||
int r;
|
int r;
|
||||||
@ -81,6 +165,12 @@ static int run(int argc, char *argv[]) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (argc > 6) {
|
||||||
|
r = parse_options(argv[6]);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse options: %m");
|
||||||
|
}
|
||||||
|
|
||||||
r = crypt_load(cd, CRYPT_VERITY, NULL);
|
r = crypt_load(cd, CRYPT_VERITY, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to load verity superblock: %m");
|
return log_error_errno(r, "Failed to load verity superblock: %m");
|
||||||
@ -89,19 +179,19 @@ static int run(int argc, char *argv[]) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to configure data device: %m");
|
return log_error_errno(r, "Failed to configure data device: %m");
|
||||||
|
|
||||||
if (argc > 6) {
|
if (arg_root_hash_signature && *arg_root_hash_signature) {
|
||||||
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
|
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
|
||||||
_cleanup_free_ char *hash_sig = NULL;
|
_cleanup_free_ char *hash_sig = NULL;
|
||||||
size_t hash_sig_size;
|
size_t hash_sig_size;
|
||||||
char *value;
|
char *value;
|
||||||
|
|
||||||
if ((value = startswith(argv[6], "base64:"))) {
|
if ((value = startswith(arg_root_hash_signature, "base64:"))) {
|
||||||
r = unbase64mem(value, strlen(value), (void *)&hash_sig, &hash_sig_size);
|
r = unbase64mem(value, strlen(value), (void *)&hash_sig, &hash_sig_size);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to parse root hash signature '%s': %m", argv[6]);
|
return log_error_errno(r, "Failed to parse root hash signature '%s': %m", arg_root_hash_signature);
|
||||||
} else {
|
} else {
|
||||||
r = read_full_file_full(
|
r = read_full_file_full(
|
||||||
AT_FDCWD, argv[6], UINT64_MAX, SIZE_MAX,
|
AT_FDCWD, arg_root_hash_signature, UINT64_MAX, SIZE_MAX,
|
||||||
READ_FULL_FILE_CONNECT_SOCKET,
|
READ_FULL_FILE_CONNECT_SOCKET,
|
||||||
NULL,
|
NULL,
|
||||||
&hash_sig, &hash_sig_size);
|
&hash_sig, &hash_sig_size);
|
||||||
@ -109,12 +199,12 @@ static int run(int argc, char *argv[]) {
|
|||||||
return log_error_errno(r, "Failed to read root hash signature: %m");
|
return log_error_errno(r, "Failed to read root hash signature: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
r = crypt_activate_by_signed_key(cd, argv[2], m, l, hash_sig, hash_sig_size, CRYPT_ACTIVATE_READONLY);
|
r = crypt_activate_by_signed_key(cd, argv[2], m, l, hash_sig, hash_sig_size, arg_activate_flags);
|
||||||
#else
|
#else
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "activation of verity device with signature %s requested, but not supported by cryptsetup due to missing crypt_activate_by_signed_key()", argv[6]);
|
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "activation of verity device with signature %s requested, but not supported by cryptsetup due to missing crypt_activate_by_signed_key()", argv[6]);
|
||||||
#endif
|
#endif
|
||||||
} else
|
} else
|
||||||
r = crypt_activate_by_volume_key(cd, argv[2], m, l, CRYPT_ACTIVATE_READONLY);
|
r = crypt_activate_by_volume_key(cd, argv[2], m, l, arg_activate_flags);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to set up verity device: %m");
|
return log_error_errno(r, "Failed to set up verity device: %m");
|
||||||
|
|
||||||
|
@ -326,6 +326,7 @@ systemd.unit=
|
|||||||
systemd.verity=
|
systemd.verity=
|
||||||
systemd.verity_root_data=
|
systemd.verity_root_data=
|
||||||
systemd.verity_root_hash=
|
systemd.verity_root_hash=
|
||||||
|
systemd.verity_root_options=
|
||||||
systemd.volatile=
|
systemd.volatile=
|
||||||
systemd.wants=
|
systemd.wants=
|
||||||
systemd.watchdog_device=
|
systemd.watchdog_device=
|
||||||
|
@ -10,6 +10,9 @@ units = [
|
|||||||
['cryptsetup-pre.target', 'HAVE_LIBCRYPTSETUP'],
|
['cryptsetup-pre.target', 'HAVE_LIBCRYPTSETUP'],
|
||||||
['cryptsetup.target', 'HAVE_LIBCRYPTSETUP',
|
['cryptsetup.target', 'HAVE_LIBCRYPTSETUP',
|
||||||
'sysinit.target.wants/'],
|
'sysinit.target.wants/'],
|
||||||
|
['veritysetup-pre.target', 'HAVE_LIBCRYPTSETUP'],
|
||||||
|
['veritysetup.target', 'HAVE_LIBCRYPTSETUP',
|
||||||
|
'sysinit.target.wants/'],
|
||||||
['dev-hugepages.mount', '',
|
['dev-hugepages.mount', '',
|
||||||
'sysinit.target.wants/'],
|
'sysinit.target.wants/'],
|
||||||
['dev-mqueue.mount', '',
|
['dev-mqueue.mount', '',
|
||||||
@ -62,6 +65,8 @@ units = [
|
|||||||
'ctrl-alt-del.target' + (with_runlevels ? ' runlevel6.target' : '')],
|
'ctrl-alt-del.target' + (with_runlevels ? ' runlevel6.target' : '')],
|
||||||
['remote-cryptsetup.target', 'HAVE_LIBCRYPTSETUP',
|
['remote-cryptsetup.target', 'HAVE_LIBCRYPTSETUP',
|
||||||
'initrd-root-device.target.wants/'],
|
'initrd-root-device.target.wants/'],
|
||||||
|
['remote-veritysetup.target', 'HAVE_LIBCRYPTSETUP',
|
||||||
|
'initrd-root-device.target.wants/'],
|
||||||
['remote-fs-pre.target', ''],
|
['remote-fs-pre.target', ''],
|
||||||
['remote-fs.target', ''],
|
['remote-fs.target', ''],
|
||||||
['rescue.target', '',
|
['rescue.target', '',
|
||||||
|
18
units/remote-veritysetup.target
Normal file
18
units/remote-veritysetup.target
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
#
|
||||||
|
# This file is part of systemd.
|
||||||
|
#
|
||||||
|
# systemd is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Remote Verity Integrity Protected Volumes
|
||||||
|
Documentation=man:systemd.special(7)
|
||||||
|
After=remote-fs-pre.target veritysetup-pre.target
|
||||||
|
DefaultDependencies=no
|
||||||
|
Conflicts=shutdown.target
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
14
units/veritysetup-pre.target
Normal file
14
units/veritysetup-pre.target
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
#
|
||||||
|
# This file is part of systemd.
|
||||||
|
#
|
||||||
|
# systemd is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Local Verity Integrity Protected Volumes (Pre)
|
||||||
|
Documentation=man:systemd.special(7)
|
||||||
|
RefuseManualStart=yes
|
||||||
|
Before=veritysetup.target
|
12
units/veritysetup.target
Normal file
12
units/veritysetup.target
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
#
|
||||||
|
# This file is part of systemd.
|
||||||
|
#
|
||||||
|
# systemd is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Local Verity Integrity Protected Volumes
|
||||||
|
Documentation=man:systemd.special(7)
|
Loading…
Reference in New Issue
Block a user