1
0
mirror of https://github.com/systemd/systemd synced 2026-03-23 23:34:52 +01:00

Compare commits

..

8 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek
b4f0261337 udev: when setting up lo, do not return an error
From #20300:
> commit 70f32a260b5ebb68c19ecadf5d69b3844896ba55
> Author: Yu Watanabe <watanabe.yu+github@gmail.com>
> Date:   Sun May 23 16:59:40 2021 +0900

>     udev/net: do not manage loopback interfaces

>     There are nothing we can configure in udevd for loopback interfaces;
>     no ethertool configs can be applied, MAC address, interface name should

> introduced a regression for 'udevadm test-builtin net_setup_link /sys/class/net/lo/'.
> Prior to this commit this command would exit with 0 whereas after this commit
> it exists with 1. This causes cloud-init on Archlinux to fail as this command
> is run by it and likely also netplan to have networkd rescan and re-apply a
> bunch of things on NICs.

I think it's reasonable to keep returning 0 here: we are intentatinally doing
nothing for the device, and that is not an error, but a (noop) success.

Fixes #20300.
2021-07-26 14:47:03 +01:00
Ondrej Kozina
d1ae38d85a Add support for systemd-tpm2 libcryptsetup plugin.
Add support for systemd-tpm2 based LUKS2 device activation
via libcryptsetup plugin. This make the feature (tpm2 sealed
LUKS2 keyslot passphrase) usable from both systemd utilities
and cryptsetup cli.

The feature is configured via -Dlibcryptsetup-plugins combo
with default value set to 'auto'. It get's enabled automatically
when cryptsetup 2.4.0 or later is installed in build system.
2021-07-26 15:15:16 +02:00
Luca Boccassi
c5a421b3b9
Merge pull request #20276 from keszybz/rpm-restart-wip
Reload user daemons and restart user services at the end of the rpm transaction
2021-07-26 11:02:37 +01:00
Zbigniew Jędrzejewski-Szmek
1262e824a4 update-helper: also add "user-reexec" verb
This is not called from the systemd.triggers or systemd.macros files. Instead,
it would be called from the scriptlets in systemd rpm package itself, at the
place where we call systemctl daemon-reexec.

See https://github.com/systemd/systemd/pull/20289#issuecomment-885622200 .
2021-07-24 13:11:13 +02:00
Zbigniew Jędrzejewski-Szmek
36d55958cc rpm: restart user services at the end of the transaction
This closes an important gap: so far we would reexecute the system manager and
restart system services that were configured to do so, but we wouldn't do the
same for user managers or user services.

The scheme used for user managers is very similar to the system one, except
that there can be multiple user managers running, so we query the system
manager to get a list of them, and then tell each one to do the equivalent
operations: daemon-reload, disable --now, set-property Markers=+needs-restart,
reload-or-restart --marked.

The total time that can be spend on this is bounded: we execute the commands in
parallel over user managers and units, and additionally set SYSTEMD_BUS_TIMEOUT
to a lower value (15 s by default). User managers should not have too many
units running, and they should be able to do all those operations very
quickly (<< 1s). The final restart operation may take longer, but it's done
asynchronously, so we only wait for the queuing to happen.

The advantage of doing this synchronously is that we can wait for each step to
happen, and for example daemon-reloads can finish before we execute the service
restarts, etc. We can also order various steps wrt. to the phases in the rpm
transaction.

When this was initially proposed, we discussed a more relaxed scheme with bus
property notifications. Such an approach would be more complex because a bunch
of infrastructure would have to be added to system manager to propagate
appropriate notifications to the user managers, and then the user managers
would have to wait for them. Instead, now there is no new code in the managers,
all new functionality is contained in src/rpm/. The ability to call 'systemctl
--user user@' makes this approach very easy. Also, it would be very hard to
order the user manager steps and the rpm transaction steps.

Note: 'systemctl --user disable' is only called for a user managers that are
running. I don't see a nice way around this, and it shouldn't matter too much:
we'll just leave a dangling symlink in the case where the user enabled the
service manually.

A follow-up for https://bugzilla.redhat.com/show_bug.cgi?id=1792468 and
fa97d2fcf64e0558054bee673f734f523373b146.
2021-07-24 11:53:31 +02:00
Zbigniew Jędrzejewski-Szmek
3598aff4d9 rpm: call +needs-restart in parallel
Some rpms install a bunch of units… It seems nicer to invoke them all in
parallel. In particular, timeouts in systemctl also run in parallel, so if
there's some communication mishap, we will wait less.
2021-07-24 11:46:26 +02:00
Zbigniew Jędrzejewski-Szmek
6d825ab2d4 rpm: use a helper script to actually invoke systemctl commands
Instead of embedding the commands to invoke directly in the macros,
let's use a helper script as indirection. This has a couple of advantages:

- the macro language is awkward, we need to suffix most commands by "|| :"
  and "\", which is easy to get wrong. In the new scheme, the macro becomes
  a single simple command.
- in the script we can use normal syntax highlighting, shellcheck, etc.
- it's also easier to test the invoked commands by invoking the helper
  manually.
- most importantly, the logic is contained in the helper, i.e. we can
  update systemd rpm and everything uses the new helper. Before, we would
  have to rebuild all packages to update the macro definition.

This raises the question whether it makes sense to use the lua scriptlets when
the real work is done in a bash script. I think it's OK: we still have the
efficient lua scripts that do the short scripts, and we use a single shared
implementation in bash to do the more complex stuff.

The meson version is raised to 0.47 because that's needed for install_mode.
We were planning to raise the required version anyway…
2021-07-24 11:46:23 +02:00
Zbigniew Jędrzejewski-Szmek
7d9ee15d0f rpm: don't specify the full path for systemctl and other commands
We can make things a bit simpler and more readable by not specifying the path.
Since we didn't specify the full path for all commands (including those invoked
recursively by anythign we invoke), this didn't really privide any security or
robustness benefits. I guess that full paths were used because this style of
rpm packagnig was popular in the past, with macros used for everything
possible, with special macros for common commands like %{__ln} and %{__mkdir}.
2021-07-21 10:57:35 +02:00
19 changed files with 819 additions and 78 deletions

2
README
View File

