1
0
mirror of https://github.com/systemd/systemd synced 2025-10-06 20:24:45 +02:00

Compare commits

...

7 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek
0c927c98a7 basic/socket-util: reserve more space for timeval/timespec messages
As reported in https://github.com/systemd/systemd/issues/38222, we get the
buffer size calculation wrong on 32-bit arm. The reporter suggested checking if
__TIMESIZE == 64, but I think it's better to just use the bigger size in all
cases. The code to guesstimate the buffer size was already tweaked a few times
and apparently it's not easy to get it right. Systemd and glibc might be
compiled with different combinations of __TIMESIZE, so the compile-time check
is not super reliable, and by using the bigger size, we don't depend on the
details of how glibc decided whether to duplicate the struct or not. The cost
is negligible, 16 bytes on stack, so let's do the easy and robust thing.

Solution based on the suggestion by UZver24.

While at it, drop the mock struct definitions. They are only used to calculate
the size, but since the types involved are 8-bit values, there are no alignment
issues and we can just calculate the size directly.

Fixes https://github.com/systemd/systemd/issues/38222.
2025-07-18 02:06:37 +09:00
Matteo Croce
9b31b3d5ee test: add basic test for timer serialization
Set an OnCalendar= timer before the downgrade, then test for its
validity after the downgrade and the upgrade.
2025-07-17 17:22:32 +01:00
ZIHCO
ad6e02e7b4 systemd-analyze: added the verb unit-gdb to spawn and attach gdb 2025-07-17 15:09:58 +01:00
Luca Boccassi
6235121abf
netdev-util: allow setting local address based on dhcp-pd addresses as well (#38211)
This extends the functionality introduced in #21648 to allow using
addresses chosen from a delegated prefix as well as the existing
SLAAC/LL/DHCP functionality.
2025-07-17 14:14:49 +01:00
Linus Heckemann
94e5d8b0e0 netdev-util: allow finding addresses from dhcp-pd 2025-07-16 16:17:19 +02:00
Linus Heckemann
4d6c0a55e1 netdev-util: don't repeat AF check for each address type 2025-07-14 13:56:28 +02:00
Linus Heckemann
8a7a33ab1e vcs-tag.sh: use more compatible shebang 2025-07-14 13:56:07 +02:00
18 changed files with 305 additions and 91 deletions

View File

@ -251,7 +251,7 @@
<listitem><para>Use the given debugger for the <command>debug</command> <listitem><para>Use the given debugger for the <command>debug</command>
command. If not given and <varname>$SYSTEMD_DEBUGGER</varname> is unset, then command. If not given and <varname>$SYSTEMD_DEBUGGER</varname> is unset, then
<citerefentry project='man-pages'><refentrytitle>gdb</refentrytitle><manvolnum>1</manvolnum></citerefentry> <citerefentry project='man-pages'><refentrytitle>gdb</refentrytitle><manvolnum>1</manvolnum></citerefentry>
will be used. </para> will be used.</para>
<xi:include href="version-info.xml" xpointer="v239"/></listitem> <xi:include href="version-info.xml" xpointer="v239"/></listitem>
</varlistentry> </varlistentry>

View File

@ -65,6 +65,12 @@
<arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="plain">unit-files</arg> <arg choice="plain">unit-files</arg>
</cmdsynopsis> </cmdsynopsis>
<cmdsynopsis>
<command>systemd-analyze</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="plain">unit-gdb</arg>
<arg choice="plain"><replaceable>SERVICE</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis> <cmdsynopsis>
<command>systemd-analyze</command> <command>systemd-analyze</command>
<arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="opt" rep="repeat">OPTIONS</arg>
@ -1183,6 +1189,23 @@ boot efi exitrd init lib32 libx32 media opt root sbin sys usr vmlin
<xi:include href="version-info.xml" xpointer="v258"/> <xi:include href="version-info.xml" xpointer="v258"/>
</refsect2> </refsect2>
<refsect2>
<title><command>systemd-analyze unit-gdb <replaceable>SERVICE</replaceable></command></title>
<para>Spawn and attach a debugger to the given service. By default,
<citerefentry project='man-pages'><refentrytitle>gdb</refentrytitle><manvolnum>1</manvolnum></citerefentry>
will be used. This may be changed using the <option>--debugger=</option> option or the
<varname>$SYSTEMD_DEBUGGER</varname> environment variable. Use the <option>--debugger-arguments=</option> option
to pass extra command line arguments to the debugger and quote as appropriate
when <replaceable>ARGS</replaceable> contain whitespace (See Example).</para>
<example>
<programlisting>$ systemd-analyze --debugger-arguments="-batch -ex 'info all-registers'" unit-gdb systemd-oomd.service</programlisting>
</example>
<xi:include href="version-info.xml" xpointer="v258"/>
</refsect2>
</refsect1> </refsect1>
<refsect1> <refsect1>
@ -1328,8 +1351,8 @@ boot efi exitrd init lib32 libx32 media opt root sbin sys usr vmlin
<term><option>--root=<replaceable>PATH</replaceable></option></term> <term><option>--root=<replaceable>PATH</replaceable></option></term>
<listitem><para>With <command>cat-config</command>, <command>verify</command>, <listitem><para>With <command>cat-config</command>, <command>verify</command>,
<command>condition</command> and <command>security</command> when used with <command>condition</command>, <command>unit-gdb</command>, and <command>security</command> when
<option>--offline=</option>, operate on files underneath the specified root path used with <option>--offline=</option>, operate on files underneath the specified root path
<replaceable>PATH</replaceable>.</para> <replaceable>PATH</replaceable>.</para>
<xi:include href="version-info.xml" xpointer="v239"/></listitem> <xi:include href="version-info.xml" xpointer="v239"/></listitem>
@ -1784,6 +1807,26 @@ boot efi exitrd init lib32 libx32 media opt root sbin sys usr vmlin
<xi:include href="version-info.xml" xpointer="v258"/></listitem> <xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--debugger=<replaceable>DEBUGGER</replaceable></option></term>
<listitem><para>Use the given debugger for the <command>unit-gdb</command> command. If not given and
<varname>$SYSTEMD_DEBUGGER</varname> is unset, then
<citerefentry project='man-pages'><refentrytitle>gdb</refentrytitle><manvolnum>1</manvolnum></citerefentry>
will be used.</para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><option>-A</option> <replaceable>ARGS</replaceable></term>
<term><option>--debugger-arguments=<replaceable>ARGS</replaceable></option></term>
<listitem><para>Pass the given <replaceable>ARGS</replaceable> as extra command line arguments to the debugger.</para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" /> <xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" /> <xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="no-pager" /> <xi:include href="standard-options.xml" xpointer="no-pager" />

View File

@ -1508,7 +1508,7 @@ Ports=eth2</programlisting>
<para>A static local address for tunneled packets. It must be an address on another interface <para>A static local address for tunneled packets. It must be an address on another interface
of this host, or one of the special values <literal>any</literal>, of this host, or one of the special values <literal>any</literal>,
<literal>ipv4_link_local</literal>, <literal>ipv6_link_local</literal>, <literal>ipv4_link_local</literal>, <literal>ipv6_link_local</literal>,
<literal>dhcp4</literal>, <literal>dhcp6</literal>, and <literal>slaac</literal>. If one <literal>dhcp4</literal>, <literal>dhcp6</literal>, <literal>dhcp_pd</literal>, and <literal>slaac</literal>. If one
of the special values except for <literal>any</literal> is specified, an address which of the special values except for <literal>any</literal> is specified, an address which
matches the corresponding type on the underlying interface will be used. Defaults to matches the corresponding type on the underlying interface will be used. Defaults to
<literal>any</literal>.</para> <literal>any</literal>.</para>

View File

@ -63,7 +63,7 @@ _systemd_analyze() {
local -A OPTS=( local -A OPTS=(
[STANDALONE]='-h --help --version --system --user --global --order --require --no-pager [STANDALONE]='-h --help --version --system --user --global --order --require --no-pager
--man=no --generators=yes -q --quiet' --man=no --generators=yes -q --quiet'
[ARG]='-H --host -M --machine --fuzz --from-pattern --to-pattern --root' [ARG]='-H --host -M --machine --fuzz --from-pattern --to-pattern --root --debugger'
) )
local -A VERBS=( local -A VERBS=(
@ -83,6 +83,7 @@ _systemd_analyze() {
[CAPABILITY]='capability' [CAPABILITY]='capability'
[TRANSIENT_SETTINGS]='transient-settings' [TRANSIENT_SETTINGS]='transient-settings'
[UNIT_SHELL]='unit-shell' [UNIT_SHELL]='unit-shell'
[UNIT_GDB]='unit-gdb'
) )
local CONFIGS='locale.conf systemd/bootchart.conf systemd/coredump.conf systemd/journald.conf local CONFIGS='locale.conf systemd/bootchart.conf systemd/coredump.conf systemd/journald.conf
@ -241,6 +242,13 @@ _systemd_analyze() {
else else
comps=$( __get_services $mode ) comps=$( __get_services $mode )
fi fi
elif __contains_word "$verb" ${VERBS[UNIT_GDB]}; then
if [[ $cur = -* ]]; then
comps='--help --version --debugger --debugger-arguments --root'
else
comps=$( __get_services $mode )
fi
fi fi
COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) COMPREPLY=( $(compgen -W '$comps' -- "$cur") )

View File

@ -0,0 +1,123 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <stdlib.h>
#include <unistd.h>
#include "sd-bus.h"
#include "alloc-util.h"
#include "analyze.h"
#include "analyze-unit-gdb.h"
#include "bus-error.h"
#include "bus-util.h"
#include "log.h"
#include "pidref.h"
#include "process-util.h"
#include "runtime-scope.h"
#include "signal-util.h"
#include "strv.h"
#include "unit-def.h"
#include "unit-name.h"
int verb_unit_gdb(int argc, char *argv[], void *userdata) {
static const struct sigaction sa = {
.sa_sigaction = sigterm_process_group_handler,
.sa_flags = SA_SIGINFO,
};
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *unit = NULL;
int r;
if (arg_transport != BUS_TRANSPORT_LOCAL)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot spawn a debugger for a remote service");
r = unit_name_mangle_with_suffix(argv[1], "as unit", UNIT_NAME_MANGLE_WARN, ".service", &unit);
if (r < 0)
return log_error_errno(r, "Failed to mangle name '%s': %m", argv[1]);
r = acquire_bus(&bus, /* use_full_bus= */ NULL);
if (r < 0)
return bus_log_connect_error(r, arg_transport, arg_runtime_scope);
_cleanup_free_ char *object = unit_dbus_path_from_name(unit);
if (!object)
return log_oom();
r = sd_bus_get_property(
bus,
"org.freedesktop.systemd1",
object,
"org.freedesktop.systemd1.Service",
"MainPID",
&error,
&reply,
"u");
if (r < 0)
return log_error_errno(r, "Failed to get the main PID of %s: %s", unit, bus_error_message(&error, r));
pid_t pid;
r = sd_bus_message_read(reply, "u", &pid);
if (r < 0)
return log_error_errno(r, "Failed to read the main PID of %s from reply: %m", unit);
if (!arg_debugger)
arg_debugger = secure_getenv("SYSTEMD_DEBUGGER") ?: "gdb";
_cleanup_strv_free_ char **debugger_call = NULL;
r = strv_extend(&debugger_call, arg_debugger);
if (r < 0)
return log_oom();
if (!STR_IN_SET(arg_debugger, "gdb", "lldb"))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The debugger must be either 'gdb' or 'lldb'");
if (streq(arg_debugger, "gdb")) {
r = strv_extendf(&debugger_call, "--pid=" PID_FMT, pid);
if (r < 0)
return log_oom();
}
if (streq(arg_debugger, "lldb")) {
r = strv_extendf(&debugger_call, "--attach-pid=" PID_FMT, pid);
if (r < 0)
return log_oom();
}
if (arg_root) {
if (streq(arg_debugger, "gdb")) {
_cleanup_free_ char *sysroot_cmd = strjoin("set sysroot ", arg_root);
r = strv_extend_many(&debugger_call, "-iex", sysroot_cmd);
if (r < 0)
return log_oom();
} else if (streq(arg_debugger, "lldb")) {
_cleanup_free_ char *sysroot_cmd = strjoin("platform select --sysroot ", arg_root, " host");
r = strv_extend_many(&debugger_call, "-O", sysroot_cmd);
if (r < 0)
return log_oom();
}
}
/* Don't interfere with debugger and its handling of SIGINT. */
(void) ignore_signals(SIGINT);
(void) sigaction(SIGTERM, &sa, NULL);
_cleanup_free_ char *fork_name = strjoin("(", debugger_call[0], ")");
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pidref);
if (r < 0)
return log_error_errno(r, "Fork failed: %m");
if (r == 0) {
(void) execvp(debugger_call[0], debugger_call);
log_error_errno(errno, "Failed to invoke '%s': %m", debugger_call[0]);
_exit(EXIT_FAILURE);
}
return pidref_wait_for_terminate_and_check(
debugger_call[0],
&pidref,
WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS);
}

View File

@ -0,0 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
int verb_unit_gdb(int argc, char *argv[], void *userdata);

View File

@ -43,6 +43,7 @@
#include "analyze-timespan.h" #include "analyze-timespan.h"
#include "analyze-timestamp.h" #include "analyze-timestamp.h"
#include "analyze-unit-files.h" #include "analyze-unit-files.h"
#include "analyze-unit-gdb.h"
#include "analyze-unit-paths.h" #include "analyze-unit-paths.h"
#include "analyze-unit-shell.h" #include "analyze-unit-shell.h"
#include "analyze-verify.h" #include "analyze-verify.h"
@ -53,6 +54,7 @@
#include "bus-util.h" #include "bus-util.h"
#include "calendarspec.h" #include "calendarspec.h"
#include "dissect-image.h" #include "dissect-image.h"
#include "extract-word.h"
#include "image-policy.h" #include "image-policy.h"
#include "log.h" #include "log.h"
#include "loop-util.h" #include "loop-util.h"
@ -79,6 +81,8 @@ usec_t arg_fuzz = 0;
PagerFlags arg_pager_flags = 0; PagerFlags arg_pager_flags = 0;
CatFlags arg_cat_flags = 0; CatFlags arg_cat_flags = 0;
BusTransport arg_transport = BUS_TRANSPORT_LOCAL; BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
const char *arg_debugger = NULL;
static char **arg_debugger_args = NULL;
const char *arg_host = NULL; const char *arg_host = NULL;
RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM; RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
RecursiveErrors arg_recursive_errors = _RECURSIVE_ERRORS_INVALID; RecursiveErrors arg_recursive_errors = _RECURSIVE_ERRORS_INVALID;
@ -242,6 +246,7 @@ static int help(int argc, char *argv[], void *userdata) {
" security [UNIT...] Analyze security of unit\n" " security [UNIT...] Analyze security of unit\n"
" fdstore SERVICE... Show file descriptor store contents of service\n" " fdstore SERVICE... Show file descriptor store contents of service\n"
" malloc [D-BUS SERVICE...] Dump malloc stats of a D-Bus service\n" " malloc [D-BUS SERVICE...] Dump malloc stats of a D-Bus service\n"
" unit-gdb SERVICE Attach a debugger to the given running service\n"
" unit-shell SERVICE [Command]\n" " unit-shell SERVICE [Command]\n"
" Run command on the namespace of the service\n" " Run command on the namespace of the service\n"
"\n%3$sExecutable Analysis:%4$s\n" "\n%3$sExecutable Analysis:%4$s\n"
@ -296,6 +301,9 @@ static int help(int argc, char *argv[], void *userdata) {
" --image-policy=POLICY Specify disk image dissection policy\n" " --image-policy=POLICY Specify disk image dissection policy\n"
" -m --mask Parse parameter as numeric capability mask\n" " -m --mask Parse parameter as numeric capability mask\n"
" --drm-device=PATH Use this DRM device sysfs path to get EDID\n" " --drm-device=PATH Use this DRM device sysfs path to get EDID\n"
" --debugger=DEBUGGER Use the given debugger\n"
" -A --debugger-arguments=ARGS\n"
" Pass the given arguments to the debugger\n"
"\nSee the %2$s for details.\n", "\nSee the %2$s for details.\n",
program_invocation_short_name, program_invocation_short_name,
@ -344,6 +352,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_SCALE_FACTOR_SVG, ARG_SCALE_FACTOR_SVG,
ARG_DETAILED_SVG, ARG_DETAILED_SVG,
ARG_DRM_DEVICE_PATH, ARG_DRM_DEVICE_PATH,
ARG_DEBUGGER,
}; };
static const struct option options[] = { static const struct option options[] = {
@ -355,7 +364,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "root", required_argument, NULL, ARG_ROOT }, { "root", required_argument, NULL, ARG_ROOT },
{ "image", required_argument, NULL, ARG_IMAGE }, { "image", required_argument, NULL, ARG_IMAGE },
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY }, { "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
{ "recursive-errors", required_argument, NULL, ARG_RECURSIVE_ERRORS }, { "recursive-errors" , required_argument, NULL, ARG_RECURSIVE_ERRORS },
{ "offline", required_argument, NULL, ARG_OFFLINE }, { "offline", required_argument, NULL, ARG_OFFLINE },
{ "threshold", required_argument, NULL, ARG_THRESHOLD }, { "threshold", required_argument, NULL, ARG_THRESHOLD },
{ "security-policy", required_argument, NULL, ARG_SECURITY_POLICY }, { "security-policy", required_argument, NULL, ARG_SECURITY_POLICY },
@ -383,6 +392,8 @@ static int parse_argv(int argc, char *argv[]) {
{ "scale-svg", required_argument, NULL, ARG_SCALE_FACTOR_SVG }, { "scale-svg", required_argument, NULL, ARG_SCALE_FACTOR_SVG },
{ "detailed", no_argument, NULL, ARG_DETAILED_SVG }, { "detailed", no_argument, NULL, ARG_DETAILED_SVG },
{ "drm-device", required_argument, NULL, ARG_DRM_DEVICE_PATH }, { "drm-device", required_argument, NULL, ARG_DRM_DEVICE_PATH },
{ "debugger", required_argument, NULL, ARG_DEBUGGER },
{ "debugger-arguments", required_argument, NULL, 'A' },
{} {}
}; };
@ -397,7 +408,7 @@ static int parse_argv(int argc, char *argv[]) {
optind = 0; optind = 0;
for (;;) { for (;;) {
static const char option_string[] = "-hqH:M:U:m"; static const char option_string[] = "-hqH:M:U:mA:";
c = getopt_long(argc, argv, option_string + reorder, options, NULL); c = getopt_long(argc, argv, option_string + reorder, options, NULL);
if (c < 0) if (c < 0)
@ -653,6 +664,19 @@ static int parse_argv(int argc, char *argv[]) {
return r; return r;
break; break;
case ARG_DEBUGGER:
arg_debugger = strdup(optarg);
break;
case 'A': {
_cleanup_strv_free_ char **l = NULL;
r = strv_split_full(&l, optarg, WHITESPACE, EXTRACT_UNQUOTE);
if (r < 0)
return log_error_errno(r, "Failed to parse debugger arguments '%s': %m", optarg);
strv_free_and_replace(arg_debugger_args, l);
break;
}
case '?': case '?':
return -EINVAL; return -EINVAL;
@ -700,10 +724,10 @@ done:
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Option --security-policy= is only supported for security."); "Option --security-policy= is only supported for security.");
if ((arg_root || arg_image) && (!STRPTR_IN_SET(argv[optind], "cat-config", "verify", "condition", "inspect-elf")) && if ((arg_root || arg_image) && (!STRPTR_IN_SET(argv[optind], "cat-config", "verify", "condition", "inspect-elf", "unit-gdb")) &&
(!(streq_ptr(argv[optind], "security") && arg_offline))) (!(streq_ptr(argv[optind], "security") && arg_offline)))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Options --root= and --image= are only supported for cat-config, verify, condition and security when used with --offline= right now."); "Options --root= and --image= are only supported for cat-config, verify, condition, unit-gdb, and security when used with --offline= right now.");
/* Having both an image and a root is not supported by the code */ /* Having both an image and a root is not supported by the code */
if (arg_root && arg_image) if (arg_root && arg_image)
@ -756,6 +780,7 @@ static int run(int argc, char *argv[]) {
{ "dump", VERB_ANY, VERB_ANY, 0, verb_dump }, { "dump", VERB_ANY, VERB_ANY, 0, verb_dump },
{ "cat-config", 2, VERB_ANY, 0, verb_cat_config }, { "cat-config", 2, VERB_ANY, 0, verb_cat_config },
{ "unit-files", VERB_ANY, VERB_ANY, 0, verb_unit_files }, { "unit-files", VERB_ANY, VERB_ANY, 0, verb_unit_files },
{ "unit-gdb", 2, VERB_ANY, 0, verb_unit_gdb },
{ "unit-paths", 1, 1, 0, verb_unit_paths }, { "unit-paths", 1, 1, 0, verb_unit_paths },
{ "unit-shell", 2, VERB_ANY, 0, verb_unit_shell }, { "unit-shell", 2, VERB_ANY, 0, verb_unit_shell },
{ "exit-status", VERB_ANY, VERB_ANY, 0, verb_exit_status }, { "exit-status", VERB_ANY, VERB_ANY, 0, verb_exit_status },

View File

@ -24,6 +24,7 @@ extern PagerFlags arg_pager_flags;
extern CatFlags arg_cat_flags; extern CatFlags arg_cat_flags;
extern BusTransport arg_transport; extern BusTransport arg_transport;
extern const char *arg_host; extern const char *arg_host;
extern const char *arg_debugger;
extern RuntimeScope arg_runtime_scope; extern RuntimeScope arg_runtime_scope;
extern RecursiveErrors arg_recursive_errors; extern RecursiveErrors arg_recursive_errors;
extern bool arg_man; extern bool arg_man;

View File

@ -32,6 +32,7 @@ systemd_analyze_sources = files(
'analyze-timespan.c', 'analyze-timespan.c',
'analyze-timestamp.c', 'analyze-timestamp.c',
'analyze-unit-files.c', 'analyze-unit-files.c',
'analyze-unit-gdb.c',
'analyze-unit-paths.c', 'analyze-unit-paths.c',
'analyze-unit-shell.c', 'analyze-unit-shell.c',
'analyze-verify.c', 'analyze-verify.c',

View File

@ -5,6 +5,7 @@
#include "errno-util.h" #include "errno-util.h"
#include "parse-util.h" #include "parse-util.h"
#include "process-util.h"
#include "signal-util.h" #include "signal-util.h"
#include "stdio-util.h" #include "stdio-util.h"
#include "string-table.h" #include "string-table.h"
@ -319,3 +320,15 @@ int parse_signo(const char *s, int *ret) {
return 0; return 0;
} }
void sigterm_process_group_handler(int signal, siginfo_t *info, void *ucontext) {
assert(signal == SIGTERM);
assert(info);
/* If the sender is not us, propagate the signal to all processes in
* the same process group */
if (si_code_from_process(info->si_code) &&
pid_is_valid(info->si_pid) &&
info->si_pid != getpid_cached())
(void) kill(0, signal);
}

View File

@ -93,3 +93,5 @@ static inline bool si_code_from_process(int si_code) {
return si_code < 0 || IN_SET(si_code, SI_USER, SI_QUEUE); return si_code < 0 || IN_SET(si_code, SI_USER, SI_QUEUE);
} }
void sigterm_process_group_handler(int signal, siginfo_t *info, void *ucontext);

View File

@ -254,27 +254,13 @@ int socket_bind_to_ifindex(int fd, int ifindex);
int socket_autobind(int fd, char **ret_name); int socket_autobind(int fd, char **ret_name);
/* Define a 64-bit version of timeval/timespec in any case, even on 32-bit userspace. */
struct timeval_large {
uint64_t tvl_sec, tvl_usec;
};
struct timespec_large {
uint64_t tvl_sec, tvl_nsec;
};
/* glibc duplicates timespec/timeval on certain 32-bit arches, once in 32-bit and once in 64-bit. /* glibc duplicates timespec/timeval on certain 32-bit arches, once in 32-bit and once in 64-bit.
* See __convert_scm_timestamps() in glibc source code. Hence, we need additional buffer space for them * See __convert_scm_timestamps() in glibc source code. Hence, we need additional buffer space for them
* to prevent truncating control msg (recvmsg() MSG_CTRUNC). */ * to prevent truncating control msg (recvmsg() MSG_CTRUNC). */
#define CMSG_SPACE_TIMEVAL \ #define CMSG_SPACE_TIMEVAL \
((sizeof(struct timeval) == sizeof(struct timeval_large)) ? \ (CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(2 * sizeof(uint64_t)))
CMSG_SPACE(sizeof(struct timeval)) : \
CMSG_SPACE(sizeof(struct timeval)) + \
CMSG_SPACE(sizeof(struct timeval_large)))
#define CMSG_SPACE_TIMESPEC \ #define CMSG_SPACE_TIMESPEC \
((sizeof(struct timespec) == sizeof(struct timespec_large)) ? \ (CMSG_SPACE(sizeof(struct timespec)) + CMSG_SPACE(2 * sizeof(uint64_t)))
CMSG_SPACE(sizeof(struct timespec)) : \
CMSG_SPACE(sizeof(struct timespec)) + \
CMSG_SPACE(sizeof(struct timespec_large)))
ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags); ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags);

View File

@ -1164,21 +1164,9 @@ static int dump_core(int argc, char **argv, void *userdata) {
return 0; return 0;
} }
static void sigterm_handler(int signal, siginfo_t *info, void *ucontext) {
assert(signal == SIGTERM);
assert(info);
/* If the sender is not us, propagate the signal to all processes in
* the same process group */
if (si_code_from_process(info->si_code) &&
pid_is_valid(info->si_pid) &&
info->si_pid != getpid_cached())
(void) kill(0, signal);
}
static int run_debug(int argc, char **argv, void *userdata) { static int run_debug(int argc, char **argv, void *userdata) {
static const struct sigaction sa = { static const struct sigaction sa = {
.sa_sigaction = sigterm_handler, .sa_sigaction = sigterm_process_group_handler,
.sa_flags = SA_SIGINFO, .sa_flags = SA_SIGINFO,
}; };

View File

@ -12,6 +12,7 @@ static const char * const netdev_local_address_type_table[_NETDEV_LOCAL_ADDRESS_
[NETDEV_LOCAL_ADDRESS_DHCP4] = "dhcp4", [NETDEV_LOCAL_ADDRESS_DHCP4] = "dhcp4",
[NETDEV_LOCAL_ADDRESS_DHCP6] = "dhcp6", [NETDEV_LOCAL_ADDRESS_DHCP6] = "dhcp6",
[NETDEV_LOCAL_ADDRESS_SLAAC] = "slaac", [NETDEV_LOCAL_ADDRESS_SLAAC] = "slaac",
[NETDEV_LOCAL_ADDRESS_DHCP_PD] = "dhcp_pd",
}; };
DEFINE_STRING_TABLE_LOOKUP(netdev_local_address_type, NetDevLocalAddressType); DEFINE_STRING_TABLE_LOOKUP(netdev_local_address_type, NetDevLocalAddressType);
@ -29,22 +30,14 @@ int link_get_local_address(
switch (type) { switch (type) {
case NETDEV_LOCAL_ADDRESS_IPV4LL: case NETDEV_LOCAL_ADDRESS_IPV4LL:
assert(IN_SET(family, AF_UNSPEC, AF_INET));
family = AF_INET;
break;
case NETDEV_LOCAL_ADDRESS_IPV6LL:
assert(IN_SET(family, AF_UNSPEC, AF_INET6));
family = AF_INET6;
break;
case NETDEV_LOCAL_ADDRESS_DHCP4: case NETDEV_LOCAL_ADDRESS_DHCP4:
assert(IN_SET(family, AF_UNSPEC, AF_INET)); assert(IN_SET(family, AF_UNSPEC, AF_INET));
family = AF_INET; family = AF_INET;
break; break;
case NETDEV_LOCAL_ADDRESS_IPV6LL:
case NETDEV_LOCAL_ADDRESS_DHCP6: case NETDEV_LOCAL_ADDRESS_DHCP6:
assert(IN_SET(family, AF_UNSPEC, AF_INET6));
family = AF_INET6;
break;
case NETDEV_LOCAL_ADDRESS_SLAAC: case NETDEV_LOCAL_ADDRESS_SLAAC:
case NETDEV_LOCAL_ADDRESS_DHCP_PD:
assert(IN_SET(family, AF_UNSPEC, AF_INET6)); assert(IN_SET(family, AF_UNSPEC, AF_INET6));
family = AF_INET6; family = AF_INET6;
break; break;
@ -86,6 +79,10 @@ int link_get_local_address(
if (a->source != NETWORK_CONFIG_SOURCE_NDISC) if (a->source != NETWORK_CONFIG_SOURCE_NDISC)
continue; continue;
break; break;
case NETDEV_LOCAL_ADDRESS_DHCP_PD:
if (a->source != NETWORK_CONFIG_SOURCE_DHCP_PD)
continue;
break;
default: default:
assert_not_reached(); assert_not_reached();
} }

View File

@ -9,6 +9,7 @@ typedef enum NetDevLocalAddressType {
NETDEV_LOCAL_ADDRESS_DHCP4, NETDEV_LOCAL_ADDRESS_DHCP4,
NETDEV_LOCAL_ADDRESS_DHCP6, NETDEV_LOCAL_ADDRESS_DHCP6,
NETDEV_LOCAL_ADDRESS_SLAAC, NETDEV_LOCAL_ADDRESS_SLAAC,
NETDEV_LOCAL_ADDRESS_DHCP_PD,
_NETDEV_LOCAL_ADDRESS_TYPE_MAX, _NETDEV_LOCAL_ADDRESS_TYPE_MAX,
_NETDEV_LOCAL_ADDRESS_TYPE_INVALID = -EINVAL, _NETDEV_LOCAL_ADDRESS_TYPE_INVALID = -EINVAL,
} NetDevLocalAddressType; } NetDevLocalAddressType;

View File

@ -11,6 +11,7 @@
#include "conf-parser.h" #include "conf-parser.h"
#include "hexdecoct.h" #include "hexdecoct.h"
#include "missing-network.h" #include "missing-network.h"
#include "netdev-util.h"
#include "netlink-util.h" #include "netlink-util.h"
#include "networkd-manager.h" #include "networkd-manager.h"
#include "parse-util.h" #include "parse-util.h"
@ -784,7 +785,7 @@ int config_parse_tunnel_local_address(
type = netdev_local_address_type_from_string(rvalue); type = netdev_local_address_type_from_string(rvalue);
if (IN_SET(type, NETDEV_LOCAL_ADDRESS_IPV4LL, NETDEV_LOCAL_ADDRESS_DHCP4)) if (IN_SET(type, NETDEV_LOCAL_ADDRESS_IPV4LL, NETDEV_LOCAL_ADDRESS_DHCP4))
f = AF_INET; f = AF_INET;
else if (IN_SET(type, NETDEV_LOCAL_ADDRESS_IPV6LL, NETDEV_LOCAL_ADDRESS_DHCP6, NETDEV_LOCAL_ADDRESS_SLAAC)) else if (IN_SET(type, NETDEV_LOCAL_ADDRESS_IPV6LL, NETDEV_LOCAL_ADDRESS_DHCP6, NETDEV_LOCAL_ADDRESS_SLAAC, NETDEV_LOCAL_ADDRESS_DHCP_PD))
f = AF_INET6; f = AF_INET6;
else { else {
type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID; type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID;

View File

@ -28,7 +28,7 @@ if [[ $($unitscmd --output json | jq length) -gt 0 ]]; then
fi fi
check_sd() { check_sd() {
local unit fail=0 local unit fail=0 timer1_new timer2_new
for unit in $($unitscmd --output json | jq -r '.[].unit'); do for unit in $($unitscmd --output json | jq -r '.[].unit'); do
if ! grep -sxqF "$unit" /tmp/failed-units; then if ! grep -sxqF "$unit" /tmp/failed-units; then
fail=1 fail=1
@ -52,12 +52,33 @@ check_sd() {
fail=1 fail=1
fi fi
# ignore the systemctl status error code until we sort out
# https://github.com/systemd/systemd/issues/38214
systemctl status upgrade_timer_test.{service,timer} || true
timer1_new=$(systemctl show -P TimersCalendar upgrade_timer_test.timer)
timer2_new=$(systemctl show -P NextElapseUSecRealtime upgrade_timer_test.timer)
if [[ "$timer1" != "$timer1_new" ]]; then
echo "Timer changed unexpectedly: '$timer1' != '$timer1_new'"
fail=1
fi
if [[ "$timer2" != "$timer2_new" ]]; then
echo "Timer changed unexpectedly: '$timer2' != '$timer2_new'"
fail=1
fi
[[ $fail -eq 0 ]] [[ $fail -eq 0 ]]
} }
# Copy the unit in /run so systemd finds it after the downgrade # Copy the unit in /run so systemd finds it after the downgrade
cp /usr/lib/systemd/tests/testdata/units/TEST-88-UPGRADE.service /run/systemd/system cp /usr/lib/systemd/tests/testdata/units/TEST-88-UPGRADE.service /run/systemd/system
now=$(date +%s)
after_2h=$((now + 3600 * 2))
systemd-run --on-calendar="@$after_2h" -u upgrade_timer_test date
timer1=$(systemctl show -P TimersCalendar upgrade_timer_test.timer)
timer2=$(systemctl show -P NextElapseUSecRealtime upgrade_timer_test.timer)
dnf downgrade -y --allowerasing --disablerepo '*' "$pkgdir"/distro/*.rpm dnf downgrade -y --allowerasing --disablerepo '*' "$pkgdir"/distro/*.rpm
# Some distros don't ship networkd, so the test will always fail # Some distros don't ship networkd, so the test will always fail

View File

@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
set -e set -e