1
0
mirror of https://github.com/systemd/systemd synced 2025-11-08 19:34:45 +01:00

Compare commits

...

20 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek
2859bb932b
Merge pull request #16530 from yuwata/udev-fix-race-in-renaming-network-interface
udev: fix race in renaming network interface
2020-07-22 11:50:09 +02:00
Lennart Poettering
63fdaa36c5
Merge pull request #16407 from bluca/verity_reuse
verity: re-use already open devices if the hashes match
2020-07-22 11:36:49 +02:00
Zbigniew Jędrzejewski-Szmek
8fa2cd83c6 Revert "man: add note about systemd-vconsole-setup.service and tty as input/output"
This reverts commit 0b578036301d7c3f2dab8df1f31f0121552a4e10.

From https://github.com/systemd/systemd/pull/16503#issuecomment-660212813:
systemd-vconsole-setup (the binary) is supposed to run asynchronously by udev
therefore ordering early interactive services after systemd-vconsole-setup.service
has basically no effect.

Let's remove this paragraph. It's better to say nothing than to give pointless
advice.
2020-07-22 10:43:52 +02:00
Elisei Roca
2aa5a13aa9 test: adapt test-functions for SUSE 2020-07-22 10:42:42 +02:00
Zbigniew Jędrzejewski-Szmek
f25e9eda52
Merge pull request #16514 from keszybz/zstd-decompress-fix
Fix coredumpctl operation with zstd-compressed journals
2020-07-22 10:40:19 +02:00
Zbigniew Jędrzejewski-Szmek
b876b07812
Merge pull request #16540 from poettering/acl-fix
two ACL handling fixes
2020-07-22 10:34:12 +02:00
Luca Boccassi
ac1f3ad05f verity: re-use already open devices if the hashes match
Opening a verity device is an expensive operation. The kernelspace operations
are mostly sequential with a global lock held regardless of which device
is being opened. In userspace jumps in and out of multiple libraries are
required. When signatures are used, there's the additional cryptographic
checks.

We know when two devices are identical: they have the same root hash.
If libcrypsetup returns EEXIST, double check that the hashes are really
the same, and that either both or none have a signature, and if everything
matches simply remount the already open device. The kernel will do
reference counting for us.

In order to quickly and reliably discover if a device is already open,
change the node naming scheme from '/dev/mapper/major:minor-verity' to
'/dev/mapper/$roothash-verity'.