@ -193,7 +193,7 @@ REQUIREMENTS:
python-jinja2 python-jinja2
python-lxml (optional, required to build the indices) python-lxml (optional, required to build the indices)
python >= 3.5 python >= 3.5
meson >= 0.46 (>= 0.49 is required to build position-independent executables) meson >= 0.47 (>= 0.49 is required to build position-independent executables)
ninja ninja
gcc, awk, sed, grep, and similar tools gcc, awk, sed, grep, and similar tools
clang >= 10.0, llvm >= 10.0 (optional, required to build BPF programs clang >= 10.0, llvm >= 10.0 (optional, required to build BPF programs

View File

@ -10,7 +10,7 @@ project('systemd', 'c',
'localstatedir=/var', 'localstatedir=/var',
'warning_level=2', 'warning_level=2',
], ],
meson_version : '>= 0.46', meson_version : '>= 0.47',
) )
libsystemd_version = '0.32.0' libsystemd_version = '0.32.0'
@ -209,6 +209,11 @@ if pamconfdir == ''
pamconfdir = join_paths(prefixdir, 'lib/pam.d') pamconfdir = join_paths(prefixdir, 'lib/pam.d')
endif endif
libcryptsetup_plugins_dir = get_option('libcryptsetup-plugins-dir')
if libcryptsetup_plugins_dir == ''
libcryptsetup_plugins_dir = join_paths(rootlibdir, 'cryptsetup')
endif
memory_accounting_default = get_option('memory-accounting-default') memory_accounting_default = get_option('memory-accounting-default')
status_unit_format_default = get_option('status-unit-format-default') status_unit_format_default = get_option('status-unit-format-default')
@ -255,6 +260,7 @@ conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH', join_paths(rootlib
conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH', join_paths(bindir, 'systemd-stdio-bridge')) conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH', join_paths(bindir, 'systemd-stdio-bridge'))
conf.set_quoted('SYSTEMD_TEST_DATA', join_paths(testsdir, 'testdata')) conf.set_quoted('SYSTEMD_TEST_DATA', join_paths(testsdir, 'testdata'))
conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', join_paths(rootbindir, 'systemd-tty-ask-password-agent')) conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', join_paths(rootbindir, 'systemd-tty-ask-password-agent'))
conf.set_quoted('SYSTEMD_UPDATE_HELPER_PATH', join_paths(rootlibexecdir, 'systemd-update-helper'))
conf.set_quoted('SYSTEMD_USERWORK_PATH', join_paths(rootlibexecdir, 'systemd-userwork')) conf.set_quoted('SYSTEMD_USERWORK_PATH', join_paths(rootlibexecdir, 'systemd-userwork'))
conf.set_quoted('SYSTEMD_VERITYSETUP_PATH', join_paths(rootlibexecdir, 'systemd-veritysetup')) conf.set_quoted('SYSTEMD_VERITYSETUP_PATH', join_paths(rootlibexecdir, 'systemd-veritysetup'))
conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', join_paths(pkgsysconfdir, 'system')) conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', join_paths(pkgsysconfdir, 'system'))
@ -271,6 +277,7 @@ conf.set_quoted('TMPFILES_DIR', tmpfilesdir)
conf.set_quoted('UDEVLIBEXECDIR', udevlibexecdir) conf.set_quoted('UDEVLIBEXECDIR', udevlibexecdir)
conf.set_quoted('UDEV_HWDB_DIR', udevhwdbdir) conf.set_quoted('UDEV_HWDB_DIR', udevhwdbdir)
conf.set_quoted('UDEV_RULES_DIR', udevrulesdir) conf.set_quoted('UDEV_RULES_DIR', udevrulesdir)
conf.set_quoted('UPDATE_HELPER_USER_TIMEOUT', get_option('update-helper-user-timeout'))
conf.set_quoted('USER_CONFIG_UNIT_DIR', join_paths(pkgsysconfdir, 'user')) conf.set_quoted('USER_CONFIG_UNIT_DIR', join_paths(pkgsysconfdir, 'user'))
conf.set_quoted('USER_DATA_UNIT_DIR', userunitdir) conf.set_quoted('USER_DATA_UNIT_DIR', userunitdir)
conf.set_quoted('USER_ENV_GENERATOR_DIR', userenvgeneratordir) conf.set_quoted('USER_ENV_GENERATOR_DIR', userenvgeneratordir)
@ -1104,10 +1111,16 @@ endif
conf.set10('HAVE_MICROHTTPD', have) conf.set10('HAVE_MICROHTTPD', have)
want_libcryptsetup = get_option('libcryptsetup') want_libcryptsetup = get_option('libcryptsetup')
want_libcryptsetup_plugins = get_option('libcryptsetup-plugins')
if want_libcryptsetup_plugins == 'true' and want_libcryptsetup == 'false'
error('libcryptsetup-plugins can not be requested without libcryptsetup')
endif
if want_libcryptsetup != 'false' and not skip_deps if want_libcryptsetup != 'false' and not skip_deps
libcryptsetup = dependency('libcryptsetup', libcryptsetup = dependency('libcryptsetup',
version : '>= 2.0.1', version : want_libcryptsetup_plugins == 'true' ? '>= 2.4.0' : '>= 2.0.1',
required : want_libcryptsetup == 'true') required : want_libcryptsetup == 'true' or want_libcryptsetup_plugins == 'true')
have = libcryptsetup.found() have = libcryptsetup.found()
conf.set10('HAVE_CRYPT_SET_METADATA_SIZE', conf.set10('HAVE_CRYPT_SET_METADATA_SIZE',
@ -1122,6 +1135,14 @@ else
endif endif
conf.set10('HAVE_LIBCRYPTSETUP', have) conf.set10('HAVE_LIBCRYPTSETUP', have)
if want_libcryptsetup_plugins != 'false' and not skip_deps
have = (cc.has_function('crypt_activate_by_token_pin', dependencies : libcryptsetup) and
cc.has_function('crypt_token_external_path', dependencies : libcryptsetup))
else
have = false
endif
conf.set10('HAVE_LIBCRYPTSETUP_PLUGINS', have)
want_libcurl = get_option('libcurl') want_libcurl = get_option('libcurl')
if want_libcurl != 'false' and not skip_deps if want_libcurl != 'false' and not skip_deps
libcurl = dependency('libcurl', libcurl = dependency('libcurl',
@ -1674,6 +1695,7 @@ subdir('src/libsystemd')
subdir('src/shared') subdir('src/shared')
subdir('src/udev') subdir('src/udev')
subdir('src/libudev') subdir('src/libudev')
subdir('src/cryptsetup/cryptsetup-tokens')
libsystemd = shared_library( libsystemd = shared_library(
'systemd', 'systemd',
@ -1750,6 +1772,22 @@ install_libudev_static = static_library(
c_args : static_libudev_pic ? [] : ['-fno-PIC'], c_args : static_libudev_pic ? [] : ['-fno-PIC'],
pic : static_libudev_pic) pic : static_libudev_pic)
if conf.get('HAVE_LIBCRYPTSETUP_PLUGINS') == 1
if conf.get('HAVE_TPM2') == 1
cryptsetup_token_systemd_tpm2 = shared_library(
'cryptsetup-token-systemd-tpm2',
link_args : ['-shared',
'-Wl,--version-script=' + cryptsetup_token_sym_path],
dependencies : libshared_deps + [libcryptsetup],
link_with : [libshared],
link_whole : [cryptsetup_token_systemd_tpm2_static],
link_depends : cryptsetup_token_sym,
install_rpath : rootlibexecdir,
install : true,
install_dir : libcryptsetup_plugins_dir)
endif
endif
############################################################ ############################################################
# systemd-analyze requires 'libcore' # systemd-analyze requires 'libcore'
@ -3745,6 +3783,7 @@ status = [
'SysV rc?.d directories: @0@'.format(sysvrcnd_path), 'SysV rc?.d directories: @0@'.format(sysvrcnd_path),
'PAM modules directory: @0@'.format(pamlibdir), 'PAM modules directory: @0@'.format(pamlibdir),
'PAM configuration directory: @0@'.format(pamconfdir), 'PAM configuration directory: @0@'.format(pamconfdir),
'libcryptsetup plugins directory: @0@'.format(libcryptsetup_plugins_dir),
'RPM macros directory: @0@'.format(rpmmacrosdir), 'RPM macros directory: @0@'.format(rpmmacrosdir),
'modprobe.d directory: @0@'.format(modprobedir), 'modprobe.d directory: @0@'.format(modprobedir),
'D-Bus policy directory: @0@'.format(dbuspolicydir), 'D-Bus policy directory: @0@'.format(dbuspolicydir),
@ -3829,6 +3868,7 @@ foreach tuple : [
['gnutls'], ['gnutls'],
['libbpf'], ['libbpf'],
['libcryptsetup'], ['libcryptsetup'],
['libcryptsetup-plugins'],
['libcurl'], ['libcurl'],
['libfdisk'], ['libfdisk'],
['libfido2'], ['libfido2'],

View File

@ -182,10 +182,14 @@ option('xinitrcdir', type : 'string', value : '',
description : 'directory for xinitrc files') description : 'directory for xinitrc files')
option('rpmmacrosdir', type : 'string', value : 'lib/rpm/macros.d', option('rpmmacrosdir', type : 'string', value : 'lib/rpm/macros.d',
description : 'directory for rpm macros ["no" disables]') description : 'directory for rpm macros ["no" disables]')
option('update-helper-user-timeout', type : 'string', value : '15s',
description : 'how long to wait for user manager operations')
option('pamlibdir', type : 'string', option('pamlibdir', type : 'string',
description : 'directory for PAM modules') description : 'directory for PAM modules')
option('pamconfdir', type : 'string', option('pamconfdir', type : 'string',
description : 'directory for PAM configuration ["no" disables]') description : 'directory for PAM configuration ["no" disables]')
option('libcryptsetup-plugins-dir', type : 'string',
description : 'directory for libcryptsetup plugins')
option('docdir', type : 'string', option('docdir', type : 'string',
description : 'documentation directory') description : 'documentation directory')
option('install-sysconfdir', type : 'combo', choices : ['true', 'no-samples', 'false'], value : 'true', option('install-sysconfdir', type : 'combo', choices : ['true', 'no-samples', 'false'], value : 'true',
@ -353,6 +357,8 @@ option('microhttpd', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'libµhttpd support') description : 'libµhttpd support')
option('libcryptsetup', type : 'combo', choices : ['auto', 'true', 'false'], option('libcryptsetup', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'libcryptsetup support') description : 'libcryptsetup support')
option('libcryptsetup-plugins', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'libcryptsetup LUKS2 external token handlers support (plugins)')
option('libcurl', type : 'combo', choices : ['auto', 'true', 'false'], option('libcurl', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'libcurl support') description : 'libcurl support')
option('idn', type : 'boolean', option('idn', type : 'boolean',

View File

@ -0,0 +1,232 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <errno.h>
#include <libcryptsetup.h>
#include "cryptsetup-token.h"
#include "cryptsetup-token-util.h"
#include "hexdecoct.h"
#include "luks2-tpm2.h"
#include "memory-util.h"
#include "tpm2-util.h"
#include "version.h"
#define TOKEN_NAME "systemd-tpm2"
#define TOKEN_VERSION_MAJOR "1"
#define TOKEN_VERSION_MINOR "0"
/* for libcryptsetup debug purpose */
_public_ const char *cryptsetup_token_version(void) {
return TOKEN_VERSION_MAJOR "." TOKEN_VERSION_MINOR " systemd-v" STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")";
}
static int log_debug_open_error(struct crypt_device *cd, int r) {
if (r == -EAGAIN) {
crypt_log_debug(cd, "TPM2 device not found.");
return r;
} else if (r == -ENXIO) {
crypt_log_debug(cd, "No matching TPM2 token data found.");
return r;
}
return crypt_log_debug_errno(cd, r, TOKEN_NAME " open failed: %m.");
}
/*
* This function is called from within following libcryptsetup calls
* provided conditions further below are met:
*
* crypt_activate_by_token(), crypt_activate_by_token_type(type == 'systemd-tpm2'):
*
* - token is assigned to at least one luks2 keyslot eligible to activate LUKS2 device
* (alternatively: name is set to null, flags contains CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY
* and token is assigned to at least single keyslot).
*
* - if plugin defines validate funtion (see cryptsetup_token_validate below) it must have
* passed the check (aka return 0)
*/
_public_ int cryptsetup_token_open(
struct crypt_device *cd, /* is always LUKS2 context */
int token /* is always >= 0 */,
char **password, /* freed by cryptsetup_token_buffer_free */
size_t *password_len,
void *usrptr /* plugin defined parameter passed to crypt_activate_by_token*() API */) {
int r;
const char *json;
size_t blob_size, policy_hash_size, decrypted_key_size;
uint32_t pcr_mask;
systemd_tpm2_plugin_params params = {
.search_pcr_mask = UINT32_MAX
};
_cleanup_free_ void *blob = NULL, *policy_hash = NULL;
_cleanup_free_ char *base64_blob = NULL, *hex_policy_hash = NULL;
_cleanup_(erase_and_freep) void *decrypted_key = NULL;
_cleanup_(erase_and_freep) char *base64_encoded = NULL;
assert(password);
assert(password_len);
assert(token >= 0);
/* This must not fail at this moment (internal error) */
r = crypt_token_json_get(cd, token, &json);
assert(token == r);
assert(json);
if (usrptr)
params = *(systemd_tpm2_plugin_params *)usrptr;
r = parse_luks2_tpm2_data(json, params.search_pcr_mask, &pcr_mask, &base64_blob, &hex_policy_hash);
if (r < 0)
return log_debug_open_error(cd, r);
/* should not happen since cryptsetup_token_validate have passed */
r = unbase64mem(base64_blob, SIZE_MAX, &blob, &blob_size);
if (r < 0)
return log_debug_open_error(cd, r);
/* should not happen since cryptsetup_token_validate have passed */
r = unhexmem(hex_policy_hash, SIZE_MAX, &policy_hash, &policy_hash_size);
if (r < 0)
return log_debug_open_error(cd, r);
r = acquire_luks2_key(
pcr_mask,
params.device,
blob,
blob_size,
policy_hash,
policy_hash_size,
&decrypted_key,
&decrypted_key_size);
if (r < 0)
return log_debug_open_error(cd, r);
/* Before using this key as passphrase we base64 encode it, for compat with homed */
r = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
if (r < 0)
return log_debug_open_error(cd, r);
/* free'd automaticaly by libcryptsetup */
*password_len = strlen(base64_encoded);
*password = TAKE_PTR(base64_encoded);
return 0;
}
/*
* libcryptsetup callback for memory deallocation of 'password' parameter passed in
* any crypt_token_open_* plugin function
*/
_public_ void cryptsetup_token_buffer_free(void *buffer, size_t buffer_len) {
erase_and_free(buffer);
}
/*
* prints systemd-tpm2 token content in crypt_dump().
* 'type' and 'keyslots' fields are printed by libcryptsetup
*/
_public_ void cryptsetup_token_dump(
struct crypt_device *cd /* is always LUKS2 context */,
const char *json /* validated 'systemd-tpm2' token if cryptsetup_token_validate is defined */) {
int r;
uint32_t i, pcr_mask;
size_t decoded_blob_size;
_cleanup_free_ char *base64_blob = NULL, *hex_policy_hash = NULL,
*pcrs_str = NULL, *blob_str = NULL, *policy_hash_str = NULL;
_cleanup_free_ void *decoded_blob = NULL;
assert(json);
r = parse_luks2_tpm2_data(json, UINT32_MAX, &pcr_mask, &base64_blob, &hex_policy_hash);
if (r < 0)
return (void) crypt_log_debug_errno(cd, r, "Failed to parse " TOKEN_NAME " metadata: %m.");
for (i = 0; i < TPM2_PCRS_MAX; i++) {
if ((pcr_mask & (UINT32_C(1) << i)) &&
((r = strextendf_with_separator(&pcrs_str, ", ", "%" PRIu32, i)) < 0))
return (void) crypt_log_debug_errno(cd, r, "Can not dump " TOKEN_NAME " content: %m");
}
r = unbase64mem(base64_blob, SIZE_MAX, &decoded_blob, &decoded_blob_size);
if (r < 0)
return (void) crypt_log_debug_errno(cd, r, "Can not dump " TOKEN_NAME " content: %m");
r = crypt_dump_buffer_to_hex_string(decoded_blob, decoded_blob_size, &blob_str);
if (r < 0)
return (void) crypt_log_debug_errno(cd, r, "Can not dump " TOKEN_NAME " content: %m");
r = crypt_dump_hex_string(hex_policy_hash, &policy_hash_str);
if (r < 0)
return (void) crypt_log_debug_errno(cd, r, "Can not dump " TOKEN_NAME " content: %m");
crypt_log(cd, "\ttpm2-pcrs: %s\n", pcrs_str ?: "");
crypt_log(cd, "\ttmp2-blob: %s\n", blob_str);
crypt_log(cd, "\ttmp2-policy-hash:" CRYPT_DUMP_LINE_SEP "%s\n", policy_hash_str);
}
/*
* Note:
* If plugin is available in library path, it's called in before following libcryptsetup calls:
*
* crypt_token_json_set, crypt_dump, any crypt_activate_by_token_* flavour
*/
_public_ int cryptsetup_token_validate(
struct crypt_device *cd, /* is always LUKS2 context */
const char *json /* contains valid 'type' and 'keyslots' fields. 'type' is 'systemd-tpm2' */) {
int r;
JsonVariant *w, *e;
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
assert(json);
r = json_parse(json, 0, &v, NULL, NULL);
if (r < 0)
return crypt_log_debug_errno(cd, r, "Could not parse " TOKEN_NAME " json object: %m");
w = json_variant_by_key(v, "tpm2-pcrs");
if (!w || !json_variant_is_array(w)) {
crypt_log_debug(cd, "TPM2 token data lacks 'tpm2-pcrs' field.");
return 1;
}
JSON_VARIANT_ARRAY_FOREACH(e, w) {
uintmax_t u;
if (!json_variant_is_number(e)) {
crypt_log_debug(cd, "TPM2 PCR is not a number.");
return 1;
}
u = json_variant_unsigned(e);
if (u >= TPM2_PCRS_MAX) {
crypt_log_debug(cd, "TPM2 PCR number out of range.");
return 1;
}
}
w = json_variant_by_key(v, "tpm2-blob");
if (!w || !json_variant_is_string(w)) {
crypt_log_debug(cd, "TPM2 token data lacks 'tpm2-blob' field.");
return 1;
}
r = unbase64mem(json_variant_string(w), SIZE_MAX, NULL, NULL);
if (r < 0)
return crypt_log_debug_errno(cd, r, "Invalid base64 data in 'tpm2-blob' field: %m");
w = json_variant_by_key(v, "tpm2-policy-hash");
if (!w || !json_variant_is_string(w)) {
crypt_log_debug(cd, "TPM2 token data lacks 'tpm2-policy-hash' field.");
return 1;
}
r = unhexmem(json_variant_string(w), SIZE_MAX, NULL, NULL);
if (r < 0)
return crypt_log_debug_errno(cd, r, "Invalid base64 data in 'tpm2-policy-hash' field: %m");
return 0;
}

View File

@ -0,0 +1,58 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "cryptsetup-token-util.h"
#include "string-util.h"
int crypt_dump_buffer_to_hex_string(
const char *buf,
size_t buf_size,
char **ret_dump_str) {
int r;
_cleanup_free_ char *dump_str = NULL;
assert(buf || !buf_size);
assert(ret_dump_str);
for (size_t i = 0; i < buf_size; i++) {
/* crypt_dump() breaks line after every
* 16th couple of chars in dumped hexstring */
r = strextendf_with_separator(
&dump_str,
(i && !(i % 16)) ? CRYPT_DUMP_LINE_SEP : " ",
"%02hhx", buf[i]);
if (r < 0)
return r;
}
*ret_dump_str = TAKE_PTR(dump_str);
return 0;
}
int crypt_dump_hex_string(const char *hex_str, char **ret_dump_str) {
int r;
size_t len;
_cleanup_free_ char *dump_str = NULL;
assert(hex_str);
assert(ret_dump_str);
len = strlen(hex_str) >> 1;
for (size_t i = 0; i < len; i++) {
/* crypt_dump() breaks line after every
* 16th couple of chars in dumped hexstring */
r = strextendf_with_separator(
&dump_str,
(i && !(i % 16)) ? CRYPT_DUMP_LINE_SEP : " ",
"%.2s", hex_str + (i<<1));
if (r < 0)
return r;
}
*ret_dump_str = TAKE_PTR(dump_str);
return 0;
}

View File

@ -0,0 +1,27 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stddef.h>
/* crypt_dump() internal indentation magic */
#define CRYPT_DUMP_LINE_SEP "\n\t "
#define crypt_log_debug(cd, ...) crypt_logf(cd, CRYPT_LOG_DEBUG, __VA_ARGS__)
#define crypt_log_error(cd, ...) crypt_logf(cd, CRYPT_LOG_ERROR, __VA_ARGS__)
#define crypt_log(cd, ...) crypt_logf(cd, CRYPT_LOG_NORMAL, __VA_ARGS__)
#define crypt_log_debug_errno(cd, e, ...) ({ \
int _e = abs(e), _s = errno; \
errno = _e; \
crypt_logf(cd, CRYPT_LOG_DEBUG, __VA_ARGS__); \
errno = _s; \
-_e; \
})
int crypt_dump_buffer_to_hex_string(
const char *buf,
size_t buf_size,
char **ret_dump_str);
int crypt_dump_hex_string(const char *hex_str, char **ret_dump_str);

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
/* for more information see libcryptsetup.h crypt-tokens section */
const char *cryptsetup_token_version(void);
int cryptsetup_token_open(struct crypt_device *cd, int token,
char **password, size_t *password_len, void *usrptr);
void cryptsetup_token_dump(struct crypt_device *cd, const char *json);
int cryptsetup_token_validate(struct crypt_device *cd, const char *json);
void cryptsetup_token_buffer_free(void *buffer, size_t buffer_len);

View File

@ -0,0 +1,18 @@
/***
SPDX-License-Identifier: LGPL-2.1-or-later
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.
***/
CRYPTSETUP_TOKEN_1.0 {
global:
cryptsetup_token_open;
cryptsetup_token_buffer_free;
cryptsetup_token_validate;
cryptsetup_token_dump;
cryptsetup_token_version;
local: *;
};

View File

@ -0,0 +1,105 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "hexdecoct.h"
#include "json.h"
#include "luks2-tpm2.h"
#include "parse-util.h"
#include "random-util.h"
#include "tpm2-util.h"
int acquire_luks2_key(
uint32_t pcr_mask,
const char *device,
const void *key_data,
size_t key_data_size,
const void *policy_hash,
size_t policy_hash_size,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size) {
_cleanup_free_ char *auto_device = NULL;
int r;
assert(ret_decrypted_key);
assert(ret_decrypted_key_size);
if (!device) {
r = tpm2_find_device_auto(LOG_DEBUG, &auto_device);
if (r == -ENODEV)
return -EAGAIN; /* Tell the caller to wait for a TPM2 device to show up */
if (r < 0)
return r;
device = auto_device;
}
return tpm2_unseal(device, pcr_mask, key_data, key_data_size, policy_hash, policy_hash_size, ret_decrypted_key, ret_decrypted_key_size);
}
/* this function expects valid "systemd-tpm2" in json */
int parse_luks2_tpm2_data(
const char *json,
uint32_t search_pcr_mask,
uint32_t *ret_pcr_mask,
char **ret_base64_blob,
char **ret_hex_policy_hash) {
int r;
JsonVariant *w, *e;
uint32_t pcr_mask = 0;
_cleanup_free_ char *base64_blob = NULL, *hex_policy_hash = NULL;
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
assert(json);
assert(ret_base64_blob);
assert(ret_hex_policy_hash);
assert(ret_pcr_mask);
r = json_parse(json, 0, &v, NULL, NULL);
if (r < 0)
return -EINVAL;
w = json_variant_by_key(v, "tpm2-pcrs");
if (!w || !json_variant_is_array(w))
return -EINVAL;
JSON_VARIANT_ARRAY_FOREACH(e, w) {
uintmax_t u;
if (!json_variant_is_number(e))
return -EINVAL;
u = json_variant_unsigned(e);
if (u >= TPM2_PCRS_MAX)
return -EINVAL;
pcr_mask |= UINT32_C(1) << u;
}
if (search_pcr_mask != UINT32_MAX &&
search_pcr_mask != pcr_mask)
return -ENXIO;
w = json_variant_by_key(v, "tpm2-blob");
if (!w || !json_variant_is_string(w))
return -EINVAL;
base64_blob = strdup(json_variant_string(w));
if (!base64_blob)
return -ENOMEM;
w = json_variant_by_key(v, "tpm2-policy-hash");
if (!w || !json_variant_is_string(w))
return -EINVAL;
hex_policy_hash = strdup(json_variant_string(w));
if (!hex_policy_hash)
return -ENOMEM;
*ret_pcr_mask = pcr_mask;
*ret_base64_blob = TAKE_PTR(base64_blob);
*ret_hex_policy_hash = TAKE_PTR(hex_policy_hash);
return 0;
}

View File

@ -0,0 +1,22 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
struct crypt_device;
int acquire_luks2_key(
uint32_t pcr_mask,
const char *device,
const void *key_data,
size_t key_data_size,
const void *policy_hash,
size_t policy_hash_size,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size);
int parse_luks2_tpm2_data(
const char *json,
uint32_t search_pcr_mask,
uint32_t *ret_pcr_mask,
char **ret_base64_blob,
char **ret_hex_policy_hash);

View File

@ -0,0 +1,28 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if conf.get('HAVE_LIBCRYPTSETUP_PLUGINS') == 1
cryptsetup_token_c_args = ['-fvisibility=hidden']
cryptsetup_token_sym = files('cryptsetup-token.sym')
cryptsetup_token_sym_path = join_paths(meson.current_source_dir(), 'cryptsetup-token.sym')
if conf.get('HAVE_TPM2') == 1
cryptsetup_token_systemd_tpm2_sources = files('''
cryptsetup-token-systemd-tpm2.c
cryptsetup-token.h
cryptsetup-token-util.h
cryptsetup-token-util.c
luks2-tpm2.c
luks2-tpm2.h
'''.split())
cryptsetup_token_systemd_tpm2_static = static_library(
'cryptsetup-token-systemd-tpm2_static',
cryptsetup_token_systemd_tpm2_sources,
include_directories : includes,
dependencies : libshared_deps + [libcryptsetup],
c_args : cryptsetup_token_c_args)
endif
endif

View File

@ -1041,6 +1041,33 @@ static int make_tpm2_device_monitor(sd_event *event, sd_device_monitor **ret) {
return 0; return 0;
} }
static int attach_luks2_by_tpm2(
struct crypt_device *cd,
const char *name,
uint32_t flags) {
#if HAVE_LIBCRYPTSETUP_PLUGINS
int r;
systemd_tpm2_plugin_params params = {
.search_pcr_mask = arg_tpm2_pcr_mask,
.device = arg_tpm2_device
};
if (crypt_token_external_path() == NULL)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Libcryptsetup has external plugins support disabled.");
r = crypt_activate_by_token_pin(cd, name, "systemd-tpm2", CRYPT_ANY_TOKEN, NULL, 0, &params, flags);
if (r > 0) /* returns unlocked keyslot id on success */
r = 0;
return r;
#else
return -EOPNOTSUPP;
#endif
}
static int attach_luks_or_plain_or_bitlk_by_tpm2( static int attach_luks_or_plain_or_bitlk_by_tpm2(
struct crypt_device *cd, struct crypt_device *cd,
const char *name, const char *name,
@ -1087,6 +1114,20 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
if (r != -EAGAIN) /* EAGAIN means: no tpm2 chip found */ if (r != -EAGAIN) /* EAGAIN means: no tpm2 chip found */
return r; return r;
} else { } else {
r = attach_luks2_by_tpm2(cd, name, flags);
/* EAGAIN means: no tpm2 chip found
* EOPNOTSUPP means: no libcryptsetup plugins support */
if (r == -ENXIO)
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
"No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking.");
if (r == -ENOENT)
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
"No TPM2 metadata enrolled in LUKS2 header or TPM2 support not available, falling back to traditional unlocking.");
if (!IN_SET(r, -EOPNOTSUPP, -EAGAIN))
return r;
}
if (r == -EOPNOTSUPP) {
_cleanup_free_ void *blob = NULL, *policy_hash = NULL; _cleanup_free_ void *blob = NULL, *policy_hash = NULL;
size_t blob_size, policy_hash_size; size_t blob_size, policy_hash_size;
bool found_some = false; bool found_some = false;

View File

@ -46,31 +46,33 @@ OrderWithRequires(postun): systemd \
%systemd_post() \ %systemd_post() \
%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_post}} \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_post}} \
if [ $1 -eq 1 ] && [ -x %{_bindir}/systemctl ]; then \ if [ $1 -eq 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \
# Initial installation \ # Initial installation \
%{_bindir}/systemctl --no-reload preset %{?*} || : \ {{SYSTEMD_UPDATE_HELPER_PATH}} install-system-units %{?*} || : \
fi \ fi \
%{nil} %{nil}
%systemd_user_post() %{expand:%systemd_post \\--global %%{?*}} %systemd_user_post() \
%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_post}} \
if [ $1 -eq 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \
# Initial installation \
{{SYSTEMD_UPDATE_HELPER_PATH}} install-user-units %{?*} || : \
fi \
%{nil}
%systemd_preun() \ %systemd_preun() \
%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_preun}} \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_preun}} \
if [ $1 -eq 0 ] && [ -x %{_bindir}/systemctl ]; then \ if [ $1 -eq 0 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \
# Package removal, not upgrade \ # Package removal, not upgrade \
if [ -d /run/systemd/system ]; then \ {{SYSTEMD_UPDATE_HELPER_PATH}} remove-system-units %{?*} || : \
%{_bindir}/systemctl --no-reload disable --now %{?*} || : \
else \
%{_bindir}/systemctl --no-reload disable %{?*} || : \
fi \
fi \ fi \
%{nil} %{nil}
%systemd_user_preun() \ %systemd_user_preun() \
%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_preun}} \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_preun}} \
if [ $1 -eq 0 ] && [ -x %{_bindir}/systemctl ]; then \ if [ $1 -eq 0 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \
# Package removal, not upgrade \ # Package removal, not upgrade \
%{_bindir}/systemctl --global disable %{?*} || : \ {{SYSTEMD_UPDATE_HELPER_PATH}} remove-user-units %{?*} || : \
fi \ fi \
%{nil} %{nil}
@ -84,16 +86,18 @@ fi \
%systemd_postun_with_restart() \ %systemd_postun_with_restart() \
%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_restart}} \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_restart}} \
if [ $1 -ge 1 ] && [ -x %{_bindir}/systemctl ]; then \ if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \
# Package upgrade, not uninstall \ # Package upgrade, not uninstall \
for unit in %{?*}; do \ {{SYSTEMD_UPDATE_HELPER_PATH}} mark-restart-system-units %{?*} || : \
%{_bindir}/systemctl set-property $unit Markers=+needs-restart || : \
done \
fi \ fi \
%{nil} %{nil}
%systemd_user_postun_with_restart() \ %systemd_user_postun_with_restart() \
%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_restart}} \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_postun_with_restart}} \
if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \
# Package upgrade, not uninstall \
{{SYSTEMD_UPDATE_HELPER_PATH}} mark-restart-user-units %{?*} || : \
fi \
%{nil} %{nil}
%udev_hwdb_update() %{nil} %udev_hwdb_update() %{nil}
@ -105,17 +109,17 @@ fi \
# Deprecated. Use %tmpfiles_create_package instead # Deprecated. Use %tmpfiles_create_package instead
%tmpfiles_create() \ %tmpfiles_create() \
%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# tmpfiles_create}} \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# tmpfiles_create}} \
[ -x %{_bindir}/systemd-tmpfiles ] && %{_bindir}/systemd-tmpfiles --create %{?*} || : \ command -v systemd-tmpfiles >/dev/null && systemd-tmpfiles --create %{?*} || : \
%{nil} %{nil}
# Deprecated. Use %sysusers_create_package instead # Deprecated. Use %sysusers_create_package instead
%sysusers_create() \ %sysusers_create() \
%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# sysusers_create}} \ %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# sysusers_create}} \
[ -x %{_bindir}/systemd-sysusers ] && %{_bindir}/systemd-sysusers %{?*} || : \ command -v systemd-sysusers >/dev/null && systemd-sysusers %{?*} || : \
%{nil} %{nil}
%sysusers_create_inline() \ %sysusers_create_inline() \
[ -x %{_bindir}/systemd-sysusers ] && %{_bindir}/systemd-sysusers - <<SYSTEMD_INLINE_EOF || : \ command -v systemd-sysusers >/dev/null && systemd-sysusers - <<SYSTEMD_INLINE_EOF || : \
%{?*} \ %{?*} \
SYSTEMD_INLINE_EOF\ SYSTEMD_INLINE_EOF\
%{nil} %{nil}

