]> git.proxmox.com Git - systemd.git/commitdiff
New upstream version 246.4
authorMichael Biebl <biebl@debian.org>
Wed, 2 Sep 2020 11:28:10 +0000 (13:28 +0200)
committerMichael Biebl <biebl@debian.org>
Wed, 2 Sep 2020 11:28:10 +0000 (13:28 +0200)
49 files changed:
man/networkctl.xml
man/org.freedesktop.systemd1.xml
man/sd_bus_message_append.xml
man/sd_bus_message_read.xml
man/sd_bus_message_read_basic.xml
man/sd_listen_fds.xml
man/systemctl.xml
man/systemd.service.xml
man/systemd.socket.xml
man/systemd.time.xml
shell-completion/zsh/_networkctl
src/analyze/analyze.c
src/basic/missing_capability.h
src/basic/path-util.c
src/basic/siphash24.h
src/core/load-fragment.c
src/core/main.c
src/core/manager.c
src/core/manager.h
src/core/mount-setup.c
src/core/transaction.c
src/core/unit.c
src/core/unit.h
src/coredump/coredump.c
src/firstboot/firstboot.c
src/home/homed-home.c
src/login/logind.h
src/login/user-runtime-dir.c
src/network/networkctl.c
src/network/networkd-dhcp6.c
src/nspawn/nspawn.c
src/partition/makefs.c
src/partition/test-repart.sh
src/resolve/resolved-dns-transaction.c
src/shared/ask-password-api.c
src/shared/dev-setup.c
src/shared/dev-setup.h
src/shared/dissect-image.c
src/shared/group-record-nss.c
src/shared/libcrypt-util.c
src/shared/libcrypt-util.h
src/shared/unit-file.c
src/shared/unit-file.h
src/shared/user-record-nss.c
src/shared/varlink.c
src/test/test-dev-setup.c
src/tty-ask-password-agent/tty-ask-password-agent.c
src/userdb/userdbctl.c
units/meson.build

index bd958fb1e0152905dd027e2a43f7ce98309202ad..5a6ca5ab2752cb3d6d8fed8fe35ae064fd40d75e 100644 (file)
@@ -255,6 +255,7 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
        <varlistentry>
         <term>
           <command>delete</command>
+          <replaceable>DEVICE…</replaceable>
         </term>
         <listitem><para>Deletes virtual netdevs. Takes interface name or index number.</para></listitem>
       </varlistentry>
@@ -262,6 +263,7 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
        <varlistentry>
         <term>
           <command>up</command>
+          <replaceable>DEVICE…</replaceable>
         </term>
         <listitem><para>Bring devices up. Takes interface name or index number.</para></listitem>
       </varlistentry>
@@ -269,6 +271,7 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
        <varlistentry>
         <term>
           <command>down</command>
+          <replaceable>DEVICE…</replaceable>
         </term>
         <listitem><para>Bring devices down. Takes interface name or index number.</para></listitem>
       </varlistentry>
@@ -276,6 +279,7 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
        <varlistentry>
         <term>
           <command>renew</command>
+          <replaceable>DEVICE…</replaceable>
         </term>
         <listitem><para>Renew dynamic configurations e.g. addresses received from DHCP server.
         Takes interface name or index number.</para></listitem>
@@ -284,6 +288,7 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
       <varlistentry>
         <term>
           <command>forcerenew</command>
+          <replaceable>DEVICE…</replaceable>
         </term>
         <listitem><para>Send a FORCERENEW message to all connected clients, triggering DHCP reconfiguration.
         Takes interface name or index number.</para></listitem>
@@ -292,6 +297,7 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
       <varlistentry>
         <term>
           <command>reconfigure</command>
+          <replaceable>DEVICE…</replaceable>
         </term>
         <listitem><para>Reconfigure network interfaces. Takes interface name or index number.</para></listitem>
       </varlistentry>
index 12e18109b2701474c3dc04ec1958aa25f5d0a534..ef9dfb4f13d2624c3d988f4a94a80a65075a53aa 100644 (file)
@@ -2698,12 +2698,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <!--property RestartUSec is not documented!-->
 
-    <!--property TimeoutStartUSec is not documented!-->
-
-    <!--property TimeoutStopUSec is not documented!-->
-
-    <!--property TimeoutAbortUSec is not documented!-->
-
     <!--property TimeoutStartFailureMode is not documented!-->
 
     <!--property TimeoutStopFailureMode is not documented!-->
@@ -3706,6 +3700,18 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
       <para>Most properties of the Service interface map directly to the corresponding settings in service
       unit files. For the sake of brevity, here's a list of all exceptions only:</para>
 
+      <para><varname>TimeoutStartUSec</varname>, <varname>TimeoutStopUSec</varname> and
+      <varname>TimeoutAbortUSec</varname> contain the start, stop and abort timeouts, in microseconds. Note
+      the slight difference in naming when compared to the matching unit file settings (see
+      <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>7</manvolnum></citerefentry>):
+      these bus properties strictly use microseconds (and thus are suffixed <varname>…USec</varname>) while
+      the unit file settings default to a time unit of seconds (and thus are suffixed
+      <varname>…Sec</varname>), unless a different unit is explicitly specified. This reflects that fact that
+      internally the service manager deals in microsecond units only, and the bus properties are a relatively
+      low-level (binary) concept exposing this. The unit file settings on the other hand are relatively
+      high-level (string-based) concepts and thus support more user friendly time specifications which
+      default to second time units but allow other units too, if specified.</para>
+
       <para><varname>WatchdogTimestamp</varname> and <varname>WatchdogTimestampMonotonic</varname> contain
       <constant>CLOCK_REALTIME</constant>/<constant>CLOCK_MONOTONIC</constant> microsecond timestamps of the
       last watchdog ping received from the service, or 0 if none was ever received.</para>
@@ -8968,8 +8974,6 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
 
     <!--method AttachProcesses is not documented!-->
 
-    <!--property TimeoutStopUSec is not documented!-->
-
     <!--property RuntimeMaxUSec is not documented!-->
 
     <!--property Slice is not documented!-->
index 5faadd603a123cfd915e7fe998307826b90e3407..7f9235954f47aba033efdc637019d69dbd06bef4 100644 (file)
       </tgroup>
     </table>
 
-    <para>For types "s" and "g" (unicode string or signature), the pointer may be
-    <constant>NULL</constant>, which is equivalent to an empty string. See
+    <para>For types <literal>s</literal> and <literal>g</literal> (unicode string or signature), the pointer
+    may be <constant>NULL</constant>, which is equivalent to an empty string. For <literal>h</literal> (UNIX
+    file descriptor), the descriptor is duplicated by this call and the passed descriptor stays in possession
+    of the caller. See
     <citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     for the precise interpretation of those and other types.</para>
   </refsect1>
index 1b9f36cd84ed8f2a55672e5bacd1f6db1213af6b..2b5f1000be7c1d1ce8fac81ba56fd65f0a5e059e 100644 (file)
     should be read. See the table below for a complete list of allowed arguments and their types. Note that,
     if the basic type is a pointer (e.g., <type>const char *</type> in the case of a string), the argument is
     a pointer to a pointer, and also the pointer value that is written is only borrowed and the contents must
-    be copied if they are to be used after the end of the messages lifetime.</para>
+    be copied if they are to be used after the end of the messages lifetime. If the type is
+    <literal>h</literal> (UNIX file descriptor), the descriptor is not duplicated by this call and the
+    returned descriptor remains in possession of the message object, and needs to be duplicated by the caller
+    in order to keep an open reference to it after the message object is freed.</para>
 
     <para>Each argument may also be <constant>NULL</constant>, in which case the value is read and ignored.
     </para>
@@ -228,6 +231,15 @@ const char *s, *t, *u;
 
 sd_bus_message_read(m, "a{is}", 3, &amp;i, &amp;s, &amp;j, &amp;t, &amp;k, &amp;u);
      </programlisting>
