]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #16407 from bluca/verity_reuse
authorLennart Poettering <lennart@poettering.net>
Wed, 22 Jul 2020 09:36:49 +0000 (11:36 +0200)
committerGitHub <noreply@github.com>
Wed, 22 Jul 2020 09:36:49 +0000 (11:36 +0200)
verity: re-use already open devices if the hashes match

14 files changed:
TODO
man/sd_journal_get_data.xml
man/sd_journal_query_unique.xml
man/systemd.exec.xml
src/coredump/coredump.c
src/home/homectl-pkcs11.c
src/journal/compress.c
src/journal/journal-internal.h
src/journal/sd-journal.c
src/journal/test-compress.c
src/libsystemd/libsystemd.sym
src/shared/acl-util.c
src/systemd/sd-journal.h
test/test-functions

diff --git a/TODO b/TODO
index f1593a2c02a67723f56f921fada6b1e7fa6c6b32..099ce36f01a310437e91ad56834030d326ffb17a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -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() inhe 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
index 0a0030e3007fdba6b5ba987bb5368a99b18896ab..209f5deaa1dde53b989b7aa11e6361c4ca647a5f 100644 (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>
         <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>
   <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
     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>
   <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>
index 1bf83968dd3c16710122f7223c416c2dcb1474af..88beaa6460cd4f05904a656de68395f6db583481 100644 (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>
         <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>
   <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_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_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 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
     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
   <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>
   <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>
index 6d6eca09a133dba29192f93bb71b6e2e8b27087e..8afcbd246f7c04ce11b74b1018a158bfa51d4c4b 100644 (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>
index 1a41f260499e4b2641229fe9903cac621f99d951..8b052dac26cb9636993a2816aa0507d588c08758 100644 (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;
index 830aafaab14494b6ce7ac835a2ebe960ae36bc1a..f4253ed7bf28d583b45420f89a6a49894caa256f 100644 (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,
index e6ce64fc6529efafa2c9717c92b94f83d879be37..a59c2b7a88397d4a1d21314f8dcf3063e16ebc90 100644 (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_tdst_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;
-
-        if (!greedy_realloc(dst, dst_alloc_size, space, 1))
-                return -ENOMEM;
+        size = ZSTD_getFrameContentSize(src, src_size);
+        if (IN_SET(size, ZSTD_CONTENTSIZE_ERROR, ZSTD_CONTENTSIZE_UNKNOWN))
+                return -EBADMSG;
 
-        for (;;) {
-                size_t k;
+        if (dst_max > 0 && size > dst_max)
+                size = dst_max;
+        if (size > SIZE_MAX)
+                return -E2BIG;
 
-                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);
+        if (!(greedy_realloc(dst, dst_alloc_size, MAX(ZSTD_DStreamOutSize(), size), 1)))
+                return -ENOMEM;
 
-                if (dst_max > 0 && space >= dst_max) /* Already at max? */
-                        return -ENOBUFS;
-                if (space > SIZE_MAX / 2) /* Overflow? */
-                        return -ENOBUFS;
+        _cleanup_(ZSTD_freeDCtxp) ZSTD_DCtx *dctx = ZSTD_createDCtx();
+        if (!dctx)
+                return -ENOMEM;
 
-                space *= 2;
-                if (dst_max > 0 && space > dst_max)
-                        space = dst_max;
+        ZSTD_inBuffer input = {
+                .src = src,
+                .size = src_size,
+        };
+        ZSTD_outBuffer output = {
+                .dst = *dst,
+                .size = *dst_alloc_size,
+        };
 
-                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
index a649acf634e74d4409da33af209cce716f5a7eaa..d87b0a11e5899dc55d49500554ba001ab06ea555 100644 (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 */
+}
index 853dd0c28b7c92ef2808d5889f59200a3b67aca9..6fb0abb419d9e97f23083071537d813818c91c51 100644 (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;
index 0990f7604d549d5bc2660b353c4810dc272f0c52..f50fb0acea82dc635bb5759137e9011a7e2efaeb 100644 (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);
index 6f00985f5d8ae646187bb7a51dd97b5831ee4697..1e654b49ea3c1b07b10b87327bd993efa65a1917 100644 (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;
index 1ccb4f8295f06a013060881c5defc290f9cd0de6..dd2b1efb112901fd80a99ff11156c82bb6ebf9c4 100644 (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;
 }
index a232992f0307b314cc63f36b369a9f97e4f7c4c2..d220f21aa29f518578d22d619f19aeefa250cfe8 100644 (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) \
index 456bfe666919a69ce8cac789b9daa0056cd836cf..863cc18aeff0d29cbe9e801b7f72c70f5604768e 100644 (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() {