View File

@ -1,7 +1,11 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
in_files = [ in_files = [
['macros.systemd', rpmmacrosdir != 'no'], ['macros.systemd', rpmmacrosdir != 'no', rpmmacrosdir],
# we conditionalize on rpmmacrosdir, but install into rootlibexecdir
['systemd-update-helper', rpmmacrosdir != 'no', rootlibexecdir, 'rwxr-xr-x'],
['triggers.systemd', false], ['triggers.systemd', false],
['triggers.systemd.sh', false]] ['triggers.systemd.sh', false]]
@ -17,6 +21,7 @@ foreach tuple : in_files
command : [meson_render_jinja2, config_h, '@INPUT@'], command : [meson_render_jinja2, config_h, '@INPUT@'],
capture : true, capture : true,
install : tuple[1], install : tuple[1],
install_dir : rpmmacrosdir, install_dir : tuple.length() > 2 ? tuple[2] : '',
install_mode : tuple.length() > 3 ? tuple[3] : false,
build_by_default : true) build_by_default : true)
endforeach endforeach

116
src/rpm/systemd-update-helper.in Executable file
View File

@ -0,0 +1,116 @@
#!/bin/bash
set -eu
set -o pipefail
command="${1:?}"
shift
command -v systemctl >/dev/null || exit 0
case "$command" in
install-system-units)
systemctl --no-reload preset "$@"
;;
install-user-units)
systemctl --no-reload preset --global "$@"
;;
remove-system-units)
if [ -d /run/systemd/system ]; then
systemctl --no-reload disable --now "$@"
else
systemctl --no-reload disable "$@"
fi
;;
remove-user-units)
systemctl --global disable "$@"
[ -d /run/systemd/system ] || exit 0
users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
for user in $users; do
SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
systemctl --user -M "$user@" disable --now "$@" &
done
wait
;;
mark-restart-system-units)
[ -d /run/systemd/system ] || exit 0
for unit in "$@"; do
systemctl set-property "$unit" Markers=+needs-restart &
done
wait
;;
mark-restart-user-units)
[ -d /run/systemd/system ] || exit 0
users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
for user in $users; do
SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
systemctl --user -M "$user@" set-property "$unit" Markers=+needs-restart &
done
wait
;;
system-reload-restart|system-reload|system-restart)
if [ -n "$*" ]; then
echo "Unexpected arguments for '$command': $*"
exit 2
fi
[ -d /run/systemd/system ] || exit 0
if [[ "$command" =~ reload ]]; then
systemctl daemon-reload
fi
if [[ "$command" =~ restart ]]; then
systemctl reload-or-restart --marked
fi
;;
user-reload-restart|user-reload|user-restart|user-reexec)
if [ -n "$*" ]; then
echo "Unexpected arguments for '$command': $*"
exit 2
fi
[ -d /run/systemd/system ] || exit 0
users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
if [[ "$command" =~ reexec ]]; then
for user in $users; do
SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
systemctl --user -M "$user@" daemon-reexec &
done
wait
fi
if [[ "$command" =~ reload ]]; then
for user in $users; do
SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
systemctl --user -M "$user@" daemon-reload &
done
wait
fi
if [[ "$command" =~ restart ]]; then
for user in $users; do
SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
systemctl --user -M "$user@" reload-or-restart --marked &
done
wait
fi
;;
*)
echo "Unknown verb '$command'"
exit 3
;;
esac