+
+     <para>Read a single file descriptor, and duplicate it in order to keep it open after the message is
+     freed.</para>
+
+     <programlisting>sd_bus_message *m;
+int fd, fd_copy;
+
+sd_bus_message_read(m, "h", &amp;fd);
+fd_copy = fcntl(fd, FD_DUPFD_CLOEXEC, 3);</programlisting>
   </refsect1>
 
   <refsect1>
index e1e993434ac3f5a8b7dd2855b14a8a5c16314ec4..dc9f960618cf0788c83e2bbc1c0e7a62f651aa1e 100644 (file)
     </para>
 
     <para>
-      If <parameter>p</parameter> is not <constant>NULL</constant>, it should contain
-      a pointer to an appropriate object. For example, if <parameter>type</parameter>
-      is <constant>'y'</constant>, the object passed in <parameter>p</parameter>
-      should have type <type>uint8_t *</type>. If <parameter>type</parameter> is
-      <constant>'s'</constant>, the object passed in <parameter>p</parameter> should
-      have type <type>const char **</type>. Note that, if the basic type is a pointer
-      (e.g., <type>const char *</type> in the case of a string), the pointer is only
-      borrowed and the contents must be copied if they are to be used after the end
-      of the messages lifetime. Similarly, during the lifetime of such a pointer, the
-      message must not be modified. See the table below for a complete list of allowed
-      types.
+      If <parameter>p</parameter> is not <constant>NULL</constant>, it should contain a pointer to an
+      appropriate object. For example, if <parameter>type</parameter> is <constant>'y'</constant>, the object
+      passed in <parameter>p</parameter> should have type <type>uint8_t *</type>. If
+      <parameter>type</parameter> is <constant>'s'</constant>, the object passed in <parameter>p</parameter>
+      should have type <type>const char **</type>. Note that, if the basic type is a pointer (e.g.,
+      <type>const char *</type> in the case of a string), the pointer is only borrowed and the contents must
+      be copied if they are to be used after the end of the messages lifetime. Similarly, during the lifetime
+      of such a pointer, the message must not be modified. If <parameter>type</parameter> is
+      <constant>'h'</constant> (UNIX file descriptor), the descriptor is not duplicated by this call and the
+      returned descriptor remains in possession of the message object, and needs to be duplicated by the caller
+      in order to keep an open reference to it after the message object is freed (for example by calling
+      <literal>fcntl(fd, FD_DUPFD_CLOEXEC, 3)</literal>). See the table below for a complete list of
+      allowed types.
     </para>
 
     <table id='format-specifiers'>
index 9a66ee33bae74f7ee5a17510280424936ae09376..4973718ef6b5f6cf68b125ec73f9b070289ad715 100644 (file)
     (i.e. <constant>SD_LISTEN_FDS_START</constant>), the remaining
     descriptors follow at 4, 5, 6, …, if any.</para>
 
-    <para>If a daemon receives more than one file descriptor, they
-    will be passed in the same order as configured in the systemd
-    socket unit file (see
-    <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>
-    for details). Nonetheless, it is recommended to verify the correct
-    socket types before using them. To simplify this checking, the
-    functions
+    <para>If a daemon receives more than one file descriptor, they will be passed in the same order as
+    configured in the systemd socket unit file (see
+    <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+    details) — if there's only one such file (see below).  Nonetheless, it is recommended to verify the
+    correct socket types before using them. To simplify this checking, the functions
     <citerefentry><refentrytitle>sd_is_fifo</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
     <citerefentry><refentrytitle>sd_is_socket</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
     <citerefentry><refentrytitle>sd_is_socket_inet</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-    <citerefentry><refentrytitle>sd_is_socket_unix</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-    are provided. In order to maximize flexibility, it is recommended
-    to make these checks as loose as possible without allowing
-    incorrect setups. i.e. often, the actual port number a socket is
-    bound to matters little for the service to work, hence it should
-    not be verified. On the other hand, whether a socket is a datagram
-    or stream socket matters a lot for the most common program logics
-    and should be checked.</para>
+    <citerefentry><refentrytitle>sd_is_socket_unix</refentrytitle><manvolnum>3</manvolnum></citerefentry> are
+    provided. In order to maximize flexibility, it is recommended to make these checks as loose as possible
+    without allowing incorrect setups. i.e. often, the actual port number a socket is bound to matters little
+    for the service to work, hence it should not be verified. On the other hand, whether a socket is a
+    datagram or stream socket matters a lot for the most common program logics and should be checked.</para>
 
     <para>This function call will set the FD_CLOEXEC flag for all
     passed file descriptors to avoid further inheritance to children
index 506f9ca68f870b4c87928a9833c0c29b4ac00a6e..1e2b6c16ecd6f0bbba33bdc3b723cdc04ce28546 100644 (file)
@@ -446,7 +446,11 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
             current main process identifier as <literal>MainPID</literal> (which is runtime state), and time settings
             are always exposed as properties ending in the <literal>…USec</literal> suffix even if a matching
             configuration options end in <literal>…Sec</literal>, because microseconds is the normalized time unit used
-            by the system and service manager.</para>
+            internally by the system and service manager.</para>
+
+            <para>For details about many of these properties, see the documentation of the D-Bus interface
+            backing these properties, see
+            <citerefentry><refentrytitle>org.freedesktop.systemd1</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
index 5aec511724ea6b3c899c441239822d2ef7e55823..124fa383aba5e9f52bbdebe2e07ae55900fb390b 100644 (file)
 
       <varlistentry>
         <term><varname>FileDescriptorStoreMax=</varname></term>
-        <listitem><para>Configure how many file descriptors may be stored in the service manager for the service using
+        <listitem><para>Configure how many file descriptors may be stored in the service manager for the
+        service using
         <citerefentry><refentrytitle>sd_pid_notify_with_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>'s
-        <literal>FDSTORE=1</literal> messages. This is useful for implementing services that can restart after an
-        explicit request or a crash without losing state. Any open sockets and other file descriptors which should not
-        be closed during the restart may be stored this way. Application state can either be serialized to a file in
-        <filename>/run</filename>, or better, stored in a
-        <citerefentry><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry> memory file
-        descriptor. Defaults to 0, i.e. no file descriptors may be stored in the service manager. All file descriptors
-        passed to the service manager from a specific service are passed back to the service's main process on the next
-        service restart. Any file descriptors passed to the service manager are automatically closed when
-        <constant>POLLHUP</constant> or <constant>POLLERR</constant> is seen on them, or when the service is fully
-        stopped and no job is queued or being executed for it. If this option is used, <varname>NotifyAccess=</varname>
-        (see above) should be set to open access to the notification socket provided by systemd. If
-        <varname>NotifyAccess=</varname> is not set, it will be implicitly set to
+        <literal>FDSTORE=1</literal> messages. This is useful for implementing services that can restart
+        after an explicit request or a crash without losing state. Any open sockets and other file
+        descriptors which should not be closed during the restart may be stored this way. Application state
+        can either be serialized to a file in <filename>/run</filename>, or better, stored in a
+        <citerefentry><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+        memory file descriptor. Defaults to 0, i.e. no file descriptors may be stored in the service
+        manager. All file descriptors passed to the service manager from a specific service are passed back
+        to the service's main process on the next service restart (see
+        <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry> for
+        details about the precise protocol used and the order in which the file descriptors are passed). Any
+        file descriptors passed to the service manager are automatically closed when
+        <constant>POLLHUP</constant> or <constant>POLLERR</constant> is seen on them, or when the service is
+        fully stopped and no job is queued or being executed for it. If this option is used,
+        <varname>NotifyAccess=</varname> (see above) should be set to open access to the notification socket
+        provided by systemd. If <varname>NotifyAccess=</varname> is not set, it will be implicitly set to
         <option>main</option>.</para></listitem>
       </varlistentry>
 
index f989b99f955cb14d0ffac00ba462229194a2cdf4..29ce0b1c2008749c8aac7be65c1caebe15222766 100644 (file)
     services, as well as parallelized starting of services. See the
     blog stories linked at the end for an introduction.</para>
 