Unfortunately libdevmapper is not 100% reliable, so in some case it
will say that the device already exists and it is active, but in
reality it is not usable. Fallback to an individually-activated
unique device name in those cases for robustness.
2020-07-21 23:42:03 +01:00
Luca Boccassi
536879480a dm-util: use CRYPT_DEACTIVATE_DEFERRED instead of ioctl 2020-07-21 23:26:41 +01:00
Lennart Poettering
d81be4e752 coredump: port to use common add_acls_for_user()
It's line-by-line the same logic, hence use the common implementation.
2020-07-21 22:58:40 +02:00
Lennart Poettering
2ea6247e01 acl-util: fix error handling in add_acls_for_user() 2020-07-21 22:58:40 +02:00
Zbigniew Jędrzejewski-Szmek
0da322d9a4 man: update docs with the new functions and other enhancements 2020-07-21 17:42:16 +02:00
Zbigniew Jędrzejewski-Szmek
7cbb7d62c6 homectl: fix warning about unused function
../src/home/homectl-pkcs11.c:19:13: warning: ‘pkcs11_callback_data_release’ defined but not used [-Wunused-function]
   19 | static void pkcs11_callback_data_release(struct pkcs11_callback_data *data) {
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
2020-07-21 17:42:16 +02:00
Zbigniew Jędrzejewski-Szmek
06847d0fba TODO: add entry for XZ
The docs for XZ don't seem to answer this at first blush, or maybe
I'm looking in the wrong place... This might make XZ less terribly slow,
but on the other hand, almost nobody uses it, so it doesn't matter that
much.
2020-07-21 17:42:15 +02:00
Zbigniew Jędrzejewski-Szmek
e4a321fc08 journal/compress: remove loop in decompress_startswith_zstd()
This should be more efficient with no downsides. Same considerations as in the
previous commit hold.
2020-07-21 17:42:15 +02:00
Zbigniew Jędrzejewski-Szmek
a24153279e journal/compress: fix zstd decompression with capped output size
decompress_blob_zstd() would allocate ever bigger buffers in a loop trying to
get a buffer big enough to decompress the input data. This is wasteful, since
we can just query the size of the decompressed data from the compressed header.
Worse, it doesn't work when the output size is capped, i.e. when dst_max != 0.
If the decompressed blob happened to be bigger than dst_max, decompression
would fail with -ENOBUFS. We need to use "stream decompression" instead, and
only get min(uncompressed size, dst_max) bytes of output.

Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1856037 in a second way.
2020-07-21 17:42:15 +02:00
Zbigniew Jędrzejewski-Szmek
b4a11ca3f2 journal: use -EPROTONOSUPPORT for unknown compression
We might add more compression types in the future, and we should treat that
as unsupported, and not a format error.
2020-07-21 17:42:15 +02:00
Zbigniew Jędrzejewski-Szmek
76cbafcdd4 sd-journal: when enumerating, continue even after an inaccessible field
SD_JOURNAL_FOREACH_DATA() and SD_JOURNAL_FOREACH_UNIQUE() would immediately
terminate when a field couldn't be accessed. This can happen for example when a
field is compressed with an unavailable compression format. But it's likely
that this is the wrong thing to do: the caller for example might want to
iterate over the fields but isn't interested in all of them. coredumpctl is
like this: it uses SD_JOURNAL_FOREACH_DATA() but only uses a subset of the
fields.

Add two new functions sd_journal_enumerate_good_data() and
sd_journal_enumerate_good_unique() that retry sd_journal_enumerate_data() and
sd_journal_enumerate_unique() if the return value is something that applies to
a single field: ENOBUS, E2BIG, EOPNOTSUPP.

Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1856037.

An alternative would be to make the macros themselves smarter instead of adding
new symbols, and do the looping internally in the macro. I don't like that
approach for two reasons. First, it would embed the logic in the macro, so
recompilation would be required if we decide to update the logic. With the
current version of the patch, recompilation is required to use the new symbols,
but after that, library upgrades are enough. So the current approach is safer
in case further updates are needed. Second, our headers use primitive C, and it
is hard to do the macros without using newer features.
2020-07-21 17:42:11 +02:00
Yu Watanabe
28266c446a udev: drop unnecessary checks
Also, drop one unnecessary sd_device_unref(), as dev_db_clone will be
unref()ed in udev_event_free().
2020-07-21 11:55:28 +09:00
Yu Watanabe
ae353ec2f6 udev: save ID_RENAMING= property to database before renaming network interface 2020-07-21 11:55:28 +09:00
Yu Watanabe
1cdea1a2f7 network: update one log message 2020-07-21 11:55:28 +09:00
22 changed files with 469 additions and 234 deletions

3
TODO
View File

@ -1029,7 +1029,7 @@ Features:
- journal: add a setgid "systemd-journal" utility to invoke from libsystemd-journal, which passes fds via STDOUT and does PK access
- journactl: support negative filtering, i.e. FOOBAR!="waldo",
and !FOOBAR for events without FOOBAR.
- journal: store timestamp of journal_file_set_offline() int he header,
- journal: store timestamp of journal_file_set_offline() in the header,
so it is possible to display when the file was last synced.
- journal-send.c, log.c: when the log socket is clogged, and we drop, count this and write a message about this when it gets unclogged again.
- journal: find a way to allow dropping history early, based on priority, other rules
@ -1071,6 +1071,7 @@ Features:
them via machined, and also watch containers coming and going.
Benefit: nspawn --ephemeral would start working nicely with the journal.
- assign MESSAGE_ID to log messages about failed services
- check if loop in decompress_blob_xz() is necessary
* add a test if all entries in the catalog are properly formatted.
(Adding dashes in a catalog entry currently results in the catalog entry

View File

@ -18,6 +18,7 @@
<refnamediv>
<refname>sd_journal_get_data</refname>
<refname>sd_journal_enumerate_data</refname>
<refname>sd_journal_enumerate_available_data</refname>
<refname>sd_journal_restart_data</refname>
<refname>SD_JOURNAL_FOREACH_DATA</refname>
<refname>sd_journal_set_data_threshold</refname>
@ -44,6 +45,13 @@
<paramdef>size_t *<parameter>length</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_journal_enumerate_available_data</function></funcdef>
<paramdef>sd_journal *<parameter>j</parameter></paramdef>
<paramdef>const void **<parameter>data</parameter></paramdef>
<paramdef>size_t *<parameter>length</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>void <function>sd_journal_restart_data</function></funcdef>
<paramdef>sd_journal *<parameter>j</parameter></paramdef>
@ -73,24 +81,18 @@
<refsect1>
<title>Description</title>
<para><function>sd_journal_get_data()</function> gets the data
object associated with a specific field from the current journal
entry. It takes four arguments: the journal context object, a
string with the field name to request, plus a pair of pointers to
pointer/size variables where the data object and its size shall be
stored in. The field name should be an entry field name.
Well-known field names are listed in
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
The returned data is in a read-only memory map and is only valid
until the next invocation of
<function>sd_journal_get_data()</function> or
<function>sd_journal_enumerate_data()</function>, or the read
pointer is altered. Note that the data returned will be prefixed
with the field name and '='. Also note that, by default, data fields
larger than 64K might get truncated to 64K. This threshold may be
changed and turned off with
<function>sd_journal_set_data_threshold()</function> (see
below).</para>
<para><function>sd_journal_get_data()</function> gets the data object associated with a specific field
from the current journal entry. It takes four arguments: the journal context object, a string with the
field name to request, plus a pair of pointers to pointer/size variables where the data object and its
size shall be stored in. The field name should be an entry field name. Well-known field names are listed in
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
but any field can be specified. The returned data is in a read-only memory map and is only valid until
the next invocation of <function>sd_journal_get_data()</function>,
<function>sd_journal_enumerate_data()</function>,
<function>sd_journal_enumerate_available_data()</function>, or when the read pointer is altered. Note
that the data returned will be prefixed with the field name and <literal>=</literal>. Also note that, by
default, data fields larger than 64K might get truncated to 64K. This threshold may be changed and turned
off with <function>sd_journal_set_data_threshold()</function> (see below).</para>
<para><function>sd_journal_enumerate_data()</function> may be used
to iterate through all fields of the current entry. On each
@ -99,15 +101,18 @@
format as with <function>sd_journal_get_data()</function> and also
follows the same life-time semantics.</para>
<para><function>sd_journal_enumerate_available_data()</function> is similar to
<function>sd_journal_enumerate_data()</function>, but silently skips any fields which may be valid, but
are too large or not supported by current implementation.</para>
<para><function>sd_journal_restart_data()</function> resets the
data enumeration index to the beginning of the entry. The next
invocation of <function>sd_journal_enumerate_data()</function>
will return the first field of the entry again.</para>
<para>Note that the <function>SD_JOURNAL_FOREACH_DATA()</function>
macro may be used as a handy wrapper around
<function>sd_journal_restart_data()</function> and
<function>sd_journal_enumerate_data()</function>.</para>
<para>Note that the <function>SD_JOURNAL_FOREACH_DATA()</function> macro may be used as a handy wrapper
around <function>sd_journal_restart_data()</function> and
<function>sd_journal_enumerate_available_data()</function>.</para>
<para>Note that these functions will not work before
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>
@ -139,18 +144,88 @@
<refsect1>
<title>Return Value</title>
<para><function>sd_journal_get_data()</function> returns 0 on
success or a negative errno-style error code. If the current entry
does not include the specified field, -ENOENT is returned. If
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>
has not been called at least once, -EADDRNOTAVAIL is returned.
<function>sd_journal_enumerate_data()</function> returns a
positive integer if the next field has been read, 0 when no more
fields are known, or a negative errno-style error code.
<function>sd_journal_restart_data()</function> returns nothing.
<function>sd_journal_set_data_threshold()</function> and
<function>sd_journal_get_threshold()</function> return 0 on
success or a negative errno-style error code.</para>
<para><function>sd_journal_get_data()</function> returns 0 on success or a negative errno-style error
code. <function>sd_journal_enumerate_data()</function> and
<function>sd_journal_enumerate_available_data()</function> return a positive integer if the next field
has been read, 0 when no more fields remain, or a negative errno-style error code.
<function>sd_journal_restart_data()</function> doesn't return anything.
<function>sd_journal_set_data_threshold()</function> and <function>sd_journal_get_threshold()</function>
return 0 on success or a negative errno-style error code.</para>
<refsect2>
<title>Errors</title>
<para>Returned errors may indicate the following problems:</para>
<variablelist>
<varlistentry id='EINVAL'>
<term><constant>-EINVAL</constant></term>
<listitem><para>One of the required parameters is <constant>NULL</constant> or invalid.
</para></listitem>
</varlistentry>
<varlistentry id='ECHILD'>
<term><constant>-ECHILD</constant></term>
<listitem><para>The journal object was created in a different process.</para></listitem>
</varlistentry>
<varlistentry id='EADDRNOTAVAIL'>
<term><constant>-EADDRNOTAVAIL</constant></term>
<listitem><para>The read pointer is not positioned at a valid entry;
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>
or a related call has not been called at least once.</para></listitem>
</varlistentry>
<varlistentry id='ENOENT'>
<term><constant>-ENOENT</constant></term>
<listitem><para>The current entry does not include the specified field.</para>
</listitem>
</varlistentry>
<varlistentry id='ENOMEM'>
<term><constant>-ENOMEM</constant></term>
<listitem><para>Memory allocation failed.</para></listitem>
</varlistentry>
<varlistentry id='ENOBUFS'>
<term><constant>-ENOBUFS</constant></term>
<listitem><para>A compressed entry is too large.</para></listitem>
</varlistentry>
<varlistentry id='E2BIG'>
<term><constant>-E2BIG</constant></term>
<listitem><para>The data field is too large for this computer architecture (e.g. above 4 GB on a
32-bit architecture).</para></listitem>
</varlistentry>
<varlistentry id='EPROTONOSUPPORT'>
<term><constant>-EPROTONOSUPPORT</constant></term>
<listitem><para>The journal is compressed with an unsupported method or the journal uses an
unsupported feature.</para></listitem>
</varlistentry>
<varlistentry id='EBADMSG'>
<term><constant>-EBADMSG</constant></term>
<listitem><para>The journal is corrupted (possibly just the entry being iterated over).
</para></listitem>
</varlistentry>
<varlistentry id='EIO'>
<term><constant>-EIO</constant></term>
<listitem><para>An I/O error was reported by the kernel.</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
</refsect1>
<refsect1>

View File

@ -18,6 +18,7 @@
<refnamediv>
<refname>sd_journal_query_unique</refname>
<refname>sd_journal_enumerate_unique</refname>
<refname>sd_journal_enumerate_available_unique</refname>
<refname>sd_journal_restart_unique</refname>
<refname>SD_JOURNAL_FOREACH_UNIQUE</refname>
<refpurpose>Read unique data fields from the journal</refpurpose>
@ -33,6 +34,13 @@
<paramdef>const char *<parameter>field</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_journal_enumerate_available_unique</function></funcdef>
<paramdef>sd_journal *<parameter>j</parameter></paramdef>
<paramdef>const void **<parameter>data</parameter></paramdef>
<paramdef>size_t *<parameter>length</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_journal_enumerate_unique</function></funcdef>
<paramdef>sd_journal *<parameter>j</parameter></paramdef>
@ -58,33 +66,31 @@
<refsect1>
<title>Description</title>
<para><function>sd_journal_query_unique()</function> queries the
journal for all unique values the specified field can take. It
takes two arguments: the journal to query and the field name to
look for. Well-known field names are listed on
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
Field names must be specified without a trailing '='. After this
function has been executed successfully the field values may be
queried using <function>sd_journal_enumerate_unique()</function>.
Invoking this call a second time will change the field name being
queried and reset the enumeration index to the first field value
that matches.</para>
<para><function>sd_journal_query_unique()</function> queries the journal for all unique values the
specified field can take. It takes two arguments: the journal to query and the field name to look
for. Well-known field names are listed on
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
but any field can be specified. Field names must be specified without a trailing
<literal>=</literal>. After this function has been executed successfully the field values may be queried
using <function>sd_journal_enumerate_unique()</function> and
<function>sd_journal_enumerate_available_unique()</function>. Invoking one of those calls will change the
field name being queried and reset the enumeration index to the first field value that matches.</para>
<para><function>sd_journal_enumerate_unique()</function> may be
used to iterate through all data fields which match the previously
selected field name as set with
<function>sd_journal_query_unique()</function>. On each invocation
the next field data matching the field name is returned. The order
of the returned data fields is not defined. It takes three
arguments: the journal context object, plus a pair of pointers to
pointer/size variables where the data object and its size shall be
stored in. The returned data is in a read-only memory map and is
only valid until the next invocation of
<function>sd_journal_enumerate_unique()</function>. Note that the
data returned will be prefixed with the field name and '='. Note
that this call is subject to the data field size threshold as
controlled by
<function>sd_journal_set_data_threshold()</function>.</para>
<para><function>sd_journal_enumerate_unique()</function> may be used to iterate through all data fields
which match the previously selected field name as set with
<function>sd_journal_query_unique()</function>. On each invocation the next field data matching the field
name is returned. The order of the returned data fields is not defined. It takes three arguments: the
journal object, plus a pair of pointers to pointer/size variables where the data object and its size
shall be stored. The returned data is in a read-only memory map and is only valid until the next
invocation of <function>sd_journal_enumerate_unique()</function>. Note that the data returned will be
prefixed with the field name and <literal>=</literal>. Note that this call is subject to the data field
size threshold as controlled by <function>sd_journal_set_data_threshold()</function> and only the initial
part of the field up to the threshold is returned. An error is returned for fields which cannot be
retrieved. See the error list below for details.</para>
<para><function>sd_journal_enumerate_available_unique()</function> is similar to
<function>sd_journal_enumerate_unique()</function>, but silently skips any fields which may be valid, but
are too large or not supported by current implementation.</para>
<para><function>sd_journal_restart_unique()</function> resets the
data enumeration index to the beginning of the list. The next
@ -92,11 +98,9 @@
will return the first field data matching the field name
again.</para>
<para>Note that the
<function>SD_JOURNAL_FOREACH_UNIQUE()</function> macro may be used
as a handy wrapper around
<function>sd_journal_restart_unique()</function> and
<function>sd_journal_enumerate_unique()</function>.</para>
<para>Note that the <function>SD_JOURNAL_FOREACH_UNIQUE()</function> macro may be used as a handy wrapper
around <function>sd_journal_restart_unique()</function> and
<function>sd_journal_enumerate_available_unique()</function>.</para>
<para>Note that these functions currently are not influenced by
matches set with <function>sd_journal_add_match()</function> but
@ -111,13 +115,29 @@
<refsect1>
<title>Return Value</title>
<para><function>sd_journal_query_unique()</function> returns 0 on
success or a negative errno-style error code.
<function>sd_journal_enumerate_unique()</function> returns a
positive integer if the next field data has been read, 0 when no
more fields are known, or a negative errno-style error code.
<function>sd_journal_restart_unique()</function> returns
nothing.</para>
<para><function>sd_journal_query_unique()</function> returns 0 on success or a negative errno-style error
code. <function>sd_journal_enumerate_unique()</function> and and
<function>sd_journal_query_available_unique()</function> return a positive integer if the next field data
has been read, 0 when no more fields remain, or a negative errno-style error code.
<function>sd_journal_restart_unique()</function> doesn't return anything.</para>
<refsect2>
<title>Errors</title>
<para>Returned errors may indicate the following problems:</para>
<variablelist>
<xi:include href="sd_journal_get_data.xml" xpointer="EINVAL"/>
<xi:include href="sd_journal_get_data.xml" xpointer="ECHILD"/>
<xi:include href="sd_journal_get_data.xml" xpointer="EADDRNOTAVAIL"/>
<xi:include href="sd_journal_get_data.xml" xpointer="ENOENT"/>
<xi:include href="sd_journal_get_data.xml" xpointer="ENOBUFS"/>
<xi:include href="sd_journal_get_data.xml" xpointer="E2BIG"/>
<xi:include href="sd_journal_get_data.xml" xpointer="EPROTONOSUPPORT"/>
<xi:include href="sd_journal_get_data.xml" xpointer="EBADMSG"/>
<xi:include href="sd_journal_get_data.xml" xpointer="EIO"/>
</variablelist>
</refsect2>
</refsect1>
<refsect1>
@ -131,10 +151,9 @@
<refsect1>
<title>Examples</title>
<para>Use the <function>SD_JOURNAL_FOREACH_UNIQUE</function> macro
to iterate through all values a field of the journal can take. The
following example lists all unit names referenced in the
journal:</para>
<para>Use the <function>SD_JOURNAL_FOREACH_UNIQUE</function> macro to iterate through all values a field
of the journal can take (and which can be accessed on the given architecture and are not compressed with
an unsupported mechanism). The following example lists all unit names referenced in the journal:</para>
<programlisting><xi:include href="journal-iterate-unique.c" parse="text" /></programlisting>
</refsect1>

View File

@ -2163,13 +2163,7 @@ SystemCallErrorNumber=EPERM</programlisting>
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more
details about named file descriptors and their ordering.</para>
<para>This setting defaults to <option>null</option>.</para>
<para>Note that services which specify <option>DefaultDependencies=no</option> and use
<varname>StandardInput=</varname> or <varname>StandardOutput=</varname> with
<option>tty</option>/<option>tty-force</option>/<option>tty-fail</option>, should specify
<option>After=systemd-vconsole-setup.service</option>, to make sure that the tty initialization is
finished before they start.</para></listitem>
<para>This setting defaults to <option>null</option>.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -177,38 +177,18 @@ static uint64_t storage_size_max(void) {
static int fix_acl(int fd, uid_t uid) {
#if HAVE_ACL
_cleanup_(acl_freep) acl_t acl = NULL;
acl_entry_t entry;
acl_permset_t permset;
int r;
assert(fd >= 0);
assert(uid_is_valid(uid));
if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY)
return 0;
/* Make sure normal users can read (but not write or delete)
* their own coredumps */
acl = acl_get_fd(fd);
if (!acl)
return log_error_errno(errno, "Failed to get ACL: %m");
if (acl_create_entry(&acl, &entry) < 0 ||
acl_set_tag_type(entry, ACL_USER) < 0 ||
acl_set_qualifier(entry, &uid) < 0)
return log_error_errno(errno, "Failed to patch ACL: %m");
if (acl_get_permset(entry, &permset) < 0 ||
acl_add_perm(permset, ACL_READ) < 0)
return log_warning_errno(errno, "Failed to patch ACL: %m");
r = calc_acl_mask_if_needed(&acl);
/* Make sure normal users can read (but not write or delete) their own coredumps */
r = add_acls_for_user(fd, uid);
if (r < 0)
return log_warning_errno(r, "Failed to patch ACL: %m");
if (acl_set_fd(fd, acl) < 0)
return log_error_errno(errno, "Failed to apply ACL: %m");
return log_error_errno(r, "Failed to adjust ACL of coredump: %m");
#endif
return 0;

View File

@ -16,12 +16,12 @@ struct pkcs11_callback_data {
X509 *cert;
};
#if HAVE_P11KIT
static void pkcs11_callback_data_release(struct pkcs11_callback_data *data) {
erase_and_free(data->pin_used);
X509_free(data->cert);
}
#if HAVE_P11KIT
static int pkcs11_callback(
CK_FUNCTION_LIST *m,
CK_SESSION_HANDLE session,

View File

@ -1295,7 +1295,7 @@ int home_activate_luks(
loop_device_relinquish(setup.loop);
r = dm_deferred_remove(setup.dm_name);
r = crypt_deactivate_by_name(NULL, setup.dm_name, CRYPT_DEACTIVATE_DEFERRED);
if (r < 0)
log_warning_errno(r, "Failed to relinquish DM device, ignoring: %m");

View File

@ -259,10 +259,10 @@ int decompress_blob_lz4(const void *src, uint64_t src_size,
int decompress_blob_zstd(
const void *src, uint64_t src_size,
void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max) {
void **dst, size_t *dst_alloc_size, size_t *dst_size, size_t dst_max) {
#if HAVE_ZSTD
size_t space;
uint64_t size;
assert(src);
assert(src_size > 0);
@ -271,38 +271,40 @@ int decompress_blob_zstd(
assert(dst_size);
assert(*dst_alloc_size == 0 || *dst);
if (src_size > SIZE_MAX/2) /* Overflow? */
return -ENOBUFS;
space = src_size * 2;
if (dst_max > 0 && space > dst_max)
space = dst_max;
size = ZSTD_getFrameContentSize(src, src_size);
if (IN_SET(size, ZSTD_CONTENTSIZE_ERROR, ZSTD_CONTENTSIZE_UNKNOWN))
return -EBADMSG;
if (!greedy_realloc(dst, dst_alloc_size, space, 1))
if (dst_max > 0 && size > dst_max)
size = dst_max;
if (size > SIZE_MAX)
return -E2BIG;
if (!(greedy_realloc(dst, dst_alloc_size, MAX(ZSTD_DStreamOutSize(), size), 1)))
return -ENOMEM;
for (;;) {
size_t k;
_cleanup_(ZSTD_freeDCtxp) ZSTD_DCtx *dctx = ZSTD_createDCtx();
if (!dctx)
return -ENOMEM;
k = ZSTD_decompress(*dst, *dst_alloc_size, src, src_size);
if (!ZSTD_isError(k)) {
*dst_size = k;
return 0;
}
if (ZSTD_getErrorCode(k) != ZSTD_error_dstSize_tooSmall)
return zstd_ret_to_errno(k);
ZSTD_inBuffer input = {
.src = src,
.size = src_size,
};
ZSTD_outBuffer output = {
.dst = *dst,
.size = *dst_alloc_size,
};
if (dst_max > 0 && space >= dst_max) /* Already at max? */
return -ENOBUFS;
if (space > SIZE_MAX / 2) /* Overflow? */
return -ENOBUFS;
space *= 2;
if (dst_max > 0 && space > dst_max)
space = dst_max;
if (!greedy_realloc(dst, dst_alloc_size, space, 1))
return -ENOMEM;
size_t k = ZSTD_decompressStream(dctx, &output, &input);
if (ZSTD_isError(k)) {
log_debug("ZSTD decoder failed: %s", ZSTD_getErrorName(k));
return zstd_ret_to_errno(k);
}
assert(output.pos >= size);
*dst_size = size;
return 0;
#else
return -EPROTONOSUPPORT;
#endif
@ -326,7 +328,7 @@ int decompress_blob(
src, src_size,
dst, dst_alloc_size, dst_size, dst_max);
else
return -EBADMSG;
return -EPROTONOSUPPORT;
}
int decompress_startswith_xz(const void *src, uint64_t src_size,
@ -456,9 +458,6 @@ int decompress_startswith_zstd(
const void *prefix, size_t prefix_len,
uint8_t extra) {
#if HAVE_ZSTD
_cleanup_(ZSTD_freeDCtxp) ZSTD_DCtx *dctx = NULL;
size_t k;
assert(src);
assert(src_size > 0);
assert(buffer);
@ -466,7 +465,14 @@ int decompress_startswith_zstd(
assert(prefix);
assert(*buffer_size == 0 || *buffer);
dctx = ZSTD_createDCtx();
uint64_t size = ZSTD_getFrameContentSize(src, src_size);
if (IN_SET(size, ZSTD_CONTENTSIZE_ERROR, ZSTD_CONTENTSIZE_UNKNOWN))
return -EBADMSG;
if (size < prefix_len + 1)
return 0; /* Decompressed text too short to match the prefix and extra */
_cleanup_(ZSTD_freeDCtxp) ZSTD_DCtx *dctx = ZSTD_createDCtx();
if (!dctx)
return -ENOMEM;
@ -481,30 +487,17 @@ int decompress_startswith_zstd(
.dst = *buffer,
.size = *buffer_size,
};
size_t k;
for (;;) {
k = ZSTD_decompressStream(dctx, &output, &input);
if (ZSTD_isError(k)) {
log_debug("ZSTD decoder failed: %s", ZSTD_getErrorName(k));
return zstd_ret_to_errno(k);
}
if (output.pos >= prefix_len + 1)
return memcmp(*buffer, prefix, prefix_len) == 0 &&
((const uint8_t*) *buffer)[prefix_len] == extra;
if (input.pos >= input.size)
return 0;
if (*buffer_size > SIZE_MAX/2)
return -ENOBUFS;
if (!(greedy_realloc(buffer, buffer_size, *buffer_size * 2, 1)))
return -ENOMEM;
output.dst = *buffer;
output.size = *buffer_size;
k = ZSTD_decompressStream(dctx, &output, &input);
if (ZSTD_isError(k)) {
log_debug("ZSTD decoder failed: %s", ZSTD_getErrorName(k));
return zstd_ret_to_errno(k);
}
assert(output.pos >= prefix_len + 1);
return memcmp(*buffer, prefix, prefix_len) == 0 &&
((const uint8_t*) *buffer)[prefix_len] == extra;
#else
return -EPROTONOSUPPORT;
#endif

View File

@ -127,3 +127,12 @@ void journal_print_header(sd_journal *j);
#define JOURNAL_FOREACH_DATA_RETVAL(j, data, l, retval) \
for (sd_journal_restart_data(j); ((retval) = sd_journal_enumerate_data((j), &(data), &(l))) > 0; )
/* All errors that we might encounter while extracting a field that are not real errors,
* but only mean that the field is too large or we don't support the compression. */
static inline bool JOURNAL_ERRNO_IS_UNAVAILABLE_FIELD(int r) {
return IN_SET(abs(r),
ENOBUFS, /* Field or decompressed field too large */
E2BIG, /* Field too large for pointer width */
EPROTONOSUPPORT); /* Unsupported compression */
}

View File

@ -2462,6 +2462,19 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t
return 1;
}
_public_ int sd_journal_enumerate_available_data(sd_journal *j, const void **data, size_t *size) {
for (;;) {
int r;
r = sd_journal_enumerate_data(j, data, size);
if (r >= 0)
return r;
if (!JOURNAL_ERRNO_IS_UNAVAILABLE_FIELD(r))
return r;
j->current_field++; /* Try with the next field */
}
}
_public_ void sd_journal_restart_data(sd_journal *j) {
if (!j)
return;
@ -3002,6 +3015,20 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
}
}
_public_ int sd_journal_enumerate_available_unique(sd_journal *j, const void **data, size_t *size) {
for (;;) {
int r;
r = sd_journal_enumerate_unique(j, data, size);
if (r >= 0)
return r;
if (!JOURNAL_ERRNO_IS_UNAVAILABLE_FIELD(r))
return r;
/* Try with the next field. sd_journal_enumerate_unique() modifies state, so on the next try
* we will access the next field. */
}
}
_public_ void sd_journal_restart_unique(sd_journal *j) {
if (!j)
return;

View File

@ -232,6 +232,8 @@ static void test_lz4_decompress_partial(void) {
int r;
_cleanup_free_ char *huge = NULL;
log_debug("/* %s */", __func__);
assert_se(huge = malloc(HUGE_SIZE));
memcpy(huge, "HUGE=", STRLEN("HUGE="));
memset(&huge[STRLEN("HUGE=")], 'x', HUGE_SIZE - STRLEN("HUGE=") - 1);

View File

@ -717,4 +717,7 @@ global:
sd_path_lookup_strv;
sd_notify_barrier;
sd_journal_enumerate_available_data;
sd_journal_enumerate_available_unique;
} LIBSYSTEMD_245;

View File

@ -241,7 +241,7 @@ static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *devi
return 0;
}
if (r > 0) {
log_device_debug(device, "Interface is under renaming, wait for the interface to be renamed: %m");
log_device_debug(device, "Interface is under renaming, wait for the interface to be renamed.");
return 0;
}

View File

@ -378,10 +378,13 @@ int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
int add_acls_for_user(int fd, uid_t uid) {
_cleanup_(acl_freep) acl_t acl = NULL;
acl_entry_t entry;
acl_permset_t permset;
acl_entry_t entry;
int r;
assert(fd >= 0);
assert(uid_is_valid(uid));
acl = acl_get_fd(fd);
if (!acl)
return -errno;
@ -394,8 +397,8 @@ int add_acls_for_user(int fd, uid_t uid) {
return -errno;
}
/* We do not recalculate the mask unconditionally here,
* so that the fchmod() mask above stays intact. */
/* We do not recalculate the mask unconditionally here, so that the fchmod() mask above stays
* intact. */
if (acl_get_permset(entry, &permset) < 0 ||
acl_add_perm(permset, ACL_READ) < 0)
return -errno;
@ -404,5 +407,8 @@ int add_acls_for_user(int fd, uid_t uid) {
if (r < 0)
return r;
return acl_set_fd(fd, acl);
if (acl_set_fd(fd, acl) < 0)
return -errno;
return 0;
}

View File

@ -1140,8 +1140,9 @@ static int make_dm_name_and_node(const void *original_node, const char *suffix,
base = strrchr(original_node, '/');
if (!base)
return -EINVAL;
base++;
base = original_node;
else
base++;
if (isempty(base))
return -EINVAL;
@ -1217,6 +1218,50 @@ static int decrypt_partition(
return 0;
}
static int verity_can_reuse(const void *root_hash, size_t root_hash_size, bool has_sig, const char *name, struct crypt_device **ret_cd) {
/* If the same volume was already open, check that the root hashes match, and reuse it if they do */
_cleanup_free_ char *root_hash_existing = NULL;
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
struct crypt_params_verity crypt_params = {};
size_t root_hash_existing_size = root_hash_size;
int r;
assert(ret_cd);
r = crypt_init_by_name(&cd, name);
if (r < 0)
return log_debug_errno(r, "Error opening verity device, crypt_init_by_name failed: %m");
r = crypt_get_verity_info(cd, &crypt_params);
if (r < 0)
return log_debug_errno(r, "Error opening verity device, crypt_get_verity_info failed: %m");
root_hash_existing = malloc0(root_hash_size);
if (!root_hash_existing)
return -ENOMEM;
r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash_existing, &root_hash_existing_size, NULL, 0);
if (r < 0)
return log_debug_errno(r, "Error opening verity device, crypt_volume_key_get failed: %m");
if (root_hash_size != root_hash_existing_size || memcmp(root_hash_existing, root_hash, root_hash_size) != 0)
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Error opening verity device, it already exists but root hashes are different.");
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
/* Ensure that, if signatures are supported, we only reuse the device if the previous mount
* used the same settings, so that a previous unsigned mount will not be reused if the user
* asks to use signing for the new one, and viceversa. */
if (has_sig != !!(crypt_params.flags & CRYPT_VERITY_ROOT_HASH_SIGNATURE))
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Error opening verity device, it already exists but signature settings are not the same.");
#endif
*ret_cd = TAKE_PTR(cd);
return 0;
}
static inline void dm_deferred_remove_clean(char *name) {
if (!name)
return;
(void) crypt_deactivate_by_name(NULL, name, CRYPT_DEACTIVATE_DEFERRED);
free(name);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char *, dm_deferred_remove_clean);
static int verity_partition(
DissectedPartition *m,
DissectedPartition *v,
@ -1229,8 +1274,9 @@ static int verity_partition(
DissectImageFlags flags,
DecryptedImage *d) {
_cleanup_free_ char *node = NULL, *name = NULL;
_cleanup_free_ char *node = NULL, *name = NULL, *hash_sig_from_file = NULL;
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
_cleanup_(dm_deferred_remove_cleanp) char *restore_deferred_remove = NULL;
int r;
assert(m);
@ -1249,12 +1295,23 @@ static int verity_partition(
return 0;
}
r = make_dm_name_and_node(m->node, "-verity", &name, &node);
if (FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE)) {
/* Use the roothash, which is unique per volume, as the device node name, so that it can be reused */
_cleanup_free_ char *root_hash_encoded = NULL;
root_hash_encoded = hexmem(root_hash, root_hash_size);
if (!root_hash_encoded)
return -ENOMEM;
r = make_dm_name_and_node(root_hash_encoded, "-verity", &name, &node);
} else
r = make_dm_name_and_node(m->node, "-verity", &name, &node);
if (r < 0)
return r;
if (!GREEDY_REALLOC0(d->decrypted, d->n_allocated, d->n_decrypted + 1))
return -ENOMEM;
if (!root_hash_sig && root_hash_sig_path) {
r = read_full_file_full(AT_FDCWD, root_hash_sig_path, 0, &hash_sig_from_file, &root_hash_sig_size);
if (r < 0)
return r;
}
r = crypt_init(&cd, verity_data ?: v->node);
if (r < 0)
@ -1270,27 +1327,69 @@ static int verity_partition(
if (r < 0)
return r;
if (root_hash_sig || root_hash_sig_path) {
if (!GREEDY_REALLOC0(d->decrypted, d->n_allocated, d->n_decrypted + 1))
return -ENOMEM;
/* If activating fails because the device already exists, check the metadata and reuse it if it matches.
* In case of ENODEV/ENOENT, which can happen if another process is activating at the exact same time,
* retry a few times before giving up. */
for (unsigned i = 0; i < N_DEVICE_NODE_LIST_ATTEMPTS; i++) {
if (root_hash_sig || hash_sig_from_file) {
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
if (root_hash_sig)
r = crypt_activate_by_signed_key(cd, name, root_hash, root_hash_size, root_hash_sig, root_hash_sig_size, CRYPT_ACTIVATE_READONLY);
else {
_cleanup_free_ char *hash_sig = NULL;
size_t hash_sig_size;
r = read_full_file_full(AT_FDCWD, root_hash_sig_path, 0, &hash_sig, &hash_sig_size);
if (r < 0)
return r;
r = crypt_activate_by_signed_key(cd, name, root_hash, root_hash_size, hash_sig, hash_sig_size, CRYPT_ACTIVATE_READONLY);
}
r = crypt_activate_by_signed_key(cd, name, root_hash, root_hash_size, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, CRYPT_ACTIVATE_READONLY);
#else
r = log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "activation of verity device with signature requested, but not supported by cryptsetup due to missing crypt_activate_by_signed_key()");
r = log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "activation of verity device with signature requested, but not supported by cryptsetup due to missing crypt_activate_by_signed_key()");
#endif
} else
r = crypt_activate_by_volume_key(cd, name, root_hash, root_hash_size, CRYPT_ACTIVATE_READONLY);
if (r < 0)
return r;
} else
r = crypt_activate_by_volume_key(cd, name, root_hash, root_hash_size, CRYPT_ACTIVATE_READONLY);
/* libdevmapper can return EINVAL when the device is already in the activation stage.
* There's no way to distinguish this situation from a genuine error due to invalid
* parameters, so immediately fallback to activating the device with a unique name.
* Improvements in libcrypsetup can ensure this never happens: https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/96 */
if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
return verity_partition(m, v, root_hash, root_hash_size, verity_data, NULL, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
if (!IN_SET(r, 0, -EEXIST, -ENODEV))
return r;
if (r == -EEXIST) {
struct crypt_device *existing_cd = NULL;
if (!restore_deferred_remove){
/* To avoid races, disable automatic removal on umount while setting up the new device. Restore it on failure. */
r = dm_deferred_remove_cancel(name);
if (r < 0)
return log_debug_errno(r, "Disabling automated deferred removal for verity device %s failed: %m", node);
restore_deferred_remove = strdup(name);
if (!restore_deferred_remove)
return -ENOMEM;
}
r = verity_can_reuse(root_hash, root_hash_size, !!root_hash_sig || !!hash_sig_from_file, name, &existing_cd);
/* Same as above, -EINVAL can randomly happen when it actually means -EEXIST */
if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
return verity_partition(m, v, root_hash, root_hash_size, verity_data, NULL, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
if (!IN_SET(r, 0, -ENODEV, -ENOENT))
return log_debug_errno(r, "Checking whether existing verity device %s can be reused failed: %m", node);
if (r == 0) {
if (cd)
crypt_free(cd);
cd = existing_cd;
}
}
if (r == 0)
break;
}
/* Sanity check: libdevmapper is known to report that the device already exists and is active,
* but it's actually not there, so the later filesystem probe or mount would fail. */
if (r == 0)
r = access(node, F_OK);
/* An existing verity device was reported by libcryptsetup/libdevmapper, but we can't use it at this time.
* Fall back to activating it with a unique device name. */
if (r != 0 && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
return verity_partition(m, v, root_hash, root_hash_size, verity_data, NULL, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
/* Everything looks good and we'll be able to mount the device, so deferred remove will be re-enabled at that point. */
restore_deferred_remove = mfree(restore_deferred_remove);
d->decrypted[d->n_decrypted].name = TAKE_PTR(name);
d->decrypted[d->n_decrypted].device = TAKE_PTR(cd);
@ -1357,7 +1456,7 @@ int dissected_image_decrypt(
k = PARTITION_VERITY_OF(i);
if (k >= 0) {
r = verity_partition(p, m->partitions + k, root_hash, root_hash_size, verity_data, root_hash_sig_path, root_hash_sig, root_hash_sig_size, flags, d);
r = verity_partition(p, m->partitions + k, root_hash, root_hash_size, verity_data, root_hash_sig_path, root_hash_sig, root_hash_sig_size, flags | DISSECT_IMAGE_VERITY_SHARE, d);
if (r < 0)
return r;
}
@ -1437,7 +1536,7 @@ int decrypted_image_relinquish(DecryptedImage *d) {
if (p->relinquished)
continue;
r = dm_deferred_remove(p->name);
r = crypt_deactivate_by_name(NULL, p->name, CRYPT_DEACTIVATE_DEFERRED);
if (r < 0)
return log_debug_errno(r, "Failed to mark %s for auto-removal: %m", p->name);

View File

@ -64,6 +64,7 @@ typedef enum DissectImageFlags {
DISSECT_IMAGE_RELAX_VAR_CHECK = 1 << 10, /* Don't insist that the UUID of /var is hashed from /etc/machine-id */
DISSECT_IMAGE_FSCK = 1 << 11, /* File system check the partition before mounting (no effect when combined with DISSECT_IMAGE_READ_ONLY) */
DISSECT_IMAGE_NO_PARTITION_TABLE = 1 << 12, /* Only recognize single file system images */
DISSECT_IMAGE_VERITY_SHARE = 1 << 13, /* When activating a verity device, reuse existing one if already open */
} DissectImageFlags;
struct DissectedImage {

View File

@ -6,35 +6,37 @@
#include "fd-util.h"
#include "string-util.h"
int dm_deferred_remove(const char *name) {
struct dm_ioctl dm = {
.version = {
DM_VERSION_MAJOR,
DM_VERSION_MINOR,
DM_VERSION_PATCHLEVEL
},
.data_size = sizeof(dm),
.flags = DM_DEFERRED_REMOVE,
};
int dm_deferred_remove_cancel(const char *name) {
_cleanup_close_ int fd = -1;
struct message {
struct dm_ioctl dm_ioctl;
struct dm_target_msg dm_target_msg;
char msg_text[STRLEN("@cancel_deferred_remove") + 1];
} _packed_ message = {
.dm_ioctl = {
.version = {
DM_VERSION_MAJOR,
DM_VERSION_MINOR,
DM_VERSION_PATCHLEVEL
},
.data_size = sizeof(struct message),
.data_start = sizeof(struct dm_ioctl),
},
.msg_text = "@cancel_deferred_remove",
};
assert(name);
/* Unfortunately, libcryptsetup doesn't provide a proper API for this, hence call the ioctl()
* directly. */
if (strlen(name) >= sizeof(dm.name))
if (strlen(name) >= sizeof(message.dm_ioctl.name))
return -ENODEV; /* A device with a name longer than this cannot possibly exist */
strncpy_exact(message.dm_ioctl.name, name, sizeof(message.dm_ioctl.name));
fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
if (fd < 0)
return -errno;
strncpy_exact(dm.name, name, sizeof(dm.name));
if (ioctl(fd, DM_DEV_REMOVE, &dm))
if (ioctl(fd, DM_TARGET_MSG, &message))
return -errno;
return 0;

View File

@ -1,4 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
int dm_deferred_remove(const char *name);
int dm_deferred_remove_cancel(const char *name);

View File

@ -105,6 +105,7 @@ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz);
int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l);
int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l);
int sd_journal_enumerate_available_data(sd_journal *j, const void **data, size_t *l);
void sd_journal_restart_data(sd_journal *j);
int sd_journal_add_match(sd_journal *j, const void *data, size_t size);
@ -128,6 +129,7 @@ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes);
int sd_journal_query_unique(sd_journal *j, const char *field);
int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l);
int sd_journal_enumerate_available_unique(sd_journal *j, const void **data, size_t *l);
void sd_journal_restart_unique(sd_journal *j);
int sd_journal_enumerate_fields(sd_journal *j, const char **field);
@ -156,13 +158,13 @@ int sd_journal_has_persistent_files(sd_journal *j);
if (sd_journal_seek_tail(j) < 0) { } \
else while (sd_journal_previous(j) > 0)
/* Iterate through the data fields of the current journal entry */
/* Iterate through all available data fields of the current journal entry */
#define SD_JOURNAL_FOREACH_DATA(j, data, l) \
for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
for (sd_journal_restart_data(j); sd_journal_enumerate_available_data((j), &(data), &(l)) > 0; )
/* Iterate through the all known values of a specific field */
/* Iterate through all available values of a specific field */
#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \
for (sd_journal_restart_unique(j); sd_journal_enumerate_unique((j), &(data), &(l)) > 0; )
for (sd_journal_restart_unique(j); sd_journal_enumerate_available_unique((j), &(data), &(l)) > 0; )
/* Iterate through all known field names */
#define SD_JOURNAL_FOREACH_FIELD(j, field) \

View File

@ -840,11 +840,6 @@ static int rename_netif(UdevEvent *event) {
if (r < 0)
return log_device_error_errno(dev, r, "Failed to get ifindex: %m");
r = rtnl_set_link_name(&event->rtnl, ifindex, event->name);
if (r < 0)
return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m",
ifindex, oldname, event->name);
/* Set ID_RENAMING boolean property here, and drop it in the corresponding move uevent later. */
r = device_add_property(dev, "ID_RENAMING", "1");
if (r < 0)
@ -854,6 +849,22 @@ static int rename_netif(UdevEvent *event) {
if (r < 0)
return log_device_warning_errno(dev, r, "Failed to update properties with new name '%s': %m", event->name);
/* Also set ID_RENAMING boolean property to cloned sd_device object and save it to database
* before calling rtnl_set_link_name(). Otherwise, clients (e.g., systemd-networkd) may receive
* RTM_NEWLINK netlink message before the database is updated. */
r = device_add_property(event->dev_db_clone, "ID_RENAMING", "1");
if (r < 0)
return log_device_warning_errno(event->dev_db_clone, r, "Failed to add 'ID_RENAMING' property: %m");
r = device_update_db(event->dev_db_clone);
if (r < 0)
return log_device_debug_errno(event->dev_db_clone, r, "Failed to update database under /run/udev/data/: %m");
r = rtnl_set_link_name(&event->rtnl, ifindex, event->name);
if (r < 0)
return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m",
ifindex, oldname, event->name);
log_device_debug(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, oldname, event->name);
return 1;
@ -870,8 +881,7 @@ static int update_devnode(UdevEvent *event) {
return log_device_error_errno(dev, r, "Failed to get devnum: %m");
/* remove/update possible left-over symlinks from old database entry */
if (event->dev_db_clone)
(void) udev_node_update_old_links(dev, event->dev_db_clone);
(void) udev_node_update_old_links(dev, event->dev_db_clone);
if (!uid_is_valid(event->uid)) {
r = device_get_devnode_uid(dev, &event->uid);
@ -934,8 +944,7 @@ static int udev_event_on_move(UdevEvent *event) {
sd_device *dev = event->dev;
int r;
if (event->dev_db_clone &&
sd_device_get_devnum(dev, NULL) < 0) {
if (sd_device_get_devnum(dev, NULL) < 0) {
r = device_copy_properties(dev, event->dev_db_clone);
if (r < 0)
log_device_debug_errno(dev, r, "Failed to copy properties from cloned sd_device object, ignoring: %m");
@ -981,7 +990,7 @@ int udev_event_execute_rules(UdevEvent *event,
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to clone sd_device object: %m");
if (event->dev_db_clone && sd_device_get_devnum(dev, NULL) >= 0)
if (sd_device_get_devnum(dev, NULL) >= 0)
/* Disable watch during event processing. */
(void) udev_watch_end(event->dev_db_clone);
@ -1019,8 +1028,6 @@ int udev_event_execute_rules(UdevEvent *event,
device_set_is_initialized(dev);
event->dev_db_clone = sd_device_unref(event->dev_db_clone);
return 0;
}

View File

@ -633,6 +633,9 @@ install_dmevent() {
else
inst_rules 10-dm.rules 13-dm-disk.rules 95-dm-notify.rules
fi
if [[ "$LOOKS_LIKE_SUSE" ]]; then
inst_rules 60-persistent-storage.rules 61-persistent-storage-compat.rules 99-systemd.rules
fi
}
install_systemd() {
@ -932,7 +935,7 @@ install_config_files() {
inst /etc/sysconfig/init || :
inst /etc/passwd
inst /etc/shadow
inst /etc/login.defs
inst_any /etc/login.defs /usr/etc/login.defs
inst /etc/group
inst /etc/shells
inst_any /etc/nsswitch.conf /usr/etc/nsswitch.conf
@ -1948,6 +1951,7 @@ setup_suse() {
ln -fs ../usr/bin/systemctl $initdir/bin/
ln -fs ../usr/lib/systemd $initdir/lib/
inst_simple "/usr/lib/systemd/system/haveged.service"
instmods ext4
}
_umount_dir() {

View File

@ -40,12 +40,23 @@ mv ${image}.roothash ${image}.foohash
mv ${image}.fooverity ${image}.verity
mv ${image}.foohash ${image}.roothash
mkdir -p ${image_dir}/mount
mkdir -p ${image_dir}/mount ${image_dir}/mount2
/usr/lib/systemd/systemd-dissect --mount ${image}.raw ${image_dir}/mount
cat ${image_dir}/mount/usr/lib/os-release | grep -q -F -f /usr/lib/os-release
cat ${image_dir}/mount/etc/os-release | grep -q -F -f /usr/lib/os-release
cat ${image_dir}/mount/usr/lib/os-release | grep -q -F "MARKER=1"
# Verity volume should be shared (opened only once)
/usr/lib/systemd/systemd-dissect --mount ${image}.raw ${image_dir}/mount2
verity_count=$(ls -1 /dev/mapper/ | grep -c verity)
# In theory we should check that count is exactly one. In practice, libdevmapper
# randomly and unpredictably fails with an unhelpful EINVAL when a device is open
# (and even mounted and in use), so best-effort is the most we can do for now
if [ ${verity_count} -lt 1 ]; then
echo "Verity device ${image}.raw not found in /dev/mapper/"
exit 1
fi
umount ${image_dir}/mount
umount ${image_dir}/mount2
systemd-run -t --property RootImage=${image}.raw /usr/bin/cat /usr/lib/os-release | grep -q -F "MARKER=1"
mv ${image}.verity ${image}.fooverity