mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-23 17:34:00 +03:00
verity: add support for setting up verity-protected root disks in the initrd
This adds a generator and a small service that will look for "roothash=" on the kernel command line and use it for setting up a very partition for the root device. This provides similar functionality to nspawn's existing --roothash= switch.
This commit is contained in:
parent
72e18a98ba
commit
2f3dfc6fb4
2
.gitignore
vendored
2
.gitignore
vendored
@ -126,6 +126,8 @@
|
|||||||
/systemd-update-utmp
|
/systemd-update-utmp
|
||||||
/systemd-user-sessions
|
/systemd-user-sessions
|
||||||
/systemd-vconsole-setup
|
/systemd-vconsole-setup
|
||||||
|
/systemd-veritysetup
|
||||||
|
/systemd-veritysetup-generator
|
||||||
/systemd-volatile-root
|
/systemd-volatile-root
|
||||||
/tags
|
/tags
|
||||||
/test-acd
|
/test-acd
|
||||||
|
@ -2276,13 +2276,20 @@ if HAVE_LIBCRYPTSETUP
|
|||||||
MANPAGES += \
|
MANPAGES += \
|
||||||
man/crypttab.5 \
|
man/crypttab.5 \
|
||||||
man/systemd-cryptsetup-generator.8 \
|
man/systemd-cryptsetup-generator.8 \
|
||||||
man/systemd-cryptsetup@.service.8
|
man/systemd-cryptsetup@.service.8 \
|
||||||
|
man/systemd-veritysetup-generator.8 \
|
||||||
|
man/systemd-veritysetup@.service.8
|
||||||
MANPAGES_ALIAS += \
|
MANPAGES_ALIAS += \
|
||||||
man/systemd-cryptsetup.8
|
man/systemd-cryptsetup.8 \
|
||||||
|
man/systemd-veritysetup.8
|
||||||
man/systemd-cryptsetup.8: man/systemd-cryptsetup@.service.8
|
man/systemd-cryptsetup.8: man/systemd-cryptsetup@.service.8
|
||||||
|
man/systemd-veritysetup.8: man/systemd-veritysetup@.service.8
|
||||||
man/systemd-cryptsetup.html: man/systemd-cryptsetup@.service.html
|
man/systemd-cryptsetup.html: man/systemd-cryptsetup@.service.html
|
||||||
$(html-alias)
|
$(html-alias)
|
||||||
|
|
||||||
|
man/systemd-veritysetup.html: man/systemd-veritysetup@.service.html
|
||||||
|
$(html-alias)
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_MICROHTTPD
|
if HAVE_MICROHTTPD
|
||||||
@ -2810,6 +2817,8 @@ EXTRA_DIST += \
|
|||||||
man/systemd-update-utmp.service.xml \
|
man/systemd-update-utmp.service.xml \
|
||||||
man/systemd-user-sessions.service.xml \
|
man/systemd-user-sessions.service.xml \
|
||||||
man/systemd-vconsole-setup.service.xml \
|
man/systemd-vconsole-setup.service.xml \
|
||||||
|
man/systemd-veritysetup-generator.xml \
|
||||||
|
man/systemd-veritysetup@.service.xml \
|
||||||
man/systemd-volatile-root.service.xml \
|
man/systemd-volatile-root.service.xml \
|
||||||
man/systemd.automount.xml \
|
man/systemd.automount.xml \
|
||||||
man/systemd.device.xml \
|
man/systemd.device.xml \
|
||||||
|
23
Makefile.am
23
Makefile.am
@ -4833,10 +4833,12 @@ EXTRA_DIST += \
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
if HAVE_LIBCRYPTSETUP
|
if HAVE_LIBCRYPTSETUP
|
||||||
rootlibexec_PROGRAMS += \
|
rootlibexec_PROGRAMS += \
|
||||||
systemd-cryptsetup
|
systemd-cryptsetup \
|
||||||
|
systemd-veritysetup
|
||||||
|
|
||||||
systemgenerator_PROGRAMS += \
|
systemgenerator_PROGRAMS += \
|
||||||
systemd-cryptsetup-generator
|
systemd-cryptsetup-generator \
|
||||||
|
systemd-veritysetup-generator
|
||||||
|
|
||||||
dist_systemunit_DATA += \
|
dist_systemunit_DATA += \
|
||||||
units/cryptsetup.target \
|
units/cryptsetup.target \
|
||||||
@ -4859,6 +4861,23 @@ systemd_cryptsetup_generator_SOURCES = \
|
|||||||
systemd_cryptsetup_generator_LDADD = \
|
systemd_cryptsetup_generator_LDADD = \
|
||||||
libsystemd-shared.la
|
libsystemd-shared.la
|
||||||
|
|
||||||
|
systemd_veritysetup_SOURCES = \
|
||||||
|
src/veritysetup/veritysetup.c
|
||||||
|
|
||||||
|
systemd_veritysetup_CFLAGS = \
|
||||||
|
$(AM_CFLAGS) \
|
||||||
|
$(LIBCRYPTSETUP_CFLAGS)
|
||||||
|
|
||||||
|
systemd_veritysetup_LDADD = \
|
||||||
|
libsystemd-shared.la \
|
||||||
|
$(LIBCRYPTSETUP_LIBS)
|
||||||
|
|
||||||
|
systemd_veritysetup_generator_SOURCES = \
|
||||||
|
src/veritysetup/veritysetup-generator.c
|
||||||
|
|
||||||
|
systemd_veritysetup_generator_LDADD = \
|
||||||
|
libsystemd-shared.la
|
||||||
|
|
||||||
SYSINIT_TARGET_WANTS += \
|
SYSINIT_TARGET_WANTS += \
|
||||||
cryptsetup.target
|
cryptsetup.target
|
||||||
|
|
||||||
|
@ -333,6 +333,19 @@
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>roothash=</varname></term>
|
||||||
|
<term><varname>systemd.verity=</varname></term>
|
||||||
|
<term><varname>rd.systemd.verity=</varname></term>
|
||||||
|
<term><varname>systemd.verity_root_data=</varname></term>
|
||||||
|
<term><varname>systemd.verity_root_hash=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Configures the integrity protection root hash for the root file system, and other related
|
||||||
|
parameters. For details, see
|
||||||
|
<citerefentry><refentrytitle>systemd-veritysetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>systemd.gpt_auto=</varname></term>
|
<term><varname>systemd.gpt_auto=</varname></term>
|
||||||
<term><varname>rd.systemd.gpt_auto=</varname></term>
|
<term><varname>rd.systemd.gpt_auto=</varname></term>
|
||||||
@ -402,6 +415,7 @@
|
|||||||
<citerefentry><refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
<citerefentry project='die-net'><refentrytitle>plymouth</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
<citerefentry project='die-net'><refentrytitle>plymouth</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>systemd-cryptsetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>systemd-cryptsetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
|
<citerefentry><refentrytitle>systemd-veritysetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>systemd-volatile-root.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>systemd-volatile-root.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
|
122
man/systemd-veritysetup-generator.xml
Normal file
122
man/systemd-veritysetup-generator.xml
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--*-nxml-*-->
|
||||||
|
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||||
|
<!--
|
||||||
|
This file is part of systemd.
|
||||||
|
|
||||||
|
Copyright 2016 Lennart Poettering
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
systemd is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
<refentry id="systemd-veritysetup-generator" conditional='HAVE_LIBCRYPTSETUP'>
|
||||||
|
|
||||||
|
<refentryinfo>
|
||||||
|
<title>systemd-veritysetup-generator</title>
|
||||||
|
<productname>systemd</productname>
|
||||||
|
|
||||||
|
<authorgroup>
|
||||||
|
<author>
|
||||||
|
<contrib>Developer</contrib>
|
||||||
|
<firstname>Lennart</firstname>
|
||||||
|
<surname>Poettering</surname>
|
||||||
|
<email>lennart@poettering.net</email>
|
||||||
|
</author>
|
||||||
|
</authorgroup>
|
||||||
|
</refentryinfo>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>systemd-veritysetup-generator</refentrytitle>
|
||||||
|
<manvolnum>8</manvolnum>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>systemd-veritysetup-generator</refname>
|
||||||
|
<refpurpose>Unit generator for integrity protected block devices</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<para><filename>/usr/lib/systemd/system-generators/systemd-veritysetup-generator</filename></para>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para><filename>systemd-veritysetup-generator</filename> is a generator that translates kernel command line options
|
||||||
|
configuring integrity protected block devices (verity) into native systemd units early at boot and when
|
||||||
|
configuration of the system manager is reloaded. This will create
|
||||||
|
<citerefentry><refentrytitle>systemd-veritysetup@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
|
units as necessary.</para>
|
||||||
|
|
||||||
|
<para>Currently, only a single verity device may be se up with this generator, backing the root file system of the
|
||||||
|
OS.</para>
|
||||||
|
|
||||||
|
<para><filename>systemd-veritysetup-generator</filename> implements
|
||||||
|
<citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Kernel Command Line</title>
|
||||||
|
|
||||||
|
<para><filename>systemd-veritysetup-generator</filename>
|
||||||
|
understands the following kernel command line parameters:</para>
|
||||||
|
|
||||||
|
<variablelist class='kernel-commandline-options'>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>systemd.verity=</varname></term>
|
||||||
|
<term><varname>rd.systemd.verity=</varname></term>
|
||||||
|
|
||||||
|
<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
|
||||||
|
(initrd) while <varname>systemd.verity=</varname> is honored by both the host system and the
|
||||||
|
initrd. </para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>roothash=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a root hash value for the root file system. Expects a hash value formatted in hexadecimal
|
||||||
|
characters, of the appropriate length (i.e. most likely 256 bit/64 characters, or longer). If not specified via
|
||||||
|
<varname>systemd.verity_root_data=</varname> and <varname>systemd.verity_root_hash=</varname>, the hash and
|
||||||
|
data devices to use are automatically derived from the specified hash value. Specifically, the data partition
|
||||||
|
device is looked for under a GPT partition UUID derived from the first 128bit of the root hash, the hash
|
||||||
|
partition device is looked for under a GPT partition UUID derived from the last 128bit of the root hash. Hence
|
||||||
|
it is usually sufficient to specify the root hash to boot from an integrity protected root file system, as
|
||||||
|
device paths are automatically determined from it — as long as the partition table is properly set up.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>systemd.verity_root_data=</varname></term>
|
||||||
|
<term><varname>systemd.verity_root_hash=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>These two settings take block device paths as arguments, and may be use to explicitly configure
|
||||||
|
the data partition and hash partition to use for setting up the integrity protection for the root file
|
||||||
|
system. If not specified, these paths are automatically derived from the <varname>roothash=</varname> argument
|
||||||
|
(see above).</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</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 project='die-net'><refentrytitle>veritysetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
|
<citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
75
man/systemd-veritysetup@.service.xml
Normal file
75
man/systemd-veritysetup@.service.xml
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--*-nxml-*-->
|
||||||
|
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||||
|
<!--
|
||||||
|
This file is part of systemd.
|
||||||
|
|
||||||
|
Copyright 2016 Lennart Poettering
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
systemd is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
<refentry id="systemd-veritysetup@.service" conditional='HAVE_LIBCRYPTSETUP'>
|
||||||
|
|
||||||
|
<refentryinfo>
|
||||||
|
<title>systemd-veritysetup@.service</title>
|
||||||
|
<productname>systemd</productname>
|
||||||
|
|
||||||
|
<authorgroup>
|
||||||
|
<author>
|
||||||
|
<contrib>Developer</contrib>
|
||||||
|
<firstname>Lennart</firstname>
|
||||||
|
<surname>Poettering</surname>
|
||||||
|
<email>lennart@poettering.net</email>
|
||||||
|
</author>
|
||||||
|
</authorgroup>
|
||||||
|
</refentryinfo>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>systemd-veritysetup@.service</refentrytitle>
|
||||||
|
<manvolnum>8</manvolnum>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>systemd-veritysetup@.service</refname>
|
||||||
|
<refname>systemd-veritysetup</refname>
|
||||||
|
<refpurpose>Disk integrity protection logic</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<para><filename>systemd-veritysetup@.service</filename></para>
|
||||||
|
<para><filename>/usr/lib/systemd/systemd-veritysetup</filename></para>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para><filename>systemd-veritysetup@.service</filename> is a service responsible for setting up integrity
|
||||||
|
protection (verity) block devices. It should be instantiated for each device that requires integrity
|
||||||
|
protection.</para>
|
||||||
|
|
||||||
|
<para>At early boot and when the system manager configuration is reloaded kernel command line configuration for
|
||||||
|
integrity protected block devices is translated into <filename>systemd-veritysetup@.service</filename> units by
|
||||||
|
<citerefentry><refentrytitle>systemd-veritysetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See Also</title>
|
||||||
|
<para>
|
||||||
|
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||||
|
<citerefentry><refentrytitle>systemd-veritysetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
|
<citerefentry project='die-net'><refentrytitle>veritysetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
@ -50,6 +50,7 @@ static bool arg_fstab_enabled = true;
|
|||||||
static char *arg_root_what = NULL;
|
static char *arg_root_what = NULL;
|
||||||
static char *arg_root_fstype = NULL;
|
static char *arg_root_fstype = NULL;
|
||||||
static char *arg_root_options = NULL;
|
static char *arg_root_options = NULL;
|
||||||
|
static char *arg_root_hash = NULL;
|
||||||
static int arg_root_rw = -1;
|
static int arg_root_rw = -1;
|
||||||
static char *arg_usr_what = NULL;
|
static char *arg_usr_what = NULL;
|
||||||
static char *arg_usr_fstype = NULL;
|
static char *arg_usr_fstype = NULL;
|
||||||
@ -697,6 +698,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
|
|
||||||
free(arg_root_options);
|
free(arg_root_options);
|
||||||
arg_root_options = o;
|
arg_root_options = o;
|
||||||
|
} else if (streq(key, "roothash")) {
|
||||||
|
|
||||||
|
if (proc_cmdline_value_missing(key, value))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (free_and_strdup(&arg_root_hash, value) < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
} else if (streq(key, "mount.usr")) {
|
} else if (streq(key, "mount.usr")) {
|
||||||
|
|
||||||
@ -749,6 +757,24 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int determine_root(void) {
|
||||||
|
/* If we have a root hash but no root device then Verity is used, and we use the "root" DM device as root. */
|
||||||
|
|
||||||
|
if (arg_root_what)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!arg_root_hash)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
arg_root_what = strdup("/dev/mapper/root");
|
||||||
|
if (!arg_root_what)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
log_info("Using verity root device %s.", arg_root_what);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
@ -772,6 +798,8 @@ int main(int argc, char *argv[]) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
|
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
|
||||||
|
|
||||||
|
(void) determine_root();
|
||||||
|
|
||||||
/* Always honour root= and usr= in the kernel command line if we are in an initrd */
|
/* Always honour root= and usr= in the kernel command line if we are in an initrd */
|
||||||
if (in_initrd()) {
|
if (in_initrd()) {
|
||||||
int k;
|
int k;
|
||||||
@ -812,6 +840,7 @@ int main(int argc, char *argv[]) {
|
|||||||
free(arg_root_what);
|
free(arg_root_what);
|
||||||
free(arg_root_fstype);
|
free(arg_root_fstype);
|
||||||
free(arg_root_options);
|
free(arg_root_options);
|
||||||
|
free(arg_root_hash);
|
||||||
|
|
||||||
free(arg_usr_what);
|
free(arg_usr_what);
|
||||||
free(arg_usr_fstype);
|
free(arg_usr_fstype);
|
||||||
|
@ -718,6 +718,15 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
|
|
||||||
arg_root_enabled = streq(value, "gpt-auto");
|
arg_root_enabled = streq(value, "gpt-auto");
|
||||||
|
|
||||||
|
} else if (streq(key, "roothash")) {
|
||||||
|
|
||||||
|
if (proc_cmdline_value_missing(key, value))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Disable root disk logic if there's roothash= defined (i.e. verity enabled) */
|
||||||
|
|
||||||
|
arg_root_enabled = false;
|
||||||
|
|
||||||
} else if (streq(key, "rw") && !value)
|
} else if (streq(key, "rw") && !value)
|
||||||
arg_root_rw = true;
|
arg_root_rw = true;
|
||||||
else if (streq(key, "ro") && !value)
|
else if (streq(key, "ro") && !value)
|
||||||
|
1
src/veritysetup/Makefile
Symbolic link
1
src/veritysetup/Makefile
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../Makefile
|
253
src/veritysetup/veritysetup-generator.c
Normal file
253
src/veritysetup/veritysetup-generator.c
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
/***
|
||||||
|
This file is part of systemd.
|
||||||
|
|
||||||
|
Copyright 2016 Lennart Poettering
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
systemd is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
***/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "alloc-util.h"
|
||||||
|
#include "fd-util.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "fstab-util.h"
|
||||||
|
#include "hexdecoct.h"
|
||||||
|
#include "id128-util.h"
|
||||||
|
#include "mkdir.h"
|
||||||
|
#include "parse-util.h"
|
||||||
|
#include "proc-cmdline.h"
|
||||||
|
#include "string-util.h"
|
||||||
|
#include "unit-name.h"
|
||||||
|
|
||||||
|
static char *arg_dest = NULL;
|
||||||
|
static bool arg_enabled = true;
|
||||||
|
static char *arg_root_hash = NULL;
|
||||||
|
static char *arg_data_what = NULL;
|
||||||
|
static char *arg_hash_what = NULL;
|
||||||
|
|
||||||
|
static int create_device(void) {
|
||||||
|
_cleanup_free_ char *u = NULL, *v = NULL, *d = NULL, *e = NULL;
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
const char *p, *to;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* If all three pieces of information are missing, then verity is turned off */
|
||||||
|
if (!arg_root_hash && !arg_data_what && !arg_hash_what)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* if one of them is missing however, the data is simply incomplete and this is an error */
|
||||||
|
if (!arg_root_hash)
|
||||||
|
log_error("Verity information incomplete, root hash unspecified.");
|
||||||
|
if (!arg_data_what)
|
||||||
|
log_error("Verity information incomplete, root data device unspecified.");
|
||||||
|
if (!arg_hash_what)
|
||||||
|
log_error("Verity information incomplete, root hash device unspecified.");
|
||||||
|
|
||||||
|
if (!arg_root_hash || !arg_data_what || !arg_hash_what)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
log_debug("Using root verity data device %s,\n"
|
||||||
|
" hash device %s,\n"
|
||||||
|
" and root hash %s.", arg_data_what, arg_hash_what, arg_root_hash);
|
||||||
|
|
||||||
|
p = strjoina(arg_dest, "/systemd-veritysetup@root.service");
|
||||||
|
|
||||||
|
u = fstab_node_to_udev_node(arg_data_what);
|
||||||
|
if (!u)
|
||||||
|
return log_oom();
|
||||||
|
v = fstab_node_to_udev_node(arg_hash_what);
|
||||||
|
if (!v)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = unit_name_from_path(u, ".device", &d);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to to generate unit name: %m");
|
||||||
|
r = unit_name_from_path(v, ".device", &e);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to to generate unit name: %m");
|
||||||
|
|
||||||
|
f = fopen(p, "wxe");
|
||||||
|
if (!f)
|
||||||
|
return log_error_errno(errno, "Failed to create unit file %s: %m", p);
|
||||||
|
|
||||||
|
fprintf(f,
|
||||||
|
"# Automatically generated by systemd-veritysetup-generator\n\n"
|
||||||
|
"[Unit]\n"
|
||||||
|
"Description=Integrity Protection Setup for %%I\n"
|
||||||
|
"Documentation=man:systemd-veritysetup-generator(8) man:systemd-veritysetup@.service(8)\n"
|
||||||
|
"SourcePath=/proc/cmdline\n"
|
||||||
|
"DefaultDependencies=no\n"
|
||||||
|
"Conflicts=umount.target\n"
|
||||||
|
"BindsTo=%s %s\n"
|
||||||
|
"IgnoreOnIsolate=true\n"
|
||||||
|
"After=cryptsetup-pre.target %s %s\n"
|
||||||
|
"Before=cryptsetup.target umount.target\n"
|
||||||
|
"\n[Service]\n"
|
||||||
|
"Type=oneshot\n"
|
||||||
|
"RemainAfterExit=yes\n"
|
||||||
|
"ExecStart=" ROOTLIBEXECDIR "/systemd-veritysetup attach root '%s' '%s' '%s'\n"
|
||||||
|
"ExecStop=" ROOTLIBEXECDIR "/systemd-veritysetup detach root\n",
|
||||||
|
d, e,
|
||||||
|
d, e,
|
||||||
|
u, v, arg_root_hash);
|
||||||
|
|
||||||
|
r = fflush_and_check(f);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to write file %s: %m", p);
|
||||||
|
|
||||||
|
to = strjoina(arg_dest, "/cryptsetup.target.requires/systemd-veritysetup@root.service");
|
||||||
|
|
||||||
|
(void) mkdir_parents(to, 0755);
|
||||||
|
if (symlink("../systemd-veritysetup@root.service", to) < 0)
|
||||||
|
return log_error_errno(errno, "Failed to create symlink %s: %m", to);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (streq(key, "systemd.verity")) {
|
||||||
|
|
||||||
|
r = value ? parse_boolean(value) : 1;
|
||||||
|
if (r < 0)
|
||||||
|
log_warning("Failed to parse verity= kernel command line switch %s. Ignoring.", value);
|
||||||
|
else
|
||||||
|
arg_enabled = r;
|
||||||
|
|
||||||
|
} else if (streq(key, "roothash")) {
|
||||||
|
|
||||||
|
if (proc_cmdline_value_missing(key, value))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = free_and_strdup(&arg_root_hash, value);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
} else if (streq(key, "systemd.verity_root_data")) {
|
||||||
|
|
||||||
|
if (proc_cmdline_value_missing(key, value))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = free_and_strdup(&arg_data_what, value);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
} else if (streq(key, "systemd.verity_root_hash")) {
|
||||||
|
|
||||||
|
if (proc_cmdline_value_missing(key, value))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = free_and_strdup(&arg_hash_what, value);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int determine_devices(void) {
|
||||||
|
_cleanup_free_ void *m = NULL;
|
||||||
|
sd_id128_t root_uuid, verity_uuid;
|
||||||
|
char ids[37];
|
||||||
|
size_t l;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Try to automatically derive the root data and hash device paths from the root hash */
|
||||||
|
|
||||||
|
if (!arg_root_hash)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (arg_data_what && arg_hash_what)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = unhexmem(arg_root_hash, strlen(arg_root_hash), &m, &l);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse root hash: %s", arg_root_hash);
|
||||||
|
if (l < sizeof(sd_id128_t)) {
|
||||||
|
log_debug("Root hash is shorter than 128 bits (32 characters), ignoring for discovering verity partition.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!arg_data_what) {
|
||||||
|
memcpy(&root_uuid, m, sizeof(root_uuid));
|
||||||
|
|
||||||
|
arg_data_what = strjoin("/dev/disk/by-partuuid/", id128_to_uuid_string(root_uuid, ids));
|
||||||
|
if (!arg_data_what)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!arg_hash_what) {
|
||||||
|
memcpy(&verity_uuid, (uint8_t*) m + l - sizeof(verity_uuid), sizeof(verity_uuid));
|
||||||
|
|
||||||
|
arg_hash_what = strjoin("/dev/disk/by-partuuid/", id128_to_uuid_string(verity_uuid, ids));
|
||||||
|
if (!arg_hash_what)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (argc > 1 && argc != 4) {
|
||||||
|
log_error("This program takes three or no arguments.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
arg_dest = argv[1];
|
||||||
|
|
||||||
|
log_set_target(LOG_TARGET_SAFE);
|
||||||
|
log_parse_environment();
|
||||||
|
log_open();
|
||||||
|
|
||||||
|
umask(0022);
|
||||||
|
|
||||||
|
r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "Failed to parse kernel command line: %m");
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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) {
|
||||||
|
r = 0;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = determine_devices();
|
||||||
|
if (r < 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
r = create_device();
|
||||||
|
if (r < 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
|
||||||
|
finish:
|
||||||
|
free(arg_root_hash);
|
||||||
|
free(arg_data_what);
|
||||||
|
free(arg_hash_what);
|
||||||
|
|
||||||
|
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
|
}
|
154
src/veritysetup/veritysetup.c
Normal file
154
src/veritysetup/veritysetup.c
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/***
|
||||||
|
This file is part of systemd.
|
||||||
|
|
||||||
|
Copyright 2016 Lennart Poettering
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
systemd is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
***/
|
||||||
|
|
||||||
|
#include <libcryptsetup.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "hexdecoct.h"
|
||||||
|
#include "string-util.h"
|
||||||
|
#include "alloc-util.h"
|
||||||
|
|
||||||
|
static char *arg_root_hash = NULL;
|
||||||
|
static char *arg_data_what = NULL;
|
||||||
|
static char *arg_hash_what = NULL;
|
||||||
|
|
||||||
|
static int help(void) {
|
||||||
|
printf("%s attach VOLUME DATADEVICE HASHDEVICE ROOTHASH\n"
|
||||||
|
"%s detach VOLUME\n\n"
|
||||||
|
"Attaches or detaches an integrity protected block device.\n",
|
||||||
|
program_invocation_short_name,
|
||||||
|
program_invocation_short_name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_glue(int level, const char *msg, void *usrptr) {
|
||||||
|
log_debug("%s", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
struct crypt_device *cd = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
r = help();
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
log_error("This program requires at least two arguments.");
|
||||||
|
r = -EINVAL;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_set_target(LOG_TARGET_AUTO);
|
||||||
|
log_parse_environment();
|
||||||
|
log_open();
|
||||||
|
|
||||||
|
umask(0022);
|
||||||
|
|
||||||
|
if (streq(argv[1], "attach")) {
|
||||||
|
_cleanup_free_ void *m = NULL;
|
||||||
|
crypt_status_info status;
|
||||||
|
size_t l;
|
||||||
|
|
||||||
|
if (argc < 6) {
|
||||||
|
log_error("attach requires at least two arguments.");
|
||||||
|
r = -EINVAL;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = unhexmem(argv[5], strlen(argv[5]), &m, &l);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error("Failed to parse root hash.");
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = crypt_init(&cd, argv[4]);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to open verity device %s: %m", argv[4]);
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypt_set_log_callback(cd, log_glue, NULL);
|
||||||
|
|
||||||
|
status = crypt_status(cd, argv[2]);
|
||||||
|
if (status == CRYPT_ACTIVE || status == CRYPT_BUSY) {
|
||||||
|
log_info("Volume %s already active.", argv[2]);
|
||||||
|
r = 0;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = crypt_load(cd, CRYPT_VERITY, NULL);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to load verity superblock: %m");
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = crypt_set_data_device(cd, argv[3]);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to configure data device: %m");
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = crypt_activate_by_volume_key(cd, argv[2], m, l, CRYPT_ACTIVATE_READONLY);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to set up verity device: %m");
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (streq(argv[1], "detach")) {
|
||||||
|
|
||||||
|
r = crypt_init_by_name(&cd, argv[2]);
|
||||||
|
if (r == -ENODEV) {
|
||||||
|
log_info("Volume %s already inactive.", argv[2]);
|
||||||
|
goto finish;
|
||||||
|
} else if (r < 0) {
|
||||||
|
log_error_errno(r, "crypt_init_by_name() failed: %m");
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypt_set_log_callback(cd, log_glue, NULL);
|
||||||
|
|
||||||
|
r = crypt_deactivate(cd, argv[2]);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to deactivate: %m");
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
log_error("Unknown verb %s.", argv[1]);
|
||||||
|
r = -EINVAL;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
|
||||||
|
finish:
|
||||||
|
if (cd)
|
||||||
|
crypt_free(cd);
|
||||||
|
|
||||||
|
free(arg_root_hash);
|
||||||
|
free(arg_data_what);
|
||||||
|
free(arg_hash_what);
|
||||||
|
|
||||||
|
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user