-    <para>Note that the daemon software configured for socket
-    activation with socket units needs to be able to accept sockets
-    from systemd, either via systemd's native socket passing interface
-    (see
-    <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-    for details) or via the traditional
-    <citerefentry project='freebsd'><refentrytitle>inetd</refentrytitle><manvolnum>8</manvolnum></citerefentry>-style
-    socket passing (i.e. sockets passed in via standard input and
-    output, using <varname>StandardInput=socket</varname> in the
-    service file).</para>
+    <para>Note that the daemon software configured for socket activation with socket units needs to be able
+    to accept sockets from systemd, either via systemd's native socket passing interface (see
+    <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry> for
+    details about the precise protocol used and the order in which the file descriptors are passed) or via
+    traditional <citerefentry
+    project='freebsd'><refentrytitle>inetd</refentrytitle><manvolnum>8</manvolnum></citerefentry>-style
+    socket passing (i.e. sockets passed in via standard input and output, using
+    <varname>StandardInput=socket</varname> in the service file).</para>
 
     <para>All network sockets allocated through <filename>.socket</filename> units are allocated in the host's network
     namespace (see <citerefentry
index 5b7800e78b467b329676f6095bbf137165b31dcb..79fe9735c42984bca40fb329c4e1d05b5276a63c 100644 (file)
     <para>One can use the <command>timespan</command> command of
     <citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     to normalise a textual time span for testing and validation purposes.</para>
+
+    <para>Internally, systemd generally operates with microsecond time granularity, while the default time
+    unit in user-configurable time spans is usually seconds (see above). This disparity becomes visible when
+    comparing the same settings in the (high-level) unit file syntax with the matching (more low-level) D-Bus
+    properties (which are what
+    <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
+    <command>show</command> command displays). The former typically are suffixed with <literal>…Sec</literal>
+    to indicate the default unit of seconds, the latter are typically suffixed with <literal>…USec</literal>
+    to indicate the underlying low-level time unit, even if they both encapsulate the very same
+    settings.</para>
   </refsect1>
 
   <refsect1>
index 4995bd3d105f0be4db4176cb67ac5e8cd0221f8c..13c8009887d667021f14f48f765de71495483efe 100644 (file)
@@ -6,9 +6,16 @@
         local -a _networkctl_cmds
         _networkctl_cmds=(
             'list:List existing links'
-           'status:Show information about the specified links'
-           'lldp:Show Link Layer Discovery Protocol status'
-           'label:Show address labels'
+            'status:Show information about the specified links'
+            'lldp:Show Link Layer Discovery Protocol status'
+            'label:Show address labels'
+            'delete:Delete virtual netdevs'
+            'up:Bring devices up'
+            'down:Bring devices down'
+            'renew:Renew dynamic configurations'
+            'forcerenew:Trigger DHCP reconfiguration of all connected clients'
+            'reconfigure:Reconfigure interfaces'
+            'reload:Reload .network and .netdev files'
         )
         if (( CURRENT == 1 )); then
             _describe -t commands 'networkctl command' _networkctl_cmds
             local curcontext="$curcontext"
             local -a _links
             cmd="${${_networkctl_cmds[(r)$words[1]:*]%%:*}}"
-            if [ $cmd = "status" ]; then
-                _links=( "${(foa)$(networkctl list --no-legend | awk 'BEGIN{OFS=":"} {sub(/[[ \t]+/, ""); print $2,$0}' 2>/dev/null)}" )
-                if [[ -n "$_links" ]]; then
-                    _describe -t links 'links' _links
-                else
-                    _message "no links"
-                fi
-            else
-                _message "no more options"
-            fi
+            case $cmd in
+                (list|status|up|down|lldp|delete|renew|forcerenew|reconfigure)
+                    _links=( "${(foa)$(networkctl list --no-legend | awk 'BEGIN{OFS=":"} {sub(/[[ \t]+/, ""); print $2,$0}' 2>/dev/null)}" )
+                    if [[ -n "$_links" ]]; then
+                         _describe -t links 'links' _links
+                    else
+                        _message "no links"
+                    fi
+                    ;;
+                *)
+                    _message "no more options"
+                    ;;
+            esac
         fi
     }
 
