Compare commits

...

13 Commits

Author SHA1 Message Date
Yu Watanabe 8a0365d88f
Merge 6a8fcf7b8d into bbec1c87d3 2024-11-27 02:51:47 +08:00
gerblesh bbec1c87d3 sysext: set SELinux context for hierarchies and workdir 2024-11-26 17:47:32 +00:00
Yu Watanabe f29a07f3fc man: several more assorted fixes
Continuation of 4ebbb5bfe8.
Closes #35307.
2024-11-26 17:28:14 +01:00
Luca Boccassi 0566bd9643
machine: increase timeouts in attempt to fix #35115 (#35117)
An attempt to fix https://github.com/systemd/systemd/issues/35115
2024-11-26 16:12:56 +00:00
Lennart Poettering 7b4b3a8f7b sd-varlink: fix bug when enqueuing messages with fds asynchronously
When determining the poll events to wait for we need to take the queue
of pending messages that carry fds into account. Otherwise we might end
up not waking up if such an fd-carrying message is enqueued
asynchronously (i.e. not from a dispatch callback).
2024-11-26 16:06:53 +00:00
Winterhuman 5bed97dd57
man/systemd-system.conf: Correct "struct" to "strict" (#35364) 2024-11-26 22:41:49 +09:00
Luca Boccassi c4d7a13c06 cryptsetup: convert pkcs11/fido2 to iovec for key handling
key-data might be NULL. Fixes crash:

0  0x0000559c62120530 in attach_luks_or_plain_or_bitlk (cd=0x559c6b192830, name=0x7ffd57981dc4 "root", token_type=TOKEN_FIDO2, key_file=0x0, key_data=0x0, passwords=0x0, flags=524296, until=0)
    at ../src/cryptsetup/cryptsetup.c:2234
        pass_volume_key = false
        r = 1469577760
        __func__ = '\000' <repeats 29 times>
1  0x0000559c6212279c in run (argc=6, argv=0x7ffd5797fe98) at ../src/cryptsetup/cryptsetup.c:2597
        discovered_key_data = {iov_base = 0x0, iov_len = 0}
        key_data = 0x0
        token_type = TOKEN_FIDO2
        destroy_key_file = 0x0
        flags = 524296
        until = 0
        passphrase_type = PASSPHRASE_NONE
        volume = 0x7ffd57981dc4 "root"
        source = 0x7ffd57981dc9 "/dev/disk/by-uuid/8372fb39-9ba4-461a-a618-07dcaae66280"
        status = CRYPT_INACTIVE
        tries = 0
        key_file = 0x0
        config = 0x7ffd57981e05 "luks,discard,fido2-device=auto,x-initrd.attach"
        use_cached_passphrase = true
        try_discover_key = true
        discovered_key_fn = 0x7ffd5797fa70 "root.key"
        passwords = 0x0
        cd = 0x559c6b192830
        verb = 0x7ffd57981dbd "attach"
        r = 0
        __func__ = "\000\000\000"
2  0x0000559c621231e6 in main (argc=6, argv=0x7ffd5797fe98) at ../src/cryptsetup/cryptsetup.c:2674
        r = 32553
        __func__ = "\000\000\000\000"

Follow-up for 53b6c99018
2024-11-26 22:04:24 +09:00
Abderrahim Kitouni 0ae6f4843e updatectl: fix DBus method signature for SetFeatureEnabled
The signature was changed to 'sit' in sysupdated during review, but updatectl
kept using 'sbt'
2024-11-26 22:03:41 +09:00
Yu Watanabe 6a8fcf7b8d TEST-17: add test case for ID_PROCESSING flag on add uevent
Also, check the state of the device units on change event.
2024-11-26 04:18:41 +09:00
Yu Watanabe 638e0859de core/device: handle ID_PROCESSING udev property
If an enumerated device has ID_PROCESSING=1 property, and the service
manager does not know if the device has been processed by udevd
previously (that is, Device.deserialized_found does not have
DEVICE_FOUND_UDEV), then drop DEVICE_FOUND_UDEV flag from the device and
make the device not enter the active state.

Follow-up for 405be62f05, which was
reverted by c4fc22c4de.
2024-11-26 01:33:16 +09:00
Yu Watanabe 0e1e66c54b core/device: rename output parameters of device_setup_units() to ret_xyz
No functional change, just refactoring.
2024-11-26 01:26:52 +09:00
Ivan Kruglov 3aa3f130c1 machine: add debug for systemd-nspawn@.service 2024-11-19 19:12:32 +01:00
Ivan Kruglov df18408ac6 machine: increase timeouts in attempt to fix #35115 2024-11-19 18:04:27 +01:00
21 changed files with 230 additions and 84 deletions

View File

@ -128,7 +128,8 @@
<para>If <option>-keep-download=yes</option> is specified the image will be downloaded and stored in <para>If <option>-keep-download=yes</option> is specified the image will be downloaded and stored in
a read-only subvolume/directory in the image directory that is named after the specified URL and its a read-only subvolume/directory in the image directory that is named after the specified URL and its
HTTP etag. A writable snapshot is then taken from this subvolume, and named after the specified local HTTP etag (see <ulink url="https://en.wikipedia.org/wiki/HTTP_ETag">HTTP ETag</ulink> for more
information). A writable snapshot is then taken from this subvolume, and named after the specified local
name. This behavior ensures that creating multiple instances of the same URL is efficient, as name. This behavior ensures that creating multiple instances of the same URL is efficient, as
multiple downloads are not necessary. In order to create only the read-only image, and avoid creating multiple downloads are not necessary. In order to create only the read-only image, and avoid creating
its writable snapshot, specify <literal>-</literal> as local name.</para> its writable snapshot, specify <literal>-</literal> as local name.</para>

View File

@ -28,7 +28,9 @@
<title>Description</title> <title>Description</title>
<para><command>pam_systemd_loadkey</command> reads a NUL-separated password list from the kernel keyring, <para><command>pam_systemd_loadkey</command> reads a NUL-separated password list from the kernel keyring,
and sets the last password in the list as the PAM authtok.</para> and sets the last password in the list as the PAM authtok, which can be used by e.g.
<citerefentry project='man-pages'><refentrytitle>pam_get_authtok</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para>
<para>The password list is supposed to be stored in the "user" keyring of the root user, <para>The password list is supposed to be stored in the "user" keyring of the root user,
by an earlier call to by an earlier call to

View File

@ -61,7 +61,10 @@
<literal>systemd-run0</literal> PAM stack.</para> <literal>systemd-run0</literal> PAM stack.</para>
<para>Note that <command>run0</command> is implemented as an alternative multi-call invocation of <para>Note that <command>run0</command> is implemented as an alternative multi-call invocation of
<citerefentry><refentrytitle>systemd-run</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para> <citerefentry><refentrytitle>systemd-run</refentrytitle><manvolnum>1</manvolnum></citerefentry>. That is,
<command>run0</command> is a symbolic link to <command>systemd-run</command> executable file, and it
behaves as <command>run0</command> if it is invoked through the symbolic link, otherwise behaves as
<command>systemd-run</command>.</para>
</refsect1> </refsect1>
<refsect1> <refsect1>

View File

@ -41,8 +41,10 @@
<refsect1> <refsect1>
<title>Kernel Command Line</title> <title>Kernel Command Line</title>
<para><filename>systemd-rfkill</filename> understands the <para>
following kernel command line parameter:</para> <command>systemd-rfkill</command> understands the following kernel command line parameter. See also
<citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
</para>
<variablelist class='kernel-commandline-options'> <variablelist class='kernel-commandline-options'>
<varlistentry> <varlistentry>

View File

@ -302,7 +302,7 @@
and running in an initrd equivalent to true, otherwise false. This implements a restricted subset of and running in an initrd equivalent to true, otherwise false. This implements a restricted subset of
the per-unit setting of the same name, see the per-unit setting of the same name, see
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details: currently, the <literal>full</literal> or <literal>struct</literal> values are not details: currently, the <literal>full</literal> or <literal>strict</literal> values are not
supported.</para> supported.</para>
<xi:include href="version-info.xml" xpointer="v256"/></listitem> <xi:include href="version-info.xml" xpointer="v256"/></listitem>

View File

@ -394,9 +394,9 @@
<listitem><para>SBAT metadata associated with the UKI or addon. SBAT policies are useful to revoke <listitem><para>SBAT metadata associated with the UKI or addon. SBAT policies are useful to revoke
whole groups of UKIs or addons with a single, static policy update that does not take space in whole groups of UKIs or addons with a single, static policy update that does not take space in
DBX/MOKX. If not specified manually, a default metadata entry consisting of DBX/MOKX. If not specified manually, a default metadata entry consisting of
<literal>uki,1,UKI,uki,1,https://uapi-group.org/specifications/specs/unified_kernel_image/</literal> <programlisting>uki,1,UKI,uki,1,https://uapi-group.org/specifications/specs/unified_kernel_image/</programlisting>
for UKIs and for UKIs and
<literal>uki-addon,1,UKI Addon,addon,1,https://www.freedesktop.org/software/systemd/man/latest/systemd-stub.html</literal> <programlisting>uki-addon,1,UKI Addon,addon,1,https://www.freedesktop.org/software/systemd/man/latest/systemd-stub.html</programlisting>
for addons will be used, to ensure it is always possible to revoke them. For more information on for addons will be used, to ensure it is always possible to revoke them. For more information on
SBAT see <ulink url="https://github.com/rhboot/shim/blob/main/SBAT.md">Shim documentation</ulink>. SBAT see <ulink url="https://github.com/rhboot/shim/blob/main/SBAT.md">Shim documentation</ulink>.
</para> </para>

View File

@ -289,7 +289,8 @@ int write_string_file_full(
const char *fn, const char *fn,
const char *line, const char *line,
WriteStringFileFlags flags, WriteStringFileFlags flags,
const struct timespec *ts) { const struct timespec *ts,
const char *label_fn) {
bool call_label_ops_post = false, made_file = false; bool call_label_ops_post = false, made_file = false;
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
@ -321,7 +322,8 @@ int write_string_file_full(
mode_t mode = write_string_file_flags_to_mode(flags); mode_t mode = write_string_file_flags_to_mode(flags);
if (FLAGS_SET(flags, WRITE_STRING_FILE_LABEL|WRITE_STRING_FILE_CREATE)) { if (FLAGS_SET(flags, WRITE_STRING_FILE_LABEL|WRITE_STRING_FILE_CREATE)) {
r = label_ops_pre(dir_fd, fn, mode); const char *lookup = label_fn ? label_fn : fn;
r = label_ops_pre(dir_fd, lookup, mode);
if (r < 0) if (r < 0)
goto fail; goto fail;

View File

@ -51,12 +51,13 @@ int write_string_stream_full(FILE *f, const char *line, WriteStringFileFlags fla
static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) { static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) {
return write_string_stream_full(f, line, flags, /* ts= */ NULL); return write_string_stream_full(f, line, flags, /* ts= */ NULL);
} }
int write_string_file_full(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts);
int write_string_file_full(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts, const char *label_fn);
static inline int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) { static inline int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
return write_string_file_full(AT_FDCWD, fn, line, flags, /* ts= */ NULL); return write_string_file_full(AT_FDCWD, fn, line, flags, /* ts= */ NULL, /*label_fn=*/ NULL);
} }
static inline int write_string_file_at(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags) { static inline int write_string_file_at(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags) {
return write_string_file_full(dir_fd, fn, line, flags, /* ts= */ NULL); return write_string_file_full(dir_fd, fn, line, flags, /* ts= */ NULL, /*label_fn=*/ NULL);
} }
int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4); int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4);

