]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #14717 from yuwata/network-radv-dns-link-local
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 4 Feb 2020 16:47:17 +0000 (17:47 +0100)
committerGitHub <noreply@github.com>
Tue, 4 Feb 2020 16:47:17 +0000 (17:47 +0100)
network: make DNS= in [IPv6PrefixDelegation] section take special value '_link_local'

23 files changed:
NEWS
TODO
man/systemd.special.xml
meson.build
meson_options.txt
presets/90-systemd.preset
presets/user/90-systemd.preset
src/boot/efi/meson.build
src/core/mount.c
src/core/swap.c
src/core/unit.c
src/core/unit.h
src/cryptsetup/cryptsetup-generator.c
src/fstab-generator/fstab-generator.c
src/gpt-auto-generator/gpt-auto-generator.c
src/hibernate-resume/hibernate-resume-generator.c
src/network/networkd-network.c
src/network/test-network.c
src/shared/generator.c
src/shared/generator.h
src/udev/net/link-config.c
units/blockdev@.target [new file with mode: 0644]
units/meson.build

diff --git a/NEWS b/NEWS
index 74dc7e368e53ffcf631f0766cd79f361f52b81f4..d3d7d6f549757b5aaa49c8bb02d94fc2cdef0705 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -257,13 +257,13 @@ CHANGES WITH 245 in spe:
           permanent MAC address of a network device even if a randomized MAC
           address is used.
 
-       * systemd-logind will now validate access to the operation for changing
-         virtual terminals via a PolicyKit action. By default only users with
-         at least one session on a local VT will get access to the method call.
+        * systemd-logind will now validate access to the operation for changing
+          virtual terminals via a PolicyKit action. By default only users with
+          at least one session on a local VT will get access to the method call.
 
-       * When systemd sets up PAM sessions that invoked service processes shall
-         run in, the pam_setcred() API is now invoked, thus permitting PAM
-         modules to set additional credentials for the processes.
+        * When systemd sets up PAM sessions that invoked service processes shall
+          run in, the pam_setcred() API is now invoked, thus permitting PAM
+          modules to set additional credentials for the processes.
 
         …
 
diff --git a/TODO b/TODO
index a9902ddff2d5ad98b8858a7fdd3066811606df46..4a6c8d3512d4e6e8600552fd804b7bb3e9687b77 100644 (file)
--- a/TODO
+++ b/TODO
@@ -44,6 +44,9 @@ Features:
 * cryptsetup: allow encoding key directly in /etc/crypttab, maybe with a
   "base64:" prefix. Useful in particular for pkcs11 mode.
 
+* cryptsetup: reimplement the mkswap/mke2fs in cryptsetup-generator to use
+  systemd-makefs.service instead.
+
 * socket units: allow creating a udev monitor socket with ListenDevices= or so,
   with matches, then actviate app thorugh that passing socket oveer
 
index c839af1842c85832519f61f509f40911b7651d9f..f393283a1d56cd99d3443c89afc112f2fdb1fa30 100644 (file)
@@ -26,6 +26,7 @@
     <filename>cryptsetup-pre.target</filename>,
     <filename>cryptsetup.target</filename>,
     <filename>ctrl-alt-del.target</filename>,
+    <filename>blockdev@.target</filename>,
     <filename>boot-complete.target</filename>,
     <filename>default.target</filename>,
     <filename>emergency.target</filename>,
       not useful as only unit within a transaction.</para>
 
       <variablelist>
