1
0
mirror of https://github.com/systemd/systemd synced 2025-11-10 04:14:44 +01:00

Compare commits

..

No commits in common. "2859bb932bac2cba0a5200e35b50b404d4e3650e" and "002674387c595322ced45797652707f253d92f13" have entirely different histories.

22 changed files with 232 additions and 467 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() in the header,
- journal: store timestamp of journal_file_set_offline() int he 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,7 +1071,6 @@ 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,7 +18,6 @@
<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>
@ -45,13 +44,6 @@
<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>
@ -81,18 +73,24 @@
<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>,
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_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_enumerate_data()</function> may be used
to iterate through all fields of the current entry. On each
@ -101,18 +99,15 @@
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_available_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_data()</function>.</para>
<para>Note that these functions will not work before
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>
@ -144,88 +139,18 @@
<refsect1>
<title>Return Value</title>
<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>
<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>
</refsect1>
<refsect1>

View File

@ -18,7 +18,6 @@
<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>
@ -34,13 +33,6 @@
<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>
@ -66,31 +58,33 @@
<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>,
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_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_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_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_restart_unique()</function> resets the
data enumeration index to the beginning of the list. The next
@ -98,9 +92,11 @@
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_available_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_unique()</function>.</para>
<para>Note that these functions currently are not influenced by
matches set with <function>sd_journal_add_match()</function> but
@ -115,29 +111,13 @@
<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> 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>
<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>
</refsect1>
<refsect1>
@ -151,9 +131,10 @@
<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 (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>
<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>
<programlisting><xi:include href="journal-iterate-unique.c" parse="text" /></programlisting>
</refsect1>

View File

@ -2163,7 +2163,13 @@ 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></listitem>
<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>
</varlistentry>
<varlistentry>

View File

@ -177,18 +177,38 @@ 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 */
r = add_acls_for_user(fd, uid);
/* 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);
if (r < 0)
return log_error_errno(r, "Failed to adjust ACL of coredump: %m");
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");
#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 = crypt_deactivate_by_name(NULL, setup.dm_name, CRYPT_DEACTIVATE_DEFERRED);
r = dm_deferred_remove(setup.dm_name);
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
uint64_t size;
size_t space;
assert(src);
assert(src_size > 0);
@ -271,40 +271,38 @@ int decompress_blob_zstd(
assert(dst_size);
assert(*dst_alloc_size == 0 || *dst);
size = ZSTD_getFrameContentSize(src, src_size);
if (IN_SET(size, ZSTD_CONTENTSIZE_ERROR, ZSTD_CONTENTSIZE_UNKNOWN))
return -EBADMSG;
if (src_size > SIZE_MAX/2) /* Overflow? */
return -ENOBUFS;
space = src_size * 2;
if (dst_max > 0 && space > dst_max)
space = dst_max;
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)))
if (!greedy_realloc(dst, dst_alloc_size, space, 1))
return -ENOMEM;
_cleanup_(ZSTD_freeDCtxp) ZSTD_DCtx *dctx = ZSTD_createDCtx();
if (!dctx)
return -ENOMEM;
for (;;) {
size_t k;
ZSTD_inBuffer input = {
.src = src,
.size = src_size,
};
ZSTD_outBuffer output = {
.dst = *dst,
.size = *dst_alloc_size,
};
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);
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);
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;
}
assert(output.pos >= size);
*dst_size = size;
return 0;
#else
return -EPROTONOSUPPORT;
#endif
@ -328,7 +326,7 @@ int decompress_blob(
src, src_size,
dst, dst_alloc_size, dst_size, dst_max);
else
return -EPROTONOSUPPORT;
return -EBADMSG;
}
int decompress_startswith_xz(const void *src, uint64_t src_size,
@ -458,6 +456,9 @@ 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);
@ -465,14 +466,7 @@ int decompress_startswith_zstd(
assert(prefix);
assert(*buffer_size == 0 || *buffer);
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();
dctx = ZSTD_createDCtx();
if (!dctx)
return -ENOMEM;
@ -487,17 +481,30 @@ int decompress_startswith_zstd(
.dst = *buffer,
.size = *buffer_size,
};
size_t k;
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);
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;
}
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,12 +127,3 @@ 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,19 +2462,6 @@ _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;
@ -3015,20 +3002,6 @@ _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,8 +232,6 @@ 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,7 +717,4 @@ 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.");
log_device_debug(device, "Interface is under renaming, wait for the interface to be renamed: %m");
return 0;
}

View File

@ -378,13 +378,10 @@ 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_permset_t permset;
acl_entry_t entry;
acl_permset_t permset;
int r;
assert(fd >= 0);
assert(uid_is_valid(uid));
acl = acl_get_fd(fd);
if (!acl)
return -errno;
@ -397,8 +394,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;
@ -407,8 +404,5 @@ int add_acls_for_user(int fd, uid_t uid) {
if (r < 0)
return r;
if (acl_set_fd(fd, acl) < 0)
return -errno;
return 0;
return acl_set_fd(fd, acl);
}

View File