View File

@ -13,21 +13,20 @@
-- upgraded. We care about the case where a package is initially -- upgraded. We care about the case where a package is initially
-- installed, because other cases are covered by the *un scriptlets, -- installed, because other cases are covered by the *un scriptlets,
-- so sometimes we will reload needlessly. -- so sometimes we will reload needlessly.
if posix.access("/run/systemd/system") then
pid = posix.fork() pid = posix.fork()
if pid == 0 then if pid == 0 then
assert(posix.exec("%{_bindir}/systemctl", "daemon-reload")) assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-reload-restart"))
elseif pid > 0 then elseif pid > 0 then
posix.wait(pid) posix.wait(pid)
end end
%transfiletriggerin -P 900899 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
pid = posix.fork() pid = posix.fork()
if pid == 0 then if pid == 0 then
assert(posix.exec("%{_bindir}/systemctl", "reload-or-restart", "--marked")) assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload-restart"))
elseif pid > 0 then elseif pid > 0 then
posix.wait(pid) posix.wait(pid)
end end
end
%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system %transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
-- On removal, we need to run daemon-reload after any units have been -- On removal, we need to run daemon-reload after any units have been
@ -35,24 +34,38 @@ end
-- On upgrade, we need to run daemon-reload after any new unit files -- On upgrade, we need to run daemon-reload after any new unit files
-- have been installed, but before %postun scripts in packages get -- have been installed, but before %postun scripts in packages get
-- executed. -- executed.
if posix.access("/run/systemd/system") then
pid = posix.fork() pid = posix.fork()
if pid == 0 then if pid == 0 then
assert(posix.exec("%{_bindir}/systemctl", "daemon-reload")) assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-reload"))
elseif pid > 0 then elseif pid > 0 then
posix.wait(pid) posix.wait(pid)
end end
%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
-- Execute daemon-reload in user managers.
pid = posix.fork()
if pid == 0 then
assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload"))
elseif pid > 0 then
posix.wait(pid)
end end
%transfiletriggerpostun -P 10000 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system %transfiletriggerpostun -P 10000 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
-- We restart remaining services that should be restarted here. -- We restart remaining system services that should be restarted here.
if posix.access("/run/systemd/system") then
pid = posix.fork() pid = posix.fork()
if pid == 0 then if pid == 0 then
assert(posix.exec("%{_bindir}/systemctl", "reload-or-restart", "--marked")) assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-restart"))
elseif pid > 0 then elseif pid > 0 then
posix.wait(pid) posix.wait(pid)
end end
%transfiletriggerpostun -P 9999 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
-- We restart remaining user services that should be restarted here.
pid = posix.fork()
if pid == 0 then
assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-restart"))
elseif pid > 0 then
posix.wait(pid)
end end
%transfiletriggerin -P 100700 -p <lua> -- {{SYSUSERS_DIR}} %transfiletriggerin -P 100700 -p <lua> -- {{SYSUSERS_DIR}}
@ -62,7 +75,7 @@ end
if posix.access("/run/systemd/system") then if posix.access("/run/systemd/system") then
pid = posix.fork() pid = posix.fork()
if pid == 0 then if pid == 0 then
assert(posix.exec("%{_bindir}/systemd-sysusers")) assert(posix.execp("systemd-sysusers"))
elseif pid > 0 then elseif pid > 0 then
posix.wait(pid) posix.wait(pid)
end end
@ -74,7 +87,7 @@ end
if posix.access("/run/systemd/system") then if posix.access("/run/systemd/system") then
pid = posix.fork() pid = posix.fork()
if pid == 0 then if pid == 0 then
assert(posix.exec("%{_bindir}/systemd-hwdb", "update")) assert(posix.execp("systemd-hwdb", "update"))
elseif pid > 0 then elseif pid > 0 then
posix.wait(pid) posix.wait(pid)
end end
@ -86,7 +99,7 @@ end
if posix.access("/run/systemd/system") then if posix.access("/run/systemd/system") then
pid = posix.fork() pid = posix.fork()
if pid == 0 then if pid == 0 then
assert(posix.exec("%{_bindir}/journalctl", "--update-catalog")) assert(posix.execp("journalctl", "--update-catalog"))
elseif pid > 0 then elseif pid > 0 then
posix.wait(pid) posix.wait(pid)
end end
@ -111,7 +124,7 @@ end
if posix.access("/run/systemd/system") then if posix.access("/run/systemd/system") then
pid = posix.fork() pid = posix.fork()
if pid == 0 then if pid == 0 then
assert(posix.exec("%{_bindir}/systemd-tmpfiles", "--create")) assert(posix.execp("systemd-tmpfiles", "--create"))
elseif pid > 0 then elseif pid > 0 then
posix.wait(pid) posix.wait(pid)
end end
@ -123,7 +136,7 @@ end
if posix.access("/run/systemd/system") then if posix.access("/run/systemd/system") then
pid = posix.fork() pid = posix.fork()
if pid == 0 then if pid == 0 then
assert(posix.exec("%{_bindir}/udevadm", "control", "--reload")) assert(posix.execp("udevadm", "control", "--reload"))
elseif pid > 0 then elseif pid > 0 then
posix.wait(pid) posix.wait(pid)
end end