index 9d64e3c76cddf8829caac1f4b4d8bc4dc60f451e..f0473234dbf65f6531e58cc49954afed8af06a68 100644 (file)
@@ -1576,7 +1576,7 @@ static int dump_exit_status(int argc, char *argv[], void *userdata) {
 
                         status = exit_status_from_string(argv[i]);
                         if (status < 0)
-                                return log_error_errno(r, "Invalid exit status \"%s\": %m", argv[i]);
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid exit status \"%s\".", argv[i]);
 
                         assert(status >= 0 && (size_t) status < ELEMENTSOF(exit_status_mappings));
                         r = table_add_many(table,
index dd6bccd8700526181822265b85f6ad6cf861afbb..b31e736390274c74e371a0b3b1f12a021f64b2bc 100644 (file)
 #undef  CAP_LAST_CAP
 #define CAP_LAST_CAP   CAP_BPF
 #endif
+
+/* 124ea650d3072b005457faed69909221c2905a1f (5.9) */
+#ifndef CAP_CHECKPOINT_RESTORE
+#define CAP_CHECKPOINT_RESTORE  40
+
+#undef  CAP_LAST_CAP
+#define CAP_LAST_CAP   CAP_CHECKPOINT_RESTORE
+#endif
index d3b4978239475c656850fca3aae4c81021cb3be0..7b0863f749ad44f7c6681a43c3666db5c2b63e44 100644 (file)
@@ -637,16 +637,27 @@ int find_binary(const char *name, char **ret) {
                 if (!j)
                         return -ENOMEM;
 
-                if (is_dir(j, true))
-                        continue;
-
                 if (access(j, X_OK) >= 0) {
-                        /* Found it! */
+                        _cleanup_free_ char *with_dash;
 
-                        if (ret)
-                                *ret = path_simplify(TAKE_PTR(j), false);
+                        with_dash = strjoin(j, "/");
+                        if (!with_dash)
+                                return -ENOMEM;
 
-                        return 0;
+                        /* If this passes, it must be a directory, and so should be skipped. */
+                        if (access(with_dash, X_OK) >= 0)
+                                continue;
+
+                        /**
+                         * We can't just `continue` inverting this case, since we need to update last_error.
+                         */
+                        if (errno == ENOTDIR) {
+                                /* Found it! */
+                                if (ret)
+                                        *ret = path_simplify(TAKE_PTR(j), false);
+
+                                return 0;
+                        }
                 }
 
                 /* PATH entries which we don't have access to are ignored, as per tradition. */
index 7f799ede3d19628261ac85912c6001334f8b329c..fe43256882eccf86fe112310c11de5887247f9e1 100644 (file)
@@ -6,6 +6,8 @@
 #include <string.h>
 #include <sys/types.h>
 
+#include "time-util.h"
+
 struct siphash {
         uint64_t v0;
         uint64_t v1;
@@ -25,6 +27,10 @@ static inline void siphash24_compress_boolean(bool in, struct siphash *state) {
         siphash24_compress(&i, sizeof i, state);
 }
 
+static inline void siphash24_compress_usec_t(usec_t in, struct siphash *state) {
+        siphash24_compress(&in, sizeof in, state);
+}
+
 static inline void siphash24_compress_string(const char *in, struct siphash *state) {
         if (!in)
                 return;
index a1100d5068d1c3df8a868de524fd2dcd36204cc0..f32652633363ed3890c885c234ac81deed75be6e 100644 (file)
@@ -4943,7 +4943,7 @@ int unit_load_fragment(Unit *u) {
 
         /* Possibly rebuild the fragment map to catch new units */
         r = unit_file_build_name_map(&u->manager->lookup_paths,
-                                     &u->manager->unit_cache_mtime,
+                                     &u->manager->unit_cache_timestamp_hash,
                                      &u->manager->unit_id_map,
                                      &u->manager->unit_name_map,
                                      &u->manager->unit_path_cache);
index 4a376976e94f987c416a60fe26e6c3f48bb8d142..9a834a875e8f239cf5ef2f559e06b539196f05ad 100644 (file)
@@ -32,6 +32,7 @@
 #include "dbus-manager.h"
 #include "dbus.h"
 #include "def.h"
+#include "dev-setup.h"
 #include "efi-random.h"
 #include "efivars.h"
 #include "emergency-action.h"
@@ -53,6 +54,7 @@
 #include "loopback-setup.h"
 #include "machine-id-setup.h"
 #include "manager.h"
+#include "mkdir.h"
 #include "mount-setup.h"
 #include "os-util.h"
 #include "pager.h"
@@ -2073,6 +2075,20 @@ static int initialize_runtime(
                         if (r < 0)
                                 log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m", arg_watchdog_device);
                 }
+        } else {
+                _cleanup_free_ char *p = NULL;
+
+                /* Create the runtime directory and place the inaccessible device nodes there, if we run in
+                 * user mode. In system mode mount_setup() already did that. */
+
+                r = xdg_user_runtime_dir(&p, "/systemd");
+                if (r < 0) {
+                        *ret_error_message = "$XDG_RUNTIME_DIR is not set";
+                        return log_emergency_errno(r, "Failed to determine $XDG_RUNTIME_DIR path: %m");
+                }
+
+                (void) mkdir_p(p, 0755);
+                (void) make_inaccessible_nodes(p, UID_INVALID, GID_INVALID);
         }
 
         if (arg_timer_slack_nsec != NSEC_INFINITY)
index 41e0d73736627cd70bcfd165019416da349f0740..6b7908fc6cdffac53003e5df9940c55bc6ac71d1 100644 (file)
@@ -703,7 +703,7 @@ static void manager_free_unit_name_maps(Manager *m) {
         m->unit_id_map = hashmap_free(m->unit_id_map);
         m->unit_name_map = hashmap_free(m->unit_name_map);
         m->unit_path_cache = set_free(m->unit_path_cache);
-        m->unit_cache_mtime =  0;
+        m->unit_cache_timestamp_hash = 0;
 }
 
 static int manager_setup_run_queue(Manager *m) {
@@ -1937,19 +1937,22 @@ unsigned manager_dispatch_load_queue(Manager *m) {
         return n;
 }
 
-bool manager_unit_file_maybe_loadable_from_cache(Unit *u) {
+bool manager_unit_cache_should_retry_load(Unit *u) {
         assert(u);
 
+        /* Automatic reloading from disk only applies to units which were not found sometime in the past, and
+         * the not-found stub is kept pinned in the unit graph by dependencies. For units that were
+         * previously loaded, we don't do automatic reloading, and daemon-reload is necessary to update. */
         if (u->load_state != UNIT_NOT_FOUND)
                 return false;
 
-        if (u->manager->unit_cache_mtime == 0)
-                return false;
-
-        if (u->manager->unit_cache_mtime > u->fragment_loadtime)
+        /* The cache has been updated since the last time we tried to load the unit. There might be new
+         * fragment paths to read. */
+        if (u->manager->unit_cache_timestamp_hash != u->fragment_not_found_timestamp_hash)
                 return true;
 
-        return !lookup_paths_mtime_good(&u->manager->lookup_paths, u->manager->unit_cache_mtime);
+        /* The cache needs to be updated because there are modifications on disk. */
+        return !lookup_paths_timestamp_hash_same(&u->manager->lookup_paths, u->manager->unit_cache_timestamp_hash, NULL);
 }
 
 int manager_load_unit_prepare(
@@ -1998,10 +2001,10 @@ int manager_load_unit_prepare(
                  * first if anything in the usual paths was modified since the last time
                  * the cache was loaded. Also check if the last time an attempt to load the
                  * unit was made was before the most recent cache refresh, so that we know
-                 * we need to try again - even if the cache is current, it might have been
+                 * we need to try again  even if the cache is current, it might have been
                  * updated in a different context before we had a chance to retry loading
                  * this particular unit. */
-                if (manager_unit_file_maybe_loadable_from_cache(ret))
+                if (manager_unit_cache_should_retry_load(ret))
                         ret->load_state = UNIT_STUB;
                 else {
                         *_ret = ret;
index 81b0c13a955a7bcbbb56cc655ce74eaf24215e0f..6b29d48fae37933b5336382a69ed6715e471d1c9 100644 (file)
@@ -233,7 +233,7 @@ struct Manager {
         Hashmap *unit_id_map;
         Hashmap *unit_name_map;
         Set *unit_path_cache;
-        usec_t unit_cache_mtime;
+        uint64_t unit_cache_timestamp_hash;
 
         char **transient_environment;  /* The environment, as determined from config files, kernel cmdline and environment generators */
         char **client_environment;     /* Environment variables created by clients through the bus API */
@@ -463,7 +463,7 @@ Unit *manager_get_unit(Manager *m, const char *name);
 
 int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
 
-bool manager_unit_file_maybe_loadable_from_cache(Unit *u);
+bool manager_unit_cache_should_retry_load(Unit *u);
 int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
 int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
 int manager_load_startable_unit_or_warn(Manager *m, const char *name, const char *path, Unit **ret);
index feb88f3e6e5f5f1c865a2ecad5d613905ed65017..39662ebb080891e61b7fe1703c7bfa9941efb8cb 100644 (file)
@@ -536,8 +536,17 @@ int mount_setup(bool loaded_policy, bool leave_propagation) {
         (void) mkdir_label("/run/systemd/system", 0755);
 
         /* Also create /run/systemd/inaccessible nodes, so that we always have something to mount
-         * inaccessible nodes from. */
-        (void) make_inaccessible_nodes(NULL, UID_INVALID, GID_INVALID);
+         * inaccessible nodes from. If we run in a container the host might have created these for us already
+         * in /run/host/inaccessible/. Use those if we can, since tht way we likely get access to block/char
+         * device nodes that are inaccessible, and if userns is used to nodes that are on mounts owned by a
+         * userns outside the container and thus nicely read-only and not remountable. */
+        if (access("/run/host/inaccessible/", F_OK) < 0) {
+                if (errno != ENOENT)
+                        log_debug_errno(errno, "Failed to check if /run/host/inaccessible exists, ignoring: %m");
+
+                (void) make_inaccessible_nodes("/run/systemd", UID_INVALID, GID_INVALID);
+        } else
+                (void) symlink("../host/inaccessible", "/run/systemd/inaccessible");
 
         return 0;
 }
index 958243bc94b14747869c9d7805c6cfc5a8db2cba..0fa419787ef90acd5032e29611098287ae64f478 100644 (file)
@@ -960,12 +960,13 @@ int transaction_add_job_and_dependencies(
                  * first if anything in the usual paths was modified since the last time
                  * the cache was loaded. Also check if the last time an attempt to load the
                  * unit was made was before the most recent cache refresh, so that we know
-                 * we need to try again - even if the cache is current, it might have been
+                 * we need to try again  even if the cache is current, it might have been
                  * updated in a different context before we had a chance to retry loading
                  * this particular unit.
+                 *
                  * Given building up the transaction is a synchronous operation, attempt
                  * to load the unit immediately. */
-                if (r < 0 && manager_unit_file_maybe_loadable_from_cache(unit)) {
+                if (r < 0 && manager_unit_cache_should_retry_load(unit)) {
                         sd_bus_error_free(e);
                         unit->load_state = UNIT_STUB;
                         r = unit_load(unit);
index 2c09def06f3b228450cea414b582287422175fe5..1bda56856032975f795b9d6f76c90709775bf310 100644 (file)
@@ -1674,18 +1674,18 @@ int unit_load(Unit *u) {
         return 0;
 
 fail:
-        /* We convert ENOEXEC errors to the UNIT_BAD_SETTING load state here. Configuration parsing code should hence
-         * return ENOEXEC to ensure units are placed in this state after loading */
+        /* We convert ENOEXEC errors to the UNIT_BAD_SETTING load state here. Configuration parsing code
+         * should hence return ENOEXEC to ensure units are placed in this state after loading. */
 
         u->load_state = u->load_state == UNIT_STUB ? UNIT_NOT_FOUND :
                                      r == -ENOEXEC ? UNIT_BAD_SETTING :
                                                      UNIT_ERROR;
         u->load_error = r;
 
-        /* Record the last time we tried to load the unit, so that if the cache gets updated between now
-         * and the next time an attempt is made to load this unit, we know we need to check again */
+        /* Record the timestamp on the cache, so that if the cache gets updated between now and the next time
+         * an attempt is made to load this unit, we know we need to check again. */
         if (u->load_state == UNIT_NOT_FOUND)
-                u->fragment_loadtime = now(CLOCK_REALTIME);
+                u->fragment_not_found_timestamp_hash = u->manager->unit_cache_timestamp_hash;
 
         unit_add_to_dbus_queue(u);
         unit_add_to_gc_queue(u);
index d5e4c65989e400922724efb333714b91bfa06e67..4130cd50a9eac2e483f67b91306045bb4777cf40 100644 (file)
@@ -136,7 +136,7 @@ typedef struct Unit {
         char *source_path; /* if converted, the source file */
         char **dropin_paths;
 
-        usec_t fragment_loadtime;
+        usec_t fragment_not_found_timestamp_hash;
         usec_t fragment_mtime;
         usec_t source_mtime;
         usec_t dropin_mtime;
index 8b052dac26cb9636993a2816aa0507d588c08758..10bbf1018cab22e9f48af2b9a80ece53a16587ab 100644 (file)
@@ -77,7 +77,7 @@ enum {
         META_ARGV_UID,          /* %u: as seen in the initial user namespace */
         META_ARGV_GID,          /* %g: as seen in the initial user namespace */
         META_ARGV_SIGNAL,       /* %s: number of signal causing dump */
-        META_ARGV_TIMESTAMP,    /* %t: time of dump, expressed as seconds since the Epoch */
+        META_ARGV_TIMESTAMP,    /* %t: time of dump, expressed as seconds since the Epoch (we expand this to µs granularity) */
         META_ARGV_RLIMIT,       /* %c: core file size soft resource limit */
         META_ARGV_HOSTNAME,     /* %h: hostname */
         _META_ARGV_MAX,
@@ -311,7 +311,7 @@ static int make_filename(const Context *context, char **ret) {
                 return -ENOMEM;
 
         if (asprintf(ret,
-                     "/var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR ".%s.%s000000",
+                     "/var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR ".%s.%s",
                      c,
                      u,
                      SD_ID128_FORMAT_VAL(boot),
@@ -1016,8 +1016,11 @@ static int send_iovec(const struct iovec_wrapper *iovw, int input_fd) {
         return 0;
 }
 
-static int gather_pid_metadata_from_argv(struct iovec_wrapper *iovw, Context *context,
-                                         int argc, char **argv) {
+static int gather_pid_metadata_from_argv(
+                struct iovec_wrapper *iovw,
+                Context *context,
+                int argc, char **argv) {
+
         _cleanup_free_ char *free_timestamp = NULL;
         int i, r, signo;
         char *t;
@@ -1035,6 +1038,7 @@ static int gather_pid_metadata_from_argv(struct iovec_wrapper *iovw, Context *co
                 t = argv[i];
 
                 switch (i) {
+
                 case META_ARGV_TIMESTAMP:
                         /* The journal fields contain the timestamp padded with six
                          * zeroes, so that the kernel-supplied 1s granularity timestamps
@@ -1044,12 +1048,14 @@ static int gather_pid_metadata_from_argv(struct iovec_wrapper *iovw, Context *co
                         if (!t)
                                 return log_oom();
                         break;
+
                 case META_ARGV_SIGNAL:
                         /* For signal, record its pretty name too */
                         if (safe_atoi(argv[i], &signo) >= 0 && SIGNAL_VALID(signo))
                                 (void) iovw_put_string_field(iovw, "COREDUMP_SIGNAL_NAME=SIG",
                                                              signal_to_string(signo));
                         break;
+
                 default:
                         break;
                 }
index a3f442518ec43d207c8290523e2716a33f5cb1b5..c9fc8dd5cdc8e7002435165c796440e554203156 100644 (file)
@@ -94,7 +94,7 @@ static bool press_any_key(void) {
 static void print_welcome(void) {
         _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
         static bool done = false;
-        const char *pn;
+        const char *pn, *ac;
         int r;
 
         if (!arg_welcome)
@@ -113,9 +113,10 @@ static void print_welcome(void) {
                                "Failed to read os-release file, ignoring: %m");
 
         pn = isempty(pretty_name) ? "Linux" : pretty_name;
+        ac = isempty(ansi_color) ? "0" : ansi_color;
 
         if (colors_enabled())
-                printf("\nWelcome to your new installation of \x1B[%sm%s\x1B[0m!\n", ansi_color, pn);
+                printf("\nWelcome to your new installation of \x1B[%sm%s\x1B[0m!\n", ac, pn);
         else
                 printf("\nWelcome to your new installation of %s!\n", pn);
 
index f0c157cb7d882a117e8d1923aaaea6b41aa0c7ac..35b325413fd1db77bdffc86df8d2fcbe34eaea38 100644 (file)
@@ -1042,7 +1042,7 @@ static int home_start_work(Home *h, const char *verb, UserRecord *hr, UserRecord
                 homework = getenv("SYSTEMD_HOMEWORK_PATH") ?: SYSTEMD_HOMEWORK_PATH;
 
                 execl(homework, homework, verb, NULL);
-                log_error_errno(errno, "Failed to invoke " SYSTEMD_HOMEWORK_PATH ": %m");
+                log_error_errno(errno, "Failed to invoke %s: %m", homework);
                 _exit(EXIT_FAILURE);
         }
 
index e64ecce8e2810b8380465d7b2b2cb96000c0a89c..272fcfecd4c4df48b304a89a0e631ec188f74f72 100644 (file)
@@ -2,6 +2,7 @@
 #pragma once
 
 #include <stdbool.h>
+#include <sys/stat.h>
 
 #include "sd-bus.h"
 #include "sd-device.h"
index 8ba916f05eec8bf6f01189acd6a3c2756860d3aa..03c60f90b3d112f8c128e3b7c66f710294583f31 100644 (file)
@@ -88,7 +88,8 @@ static int user_mkdir_runtime_path(
                                 goto fail;
                         }
 
-                        log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s.\n"
+                        log_debug_errno(errno,
+                                        "Failed to mount per-user tmpfs directory %s.\n"
                                         "Assuming containerized execution, ignoring: %m", runtime_path);
 
                         r = chmod_and_chown(runtime_path, 0700, uid, gid);
@@ -103,8 +104,6 @@ static int user_mkdir_runtime_path(
                         log_warning_errno(r, "Failed to fix label of \"%s\", ignoring: %m", runtime_path);
         }
 
-        /* Set up inaccessible nodes now so they're available if we decide to use them with user namespaces. */
-        (void) make_inaccessible_nodes(runtime_path, uid, gid);
         return 0;
 
 fail:
index 48182e61ddfe803003b1601ec0f8d9c6be991867..758b85d5539ea400e7f9316928a5ff0fed5571aa 100644 (file)
@@ -2794,7 +2794,7 @@ static int networkctl_main(int argc, char *argv[]) {
                 { "list",        VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links          },
                 { "status",      VERB_ANY, VERB_ANY, 0,            link_status         },
                 { "lldp",        VERB_ANY, VERB_ANY, 0,            link_lldp_status    },
-                { "label",       VERB_ANY, VERB_ANY, 0,            list_address_labels },
+                { "label",       1,        1,        0,            list_address_labels },
                 { "delete",      2,        VERB_ANY, 0,            link_delete         },
                 { "up",          2,        VERB_ANY, 0,            link_up_down        },
                 { "down",        2,        VERB_ANY, 0,            link_up_down        },
index d671284b001906975a8e0ec4a421217838dd804f..d969995ea8399607de7e733d30a837e6eb4d599c 100644 (file)
@@ -992,7 +992,8 @@ static int dhcp6_update_address(
         addr->cinfo.ifa_valid = lifetime_valid;
 
         (void) in_addr_to_string(addr->family, &addr->in_addr, &buffer);
-        log_link_info(link, "DHCPv6 address %s/%u timeout preferred %d valid %d",
+        log_link_full(link, set_contains(link->dhcp6_addresses, addr) ? LOG_DEBUG : LOG_INFO, 0,
+                      "DHCPv6 address %s/%u timeout preferred %d valid %d",
                       strna(buffer), addr->prefixlen, lifetime_preferred, lifetime_valid);
 
         r = address_configure(addr, link, dhcp6_address_handler, true, &ret);
index eb7c3321acc3582e2e79903113b3c03d8b6313e3..43712565c25b29c4d2aa8bbf46d4cc54042eee73 100644 (file)
@@ -3531,7 +3531,7 @@ static int outer_child(
 
         (void) dev_setup(directory, arg_uid_shift, arg_uid_shift);
 
-        p = prefix_roota(directory, "/run");
+        p = prefix_roota(directory, "/run/host");
         (void) make_inaccessible_nodes(p, arg_uid_shift, arg_uid_shift);
 
         r = setup_pts(directory);
index 97f50c90335bcd426ef4158b4fa5ad533e0bd495..33ede22a6f6bca202731d986df6491e943e148c1 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include <fcntl.h>
+#include <sys/file.h>
 #include <sys/prctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
index bfb9bcb4c9b7192465f6dda873e798a2aa650668..a0fd6aa0ec22ae43fd26b208b1d944d92e6cd8c2 100755 (executable)
@@ -1,6 +1,8 @@
 #!/usr/bin/env bash
 set -ex
 
+[[ -f /dev/loop-control ]] || exit 77
+
 repart=$1
 test -x $repart
 
index e23ea273e7979835ea557548bb26c7714719e46d..016ff0136b6463234219bdfea281a08a3ffaf63b 100644 (file)
@@ -364,6 +364,14 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
         dns_transaction_gc(t);
 }
 
+static void dns_transaction_complete_errno(DnsTransaction *t, int error) {
+        assert(t);
+        assert(error != 0);
+
+        t->answer_errno = abs(error);
+        dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
+}
+
 static int dns_transaction_pick_server(DnsTransaction *t) {
         DnsServer *server;
 
@@ -415,10 +423,8 @@ static void dns_transaction_retry(DnsTransaction *t, bool next_server) {
                 dns_scope_next_dns_server(t->scope);
 
         r = dns_transaction_go(t);
-        if (r < 0) {
-                t->answer_errno = -r;
-                dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
-        }
+        if (r < 0)
+                dns_transaction_complete_errno(t, r);
 }
 
 static int dns_transaction_maybe_restart(DnsTransaction *t) {
@@ -466,10 +472,8 @@ static void on_transaction_stream_error(DnsTransaction *t, int error) {
                 dns_transaction_retry(t, true);
                 return;
         }
-        if (error != 0) {
-                t->answer_errno = error;
-                dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
-        }
+        if (error != 0)
+                dns_transaction_complete_errno(t, error);
 }
 
 static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsPacket *p) {
@@ -836,8 +840,7 @@ static void dns_transaction_process_dnssec(DnsTransaction *t) {
         return;
 
 fail:
-        t->answer_errno = -r;
-        dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
+        dns_transaction_complete_errno(t, r);
 }
 
 static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) {
@@ -1169,8 +1172,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
         return;
 
 fail:
-        t->answer_errno = -r;
-        dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
+        dns_transaction_complete_errno(t, r);
 }
 
 static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
@@ -1196,8 +1198,7 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use
                 return 0;
         }
         if (r < 0) {
-                dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
-                t->answer_errno = -r;
+                dns_transaction_complete_errno(t, r);
                 return 0;
         }
         if (r == 0)
index 3d0b9391069507049c9fcec873a5a19eafaf2e92..a727b98e7c67dd66a6c72f8391e75aeba9661e6d 100644 (file)
@@ -237,6 +237,9 @@ int ask_password_plymouth(
 
         assert(ret);
 
+        if (!message)
+                message = "Password:";
+
         if (flag_file) {
                 notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK);
                 if (notify < 0)
index 6e57e2a99d3a79fd3f22d39239bfc4c93431d0ab..528440b82fa2689344a9033ee389cf52d43d4a49 100644 (file)
@@ -57,7 +57,7 @@ int dev_setup(const char *prefix, uid_t uid, gid_t gid) {
 }
 
 int make_inaccessible_nodes(
-                const char *runtime_dir,
+                const char *parent_dir,
                 uid_t uid,
                 gid_t gid) {
 
@@ -65,28 +65,26 @@ int make_inaccessible_nodes(
                 const char *name;
                 mode_t mode;
         } table[] = {
-                { "/systemd",                   S_IFDIR  | 0755 },
-                { "/systemd/inaccessible",      S_IFDIR  | 0000 },
-                { "/systemd/inaccessible/reg",  S_IFREG  | 0000 },
-                { "/systemd/inaccessible/dir",  S_IFDIR  | 0000 },
-                { "/systemd/inaccessible/fifo", S_IFIFO  | 0000 },
-                { "/systemd/inaccessible/sock", S_IFSOCK | 0000 },
+                { "inaccessible",      S_IFDIR  | 0755 },
+                { "inaccessible/reg",  S_IFREG  | 0000 },
+                { "inaccessible/dir",  S_IFDIR  | 0000 },
+                { "inaccessible/fifo", S_IFIFO  | 0000 },
+                { "inaccessible/sock", S_IFSOCK | 0000 },
 
                 /* The following two are likely to fail if we lack the privs for it (for example in an userns
                  * environment, if CAP_SYS_MKNOD is missing, or if a device node policy prohibit major/minor of 0
                  * device nodes to be created). But that's entirely fine. Consumers of these files should carry
                  * fallback to use a different node then, for example <root>/inaccessible/sock, which is close
                  * enough in behaviour and semantics for most uses. */
-                { "/systemd/inaccessible/chr",  S_IFCHR  | 0000 },
-                { "/systemd/inaccessible/blk",  S_IFBLK  | 0000 },
+                { "inaccessible/chr",  S_IFCHR  | 0000 },
+                { "inaccessible/blk",  S_IFBLK  | 0000 },
         };
 
         _cleanup_umask_ mode_t u;
-        size_t i;
         int r;
 
-        if (!runtime_dir)
-                runtime_dir = "/run";
+        if (!parent_dir)
+                parent_dir = "/run/systemd";
 
         u = umask(0000);
 
@@ -95,10 +93,10 @@ int make_inaccessible_nodes(
          * to lock down these nodes as much as we can, but otherwise try to match them as closely as possible with the
          * underlying file, i.e. in the best case we offer the same node type as the underlying node. */
 
-        for (i = 0; i < ELEMENTSOF(table); i++) {
+        for (size_t i = 0; i < ELEMENTSOF(table); i++) {
                 _cleanup_free_ char *path = NULL;
 
-                path = path_join(runtime_dir, table[i].name);
+                path = path_join(parent_dir, table[i].name);
                 if (!path)
                         return log_oom();
 
@@ -107,8 +105,7 @@ int make_inaccessible_nodes(
                 else
                         r = mknod_label(path, table[i].mode, makedev(0, 0));
                 if (r < 0) {
-                        if (r != -EEXIST)
-                                log_debug_errno(r, "Failed to create '%s', ignoring: %m", path);
+                        log_debug_errno(r, "Failed to create '%s', ignoring: %m", path);
                         continue;
                 }
 
index 72b90ec4de8acec7a573c75103555abb6507c844..437c0e96e65289cae26243b1b22740980b9105dd 100644 (file)
@@ -5,4 +5,4 @@
 
 int dev_setup(const char *prefix, uid_t uid, gid_t gid);
 
-int make_inaccessible_nodes(const char *root, uid_t uid, gid_t gid);
+int make_inaccessible_nodes(const char *parent_dir, uid_t uid, gid_t gid);
index 24be6de6c546fa84e39afa693ff26051ebb8d6b7..d3f10b3966030ad3691aafa28fa129db955491d9 100644 (file)
@@ -51,6 +51,9 @@
 #include "user-util.h"
 #include "xattr-util.h"
 
+/* how many times to wait for the device nodes to appear */
+#define N_DEVICE_NODE_LIST_ATTEMPTS 10
+
 int probe_filesystem(const char *node, char **ret_fstype) {
         /* Try to find device content type and return it in *ret_fstype. If nothing is found,
          * 0/NULL will be returned. -EUCLEAN will be returned for ambiguous results, and an
@@ -151,9 +154,6 @@ static int enumerator_for_parent(sd_device *d, sd_device_enumerator **ret) {
         return 0;
 }
 
-/* how many times to wait for the device nodes to appear */
-#define N_DEVICE_NODE_LIST_ATTEMPTS 10
-
 static int wait_for_partitions_to_appear(
                 int fd,
                 sd_device *d,
index 5c4fae865aefa0700d038598819c4d1b0f0f7a48..b018a46e18e0185d8ab2597d5b39ef95eeba1180 100644 (file)
@@ -37,7 +37,7 @@ int nss_group_to_group_record(
         g->gid = grp->gr_gid;
 
         if (sgrp) {
-                if (hashed_password_valid(sgrp->sg_passwd)) {
+                if (looks_like_hashed_password(sgrp->sg_passwd)) {
                         g->hashed_password = strv_new(sgrp->sg_passwd);
                         if (!g->hashed_password)
                                 return -ENOMEM;
index f41685ae45010931381e7a53be05c523342c5c6f..bf6605508af4d05494fc403022d17d402691743c 100644 (file)
@@ -74,13 +74,18 @@ int make_salt(char **ret) {
 #endif
 }
 
-bool hashed_password_valid(const char *s) {
-
-        /* Returns true if the specified string is a 'valid' hashed UNIX password, i.e. if starts with '$' or
-         * with '!$' (the latter being a valid, yet locked password). */
-
-        if (isempty(s))
+bool looks_like_hashed_password(const char *s) {
+        /* Returns false if the specified string is certainly not a hashed UNIX password. crypt(5) lists
+         * various hashing methods. We only reject (return false) strings which are documented to have
+         * different meanings.
+         *
+         * In particular, we allow locked passwords, i.e. strings starting with "!", including just "!",
+         * i.e. the locked empty password. See also fc58c0c7bf7e4f525b916e3e5be0de2307fef04e.
+         */
+        if (!s)
                 return false;
 
-        return STARTSWITH_SET(s, "$", "!$");
+        s += strspn(s, "!"); /* Skip (possibly duplicated) locking prefix */
+
+        return !STR_IN_SET(s, "x", "*");
 }
index 93f0e13ffbe7554047601cb40a70c3a339ac7de5..8a860ceb0d853dccbcd6aa4445c79ca90d86f23a 100644 (file)
@@ -19,4 +19,4 @@
 
 int make_salt(char **ret);
 
-bool hashed_password_valid(const char *s);
+bool looks_like_hashed_password(const char *s);
index ed4affd6683543ea5c2d1f97f63344fe99233e92..0f030ae4313f17303b85f107afcdbb500634f804 100644 (file)
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include "sd-id128.h"
+
 #include "dirent-util.h"
 #include "fd-util.h"
 #include "fs-util.h"
@@ -199,9 +201,14 @@ static bool lookup_paths_mtime_exclude(const LookupPaths *lp, const char *path)
                streq_ptr(path, lp->runtime_control);
 }
 
-bool lookup_paths_mtime_good(const LookupPaths *lp, usec_t mtime) {
-        char **dir;
+#define HASH_KEY SD_ID128_MAKE(4e,86,1b,e3,39,b3,40,46,98,5d,b8,11,34,8f,c3,c1)
+
+bool lookup_paths_timestamp_hash_same(const LookupPaths *lp, uint64_t timestamp_hash, uint64_t *ret_new) {
+        struct siphash state;
 
+        siphash24_init(&state, HASH_KEY.bytes);
+
+        char **dir;
         STRV_FOREACH(dir, (char**) lp->search_path) {
                 struct stat st;
 
@@ -217,18 +224,20 @@ bool lookup_paths_mtime_good(const LookupPaths *lp, usec_t mtime) {
                         continue;
                 }
 
-                if (timespec_load(&st.st_mtim) > mtime) {
-                        log_debug_errno(errno, "Unit dir %s has changed, need to update cache.", *dir);
-                        return false;
-                }
+                siphash24_compress_usec_t(timespec_load(&st.st_mtim), &state);
         }
 
-        return true;
+        uint64_t updated = siphash24_finalize(&state);
+        if (ret_new)
+                *ret_new = updated;
+        if (updated != timestamp_hash)
+                log_debug("Modification times have changed, need to update cache.");
+        return updated == timestamp_hash;
 }
 
 int unit_file_build_name_map(
                 const LookupPaths *lp,
-                usec_t *cache_mtime,
+                uint64_t *cache_timestamp_hash,
                 Hashmap **unit_ids_map,
                 Hashmap **unit_names_map,
                 Set **path_cache) {
@@ -245,14 +254,18 @@ int unit_file_build_name_map(
 
         _cleanup_hashmap_free_ Hashmap *ids = NULL, *names = NULL;
         _cleanup_set_free_free_ Set *paths = NULL;
+        uint64_t timestamp_hash;
         char **dir;
         int r;
-        usec_t mtime = 0;
 
-        /* Before doing anything, check if the mtime that was passed is still valid. If
-         * yes, do nothing. If *cache_time == 0, always build the cache. */
-        if (cache_mtime && *cache_mtime > 0 && lookup_paths_mtime_good(lp, *cache_mtime))
-                return 0;
+        /* Before doing anything, check if the timestamp hash that was passed is still valid.
+         * If yes, do nothing. */
+        if (cache_timestamp_hash &&
+            lookup_paths_timestamp_hash_same(lp, *cache_timestamp_hash, &timestamp_hash))
+                        return 0;
+
+        /* The timestamp hash is now set based on the mtimes from before when we start reading files.
+         * If anything is modified concurrently, we'll consider the cache outdated. */
 
         if (path_cache) {
                 paths = set_new(&path_hash_ops_free);
@@ -263,7 +276,6 @@ int unit_file_build_name_map(
         STRV_FOREACH(dir, (char**) lp->search_path) {
                 struct dirent *de;
                 _cleanup_closedir_ DIR *d = NULL;
-                struct stat st;
 
                 d = opendir(*dir);
                 if (!d) {
@@ -272,13 +284,6 @@ int unit_file_build_name_map(
                         continue;
                 }
 
-                /* Determine the latest lookup path modification time */
-                if (fstat(dirfd(d), &st) < 0)
-                        return log_error_errno(errno, "Failed to fstat %s: %m", *dir);
-
-                if (!lookup_paths_mtime_exclude(lp, *dir))
-                        mtime = MAX(mtime, timespec_load(&st.st_mtim));
-
                 FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) {
                         char *filename;
                         _cleanup_free_ char *_filename_free = NULL, *simplified = NULL;
@@ -417,8 +422,8 @@ int unit_file_build_name_map(
                                                  basename(dst), src);
         }
 
-        if (cache_mtime)
-                *cache_mtime = mtime;
+        if (cache_timestamp_hash)
+                *cache_timestamp_hash = timestamp_hash;
 
         hashmap_free_and_replace(*unit_ids_map, ids);
         hashmap_free_and_replace(*unit_names_map, names);
index d6d041d714bc60f443ebc45aa90c82d0533bc72d..d36bb07cc275109b9a5f097647b1230b0b89df86 100644 (file)
@@ -43,19 +43,19 @@ bool unit_type_may_template(UnitType type) _const_;
 int unit_symlink_name_compatible(const char *symlink, const char *target, bool instance_propagation);
 int unit_validate_alias_symlink_and_warn(const char *filename, const char *target);
 
-bool lookup_paths_mtime_good(const LookupPaths *lp, usec_t mtime);
+bool lookup_paths_timestamp_hash_same(const LookupPaths *lp, uint64_t timestamp_hash, uint64_t *ret_new);
 int unit_file_build_name_map(
                 const LookupPaths *lp,
-                usec_t *ret_time,
-                Hashmap **ret_unit_ids_map,
-                Hashmap **ret_unit_names_map,
-                Set **ret_path_cache);
+                uint64_t *cache_timestamp_hash,
+                Hashmap **unit_ids_map,
+                Hashmap **unit_names_map,
+                Set **path_cache);
 
 int unit_file_find_fragment(
                 Hashmap *unit_ids_map,
                 Hashmap *unit_name_map,
                 const char *unit_name,
                 const char **ret_fragment_path,
-                Set **names);
+                Set **ret_names);
 
 const char* runlevel_to_target(const char *rl);
index b27a12c55d06bd15e2ad732c009eb066cb03e179..b4c35b8a53208bf10c5fba2951e990be714f1876 100644 (file)
@@ -66,7 +66,7 @@ int nss_passwd_to_user_record(
         hr->uid = pwd->pw_uid;
         hr->gid = pwd->pw_gid;
 
-        if (spwd && hashed_password_valid(spwd->sp_pwdp)) {
+        if (spwd && looks_like_hashed_password(spwd->sp_pwdp)) {
                 strv_free_erase(hr->hashed_password);
                 hr->hashed_password = strv_new(spwd->sp_pwdp);
                 if (!hr->hashed_password)
index be3559dc1037efec091ba4a1843daad3e0f0f919..0278591b14281bfe2cb615e0452c96f3f8a5309d 100644 (file)
@@ -579,11 +579,17 @@ static int varlink_parse_message(Varlink *v) {
 
         sz = e - begin + 1;
 
-        varlink_log(v, "New incoming message: %s", begin);
+        varlink_log(v, "New incoming message: %s", begin); /* FIXME: should we output the whole message here before validation?
+                                                            * This may produce a non-printable journal entry if the message
+                                                            * is invalid. We may also expose privileged information. */
 
         r = json_parse(begin, 0, &v->current, NULL, NULL);
-        if (r < 0)
-                return r;
+        if (r < 0) {
+                /* If we encounter a parse failure flush all data. We cannot possibly recover from this,
+                 * hence drop all buffered data now. */
+                v->input_buffer_index = v->input_buffer_size = v->input_buffer_unscanned = 0;
+                return varlink_log_errno(v, r, "Failed to parse JSON: %m");
+        }
 
         v->input_buffer_size -= sz;
 
index 038484e475971821df3ccbafd0eea41b602ba731..11196cd4d6adf143b78eba5319f2d7448bfcd363 100644 (file)
@@ -3,6 +3,7 @@
 #include "capability-util.h"
 #include "dev-setup.h"
 #include "fs-util.h"
+#include "mkdir.h"
 #include "path-util.h"
 #include "rm-rf.h"
 #include "tmpfile-util.h"
@@ -17,8 +18,8 @@ int main(int argc, char *argv[]) {
 
         assert_se(mkdtemp_malloc("/tmp/test-dev-setupXXXXXX", &p) >= 0);
 
-        f = prefix_roota(p, "/run");
-        assert_se(mkdir(f, 0755) >= 0);
+        f = prefix_roota(p, "/run/systemd");
+        assert_se(mkdir_p(f, 0755) >= 0);
 
         assert_se(make_inaccessible_nodes(f, 1, 1) >= 0);
 
index 4371da4785018969eb03b21d1c6f0e7f5c66457d..87779a4dd6eda9a1425cf4550fb35f4ccc1b2fc8 100644 (file)
@@ -47,7 +47,7 @@ static enum {
         ACTION_LIST,
         ACTION_QUERY,
         ACTION_WATCH,
-        ACTION_WALL
+        ACTION_WALL,
 } arg_action = ACTION_QUERY;
 
 static bool arg_plymouth = false;
@@ -143,8 +143,7 @@ static int agent_ask_password_tty(
                 const char *flag_file,
                 char ***ret) {
 
-        int tty_fd = -1;
-        int r;
+        int tty_fd = -1, r;
 
         if (arg_console) {
                 const char *con = arg_device ?: "/dev/console";
@@ -166,7 +165,7 @@ static int agent_ask_password_tty(
                 release_terminal();
         }
 
-        return 0;
+        return r;
 }
 
 static int process_one_password_file(const char *filename) {
@@ -210,7 +209,7 @@ static int process_one_password_file(const char *filename) {
 
         switch (arg_action) {
         case ACTION_LIST:
-                printf("'%s' (PID %u)\n", message, pid);
+                printf("'%s' (PID %u)\n", strna(message), pid);
                 return 0;
 
         case ACTION_WALL: {
@@ -219,7 +218,7 @@ static int process_one_password_file(const char *filename) {
                  if (asprintf(&wall,
                               "Password entry required for \'%s\' (PID %u).\r\n"
                               "Please enter password with the systemd-tty-ask-password-agent tool.",
-                              message,
+                              strna(message),
                               pid) < 0)
                          return log_oom();
 
@@ -233,7 +232,7 @@ static int process_one_password_file(const char *filename) {
 
                 if (access(socket_name, W_OK) < 0) {
                         if (arg_action == ACTION_QUERY)
-                                log_info("Not querying '%s' (PID %u), lacking privileges.", message, pid);
+                                log_info("Not querying '%s' (PID %u), lacking privileges.", strna(message), pid);
 
                         return 0;
                 }
@@ -246,7 +245,6 @@ static int process_one_password_file(const char *filename) {
                         r = ask_password_plymouth(message, not_after, flags, filename, &passwords);
                 else
                         r = agent_ask_password_tty(message, not_after, flags, filename, &passwords);
-
                 if (r < 0) {
                         /* If the query went away, that's OK */
                         if (IN_SET(r, -ETIME, -ENOENT))
@@ -262,8 +260,7 @@ static int process_one_password_file(const char *filename) {
                 if (r < 0)
                         return log_error_errno(r, "Failed to send: %m");
                 break;
-        }
-        }
+        }}
 
         return 0;
 }
@@ -713,7 +710,7 @@ static int run(int argc, char *argv[]) {
                 (void) release_terminal();
         }
 
-        return process_and_watch_password_files(arg_action != ACTION_QUERY);
+        return process_and_watch_password_files(!IN_SET(arg_action, ACTION_QUERY, ACTION_LIST));
 }
 
 DEFINE_MAIN_FUNCTION(run);
index c973ee9c0114e27a0390f5a2904ac51a45d3ae72..c6836cda03127ab791f9a6bdde964715b2a649e0 100644 (file)
@@ -685,7 +685,8 @@ static int parse_argv(int argc, char *argv[]) {
                         else if (streq(optarg, "help")) {
                                 puts("classic\n"
                                      "friendly\n"
-                                     "json");
+                                     "json\n"
+                                     "table");
                                 return 0;
                         } else
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid --output= mode: %s", optarg);
index aa2ed115ea2bcff8a146c4a10800547a76494482..275daad3f4e8609d1c253590d7fd3ca544e2d9bf 100644 (file)
@@ -148,6 +148,7 @@ units = [
         ['tmp.mount',                           '',
          'local-fs.target.wants/'],
         ['umount.target',                       ''],
+        ['usb-gadget.target',                   ''],
         ['user.slice',                          ''],
         ['var-lib-machines.mount',              'ENABLE_MACHINED',
          'remote-fs.target.wants/ machines.target.wants/'],