@ -1140,9 +1140,8 @@ static int make_dm_name_and_node(const void *original_node, const char *suffix,
base = strrchr(original_node, '/');
if (!base)
base = original_node;
else
base++;
return -EINVAL;
base++;
if (isempty(base))
return -EINVAL;
@ -1218,50 +1217,6 @@ 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,
@ -1274,9 +1229,8 @@ static int verity_partition(
DissectImageFlags flags,
DecryptedImage *d) {
_cleanup_free_ char *node = NULL, *name = NULL, *hash_sig_from_file = NULL;
_cleanup_free_ char *node = NULL, *name = NULL;
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
_cleanup_(dm_deferred_remove_cleanp) char *restore_deferred_remove = NULL;
int r;
assert(m);
@ -1295,23 +1249,12 @@ static int verity_partition(
return 0;
}
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);
r = make_dm_name_and_node(m->node, "-verity", &name, &node);
if (r < 0)
return r;
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;
}
if (!GREEDY_REALLOC0(d->decrypted, d->n_allocated, d->n_decrypted + 1))
return -ENOMEM;
r = crypt_init(&cd, verity_data ?: v->node);
if (r < 0)
@ -1327,69 +1270,27 @@ static int verity_partition(
if (r < 0)
return r;
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 (root_hash_sig || root_hash_sig_path) {
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
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_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);
/* 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 (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;
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 = read_full_file_full(AT_FDCWD, root_hash_sig_path, 0, &hash_sig, &hash_sig_size);
if (r < 0)
return r;
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;
}
r = crypt_activate_by_signed_key(cd, name, root_hash, root_hash_size, hash_sig, hash_sig_size, CRYPT_ACTIVATE_READONLY);
}
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);
#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()");
#endif
} else
r = crypt_activate_by_volume_key(cd, name, root_hash, root_hash_size, CRYPT_ACTIVATE_READONLY);
if (r < 0)
return r;
d->decrypted[d->n_decrypted].name = TAKE_PTR(name);
d->decrypted[d->n_decrypted].device = TAKE_PTR(cd);
@ -1456,7 +1357,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 | DISSECT_IMAGE_VERITY_SHARE, 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, d);
if (r < 0)
return r;
}
@ -1536,7 +1437,7 @@ int decrypted_image_relinquish(DecryptedImage *d) {
if (p->relinquished)
continue;
r = crypt_deactivate_by_name(NULL, p->name, CRYPT_DEACTIVATE_DEFERRED);
r = dm_deferred_remove(p->name);
if (r < 0)
return log_debug_errno(r, "Failed to mark %s for auto-removal: %m", p->name);

View File

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

View File

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

View File

@ -105,7 +105,6 @@ 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);
@ -129,7 +128,6 @@ 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);
@ -158,13 +156,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 all available data fields of the current journal entry */
/* Iterate through the data fields of the current journal entry */
#define SD_JOURNAL_FOREACH_DATA(j, data, l) \
for (sd_journal_restart_data(j); sd_journal_enumerate_available_data((j), &(data), &(l)) > 0; )
for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
/* Iterate through all available values of a specific field */
/* Iterate through the all known values of a specific field */
#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \
for (sd_journal_restart_unique(j); sd_journal_enumerate_available_unique((j), &(data), &(l)) > 0; )
for (sd_journal_restart_unique(j); sd_journal_enumerate_unique((j), &(data), &(l)) > 0; )
/* Iterate through all known field names */
#define SD_JOURNAL_FOREACH_FIELD(j, field) \

View File

@ -840,6 +840,11 @@ 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)
@ -849,22 +854,6 @@ 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;
@ -881,7 +870,8 @@ 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 */
(void) udev_node_update_old_links(dev, event->dev_db_clone);
if (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);
@ -944,7 +934,8 @@ static int udev_event_on_move(UdevEvent *event) {
sd_device *dev = event->dev;
int r;
if (sd_device_get_devnum(dev, NULL) < 0) {
if (event->dev_db_clone &&
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");
@ -990,7 +981,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 (sd_device_get_devnum(dev, NULL) >= 0)
if (event->dev_db_clone && sd_device_get_devnum(dev, NULL) >= 0)
/* Disable watch during event processing. */
(void) udev_watch_end(event->dev_db_clone);
@ -1028,6 +1019,8 @@ 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,9 +633,6 @@ 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() {
@ -935,7 +932,7 @@ install_config_files() {
inst /etc/sysconfig/init || :
inst /etc/passwd
inst /etc/shadow
inst_any /etc/login.defs /usr/etc/login.defs
inst /etc/login.defs
inst /etc/group
inst /etc/shells
inst_any /etc/nsswitch.conf /usr/etc/nsswitch.conf
@ -1951,7 +1948,6 @@ 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,23 +40,12 @@ mv ${image}.roothash ${image}.foohash
mv ${image}.fooverity ${image}.verity
mv ${image}.foohash ${image}.roothash
mkdir -p ${image_dir}/mount ${image_dir}/mount2
mkdir -p ${image_dir}/mount
/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