View File

@ -14,10 +14,10 @@
# upgraded. We care about the case where a package is initially # upgraded. We care about the case where a package is initially
# installed, because other cases are covered by the *un scriptlets, # installed, because other cases are covered by the *un scriptlets,
# so sometimes we will reload needlessly. # so sometimes we will reload needlessly.
if test -d "/run/systemd/system"; then {{SYSTEMD_UPDATE_HELPER_PATH}} system-reload-restart || :
%{_bindir}/systemctl daemon-reload || :
%{_bindir}/systemctl reload-or-restart --marked || : %transfiletriggerin -P 900899 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
fi {{SYSTEMD_UPDATE_HELPER_PATH}} user-reload-restart || :
%transfiletriggerpostun -P 1000100 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system %transfiletriggerpostun -P 1000100 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
# On removal, we need to run daemon-reload after any units have been # On removal, we need to run daemon-reload after any units have been
@ -25,36 +25,40 @@ fi
# On upgrade, we need to run daemon-reload after any new unit files # On upgrade, we need to run daemon-reload after any new unit files
# have been installed, but before %postun scripts in packages get # have been installed, but before %postun scripts in packages get
# executed. # executed.
if test -d "/run/systemd/system"; then {{SYSTEMD_UPDATE_HELPER_PATH}} system-reload || :
%{_bindir}/systemctl daemon-reload || :
fi %transfiletriggerpostun -P 1000099 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
# Execute daemon-reload in user managers.
{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload || :
%transfiletriggerpostun -P 10000 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system %transfiletriggerpostun -P 10000 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
# We restart remaining services that should be restarted here. # We restart remaining system services that should be restarted here.
if test -d "/run/systemd/system"; then {{SYSTEMD_UPDATE_HELPER_PATH}} system-restart || :
%{_bindir}/systemctl reload-or-restart --marked || :
fi %transfiletriggerpostun -P 9999 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
# We restart remaining user services that should be restarted here.
{{SYSTEMD_UPDATE_HELPER_PATH}} user-restart || :
%transfiletriggerin -P 1000700 -- {{SYSUSERS_DIR}} %transfiletriggerin -P 1000700 -- {{SYSUSERS_DIR}}
# This script will process files installed in {{SYSUSERS_DIR}} to create # This script will process files installed in {{SYSUSERS_DIR}} to create
# specified users automatically. The priority is set such that it # specified users automatically. The priority is set such that it
# will run before the tmpfiles file trigger. # will run before the tmpfiles file trigger.
if test -d "/run/systemd/system"; then if test -d "/run/systemd/system"; then
%{_bindir}/systemd-sysusers || : systemd-sysusers || :
fi fi
%transfiletriggerin -P 1000700 udev -- {{UDEV_HWDB_DIR}} %transfiletriggerin -P 1000700 udev -- {{UDEV_HWDB_DIR}}
# This script will automatically invoke hwdb update if files have been # This script will automatically invoke hwdb update if files have been
# installed or updated in {{UDEV_HWDB_DIR}}. # installed or updated in {{UDEV_HWDB_DIR}}.
if test -d "/run/systemd/system"; then if test -d "/run/systemd/system"; then
%{_bindir}/systemd-hwdb update || : systemd-hwdb update || :
fi fi
%transfiletriggerin -P 1000700 -- {{SYSTEMD_CATALOG_DIR}} %transfiletriggerin -P 1000700 -- {{SYSTEMD_CATALOG_DIR}}
# This script will automatically invoke journal catalog update if files # This script will automatically invoke journal catalog update if files
# have been installed or updated in {{SYSTEMD_CATALOG_DIR}}. # have been installed or updated in {{SYSTEMD_CATALOG_DIR}}.
if test -d "/run/systemd/system"; then if test -d "/run/systemd/system"; then
%{_bindir}/journalctl --update-catalog || : journalctl --update-catalog || :
fi fi
%transfiletriggerin -P 1000700 -- {{BINFMT_DIR}} %transfiletriggerin -P 1000700 -- {{BINFMT_DIR}}
@ -71,14 +75,14 @@ fi
# tmpfiles automatically. The priority is set such that it will run # tmpfiles automatically. The priority is set such that it will run
# after the sysusers file trigger, but before any other triggers. # after the sysusers file trigger, but before any other triggers.
if test -d "/run/systemd/system"; then if test -d "/run/systemd/system"; then
%{_bindir}/systemd-tmpfiles --create || : systemd-tmpfiles --create || :
fi fi
%transfiletriggerin -P 1000600 udev -- {{UDEV_RULES_DIR}} %transfiletriggerin -P 1000600 udev -- {{UDEV_RULES_DIR}}
# This script will automatically update udev with new rules if files # This script will automatically update udev with new rules if files
# have been installed or updated in {{UDEV_RULES_DIR}}. # have been installed or updated in {{UDEV_RULES_DIR}}.
if test -e /run/udev/control; then if test -e /run/udev/control; then
%{_bindir}/udevadm control --reload || : udevadm control --reload || :
fi fi
%transfiletriggerin -P 1000500 -- {{SYSCTL_DIR}} %transfiletriggerin -P 1000500 -- {{SYSCTL_DIR}}

View File

@ -49,3 +49,8 @@ int tpm2_make_luks2_json(int keyslot, uint32_t pcr_mask, const void *blob, size_
/* Default to PCR 7 only */ /* Default to PCR 7 only */
#define TPM2_PCR_MASK_DEFAULT (UINT32_C(1) << 7) #define TPM2_PCR_MASK_DEFAULT (UINT32_C(1) << 7)
typedef struct {
uint32_t search_pcr_mask;
const char *device;
} systemd_tpm2_plugin_params;

View File

@ -28,10 +28,12 @@ static int builtin_net_setup_link(sd_device *dev, int argc, char **argv, bool te
r = link_config_get(ctx, dev, &link); r = link_config_get(ctx, dev, &link);
if (r < 0) { if (r < 0) {
if (r == -ENOENT)
return log_device_debug_errno(dev, r, "No matching link configuration found.");
if (r == -ENODEV) if (r == -ENODEV)
return log_device_debug_errno(dev, r, "Link vanished while searching for configuration for it."); return log_device_debug_errno(dev, r, "Link vanished while searching for configuration for it.");
if (r == -ENOENT) {
log_device_debug_errno(dev, r, "No matching link configuration found, ignoring device.");
return 0;
}
return log_device_error_errno(dev, r, "Failed to get link config: %m"); return log_device_error_errno(dev, r, "Failed to get link config: %m");
} }