+        <varlistentry>
+          <term><filename>blockdev@.target</filename></term>
+          <listitem><para>This template unit may be used to order mount units and other consumers of block
+          devices against services that synthesize these block devices. This is intended to be used to order
+          storage services (such as
+          <citerefentry><refentrytitle>systemd-cryptsetup@.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
+          that allocate and manage a virtual block device against mount units and other consumers of
+          it. Specifically, the storage services are supposed to be orderd before an instance of
+          <filename>blockdev@.target</filename>, and the mount unit (or other consuming unit, such as a swap
+          unit) after it. The ordering is particular relevant during shutdown, as it ensures that the mount
+          is deactivated first and the service backing the mount only deactivated after that completed. The
+          <filename>blockdev@.target</filename> instance should be pulled in via a <option>Wants=</option>
+          dependency of the storage daemon and thus generally not be part of any transaction unless a storage
+          daemon is used. The instance name for instances of this template unit is supposed to be the
+          properly escaped bock device node path, e.g. <filename>blockdev@dev-mapper-foobar.target</filename>
+          for a storage device <filename>/dev/mapper/foobar</filename>.</para></listitem>
+        </varlistentry>
         <varlistentry>
           <term><filename>cryptsetup-pre.target</filename></term>
           <listitem>
index 184dbf5d243d9ca7197e580edffcabca31d397ee..0779c5bd54c18a63d47e8b4e68f43ea1f5ae73df 100644 (file)
@@ -3369,8 +3369,8 @@ if conf.get('ENABLE_EFI') == 1
                 status += [
                         'EFI machine type:                  @0@'.format(EFI_MACHINE_TYPE_NAME),
                         'EFI CC                             @0@'.format(' '.join(efi_cc)),
-                        'EFI lib directory:                 @0@'.format(efi_libdir),
-                        'EFI lds directory:                 @0@'.format(efi_ldsdir),
+                        'EFI lds:                           @0@'.format(efi_lds),
+                        'EFI crt0:                          @0@'.format(efi_crt0),
                         'EFI include directory:             @0@'.format(efi_incdir)]
         endif
 endif
index d5b6f24344c2b9f96f4ab6ce245eb5bdbb3a727c..4f82479a9ba038f0d2450ff427a1dccf12bef0a5 100644 (file)
@@ -323,8 +323,6 @@ option('efi-ld', type : 'string',
        description : 'the linker to use for EFI modules')
 option('efi-libdir', type : 'string',
        description : 'path to the EFI lib directory')
-option('efi-ldsdir', type : 'string',
-       description : 'path to the EFI lds directory')
 option('efi-includedir', type : 'string', value : '/usr/include/efi',
        description : 'path to the EFI header directory')
 option('tpm-pcrindex', type : 'integer', value : 8,
index 11960e54236a42ca309298fae17cc70212a50508..4009cbb96e659b5a0c51a73cfef0d0067ac7a2e8 100644 (file)
@@ -7,8 +7,9 @@
 #  the Free Software Foundation; either version 2.1 of the License, or
 #  (at your option) any later version.
 
-# These ones should be enabled by default, even if distributions
-# generally follow a default-off policy.
+# Settings for systemd units distributed with systemd itself. Most of these
+# should be enabled by default, even if the distribution follows a general
+# default-off policy.
 
 enable remote-fs.target
 enable remote-cryptsetup.target
@@ -34,3 +35,18 @@ disable syslog.socket
 disable systemd-journal-gatewayd.*
 disable systemd-journal-remote.*
 disable systemd-journal-upload.*
+
+# Passive targets: always off by default, since they should only be pulled in
+# by dependent units.
+
+disable cryptsetup-pre.target
+disable getty-pre.target
+disable local-fs-pre.target
+disable network.target
+disable network-pre.target
+disable nss-lookup.target
+disable nss-user-lookup.target
+disable remote-fs-pre.target
+disable rpcbind.target
+disable time-set.target
+disable time-sync.target
index 22fe41fc337937ac0c34c65125263923cd62be16..fd402c8c11cf04fb01c6979e8c3113dd5e4e6feb 100644 (file)
@@ -7,8 +7,15 @@
 #  the Free Software Foundation; either version 2.1 of the License, or
 #  (at your option) any later version.
 
-# These ones should be enabled by default, even if distributions
-# generally follow a default-off policy.
+# Settings for systemd units distributed with systemd itself. These should be
+# enabled by default, even if the distribution follows a general default-off
+# policy.
 
 enable systemd-tmpfiles-setup.service
 enable systemd-tmpfiles-clean.timer
+
+# Passive targets: always off by default, since they should only be pulled in
+# by dependent units.
+
+disable graphical-session-pre.target
+disable graphical-session.target
index 3edabfedd536f2d199c3fcbdb3f19ab58b8b4b7c..c1fe04597bc66819b56e34e88644fd13f261d02e 100644 (file)
@@ -64,12 +64,19 @@ if conf.get('ENABLE_EFI') == 1 and get_option('gnu-efi') != 'false'
 
         efi_libdir = get_option('efi-libdir')
         if efi_libdir == ''
-                ret = run_command(efi_cc + ['-print-multi-os-directory'])
-                if ret.returncode() == 0
-                        path = join_paths('/usr/lib', ret.stdout().strip())
-                        ret = run_command('realpath', '-e', path)
-                        if ret.returncode() == 0
-                                efi_libdir = ret.stdout().strip()
+                # New location first introduced with gnu-efi 3.0.11
+                efi_libdir = join_paths('/usr/lib/gnuefi', EFI_MACHINE_TYPE_NAME)
+                cmd = run_command('test', '-e', efi_libdir)
+
+                if cmd.returncode() != 0
+                        # Fall back to the old approach
+                        cmd = run_command(efi_cc + ['-print-multi-os-directory'])
+                        if cmd.returncode() == 0
+                                path = join_paths('/usr/lib', cmd.stdout().strip())
+                                cmd = run_command('realpath', '-e', path)
+                                if cmd.returncode() == 0
+                                        efi_libdir = cmd.stdout().strip()
+                                endif
                         endif
                 endif
         endif
@@ -95,20 +102,35 @@ if have_gnu_efi
 
         objcopy = find_program('objcopy')
 
-        efi_ldsdir = get_option('efi-ldsdir')
-        arch_lds = 'elf_@0@_efi.lds'.format(gnu_efi_path_arch)
-        if efi_ldsdir == ''
-                efi_ldsdir = join_paths(efi_libdir, 'gnuefi')
-                cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds))
-                if cmd.returncode() != 0
-                        efi_ldsdir = efi_libdir
-                        cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds))
-                        if cmd.returncode() != 0
-                               error('Cannot find @0@'.format(arch_lds))
+        efi_location_map = [
+                # New locations first introduced with gnu-efi 3.0.11
+                [join_paths(efi_libdir, 'efi.lds'),
+                 join_paths(efi_libdir, 'crt0.o')],
+                # Older locations...
+                [join_paths(efi_libdir, 'gnuefi', 'elf_@0@_efi.lds'.format(gnu_efi_path_arch)),
+                 join_paths(efi_libdir, 'gnuefi', 'crt0-efi-@0@.o'.format(gnu_efi_path_arch))],
+                [join_paths(efi_libdir, 'elf_@0@_efi.lds'.format(gnu_efi_path_arch)),
+                 join_paths(efi_libdir, 'crt0-efi-@0@.o'.format(gnu_efi_path_arch))]]
+        efi_lds = ''
+        foreach location : efi_location_map
+                if efi_lds == ''
+                        cmd = run_command('test', '-f', location[0])
+                        if cmd.returncode() == 0
+                                efi_lds = location[0]
+                                efi_crt0 = location[1]
                         endif
                 endif