View File

@ -332,6 +332,15 @@ static void device_catchup(Unit *u) {
Device *d = ASSERT_PTR(DEVICE(u)); Device *d = ASSERT_PTR(DEVICE(u));
/* Second, let's update the state with the enumerated state */ /* Second, let's update the state with the enumerated state */
/* If Device.found (set by Device.deserialized_found) does not have DEVICE_FOUND_UDEV, and the device
* has never been processed by udevd, then also drop the flag from Device.enumerated_found. Note, do
* not unset the flag when the device was previously processed by udevd. Otherwise, e.g. if
* systemd-udev-trigger.service is started just before reexec, reload, and so on, many devices have
* ID_PROCESSING=1 property on enumeration and will enters dead state. See issue #35329. */
if (!FLAGS_SET(d->found, DEVICE_FOUND_UDEV) && !d->processed)
d->enumerated_found &= ~DEVICE_FOUND_UDEV;
device_update_found_one(d, d->enumerated_found, _DEVICE_FOUND_MASK); device_update_found_one(d, d->enumerated_found, _DEVICE_FOUND_MASK);
} }
@ -777,8 +786,16 @@ static int device_setup_devlink_unit_one(Manager *m, const char *devlink, Set **
assert(ready_units); assert(ready_units);
assert(not_ready_units); assert(not_ready_units);
if (sd_device_new_from_devname(&dev, devlink) >= 0 && device_is_ready(dev)) if (sd_device_new_from_devname(&dev, devlink) >= 0 && device_is_ready(dev)) {
if (MANAGER_IS_RUNNING(m) && device_is_processed(dev) <= 0)
/* The device is being processed by udevd. We will receive relevant uevent for the
* device later when completed. Let's ignore the device now. */
return 0;
/* Note, even if the device is being processed by udevd, setup the unit on enumerate.
* See slso the comments in device_catchup(). */
return device_setup_unit(m, dev, devlink, /* main = */ false, ready_units); return device_setup_unit(m, dev, devlink, /* main = */ false, ready_units);
}
/* the devlink is already removed or not ready */ /* the devlink is already removed or not ready */
if (device_by_path(m, devlink, &u) < 0) if (device_by_path(m, devlink, &u) < 0)
@ -874,14 +891,15 @@ static int device_setup_extra_units(Manager *m, sd_device *dev, Set **ready_unit
return 0; return 0;
} }
static int device_setup_units(Manager *m, sd_device *dev, Set **ready_units, Set **not_ready_units) { static int device_setup_units(Manager *m, sd_device *dev, Set **ret_ready_units, Set **ret_not_ready_units) {
_cleanup_set_free_ Set *ready_units = NULL, *not_ready_units = NULL;
const char *syspath, *devname = NULL; const char *syspath, *devname = NULL;
int r; int r;
assert(m); assert(m);
assert(dev); assert(dev);
assert(ready_units); assert(ret_ready_units);
assert(not_ready_units); assert(ret_not_ready_units);
r = sd_device_get_syspath(dev, &syspath); r = sd_device_get_syspath(dev, &syspath);
if (r < 0) if (r < 0)
@ -901,13 +919,13 @@ static int device_setup_units(Manager *m, sd_device *dev, Set **ready_units, Set
/* Add the main unit named after the syspath. If this one fails, don't bother with the rest, /* Add the main unit named after the syspath. If this one fails, don't bother with the rest,
* as this one shall be the main device unit the others just follow. (Compare with how * as this one shall be the main device unit the others just follow. (Compare with how
* device_following() is implemented, see below, which looks for the sysfs device.) */ * device_following() is implemented, see below, which looks for the sysfs device.) */
r = device_setup_unit(m, dev, syspath, /* main = */ true, ready_units); r = device_setup_unit(m, dev, syspath, /* main = */ true, &ready_units);
if (r < 0) if (r < 0)
return r; return r;
/* Add an additional unit for the device node */ /* Add an additional unit for the device node */
if (sd_device_get_devname(dev, &devname) >= 0) if (sd_device_get_devname(dev, &devname) >= 0)
(void) device_setup_unit(m, dev, devname, /* main = */ false, ready_units); (void) device_setup_unit(m, dev, devname, /* main = */ false, &ready_units);
} else { } else {
Unit *u; Unit *u;
@ -915,28 +933,30 @@ static int device_setup_units(Manager *m, sd_device *dev, Set **ready_units, Set
/* If the device exists but not ready, then save the units and unset udev bits later. */ /* If the device exists but not ready, then save the units and unset udev bits later. */
if (device_by_path(m, syspath, &u) >= 0) { if (device_by_path(m, syspath, &u) >= 0) {
r = set_ensure_put(not_ready_units, NULL, DEVICE(u)); r = set_ensure_put(&not_ready_units, NULL, DEVICE(u));
if (r < 0) if (r < 0)
log_unit_debug_errno(u, r, "Failed to store unit, ignoring: %m"); log_unit_debug_errno(u, r, "Failed to store unit, ignoring: %m");
} }
if (sd_device_get_devname(dev, &devname) >= 0 && if (sd_device_get_devname(dev, &devname) >= 0 &&
device_by_path(m, devname, &u) >= 0) { device_by_path(m, devname, &u) >= 0) {
r = set_ensure_put(not_ready_units, NULL, DEVICE(u)); r = set_ensure_put(&not_ready_units, NULL, DEVICE(u));
if (r < 0) if (r < 0)
log_unit_debug_errno(u, r, "Failed to store unit, ignoring: %m"); log_unit_debug_errno(u, r, "Failed to store unit, ignoring: %m");
} }
} }
/* Next, add/update additional .device units point to aliases and symlinks. */ /* Next, add/update additional .device units point to aliases and symlinks. */
(void) device_setup_extra_units(m, dev, ready_units, not_ready_units); (void) device_setup_extra_units(m, dev, &ready_units, &not_ready_units);
/* Safety check: no unit should be in ready_units and not_ready_units simultaneously. */ /* Safety check: no unit should be in ready_units and not_ready_units simultaneously. */
Unit *u; Unit *u;
SET_FOREACH(u, *not_ready_units) SET_FOREACH(u, not_ready_units)
if (set_remove(*ready_units, u)) if (set_remove(ready_units, u))
log_unit_error(u, "Cannot activate and deactivate the unit simultaneously. Deactivating."); log_unit_error(u, "Cannot activate and deactivate the unit simultaneously. Deactivating.");
*ret_ready_units = TAKE_PTR(ready_units);
*ret_not_ready_units = TAKE_PTR(not_ready_units);
return 0; return 0;
} }
@ -1046,13 +1066,32 @@ static void device_enumerate(Manager *m) {
FOREACH_DEVICE(e, dev) { FOREACH_DEVICE(e, dev) {
_cleanup_set_free_ Set *ready_units = NULL, *not_ready_units = NULL; _cleanup_set_free_ Set *ready_units = NULL, *not_ready_units = NULL;
const char *syspath;
bool processed;
Device *d; Device *d;
r = sd_device_get_syspath(dev, &syspath);
if (r < 0) {
log_device_debug_errno(dev, r, "Failed to get syspath of enumerated device, ignoring: %m");
continue;
}
r = device_is_processed(dev);
if (r < 0)
log_device_debug_errno(dev, r, "Failed to check if device is processed by udevd, assuming not: %m");
processed = r > 0;
if (device_setup_units(m, dev, &ready_units, &not_ready_units) < 0) if (device_setup_units(m, dev, &ready_units, &not_ready_units) < 0)
continue; continue;
SET_FOREACH(d, ready_units) SET_FOREACH(d, ready_units) {
device_update_found_one(d, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV); device_update_found_one(d, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV);
/* Why we need to check the syspath here? Because the device unit may be generated by
* a devlink, and the syspath may be different from the one of the original device. */
if (streq_ptr(d->sysfs, syspath))
d->processed = processed;
}
SET_FOREACH(d, not_ready_units) SET_FOREACH(d, not_ready_units)
device_update_found_one(d, DEVICE_NOT_FOUND, DEVICE_FOUND_UDEV); device_update_found_one(d, DEVICE_NOT_FOUND, DEVICE_FOUND_UDEV);
} }
@ -1097,7 +1136,6 @@ static void device_remove_old_on_move(Manager *m, sd_device *dev) {
} }
static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata) { static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata) {
_cleanup_set_free_ Set *ready_units = NULL, *not_ready_units = NULL;
Manager *m = ASSERT_PTR(userdata); Manager *m = ASSERT_PTR(userdata);
sd_device_action_t action; sd_device_action_t action;
const char *sysfs; const char *sysfs;
@ -1150,6 +1188,7 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *
* change events */ * change events */
ready = device_is_ready(dev); ready = device_is_ready(dev);
_cleanup_set_free_ Set *ready_units = NULL, *not_ready_units = NULL;
(void) device_setup_units(m, dev, &ready_units, &not_ready_units); (void) device_setup_units(m, dev, &ready_units, &not_ready_units);
if (action == SD_DEVICE_REMOVE) { if (action == SD_DEVICE_REMOVE) {

View File

@ -31,6 +31,9 @@ struct Device {
DeviceFound found, deserialized_found, enumerated_found; DeviceFound found, deserialized_found, enumerated_found;
bool bind_mounts; bool bind_mounts;
bool processed; /* Whether udevd has been processed the device, i.e. the device has database and
* ID_PROCESSING=1 udev property is not set. This is used only by enumeration and
* subsequent catchup process. */
/* The SYSTEMD_WANTS udev property for this device the last time we saw it */ /* The SYSTEMD_WANTS udev property for this device the last time we saw it */
char **wants_property; char **wants_property;

View File

@ -16,6 +16,7 @@
#include "fileio.h" #include "fileio.h"
#include "format-util.h" #include "format-util.h"
#include "hexdecoct.h" #include "hexdecoct.h"
#include "iovec-util.h"
#include "macro.h" #include "macro.h"
#include "memory-util.h" #include "memory-util.h"
#include "parse-util.h" #include "parse-util.h"
@ -31,8 +32,7 @@ int decrypt_pkcs11_key(
const char *key_file, /* We either expect key_file and associated parameters to be set (for file keys) … */ const char *key_file, /* We either expect key_file and associated parameters to be set (for file keys) … */
size_t key_file_size, size_t key_file_size,
uint64_t key_file_offset, uint64_t key_file_offset,
const void *key_data, /* … or key_data and key_data_size (for literal keys) */ const struct iovec *key_data, /* … or literal keys via key_data */
size_t key_data_size,
usec_t until, usec_t until,
AskPasswordFlags askpw_flags, AskPasswordFlags askpw_flags,
void **ret_decrypted_key, void **ret_decrypted_key,
@ -47,15 +47,15 @@ int decrypt_pkcs11_key(
assert(friendly_name); assert(friendly_name);
assert(pkcs11_uri); assert(pkcs11_uri);
assert(key_file || key_data); assert(key_file || iovec_is_set(key_data));
assert(ret_decrypted_key); assert(ret_decrypted_key);
assert(ret_decrypted_key_size); assert(ret_decrypted_key_size);
/* The functions called here log about all errors, except for EAGAIN which means "token not found right now" */ /* The functions called here log about all errors, except for EAGAIN which means "token not found right now" */
if (key_data) { if (iovec_is_set(key_data)) {
data.encrypted_key = (void*) key_data; data.encrypted_key = (void*) key_data->iov_base;
data.encrypted_key_size = key_data_size; data.encrypted_key_size = key_data->iov_len;
data.free_encrypted_key = false; data.free_encrypted_key = false;
} else { } else {

View File

@ -16,8 +16,7 @@ int decrypt_pkcs11_key(
const char *key_file, const char *key_file,
size_t key_file_size, size_t key_file_size,
uint64_t key_file_offset, uint64_t key_file_offset,
const void *key_data, const struct iovec *key_data,
size_t key_data_size,
usec_t until, usec_t until,
AskPasswordFlags askpw_flags, AskPasswordFlags askpw_flags,
void **ret_decrypted_key, void **ret_decrypted_key,
@ -39,8 +38,7 @@ static inline int decrypt_pkcs11_key(
const char *key_file, const char *key_file,
size_t key_file_size, size_t key_file_size,
uint64_t key_file_offset, uint64_t key_file_offset,
const void *key_data, const struct iovec *key_data,
size_t key_data_size,
usec_t until, usec_t until,
AskPasswordFlags askpw_flags, AskPasswordFlags askpw_flags,
void **ret_decrypted_key, void **ret_decrypted_key,

View File

@ -1471,8 +1471,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
struct crypt_device *cd, struct crypt_device *cd,
const char *name, const char *name,
const char *key_file, const char *key_file,
const void *key_data, const struct iovec *key_data,
size_t key_data_size,
usec_t until, usec_t until,
uint32_t flags, uint32_t flags,
bool pass_volume_key) { bool pass_volume_key) {
@ -1489,7 +1488,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
assert(name); assert(name);
assert(arg_fido2_device || arg_fido2_device_auto); assert(arg_fido2_device || arg_fido2_device_auto);
if (arg_fido2_cid && !key_file && !key_data) if (arg_fido2_cid && !key_file && !iovec_is_set(key_data))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"FIDO2 mode with manual parameters selected, but no keyfile specified, refusing."); "FIDO2 mode with manual parameters selected, but no keyfile specified, refusing.");
@ -1513,7 +1512,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
arg_fido2_rp_id, arg_fido2_rp_id,
arg_fido2_cid, arg_fido2_cid_size, arg_fido2_cid, arg_fido2_cid_size,
key_file, arg_keyfile_size, arg_keyfile_offset, key_file, arg_keyfile_size, arg_keyfile_offset,
key_data, key_data_size, key_data,
until, until,
arg_fido2_manual_flags, arg_fido2_manual_flags,
"cryptsetup.fido2-pin", "cryptsetup.fido2-pin",
@ -1623,8 +1622,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
struct crypt_device *cd, struct crypt_device *cd,
const char *name, const char *name,
const char *key_file, const char *key_file,
const void *key_data, const struct iovec *key_data,
size_t key_data_size,
usec_t until, usec_t until,
uint32_t flags, uint32_t flags,
bool pass_volume_key) { bool pass_volume_key) {
@ -1635,6 +1633,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
_cleanup_(erase_and_freep) void *decrypted_key = NULL; _cleanup_(erase_and_freep) void *decrypted_key = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_free_ void *discovered_key = NULL; _cleanup_free_ void *discovered_key = NULL;
struct iovec discovered_key_data = {};
int keyslot = arg_key_slot, r; int keyslot = arg_key_slot, r;
const char *uri = NULL; const char *uri = NULL;
bool use_libcryptsetup_plugin = use_token_plugins(); bool use_libcryptsetup_plugin = use_token_plugins();
@ -1653,13 +1652,13 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
return r; return r;
uri = discovered_uri; uri = discovered_uri;
key_data = discovered_key; discovered_key_data = IOVEC_MAKE(discovered_key, discovered_key_size);
key_data_size = discovered_key_size; key_data = &discovered_key_data;
} }
} else { } else {
uri = arg_pkcs11_uri; uri = arg_pkcs11_uri;
if (!key_file && !key_data) if (!key_file && !iovec_is_set(key_data))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PKCS#11 mode selected but no key file specified, refusing."); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PKCS#11 mode selected but no key file specified, refusing.");
} }
@ -1682,7 +1681,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
friendly, friendly,
uri, uri,
key_file, arg_keyfile_size, arg_keyfile_offset, key_file, arg_keyfile_size, arg_keyfile_offset,
key_data, key_data_size, key_data,
until, until,
arg_ask_password_flags, arg_ask_password_flags,
&decrypted_key, &decrypted_key_size); &decrypted_key, &decrypted_key_size);
@ -2231,9 +2230,9 @@ static int attach_luks_or_plain_or_bitlk(
if (token_type == TOKEN_TPM2) if (token_type == TOKEN_TPM2)
return attach_luks_or_plain_or_bitlk_by_tpm2(cd, name, key_file, key_data, until, flags, pass_volume_key); return attach_luks_or_plain_or_bitlk_by_tpm2(cd, name, key_file, key_data, until, flags, pass_volume_key);
if (token_type == TOKEN_FIDO2) if (token_type == TOKEN_FIDO2)
return attach_luks_or_plain_or_bitlk_by_fido2(cd, name, key_file, key_data->iov_base, key_data->iov_len, until, flags, pass_volume_key); return attach_luks_or_plain_or_bitlk_by_fido2(cd, name, key_file, key_data, until, flags, pass_volume_key);
if (token_type == TOKEN_PKCS11) if (token_type == TOKEN_PKCS11)
return attach_luks_or_plain_or_bitlk_by_pkcs11(cd, name, key_file, key_data->iov_base, key_data->iov_len, until, flags, pass_volume_key); return attach_luks_or_plain_or_bitlk_by_pkcs11(cd, name, key_file, key_data, until, flags, pass_volume_key);
if (key_data) if (key_data)
return attach_luks_or_plain_or_bitlk_by_key_data(cd, name, key_data, flags, pass_volume_key); return attach_luks_or_plain_or_bitlk_by_key_data(cd, name, key_data, flags, pass_volume_key);
if (key_file) if (key_file)

View File

@ -1698,7 +1698,8 @@ _public_ int sd_varlink_get_events(sd_varlink *v) {
ret |= EPOLLIN; ret |= EPOLLIN;
if (!v->write_disconnected && if (!v->write_disconnected &&
v->output_buffer_size > 0) (v->output_queue ||
v->output_buffer_size > 0))
ret |= EPOLLOUT; ret |= EPOLLOUT;
return ret; return ret;

View File

@ -24,8 +24,7 @@ int acquire_fido2_key(
const char *key_file, const char *key_file,
size_t key_file_size, size_t key_file_size,
uint64_t key_file_offset, uint64_t key_file_offset,
const void *key_data, const struct iovec *key_data,
size_t key_data_size,
usec_t until, usec_t until,
Fido2EnrollFlags required, Fido2EnrollFlags required,
const char *askpw_credential, const char *askpw_credential,
@ -45,10 +44,10 @@ int acquire_fido2_key(
"Local verification is required to unlock this volume, but the 'headless' parameter was set."); "Local verification is required to unlock this volume, but the 'headless' parameter was set.");
assert(cid); assert(cid);
assert(key_file || key_data); assert(key_file || iovec_is_set(key_data));
if (key_data) if (iovec_is_set(key_data))
salt = IOVEC_MAKE(key_data, key_data_size); salt = *key_data;
else { else {
if (key_file_size > 0) if (key_file_size > 0)
log_debug("Ignoring 'keyfile-size=' option for a FIDO2 salt file."); log_debug("Ignoring 'keyfile-size=' option for a FIDO2 salt file.");
@ -252,7 +251,7 @@ int acquire_fido2_key_auto(
/* key_file= */ NULL, /* salt is read from LUKS header instead of key_file */ /* key_file= */ NULL, /* salt is read from LUKS header instead of key_file */
/* key_file_size= */ 0, /* key_file_size= */ 0,
/* key_file_offset= */ 0, /* key_file_offset= */ 0,
salt, salt_size, &IOVEC_MAKE(salt, salt_size),
until, until,
required, required,
"cryptsetup.fido2-pin", "cryptsetup.fido2-pin",

View File

@ -20,8 +20,7 @@ int acquire_fido2_key(
const char *key_file, const char *key_file,
size_t key_file_size, size_t key_file_size,
uint64_t key_file_offset, uint64_t key_file_offset,
const void *key_data, const struct iovec *key_data,
size_t key_data_size,
usec_t until, usec_t until,
Fido2EnrollFlags required, Fido2EnrollFlags required,
const char *askpw_credential, const char *askpw_credential,
@ -52,8 +51,7 @@ static inline int acquire_fido2_key(
const char *key_file, const char *key_file,
size_t key_file_size, size_t key_file_size,
uint64_t key_file_offset, uint64_t key_file_offset,
const void *key_data, const struct iovec *key_data,
size_t key_data_size,
usec_t until, usec_t until,
Fido2EnrollFlags required, Fido2EnrollFlags required,
const char *askpw_credential, const char *askpw_credential,

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <getopt.h> #include <getopt.h>
#include <linux/loop.h> #include <linux/loop.h>
@ -45,6 +46,7 @@
#include "process-util.h" #include "process-util.h"
#include "rm-rf.h" #include "rm-rf.h"
#include "sort-util.h" #include "sort-util.h"
#include "selinux-util.h"
#include "string-table.h" #include "string-table.h"
#include "string-util.h" #include "string-util.h"
#include "terminal-util.h" #include "terminal-util.h"
@ -899,6 +901,7 @@ static int resolve_mutable_directory(
_cleanup_free_ char *path = NULL, *resolved_path = NULL, *dir_name = NULL; _cleanup_free_ char *path = NULL, *resolved_path = NULL, *dir_name = NULL;
const char *root = arg_root, *base = MUTABLE_EXTENSIONS_BASE_DIR; const char *root = arg_root, *base = MUTABLE_EXTENSIONS_BASE_DIR;
int r; int r;
_cleanup_close_ int atfd = -EBADF;
assert(hierarchy); assert(hierarchy);
assert(ret_resolved_mutable_directory); assert(ret_resolved_mutable_directory);
@ -943,6 +946,14 @@ static int resolve_mutable_directory(
r = mkdir_p(path_in_root, 0700); r = mkdir_p(path_in_root, 0700);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to create a directory '%s': %m", path_in_root); return log_error_errno(r, "Failed to create a directory '%s': %m", path_in_root);
atfd = open(path_in_root, O_DIRECTORY|O_CLOEXEC);
if (atfd < 0)
return log_error_errno(errno, "Failed to open directory '%s': %m", path_in_root);
r = mac_selinux_fix_full(atfd, NULL, hierarchy, 0);
if (r < 0)
return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", path_in_root);
} }
r = chase(path, root, CHASE_PREFIX_ROOT, &resolved_path, NULL); r = chase(path, root, CHASE_PREFIX_ROOT, &resolved_path, NULL);
@ -1289,6 +1300,7 @@ static int mount_overlayfs_with_op(
int r; int r;
const char *top_layer = NULL; const char *top_layer = NULL;
_cleanup_close_ int atfd = -EBADF;
assert(op); assert(op);
assert(overlay_path); assert(overlay_path);
@ -1301,10 +1313,28 @@ static int mount_overlayfs_with_op(
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to make directory '%s': %m", meta_path); return log_error_errno(r, "Failed to make directory '%s': %m", meta_path);
atfd = open(meta_path, O_DIRECTORY|O_CLOEXEC);
if (atfd < 0)
return log_error_errno(errno, "Failed to open directory '%s': %m", meta_path);
r = mac_selinux_fix_full(atfd, NULL, op->hierarchy, 0);
if (r < 0)
return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", meta_path);
if (op->upper_dir && op->work_dir) { if (op->upper_dir && op->work_dir) {
r = mkdir_p(op->work_dir, 0700); r = mkdir_p(op->work_dir, 0700);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to make directory '%s': %m", op->work_dir); return log_error_errno(r, "Failed to make directory '%s': %m", op->work_dir);
_cleanup_close_ int dfd = -EBADF;
dfd = open(op->work_dir, O_DIRECTORY|O_CLOEXEC);
if (dfd < 0)
return log_error_errno(errno, "Failed to open directory '%s': %m", op->work_dir);
r = mac_selinux_fix_full(dfd, NULL, op->hierarchy, 0);
if (r < 0)
return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", op->work_dir);
top_layer = op->upper_dir; top_layer = op->upper_dir;
} else { } else {
assert(!strv_isempty(op->lower_dirs)); assert(!strv_isempty(op->lower_dirs));
@ -1325,7 +1355,7 @@ static int mount_overlayfs_with_op(
return 0; return 0;
} }
static int write_extensions_file(ImageClass image_class, char **extensions, const char *meta_path) { static int write_extensions_file(ImageClass image_class, char **extensions, const char *meta_path, const char *hierarchy) {
_cleanup_free_ char *f = NULL, *buf = NULL; _cleanup_free_ char *f = NULL, *buf = NULL;
int r; int r;
@ -1343,14 +1373,15 @@ static int write_extensions_file(ImageClass image_class, char **extensions, cons
if (!buf) if (!buf)
return log_oom(); return log_oom();
r = write_string_file(f, buf, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755); const char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, image_class_info[image_class].short_identifier_plural);
r = write_string_file_full(AT_FDCWD,f, buf, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755|WRITE_STRING_FILE_LABEL, NULL, hierarchy_path);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to write extension meta file '%s': %m", f); return log_error_errno(r, "Failed to write extension meta file '%s': %m", f);
return 0; return 0;
} }
static int write_dev_file(ImageClass image_class, const char *meta_path, const char *overlay_path) { static int write_dev_file(ImageClass image_class, const char *meta_path, const char *overlay_path, const char *hierarchy) {
_cleanup_free_ char *f = NULL; _cleanup_free_ char *f = NULL;
struct stat st; struct stat st;
int r; int r;
@ -1372,14 +1403,15 @@ static int write_dev_file(ImageClass image_class, const char *meta_path, const c
/* Modifying the underlying layers while the overlayfs is mounted is technically undefined, but at /* Modifying the underlying layers while the overlayfs is mounted is technically undefined, but at
* least it won't crash or deadlock, as per the kernel docs about overlayfs: * least it won't crash or deadlock, as per the kernel docs about overlayfs:
* https://www.kernel.org/doc/html/latest/filesystems/overlayfs.html#changes-to-underlying-filesystems */ * https://www.kernel.org/doc/html/latest/filesystems/overlayfs.html#changes-to-underlying-filesystems */
r = write_string_file(f, FORMAT_DEVNUM(st.st_dev), WRITE_STRING_FILE_CREATE); const char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, image_class_info[image_class].short_identifier_plural);
r = write_string_file_full(AT_FDCWD, f, FORMAT_DEVNUM(st.st_dev), WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_LABEL, NULL, hierarchy_path);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to write '%s': %m", f); return log_error_errno(r, "Failed to write '%s': %m", f);
return 0; return 0;
} }
static int write_work_dir_file(ImageClass image_class, const char *meta_path, const char *work_dir) { static int write_work_dir_file(ImageClass image_class, const char *meta_path, const char *work_dir, const char* hierarchy) {
_cleanup_free_ char *escaped_work_dir_in_root = NULL, *f = NULL; _cleanup_free_ char *escaped_work_dir_in_root = NULL, *f = NULL;
char *work_dir_in_root = NULL; char *work_dir_in_root = NULL;
int r; int r;
@ -1406,7 +1438,8 @@ static int write_work_dir_file(ImageClass image_class, const char *meta_path, co
escaped_work_dir_in_root = cescape(work_dir_in_root); escaped_work_dir_in_root = cescape(work_dir_in_root);
if (!escaped_work_dir_in_root) if (!escaped_work_dir_in_root)
return log_oom(); return log_oom();
r = write_string_file(f, escaped_work_dir_in_root, WRITE_STRING_FILE_CREATE); const char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, "work_dir");
r = write_string_file_full(AT_FDCWD, f, escaped_work_dir_in_root, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_LABEL, NULL, hierarchy_path);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to write '%s': %m", f); return log_error_errno(r, "Failed to write '%s': %m", f);
@ -1418,8 +1451,10 @@ static int store_info_in_meta(
char **extensions, char **extensions,
const char *meta_path, const char *meta_path,
const char *overlay_path, const char *overlay_path,
const char *work_dir) { const char *work_dir,
const char *hierarchy) {
_cleanup_free_ char *f = NULL;
_cleanup_close_ int atfd = -EBADF;
int r; int r;
assert(extensions); assert(extensions);
@ -1427,15 +1462,32 @@ static int store_info_in_meta(
assert(overlay_path); assert(overlay_path);
/* work_dir may be NULL */ /* work_dir may be NULL */
r = write_extensions_file(image_class, extensions, meta_path); f = path_join(meta_path, image_class_info[image_class].dot_directory_name);
if (!f)
return log_oom();
r = mkdir_p(f, 0755);
if (r < 0) if (r < 0)
return r; return r;
r = write_dev_file(image_class, meta_path, overlay_path); atfd = open(f, O_DIRECTORY|O_CLOEXEC);
if (atfd < 0)
return log_error_errno(errno, "Failed to open directory '%s': %m", f);
r = mac_selinux_fix_full(atfd, NULL, hierarchy, 0);
if (r < 0)
return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", hierarchy);
r = write_extensions_file(image_class, extensions, meta_path, hierarchy);
if (r < 0) if (r < 0)
return r; return r;
r = write_work_dir_file(image_class, meta_path, work_dir); r = write_dev_file(image_class, meta_path, overlay_path, hierarchy);
if (r < 0)
return r;
r = write_work_dir_file(image_class, meta_path, work_dir, hierarchy);
if (r < 0) if (r < 0)
return r; return r;
@ -1501,6 +1553,8 @@ static int merge_hierarchy(
assert(overlay_path); assert(overlay_path);
assert(workspace_path); assert(workspace_path);
mac_selinux_init();
r = determine_used_extensions(hierarchy, paths, &used_paths, &extensions_used); r = determine_used_extensions(hierarchy, paths, &used_paths, &extensions_used);
if (r < 0) if (r < 0)
return r; return r;
@ -1528,7 +1582,7 @@ static int merge_hierarchy(
if (r < 0) if (r < 0)
return r; return r;
r = store_info_in_meta(image_class, extensions, meta_path, overlay_path, op->work_dir); r = store_info_in_meta(image_class, extensions, meta_path, overlay_path, op->work_dir, op->hierarchy);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -1414,7 +1414,7 @@ static int verb_enable(int argc, char **argv, void *userdata) {
"SetFeatureEnabled", "SetFeatureEnabled",
&error, &error,
/* reply= */ NULL, /* reply= */ NULL,
"sbt", "sit",
*feature, *feature,
(int) enable, (int) enable,
UINT64_C(0)); UINT64_C(0));

View File

@ -29,7 +29,7 @@ static int apply_timestamp(const char *path, struct timespec *ts) {
timespec_load_nsec(ts)) < 0) timespec_load_nsec(ts)) < 0)
return log_oom(); return log_oom();
r = write_string_file_full(AT_FDCWD, path, message, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL, ts); r = write_string_file_full(AT_FDCWD, path, message, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL, ts, NULL);
if (r == -EROFS) if (r == -EROFS)
log_debug_errno(r, "Cannot create \"%s\", file system is read-only.", path); log_debug_errno(r, "Cannot create \"%s\", file system is read-only.", path);
else if (r < 0) else if (r < 0)

View File

@ -22,6 +22,11 @@ trap at_exit EXIT
systemctl service-log-level systemd-machined debug systemctl service-log-level systemd-machined debug
systemctl service-log-level systemd-importd debug systemctl service-log-level systemd-importd debug
# per request in https://github.com/systemd/systemd/pull/35117
systemctl edit --runtime --stdin 'systemd-nspawn@.service' --drop-in=debug.conf <<EOF
[Service]
Environment=SYSTEMD_LOG_LEVEL=debug
EOF
# Mount temporary directory over /var/lib/machines to not pollute the image # Mount temporary directory over /var/lib/machines to not pollute the image
mkdir -p /var/lib/machines mkdir -p /var/lib/machines
@ -278,13 +283,13 @@ varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List
# sending TRAP signal # sending TRAP signal
rm -f /var/lib/machines/long-running/trap rm -f /var/lib/machines/long-running/trap
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Kill '{"name":"long-running", "whom": "leader", "signal": 5}' varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Kill '{"name":"long-running", "whom": "leader", "signal": 5}'
timeout 30 bash -c "until test -e /var/lib/machines/long-running/trap; do sleep .5; done" timeout 120 bash -c "until test -e /var/lib/machines/long-running/trap; do sleep .5; done"
# test io.systemd.Machine.Terminate # test io.systemd.Machine.Terminate
long_running_machine_start long_running_machine_start
rm -f /var/lib/machines/long-running/terminate rm -f /var/lib/machines/long-running/terminate
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Terminate '{"name":"long-running"}' varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Terminate '{"name":"long-running"}'
timeout 10 bash -c "until test -e /var/lib/machines/long-running/terminate; do sleep .5; done" timeout 30 bash -c "until test -e /var/lib/machines/long-running/terminate; do sleep .5; done"
timeout 30 bash -c "while varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{\"name\":\"long-running\"}'; do sleep 0.5; done" timeout 30 bash -c "while varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{\"name\":\"long-running\"}'; do sleep 0.5; done"
# test io.systemd.Machine.Register # test io.systemd.Machine.Register
@ -356,7 +361,7 @@ journalctl --sync
machinectl terminate container-without-os-release machinectl terminate container-without-os-release
machinectl terminate long-running machinectl terminate long-running
# wait for the container being stopped, otherwise acquiring image metadata by io.systemd.MachineImage.List may fail in the below. # wait for the container being stopped, otherwise acquiring image metadata by io.systemd.MachineImage.List may fail in the below.
timeout 10 bash -c "while machinectl status long-running &>/dev/null; do sleep .5; done" timeout 30 bash -c "while machinectl status long-running &>/dev/null; do sleep .5; done"
systemctl kill --signal=KILL systemd-nspawn@long-running.service || : systemctl kill --signal=KILL systemd-nspawn@long-running.service || :
(ip addr show lo | grep -q 192.168.1.100) || ip address add 192.168.1.100/24 dev lo (ip addr show lo | grep -q 192.168.1.100) || ip address add 192.168.1.100/24 dev lo

View File

@ -31,18 +31,50 @@ cat >/run/udev/udev.conf.d/timeout.conf <<EOF
event_timeout=1h event_timeout=1h
EOF EOF
# First, test 'add' event.
mkdir -p /run/udev/rules.d/ mkdir -p /run/udev/rules.d/
cat >/run/udev/rules.d/99-testsuite.rules <<EOF cat >/run/udev/rules.d/99-testsuite.rules <<EOF
SUBSYSTEM=="net", ACTION=="change", KERNEL=="${IFNAME}", OPTIONS="log_level=debug", RUN+="/usr/bin/sleep 1000" SUBSYSTEM=="net", ACTION=="add", KERNEL=="${IFNAME}", OPTIONS="log_level=debug", RUN+="/usr/bin/sleep 1000"
EOF EOF
systemctl restart systemd-udevd.service systemctl restart systemd-udevd.service
ip link add "$IFNAME" type dummy ip link add "$IFNAME" type dummy
IFINDEX=$(ip -json link show "$IFNAME" | jq '.[].ifindex') IFINDEX=$(ip -json link show "$IFNAME" | jq '.[].ifindex')
udevadm wait --timeout 10 "/sys/class/net/${IFNAME}" timeout 30 bash -c "until [[ -e /run/udev/data/n${IFINDEX} ]] && grep -q -F 'ID_PROCESSING=1' /run/udev/data/n${IFINDEX}; do sleep .5; done"
# Check if the database file is created.
[[ -e "/run/udev/data/n${IFINDEX}" ]] (! systemctl is-active "sys-devices-virtual-net-${IFNAME}.device")
(! systemctl is-active "sys-subsystem-net-devices-${IFNAME}.device")
for _ in {1..3}; do
systemctl daemon-reexec
(! systemctl is-active "sys-devices-virtual-net-${IFNAME}.device")
(! systemctl is-active "sys-subsystem-net-devices-${IFNAME}.device")
done
for _ in {1..3}; do
systemctl daemon-reload
(! systemctl is-active "sys-devices-virtual-net-${IFNAME}.device")
(! systemctl is-active "sys-subsystem-net-devices-${IFNAME}.device")
done
# Check if the reexec and reload have finished during processing the event.
grep -q -F 'ID_PROCESSING=1' "/run/udev/data/n${IFINDEX}"
# Forcibly kill sleep command ivoked by the udev rule to finish processing the add event.
killall sleep
udevadm settle --timeout=20
# Check if ID_PROCESSING flag is unset, and the device units are active.
(! grep -q -F 'ID_PROCESSING=1' "/run/udev/data/n${IFINDEX}")
systemctl is-active "sys-devices-virtual-net-${IFNAME}.device"
systemctl is-active "sys-subsystem-net-devices-${IFNAME}.device"
# Next, test 'change' event.
cat >/run/udev/rules.d/99-testsuite.rules <<EOF
SUBSYSTEM=="net", ACTION=="change", KERNEL=="${IFNAME}", OPTIONS="log_level=debug", RUN+="/usr/bin/sleep 1000"
EOF
udevadm control --reload
systemd-run \ systemd-run \
-p After="sys-subsystem-net-devices-${IFNAME}.device" \ -p After="sys-subsystem-net-devices-${IFNAME}.device" \
@ -50,22 +82,29 @@ systemd-run \
-u testsleep.service \ -u testsleep.service \
sleep 1h sleep 1h
timeout 10 bash -c 'until systemctl is-active testsleep.service; do sleep .5; done'
udevadm trigger "/sys/class/net/${IFNAME}" udevadm trigger "/sys/class/net/${IFNAME}"
timeout 30 bash -c "until grep -F 'ID_PROCESSING=1' /run/udev/data/n${IFINDEX}; do sleep .5; done" timeout 30 bash -c "until grep -q -F 'ID_PROCESSING=1' /run/udev/data/n${IFINDEX}; do sleep .5; done"
# Check if the service and device units are still active even ID_PROCESSING flag is set.
systemctl is-active testsleep.service
systemctl is-active "sys-devices-virtual-net-${IFNAME}.device"
systemctl is-active "sys-subsystem-net-devices-${IFNAME}.device"
for _ in {1..3}; do for _ in {1..3}; do
systemctl daemon-reexec systemctl daemon-reexec
systemctl is-active testsleep.service systemctl is-active testsleep.service
systemctl is-active "sys-devices-virtual-net-${IFNAME}.device"
systemctl is-active "sys-subsystem-net-devices-${IFNAME}.device"
done done
for _ in {1..3}; do for _ in {1..3}; do
systemctl daemon-reload systemctl daemon-reload
systemctl is-active testsleep.service systemctl is-active testsleep.service
systemctl is-active "sys-devices-virtual-net-${IFNAME}.device"
systemctl is-active "sys-subsystem-net-devices-${IFNAME}.device"
done done
# Check if the reexec and reload have finished during processing the event. # Check if the reexec and reload have finished during processing the event.
grep -F 'ID_PROCESSING=1' "/run/udev/data/n${IFINDEX}" grep -q -F 'ID_PROCESSING=1' "/run/udev/data/n${IFINDEX}"
exit 0 exit 0