mirror of
https://git.proxmox.com/git/systemd
synced 2025-07-27 13:55:29 +00:00
New upstream version 246.4
This commit is contained in:
parent
5e42acaf16
commit
129ef395a7
@ -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>
|
||||
|
@ -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!-->
|
||||
|
@ -146,8 +146,10 @@
|
||||
</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>
|
||||
|
@ -73,7 +73,10 @@
|
||||
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, &i, &s, &j, &t, &k, &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", &fd);
|
||||
fd_copy = fcntl(fd, FD_DUPFD_CLOEXEC, 3);</programlisting>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -52,17 +52,19 @@
|
||||
</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'>
|
||||
|
@ -54,24 +54,19 @@
|
||||
(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
|
||||
|
@ -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>
|
||||
|
@ -1028,20 +1028,24 @@
|
||||
|
||||
<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>
|
||||
|
||||
|
@ -81,16 +81,14 @@
|
||||
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
|
||||
|
@ -75,6 +75,16 @@
|
||||
<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>
|
||||
|
@ -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
|
||||
@ -16,16 +23,19 @@
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -26,3 +26,11 @@
|
||||
#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
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-device.h"
|
||||
|
@ -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:
|
||||
|
@ -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 },
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -1,6 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
set -ex
|
||||
|
||||
[[ -f /dev/loop-control ]] || exit 77
|
||||
|
||||
repart=$1
|
||||
test -x $repart
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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", "*");
|
||||
}
|
||||
|
@ -19,4 +19,4 @@
|
||||
|
||||
int make_salt(char **ret);
|
||||
|
||||
bool hashed_password_valid(const char *s);
|
||||
bool looks_like_hashed_password(const char *s);
|
||||
|
@ -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, ×tamp_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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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/'],
|
||||
|
Loading…
Reference in New Issue
Block a user