network: make DNS= in [IPv6PrefixDelegation] section take special value '_link_local'
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.
…
* 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
<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>
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
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,
# 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
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
# 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
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
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',
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.
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],
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)
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)
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 */
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) {
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) {
}
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);
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;
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;
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);
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;
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;
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)
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) */
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,
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;
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;
"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;
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();
}
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) {
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
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);
}
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);
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)
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;
if (r < 0)
return r;
+ r = generator_write_blockdev_dependency(f, what);
+ if (r < 0)
+ return r;
+
fprintf(f,
"\n"
"[Mount]\n"
"# 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);
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");
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))
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) {
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();
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,
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);
--- /dev/null
+# 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
units = [
['basic.target', ''],
+ ['blockdev@.target', ''],
['bluetooth.target', ''],
['boot-complete.target', ''],
['cryptsetup-pre.target', 'HAVE_LIBCRYPTSETUP'],