+        endforeach
+        if efi_lds == ''
+                if get_option('gnu-efi') == 'true'
+                        error('gnu-efi support requested, but cannot find efi.lds')
+                else
+                        have_gnu_efi = false
+                endif
         endif
+endif
 
+if have_gnu_efi
         compile_args = ['-Wall',
                         '-Wextra',
                         '-std=gnu90',
@@ -145,14 +167,13 @@ if have_gnu_efi
                 compile_args += ['-O2']
         endif
 
-        efi_ldflags = ['-T',
-                       join_paths(efi_ldsdir, arch_lds),
+        efi_ldflags = ['-T', efi_lds,
                        '-shared',
                        '-Bsymbolic',
                        '-nostdlib',
                        '-znocombreloc',
                        '-L', efi_libdir,
-                       join_paths(efi_ldsdir, 'crt0-efi-@0@.o'.format(gnu_efi_path_arch))]
+                       efi_crt0]
         if efi_arch == 'aarch64' or efi_arch == 'arm'
                 # Aarch64 and ARM32 don't have an EFI capable objcopy. Use 'binary'
                 # instead, and add required symbols manually.
@@ -219,11 +240,9 @@ if have_gnu_efi
                 set_variable(tuple[0].underscorify(), so)
                 set_variable(tuple[0].underscorify() + '_stub', stub)
         endforeach
-endif
 
-############################################################
+        ############################################################
 
-if have_gnu_efi
         test_efi_disk_img = custom_target(
                 'test-efi-disk.img',
                 input : [systemd_boot_so, stub_so_stub],
index 668c4d7e8955f89db286962623f340796ffddd04..1c4aefd734f3e01664f419b0f0d7c5e3b41ccec8 100644 (file)
@@ -217,7 +217,7 @@ static void mount_done(Unit *u) {
         m->timer_event_source = sd_event_source_unref(m->timer_event_source);
 }
 
-_pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
+static MountParameters* get_mount_parameters_fragment(Mount *m) {
         assert(m);
 
         if (m->from_fragment)
@@ -226,7 +226,7 @@ _pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
         return NULL;
 }
 
-_pure_ static MountParameters* get_mount_parameters(Mount *m) {
+static MountParameters* get_mount_parameters(Mount *m) {
         assert(m);
 
         if (m->from_proc_self_mountinfo)
@@ -342,20 +342,18 @@ static int mount_add_device_dependencies(Mount *m) {
         if (!is_device_path(p->what))
                 return 0;
 
-        /* /dev/root is a really weird thing, it's not a real device,
-         * but just a path the kernel exports for the root file system
-         * specified on the kernel command line. Ignore it here. */
-        if (path_equal(p->what, "/dev/root"))
+        /* /dev/root is a really weird thing, it's not a real device, but just a path the kernel exports for
+         * the root file system specified on the kernel command line. Ignore it here. */
+        if (PATH_IN_SET(p->what, "/dev/root", "/dev/nfs"))
                 return 0;
 
         if (path_equal(m->where, "/"))
                 return 0;
 
-        /* Mount units from /proc/self/mountinfo are not bound to devices
-         * by default since they're subject to races when devices are
-         * unplugged. But the user can still force this dep with an
-         * appropriate option (or udev property) so the mount units are
-         * automatically stopped when the device disappears suddenly. */
+        /* Mount units from /proc/self/mountinfo are not bound to devices by default since they're subject to
+         * races when devices are unplugged. But the user can still force this dep with an appropriate option
+         * (or udev property) so the mount units are automatically stopped when the device disappears
+         * suddenly. */
         dep = mount_is_bound_to_device(m) ? UNIT_BINDS_TO : UNIT_REQUIRES;
 
         /* We always use 'what' from /proc/self/mountinfo if mounted */
@@ -365,7 +363,7 @@ static int mount_add_device_dependencies(Mount *m) {
         if (r < 0)
                 return r;
 
-        return 0;
+        return unit_add_blockdev_dependency(UNIT(m), p->what, mask);
 }
 
 static int mount_add_quota_dependencies(Mount *m) {
index 473b3483ae777e113eafc8415179436d71833e26..fd2fa557dbf66b61b3331880518e52d962becb8a 100644 (file)
@@ -184,21 +184,45 @@ static int swap_arm_timer(Swap *s, usec_t usec) {
         return 0;
 }
 
+static SwapParameters* swap_get_parameters(Swap *s) {
+        assert(s);
+
+        if (s->from_proc_swaps)
+                return &s->parameters_proc_swaps;
+
+        if (s->from_fragment)
+                return &s->parameters_fragment;
+
+        return NULL;
+}
+
 static int swap_add_device_dependencies(Swap *s) {
+        UnitDependencyMask mask;
+        SwapParameters *p;
+        int r;
+
         assert(s);
 
         if (!s->what)
                 return 0;
 
-        if (!s->from_fragment)
+        p = swap_get_parameters(s);
+        if (!p)
                 return 0;
 
-        if (is_device_path(s->what))
-                return unit_add_node_dependency(UNIT(s), s->what, UNIT_BINDS_TO, UNIT_DEPENDENCY_FILE);
+        mask = s->from_proc_swaps ? UNIT_DEPENDENCY_PROC_SWAP : UNIT_DEPENDENCY_FILE;
+
+        if (is_device_path(p->what)) {
+                r = unit_add_node_dependency(UNIT(s), p->what, UNIT_REQUIRES, mask);
+                if (r < 0)
+                        return r;
+
+                return unit_add_blockdev_dependency(UNIT(s), p->what, mask);
+        }
 
-        /* File based swap devices need to be ordered after systemd-remount-fs.service,
-         * since they might need a writable file system. */
-        return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, true, UNIT_DEPENDENCY_FILE);
+        /* File based swap devices need to be ordered after systemd-remount-fs.service, since they might need
+         * a writable file system. */
+        return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, true, mask);
 }
 
 static int swap_add_default_dependencies(Swap *s) {
index 6b97c35ffa1ebd639ab9dd05d644bc26b8baeb53..3f616e7acf1c9a288cce0b30efe4484ff6d8bb7b 100644 (file)
@@ -3866,8 +3866,8 @@ int unit_deserialize_skip(FILE *f) {
 }
 
 int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, UnitDependencyMask mask) {
-        Unit *device;
         _cleanup_free_ char *e = NULL;
+        Unit *device;
         int r;
 
         assert(u);
@@ -3879,8 +3879,7 @@ int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, Unit
         if (!is_device_path(what))
                 return 0;
 
-        /* When device units aren't supported (such as in a
-         * container), don't create dependencies on them. */
+        /* When device units aren't supported (such as in a container), don't create dependencies on them. */
         if (!unit_type_supported(UNIT_DEVICE))
                 return 0;
 
@@ -3900,6 +3899,33 @@ int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, Unit
                                          device, true, mask);
 }
 
+int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask) {
+        _cleanup_free_ char *escaped = NULL, *target = NULL;
+        int r;
+
+        assert(u);
+
+        if (isempty(what))
+                return 0;
+
+        if (!path_startswith(what, "/dev/"))
+                return 0;
+
+        /* If we don't support devices, then also don't bother with blockdev@.target */
+        if (!unit_type_supported(UNIT_DEVICE))
+                return 0;
+
+        r = unit_name_path_escape(what, &escaped);
+        if (r < 0)
+                return r;
+
+        r = unit_name_build("blockdev", escaped, ".target", &target);
+        if (r < 0)
+                return r;
+
+        return unit_add_dependency_by_name(u, UNIT_AFTER, target, true, mask);
+}
+
 int unit_coldplug(Unit *u) {
         int r = 0, q;
         char **i;
index 68de900b0d523165ea86c1fbd44c869971e64122..38d681dfb86de30ebad091b39b755335ba52a356 100644 (file)
@@ -743,6 +743,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
 int unit_deserialize_skip(FILE *f);
 
 int unit_add_node_dependency(Unit *u, const char *what, UnitDependency d, UnitDependencyMask mask);
+int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask);
 
 int unit_coldplug(Unit *u);
 void unit_catchup(Unit *u);
index b87abe9ece0571de45e0347474ed0cabce47cda9..1deab765fbb94070fa4a247c99d4863ba4af2ea6 100644 (file)
@@ -99,7 +99,14 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key
         return 0;
 }
 
-static int generate_keydev_mount(const char *name, const char *keydev, const char *keydev_timeout, bool canfail, char **unit, char **mount) {
+static int generate_keydev_mount(
+                const char *name,
+                const char *keydev,
+                const char *keydev_timeout,
+                bool canfail,
+                char **unit,
+                char **mount) {
+
         _cleanup_free_ char *u = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         int r;
@@ -223,8 +230,8 @@ static int create_disk(
                 const char *options) {
 
         _cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL,
-                *keydev_mount = NULL, *keyfile_timeout_value = NULL, *password_escaped = NULL,
-                *filtered = NULL, *u_escaped = NULL, *filtered_escaped = NULL, *name_escaped = NULL, *header_path = NULL;
+                *keydev_mount = NULL, *keyfile_timeout_value = NULL,
+                *filtered = NULL, *u_escaped = NULL, *name_escaped = NULL, *header_path = NULL, *password_buffer = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         const char *dmname;
         bool noauto, nofail, tmp, swap, netdev, attach_in_initrd;
@@ -285,39 +292,29 @@ static int create_disk(
         if (r < 0)
                 return r;
 
-        fprintf(f,
-                "[Unit]\n"
-                "Description=Cryptography Setup for %%I\n"
-                "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n"
-                "SourcePath=%s\n"
-                "DefaultDependencies=no\n"
-                "IgnoreOnIsolate=true\n"
-                "After=%s\n",
-                arg_crypttab,
-                netdev ? "remote-fs-pre.target" : "cryptsetup-pre.target");
+        r = generator_write_cryptsetup_unit_section(f, arg_crypttab);
+        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 (password) {
-                password_escaped = specifier_escape(password);
-                if (!password_escaped)
-                        return log_oom();
-        }
-
         if (keydev) {
-                _cleanup_free_ char *unit = NULL, *p = NULL;
+                _cleanup_free_ char *unit = NULL;
 
                 r = generate_keydev_mount(name, keydev, keyfile_timeout_value, keyfile_can_timeout > 0, &unit, &keydev_mount);
                 if (r < 0)
                         return log_error_errno(r, "Failed to generate keydev mount unit: %m");
 
-                p = path_join(keydev_mount, password_escaped);
-                if (!p)
+                password_buffer = path_join(keydev_mount, password);
+                if (!password_buffer)
                         return log_oom();
 
-                free_and_replace(password_escaped, p);
+                password = password_buffer;
 
                 fprintf(f, "After=%s\n", unit);
                 if (keyfile_can_timeout > 0)
@@ -344,17 +341,13 @@ static int create_disk(
                         return r;
         }
 
-        if (path_startswith(u, "/dev/")) {
+        if (path_startswith(u, "/dev/"))
                 fprintf(f,
                         "BindsTo=%s\n"
                         "After=%s\n"
                         "Before=umount.target\n",
                         d, d);
-
-                if (swap)
-                        fputs("Before=dev-mapper-%i.swap\n",
-                              f);
-        } else
+        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) */
@@ -368,23 +361,9 @@ static int create_disk(
         if (r < 0)
                 log_warning_errno(r, "Failed to write device timeout drop-in: %m");
 
-        if (filtered) {
-                filtered_escaped = specifier_escape(filtered);
-                if (!filtered_escaped)
-                        return log_oom();
-        }
-
-        fprintf(f,
-                "\n[Service]\n"
-                "Type=oneshot\n"
-                "RemainAfterExit=yes\n"
-                "TimeoutSec=0\n" /* the binary handles timeouts anyway */
-                "KeyringMode=shared\n" /* make sure we can share cached keys among instances */
-                "OOMScoreAdjust=500\n" /* unlocking can allocate a lot of memory if Argon2 is used */
-                "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
-                "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
-                name_escaped, u_escaped, strempty(password_escaped), strempty(filtered_escaped),
-                name_escaped);
+        r = generator_write_cryptsetup_service_section(f, name, u, password, filtered);
+        if (r < 0)
+                return r;
 
         if (tmp)
                 fprintf(f,
index e0f1076326f2d7d3b1a926dac13a502cb91bceaa..5a0a871759ed467df723546f99e5351a1c794b9a 100644 (file)
@@ -118,11 +118,18 @@ static int add_swap(
 
         fprintf(f,
                 "[Unit]\n"
-                "SourcePath=%s\n"
-                "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n"
-                "[Swap]\n",
+                "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n"
+                "SourcePath=%s\n",
                 fstab_path());
 
+        r = generator_write_blockdev_dependency(f, what);
+        if (r < 0)
+                return r;
+
+        fprintf(f,
+                "\n"
+                "[Swap]\n");
+
         r = write_what(f, what);
         if (r < 0)
                 return r;
@@ -174,8 +181,13 @@ static bool mount_in_initrd(struct mntent *me) {
                streq(me->mnt_dir, "/usr");
 }
 
-static int write_timeout(FILE *f, const char *where, const char *opts,
-                         const char *filter, const char *variable) {
+static int write_timeout(
+                FILE *f,
+                const char *where,
+                const char *opts,
+                const char *filter,
+                const char *variable) {
+
         _cleanup_free_ char *timeout = NULL;
         char timespan[FORMAT_TIMESPAN_MAX];
         usec_t u;
@@ -208,8 +220,12 @@ static int write_mount_timeout(FILE *f, const char *where, const char *opts) {
                              "x-systemd.mount-timeout\0", "TimeoutSec");
 }
 
-static int write_dependency(FILE *f, const char *opts,
-                const char *filter, const char *format) {
+static int write_dependency(
+                FILE *f,
+                const char *opts,
+                const char *filter,
+                const char *format) {
+
         _cleanup_strv_free_ char **names = NULL, **units = NULL;
         _cleanup_free_ char *res = NULL;
         char **s;
@@ -230,6 +246,7 @@ static int write_dependency(FILE *f, const char *opts,
                 r = unit_name_mangle_with_suffix(*s, "as dependency", 0, ".mount", &x);
                 if (r < 0)
                         return log_error_errno(r, "Failed to generate unit name: %m");
+
                 r = strv_consume(&units, x);
                 if (r < 0)
                         return log_oom();
@@ -249,7 +266,8 @@ static int write_dependency(FILE *f, const char *opts,
 }
 
 static int write_after(FILE *f, const char *opts) {
-        return write_dependency(f, opts, "x-systemd.after", "After=%1$s\n");
+        return write_dependency(f, opts,
+                                "x-systemd.after", "After=%1$s\n");
 }
 
 static int write_requires_after(FILE *f, const char *opts) {
@@ -363,8 +381,8 @@ static int add_mount(
 
         fprintf(f,
                 "[Unit]\n"
-                "SourcePath=%s\n"
-                "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
+                "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n"
+                "SourcePath=%s\n",
                 source);
 
         /* All mounts under /sysroot need to happen later, at initrd-fs.target time. IOW, it's not
@@ -411,7 +429,14 @@ static int add_mount(
                         return r;
         }
 
-        fprintf(f, "\n[Mount]\n");
+        r = generator_write_blockdev_dependency(f, what);
+        if (r < 0)
+                return r;
+
+        fprintf(f,
+                "\n"
+                "[Mount]\n");
+
         if (original_where)
                 fprintf(f, "# Canonicalized from %s\n", original_where);
 
index e03cdbd5c020376e0b51bb472b20362345ba92f9..2067eeaf89afb403e7f4a3e7d50485da3eb15a39 100644 (file)
@@ -105,9 +105,8 @@ static int open_parent_block_device(dev_t devnum, int *ret_fd) {
 }
 
 static int add_cryptsetup(const char *id, const char *what, bool rw, bool require, char **device) {
-        _cleanup_free_ char *e = NULL, *n = NULL, *d = NULL, *id_escaped = NULL, *what_escaped = NULL;
+        _cleanup_free_ char *e = NULL, *n = NULL, *d = NULL;
         _cleanup_fclose_ FILE *f = NULL;
-        const char *p;
         int r;
 
         assert(id);
@@ -125,44 +124,28 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, bool requir
         if (r < 0)
                 return log_error_errno(r, "Failed to generate unit name: %m");
 
-        id_escaped = specifier_escape(id);
-        if (!id_escaped)
-                return log_oom();
-
-        what_escaped = specifier_escape(what);
-        if (!what_escaped)
-                return log_oom();
+        r = generator_open_unit_file(arg_dest, NULL, n, &f);
+        if (r < 0)
+                return r;
 
-        p = prefix_roota(arg_dest, n);
-        f = fopen(p, "wxe");
-        if (!f)
-                return log_error_errno(errno, "Failed to create unit file %s: %m", p);
+        r = generator_write_cryptsetup_unit_section(f, NULL);
+        if (r < 0)
+                return r;
 
         fprintf(f,
-                "# Automatically generated by systemd-gpt-auto-generator\n\n"
-                "[Unit]\n"
-                "Description=Cryptography Setup for %%I\n"
-                "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
-                "DefaultDependencies=no\n"
-                "Conflicts=umount.target\n"
-                "BindsTo=dev-mapper-%%i.device %s\n"
                 "Before=umount.target cryptsetup.target\n"
-                "After=%s\n"
-                "IgnoreOnIsolate=true\n"
-                "[Service]\n"
-                "Type=oneshot\n"
-                "RemainAfterExit=yes\n"
-                "TimeoutSec=0\n" /* the binary handles timeouts anyway */
-                "KeyringMode=shared\n" /* make sure we can share cached keys among instances */
-                "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
-                "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
-                d, d,
-                id_escaped, what_escaped, rw ? "" : "read-only",
-                id_escaped);
+                "Conflicts=umount.target\n"
+                "BindsTo=%s\n"
+                "After=%s\n",
+                d, d);
+
+        r = generator_write_cryptsetup_service_section(f, id, what, NULL, rw ? NULL : "read-only");
+        if (r < 0)
+                return r;
 
         r = fflush_and_check(f);
         if (r < 0)
-                return log_error_errno(r, "Failed to write file %s: %m", p);
+                return log_error_errno(r, "Failed to write file %s: %m", n);
 
         r = generator_add_symlink(arg_dest, d, "wants", n);
         if (r < 0)
@@ -227,7 +210,6 @@ static int add_mount(
         log_debug("Adding %s: %s fstype=%s", where, what, fstype ?: "(any)");
 
         if (streq_ptr(fstype, "crypto_LUKS")) {
-
                 r = add_cryptsetup(id, what, rw, true, &crypto_what);
                 if (r < 0)
                         return r;
@@ -262,6 +244,10 @@ static int add_mount(
         if (r < 0)
                 return r;
 
+        r = generator_write_blockdev_dependency(f, what);
+        if (r < 0)
+                return r;
+
         fprintf(f,
                 "\n"
                 "[Mount]\n"
@@ -370,7 +356,14 @@ static int add_swap(const char *path) {
                 "# Automatically generated by systemd-gpt-auto-generator\n\n"
                 "[Unit]\n"
                 "Description=Swap Partition\n"
-                "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
+                "Documentation=man:systemd-gpt-auto-generator(8)\n");
+
+        r = generator_write_blockdev_dependency(f, path);
+        if (r < 0)
+                return r;
+
+        fprintf(f,
+                "\n"
                 "[Swap]\n"
                 "What=%s\n",
                 path);
index 5e40933fdf28d47afc8927a854e34bc3e932b7a6..95af8efa7e2e96ff5ca3fc105fe25dcc847dd78a 100644 (file)
@@ -93,7 +93,7 @@ static int process_resume(void) {
                 return log_error_errno(r, "Failed to generate unit name: %m");
 
         r = write_drop_in(arg_dest, device_unit, 40, "device-timeout",
-                          "# Automatically generated by systemd-cryptsetup-generator\n\n"
+                          "# Automatically generated by systemd-hibernate-resume-generator\n\n"
                           "[Unit]\nJobTimeoutSec=0");
         if (r < 0)
                 log_warning_errno(r, "Failed to write device timeout drop-in: %m");
index 4fd48be52a023720088fa2312a39cb2e7731ca00..ed59584fd1f2a35451a96f51ca53cab7e0886c4d 100644 (file)
@@ -164,10 +164,10 @@ int network_verify(Network *network) {
             strv_isempty(network->match_path) && strv_isempty(network->match_driver) &&
             strv_isempty(network->match_type) && strv_isempty(network->match_name) &&
             strv_isempty(network->match_property) && strv_isempty(network->match_ssid) && !network->conditions)
-                log_warning("%s: No valid settings found in the [Match] section. "
-                            "The file will match all interfaces. "
-                            "If that is intended, please add Name=* in the [Match] section.",
-                            network->filename);
+                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+                                         "%s: No valid settings found in the [Match] section, ignoring file. "
+                                         "To match all interfaces, add Name=* in the [Match] section.",
+                                         network->filename);
 
         /* skip out early if configuration does not match the environment */
         if (!condition_test_list(network->conditions, NULL, NULL, NULL))
index 7c37563ac22ae0a694b97024dd48a79af1dcbf90..b29523b3182fdd08b0a27ea7fc90084c8d50f6f6 100644 (file)
@@ -122,11 +122,18 @@ static int test_load_config(Manager *manager) {
 static void test_network_get(Manager *manager, sd_device *loopback) {
         Network *network;
         const struct ether_addr mac = ETHER_ADDR_NULL;
+        int r;
 
-        /* let's assume that the test machine does not have a .network file
-           that applies to the loopback device... */
-        assert_se(network_get(manager, loopback, "lo", NULL, &mac, &mac, 0, NULL, NULL, &network) == -ENOENT);
-        assert_se(!network);
+        /* Let's hope that the test machine does not have a .network file that applies to loopback device…
+         * But it is still possible, so let's allow that case too. */
+        r = network_get(manager, loopback, "lo", NULL, &mac, &mac, 0, NULL, NULL, &network);
+        if (r == -ENOENT)
+                /* The expected case */
+                assert_se(!network);
+        else if (r >= 0)
+                assert_se(network);
+        else
+                assert_not_reached("bad error!");
 }
 
 static void test_address_equality(void) {
index 1cf5887a60de1516bac1df3322d3abe8f1b4c5c3..acdd0096f1419391bae148a8a041928b4a8cd822 100644 (file)
@@ -519,6 +519,103 @@ int generator_enable_remount_fs_service(const char *dir) {
                                      SYSTEM_DATA_UNIT_PATH "/" SPECIAL_REMOUNT_FS_SERVICE);
 }
 
+int generator_write_blockdev_dependency(
+                FILE *f,
+                const char *what) {
+
+        _cleanup_free_ char *escaped = NULL;
+        int r;
+
+        assert(f);
+        assert(what);
+
+        if (!path_startswith(what, "/dev/"))
+                return 0;
+
+        r = unit_name_path_escape(what, &escaped);
+        if (r < 0)
+                return log_error_errno(r, "Failed to escape device node path %s: %m", what);
+
+        fprintf(f,
+                "After=blockdev@%s.target\n",
+                escaped);
+
+        return 0;
+}
+
+int generator_write_cryptsetup_unit_section(
+                FILE *f,
+                const char *source) {
+
+        assert(f);
+
+        fprintf(f,
+                "[Unit]\n"
+                "Description=Cryptography Setup for %%I\n"
+                "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n");
+
+        if (source)
+                fprintf(f, "SourcePath=%s\n", source);
+
+        fprintf(f,
+                "DefaultDependencies=no\n"
+                "IgnoreOnIsolate=true\n"
+                "After=cryptsetup-pre.target\n"
+                "Before=blockdev@dev-mapper-%%i.target\n"
+                "Wants=blockdev@dev-mapper-%%i.target\n");
+
+        return 0;
+}
+
+int generator_write_cryptsetup_service_section(
+                FILE *f,
+                const char *name,
+                const char *what,
+                const char *password,
+                const char *options) {
+
+        _cleanup_free_ char *name_escaped = NULL, *what_escaped = NULL, *password_escaped = NULL, *options_escaped = NULL;
+
+        assert(f);
+        assert(name);
+        assert(what);
+
+        name_escaped = specifier_escape(name);
+        if (!name_escaped)
+                return log_oom();
+
+        what_escaped = specifier_escape(what);
+        if (!what_escaped)
+                return log_oom();
+
+        if (password) {
+                password_escaped = specifier_escape(password);
+                if (!password_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"
+                "TimeoutSec=0\n"          /* The binary handles timeouts on its own */
+                "KeyringMode=shared\n"    /* Make sure we can share cached keys among instances */
+                "OOMScoreAdjust=500\n"    /* Unlocking can allocate a lot of memory if Argon2 is used */
+                "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
+                "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
+                name_escaped, what_escaped, strempty(password_escaped), strempty(options_escaped),
+                name_escaped);
+
+        return 0;
+}
+
 void log_setup_generator(void) {
         log_set_prohibit_ipc(true);
         log_setup_service();
index fa002a91143adbfd4c78841d6df5c6745f48126b..579e291fe8ab3d070a6bc3bce15b0f5f2a33fb93 100644 (file)
@@ -27,6 +27,21 @@ int generator_write_timeouts(
         const char *opts,
         char **filtered);
 
+int generator_write_blockdev_dependency(
+                FILE *f,
+                const char *what);
+
+int generator_write_cryptsetup_unit_section(
+                FILE *f,
+                const char *source);
+
+int generator_write_cryptsetup_service_section(
+                FILE *f,
+                const char *name,
+                const char *what,
+                const char *password,
+                const char *options);
+
 int generator_write_device_deps(
         const char *dir,
         const char *what,
index e1a25a54a6870f442fc251ecf0b15338b1852380..bcf9be1a0d918e33c19d65ea64f91f03cec2bb79 100644 (file)
@@ -162,11 +162,12 @@ int link_load_one(link_config_ctx *ctx, const char *filename) {
 
         if (set_isempty(link->match_mac) && set_isempty(link->match_permanent_mac) &&
             strv_isempty(link->match_path) && strv_isempty(link->match_driver) && strv_isempty(link->match_type) &&
-            strv_isempty(link->match_name) && strv_isempty(link->match_property) && !link->conditions)
-                log_warning("%s: No valid settings found in the [Match] section. "
-                            "The file will match all interfaces. "
-                            "If that is intended, please add OriginalName=* in the [Match] section.",
+            strv_isempty(link->match_name) && strv_isempty(link->match_property) && !link->conditions) {
+                log_warning("%s: No valid settings found in the [Match] section, ignoring file. "
+                            "To match all interfaces, add OriginalName=* in the [Match] section.",
                             filename);
+                return 0;
+        }
 
         if (!condition_test_list(link->conditions, NULL, NULL, NULL)) {
                 log_debug("%s: Conditions do not match the system environment, skipping.", filename);
diff --git a/units/blockdev@.target b/units/blockdev@.target
new file mode 100644 (file)
index 0000000..22a9a5b
--- /dev/null
@@ -0,0 +1,13 @@
+#  SPDX-License-Identifier: LGPL-2.1+
+#
+#  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=Block Device Preparation for %f
+Documentation=man:systemd.special(7)
+StopWhenUnneeded=yes
index 0dc85ac64a3c88cb28a19429b610d3af89bd130c..f3145a1099ec05a67b6a6a9d48ad1ed5f7a255c4 100644 (file)
@@ -2,6 +2,7 @@
 
 units = [
         ['basic.target',                        ''],
+        ['blockdev@.target',                    ''],
         ['bluetooth.target',                    ''],
         ['boot-complete.target',                ''],
         ['cryptsetup-pre.target',               'HAVE_LIBCRYPTSETUP'],