1
0
mirror of https://github.com/systemd/systemd synced 2026-04-11 17:44:58 +02:00

Compare commits

..

No commits in common. "3e7bf8535f991e6a8e4104e7b6303b783b372d21" and "cbf8fc90d50733e9096f73d590541213aa158c26" have entirely different histories.

62 changed files with 387 additions and 1918 deletions

View File

@ -9,8 +9,9 @@ success() { echo >&2 -e "\033[32;1m$1\033[0m"; }
ARGS=( ARGS=(
"--optimization=0" "--optimization=0"
"--optimization=2"
"--optimization=s" "--optimization=s"
"--optimization=3 -Db_lto=true -Ddns-over-tls=false" "--optimization=3 -Db_lto=true"
"--optimization=3 -Db_lto=false" "--optimization=3 -Db_lto=false"
"--optimization=3 -Ddns-over-tls=openssl" "--optimization=3 -Ddns-over-tls=openssl"
"--optimization=3 -Dfexecve=true -Dstandalone-binaries=true -Dstatic-libsystemd=true -Dstatic-libudev=true" "--optimization=3 -Dfexecve=true -Dstandalone-binaries=true -Dstatic-libsystemd=true -Dstatic-libudev=true"
@ -62,7 +63,6 @@ PACKAGES=(
COMPILER="${COMPILER:?}" COMPILER="${COMPILER:?}"
COMPILER_VERSION="${COMPILER_VERSION:?}" COMPILER_VERSION="${COMPILER_VERSION:?}"
LINKER="${LINKER:?}" LINKER="${LINKER:?}"
CRYPTOLIB="${CRYPTOLIB:?}"
RELEASE="$(lsb_release -cs)" RELEASE="$(lsb_release -cs)"
bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ $RELEASE main restricted universe multiverse' >>/etc/apt/sources.list" bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ $RELEASE main restricted universe multiverse' >>/etc/apt/sources.list"
@ -122,7 +122,7 @@ for args in "${ARGS[@]}"; do
CC="$CC" CC_LD="$LINKER" CFLAGS="-Werror" \ CC="$CC" CC_LD="$LINKER" CFLAGS="-Werror" \
CXX="$CXX" CXX_LD="$LINKER" CXXFLAGS="-Werror" \ CXX="$CXX" CXX_LD="$LINKER" CXXFLAGS="-Werror" \
meson -Dtests=unsafe -Dslow-tests=true -Dfuzz-tests=true --werror \ meson -Dtests=unsafe -Dslow-tests=true -Dfuzz-tests=true --werror \
-Dcryptolib="${CRYPTOLIB:?}" $args build; then $args build; then
fatal "meson failed with $args" fatal "meson failed with $args"
fi fi

View File

@ -19,20 +19,20 @@ jobs:
build: build:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
concurrency: concurrency:
group: ${{ github.workflow }}-${{ toJSON(matrix.env) }}-${{ github.ref }} group: ${{ github.workflow }}-${{ matrix.env.COMPILER }}-${{ matrix.env.COMPILER_VERSION }}-${{ matrix.env.LINKER }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
env: env:
- { COMPILER: "gcc", COMPILER_VERSION: "10", LINKER: "bfd", CRYPTOLIB: "gcrypt" } - { COMPILER: "gcc", COMPILER_VERSION: "10", LINKER: "bfd" }
- { COMPILER: "gcc", COMPILER_VERSION: "11", LINKER: "gold", CRYPTOLIB: "openssl" } - { COMPILER: "gcc", COMPILER_VERSION: "11", LINKER: "gold" }
- { COMPILER: "clang", COMPILER_VERSION: "11", LINKER: "bfd", CRYPTOLIB: "auto" } - { COMPILER: "clang", COMPILER_VERSION: "11", LINKER: "bfd" }
- { COMPILER: "clang", COMPILER_VERSION: "12", LINKER: "gold", CRYPTOLIB: "gcrypt" } - { COMPILER: "clang", COMPILER_VERSION: "12", LINKER: "gold" }
- { COMPILER: "clang", COMPILER_VERSION: "13", LINKER: "lld", CRYPTOLIB: "openssl" } - { COMPILER: "clang", COMPILER_VERSION: "13", LINKER: "lld" }
env: ${{ matrix.env }} env: ${{ matrix.env }}
steps: steps:
- name: Repository checkout - name: Repository checkout
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: ${{ format('Build check ({0}-{1}-{2}-{3})', env.COMPILER, env.COMPILER_VERSION, env.LINKER, env.CRYPTOLIB) }} - name: Build check (${{ env.COMPILER }}-${{ env.COMPILER_VERSION }}-${{ env.LINKER }})
run: sudo -E .github/workflows/build_test.sh run: sudo -E .github/workflows/build_test.sh

View File

@ -1,3 +0,0 @@
# This is the fallback locale configuration provided by systemd.
LANG="{{ SYSTEMD_DEFAULT_LOCALE }}"

View File

@ -1,11 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
factory_etc_dir = factorydir / 'etc'
custom_target(
'locale.conf',
input : 'locale.conf.in',
output : 'locale.conf',
command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'],
install : true,
install_dir : factory_etc_dir)

View File

@ -78,10 +78,10 @@
<term><command>capture</command> <arg choice="opt" rep="repeat"><replaceable>SERVICE</replaceable></arg></term> <term><command>capture</command> <arg choice="opt" rep="repeat"><replaceable>SERVICE</replaceable></arg></term>
<listitem><para>Similar to <command>monitor</command> but <listitem><para>Similar to <command>monitor</command> but
writes the output in pcapng format (for details, see writes the output in pcap format (for details, see the <ulink
<ulink url="https://github.com/pcapng/pcapng/"> url="https://wiki.wireshark.org/Development/LibpcapFileFormat">Libpcap
PCAP Next Generation (pcapng) Capture File Format</ulink>). File Format</ulink> description). Make sure to redirect
Make sure to redirect standard output to a file or pipe. Tools like standard output to a file. Tools like
<citerefentry project='die-net'><refentrytitle>wireshark</refentrytitle><manvolnum>1</manvolnum></citerefentry> <citerefentry project='die-net'><refentrytitle>wireshark</refentrytitle><manvolnum>1</manvolnum></citerefentry>
may be used to dissect and view the resulting may be used to dissect and view the resulting
files.</para></listitem> files.</para></listitem>

View File

@ -32,8 +32,7 @@
<para>The basic file format of <filename>locale.conf</filename> is <para>The basic file format of <filename>locale.conf</filename> is
a newline-separated list of environment-like shell-compatible a newline-separated list of environment-like shell-compatible
variable assignments, ignoring comments and empty lines. variable assignments. It is possible to source the configuration
It is possible to source the configuration
from shell scripts, however, beyond mere variable assignments, no from shell scripts, however, beyond mere variable assignments, no
shell features are supported, allowing applications to read the shell features are supported, allowing applications to read the
file without implementing a shell compatible execution file without implementing a shell compatible execution
@ -65,14 +64,14 @@
might be checked for locale configuration as well, however only as might be checked for locale configuration as well, however only as
fallback.</para> fallback.</para>
<para><filename>/etc/locale.conf</filename> can be updated <para><filename>/etc/locale.conf</filename> is usually created and updated
using using
<citerefentry><refentrytitle>systemd-localed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>. <citerefentry><refentrytitle>systemd-localed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
<citerefentry project='man-pages'><refentrytitle>localectl</refentrytitle><manvolnum>1</manvolnum></citerefentry> <citerefentry project='man-pages'><refentrytitle>localectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
may be used to alter the settings in this file during runtime from may be used to alter the settings in this file during runtime from
the command line. Use the command line. Use
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry> <citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
to customize them on mounted (but not booted) system images.</para> to initialize them on mounted (but not booted) system images.</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
@ -108,9 +107,7 @@
<para><filename>/etc/locale.conf</filename>:</para> <para><filename>/etc/locale.conf</filename>:</para>
<programlisting># Custom settings <programlisting>LANG=de_DE.UTF-8
LANG=de_DE.UTF-8
LC_MESSAGES=en_US.UTF-8</programlisting> LC_MESSAGES=en_US.UTF-8</programlisting>
</example> </example>

View File

@ -3546,41 +3546,6 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
</table></listitem> </table></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>$MONITOR_METADATA</varname></term>
<listitem><para>Only defined for the service unit type, this environment variable is passed to all
<varname>ExecStart=</varname> and <varname>ExecStartPre=</varname> processes which run in services
triggered by <varname>OnFailure=</varname> or <varname>OnSuccess=</varname> dependencies.</para>
<para>
The contents of this variable consists of a semi-colon separated list of metadata fields associated with the triggering
service. For each service which triggered the <varname>OnFailure=</varname> or <varname>OnSuccess=</varname>
dependency the following fields will be set:
</para>
<itemizedlist>
<listitem><para><constant>SERVICE_RESULT</constant></para></listitem>
<listitem><para><constant>EXIT_CODE</constant></para></listitem>
<listitem><para><constant>EXIT_STATUS</constant></para></listitem>
<listitem><para><constant>INVOCATION_ID</constant></para></listitem>
<listitem><para><constant>UNIT</constant></para></listitem>
</itemizedlist>
<para>The fields <constant>SERVICE_RESULT</constant>, <constant>EXIT_CODE</constant> and
<constant>EXIT_STATUS</constant> may take the same values that are allowed when set for
<varname>ExecStop=</varname> and <varname>ExecStopPost=</varname> processes. The fields
<constant>INVOCATION_ID</constant> and <constant>UNIT</constant> are the invocaton id and unit
name of the service which triggered the dependency. Each field is comma separated, i.e.</para>
<programlisting>
SERVICE_RESULT=result-string,EXIT_CODE=exit-code,EXIT_STATUS=exit-status,INVOCATION_ID=invocation-id,UNIT=triggering.service
</programlisting>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>$PIDFILE</varname></term> <term><varname>$PIDFILE</varname></term>
@ -4018,77 +3983,6 @@ SERVICE_RESULT=result-string,EXIT_CODE=exit-code,EXIT_STATUS=exit-status,INVOCAT
</table> </table>
</refsect1> </refsect1>
<refsect1>
<title>Examples</title>
<example>
<title><varname>$MONITOR_METADATA</varname> usage</title>
<para>A service <filename index="false">myfailer.service</filename> which can trigger an
<varname>OnFailure=</varname> dependency.</para>
<programlisting>
[Unit]
Description=Service which can trigger an OnFailure= dependency
OnFailure=myhandler.service
[Service]
ExecStart=/bin/myprogram
</programlisting>
<para>A service <filename index="false">mysuccess.service</filename> which can trigger an
<varname>OnSuccess=</varname> dependency.</para>
<programlisting>
[Unit]
Description=Service which can trigger an OnSuccess= dependency
OnSuccess=myhandler.service
[Service]
ExecStart=/bin/mysecondprogram
</programlisting>
<para>A service <filename index="false">myhandler.service</filename> which can be triggered
by any of the above services.</para>
<programlisting>
[Unit]
Description=Acts on service failing or succeeding
[Service]
ExecStart=/bin/bash -c "echo $MONITOR_METADATA"
</programlisting>
<para>If <filename index="false">myfailer.service</filename> were to run and exit in failure,
then <filename index="false">myhandler.service</filename> would be triggered and the
<varname>$MONITOR_METADATA</varname> variable would be set as follows:</para>
<programlisting>
MONITOR_METADATA=SERVICE_RESULT=result-string,EXIT_CODE=exit-code,EXIT_STATUS=exit-status,INVOCATION_ID=invocation-id,UNIT=myfailer.service
</programlisting>
<para>If <filename index="false">mysuccess.service</filename> were to run and exit in success,
then <filename index="false">myhandler.service</filename> would be triggered and the
<varname>$MONITOR_METADATA</varname> variable would be set as follows:</para>
<programlisting>
MONITOR_METADATA=SERVICE_RESULT=result-string,EXIT_CODE=exit-code,EXIT_STATUS=exit-status,INVOCATION_ID=invocation-id,UNIT=mysuccess.service
</programlisting>
<para>If <filename index="false">myfailer.service</filename> and <filename index="false">mysuccess.service</filename> were to run and exit,
there is a chance that the triggered dependency start job might be merged. Thus only a single invocation of
<filename index="false">myhandler.service</filename> would be triggered. In this case the <varname>$MONITOR_METADATA</varname> variable
would be a list containing exit metadata for both of <filename index="false">myfailer.service</filename>
and <filename index="false">mysuccess.service</filename>.</para>
<programlisting>
MONITOR_METADATA=SERVICE_RESULT=result-string,EXIT_CODE=exit-code,EXIT_STATUS=exit-status,INVOCATION_ID=invocation-id,UNIT=myfailer.service;SERVICE_RESULT=result-string,EXIT_CODE=exit-code,EXIT_STATUS=exit-status,INVOCATION_ID=invocation-id,UNIT=mysuccess.service
</programlisting>
</example>
</refsect1>
<refsect1> <refsect1>
<title>See Also</title> <title>See Also</title>
<para> <para>

View File

@ -1148,13 +1148,8 @@
<varlistentry> <varlistentry>
<term><varname>Local=</varname></term> <term><varname>Local=</varname></term>
<listitem> <listitem>
<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
of this host, or one of the special values <literal>any</literal>, this host, or the special value <literal>any</literal>.</para>
<literal>ipv4_link_local</literal>, <literal>ipv6_link_local</literal>,
<literal>dhcp4</literal>, <literal>dhcp6</literal>, and <literal>slaac</literal>. If one
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
<literal>any</literal>.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View File

@ -43,10 +43,6 @@ endif
skip_deps = want_ossfuzz or want_libfuzzer skip_deps = want_ossfuzz or want_libfuzzer
fuzzer_build = want_ossfuzz or want_libfuzzer fuzzer_build = want_ossfuzz or want_libfuzzer
# Create a title-less summary section early, so it ends up first in the output.
# More items are added later after they have been detected.
summary({'build mode' : get_option('mode')})
##################################################################### #####################################################################
# Try to install the git pre-commit hook # Try to install the git pre-commit hook
@ -599,11 +595,6 @@ endif
versiondep = declare_dependency(sources: version_h) versiondep = declare_dependency(sources: version_h)
shared_lib_tag = get_option('shared-lib-tag')
if shared_lib_tag == ''
shared_lib_tag = meson.project_version()
endif
sh = find_program('sh') sh = find_program('sh')
echo = find_program('echo') echo = find_program('echo')
sed = find_program('sed') sed = find_program('sed')
@ -2026,7 +2017,12 @@ dbus_programs += executable(
link_with : [libcore, link_with : [libcore,
libshared], libshared],
dependencies : [versiondep, dependencies : [versiondep,
libseccomp], threads,
librt,
libseccomp,
libselinux,
libmount,
libblkid],
install_rpath : rootlibexecdir, install_rpath : rootlibexecdir,
install : true, install : true,
install_dir : rootlibexecdir) install_dir : rootlibexecdir)
@ -2042,7 +2038,12 @@ public_programs += executable(
link_with : [libcore, link_with : [libcore,
libshared], libshared],
dependencies : [versiondep, dependencies : [versiondep,
libseccomp], threads,
librt,
libseccomp,
libselinux,
libmount,
libblkid],
install_rpath : rootlibexecdir, install_rpath : rootlibexecdir,
install : conf.get('ENABLE_ANALYZE')) install : conf.get('ENABLE_ANALYZE'))
@ -3262,7 +3263,6 @@ public_programs += executable(
busctl_sources, busctl_sources,
include_directories : includes, include_directories : includes,
link_with : [libshared], link_with : [libshared],
dependencies : [versiondep],
install_rpath : rootlibexecdir, install_rpath : rootlibexecdir,
install : true) install : true)
@ -3706,7 +3706,6 @@ subdir('docs/var-log')
install_subdir('factory/etc', install_subdir('factory/etc',
install_dir : factorydir) install_dir : factorydir)
subdir('factory/templates')
if install_sysconfdir if install_sysconfdir
install_data('xorg/50-systemd-user.sh', install_data('xorg/50-systemd-user.sh',
@ -3887,6 +3886,7 @@ alt_time_epoch = run_command('date', '-Is', '-u', '-d', '@@0@'.format(time_epoch
check : true).stdout().strip() check : true).stdout().strip()
summary({ summary({
'build mode' : get_option('mode'),
'split /usr' : split_usr, 'split /usr' : split_usr,
'split bin-sbin' : split_bin, 'split bin-sbin' : split_bin,
'prefix directory' : prefixdir, 'prefix directory' : prefixdir,
@ -3907,7 +3907,6 @@ summary({
'D-Bus system directory' : dbussystemservicedir, 'D-Bus system directory' : dbussystemservicedir,
'bash completions directory' : bashcompletiondir, 'bash completions directory' : bashcompletiondir,
'zsh completions directory' : zshcompletiondir, 'zsh completions directory' : zshcompletiondir,
'private shared lib version tag' : shared_lib_tag,
'extra start script' : get_option('rc-local'), 'extra start script' : get_option('rc-local'),
'debug shell' : '@0@ @ @1@'.format(get_option('debug-shell'), 'debug shell' : '@0@ @ @1@'.format(get_option('debug-shell'),
get_option('debug-tty')), get_option('debug-tty')),
@ -3945,6 +3944,17 @@ summary({
# CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS} # CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
# LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS} # LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS}
if conf.get('ENABLE_EFI') == 1 and conf.get('HAVE_GNU_EFI') == 1
summary({
'EFI machine type' : efi_arch[0],
'EFI CC' : '@0@'.format(' '.join(efi_cc)),
'EFI LD' : efi_ld,
'EFI lds' : efi_lds,
'EFI crt0' : efi_crt0,
'EFI include directory' : efi_incdir},
section : 'Extensible Firmware Interface')
endif
found = [] found = []
missing = [] missing = []

View File

@ -3,8 +3,6 @@
option('version-tag', type : 'string', option('version-tag', type : 'string',
description : 'override the git version string') description : 'override the git version string')
option('shared-lib-tag', type : 'string',
description : 'override the private shared library version tag (defaults to project version)')
option('mode', type : 'combo', choices : ['developer', 'release'], option('mode', type : 'combo', choices : ['developer', 'release'],
description : 'autoenable features suitable for systemd development/release builds') description : 'autoenable features suitable for systemd development/release builds')

View File

@ -25,7 +25,7 @@
"list:List bus names" "list:List bus names"
"status:Show bus service, process or bus owner credentials" "status:Show bus service, process or bus owner credentials"
"monitor:Show bus traffic" "monitor:Show bus traffic"
"capture:Capture bus traffic" "capture:Capture bus traffix as pcap"
"tree:Show object tree of service" "tree:Show object tree of service"
"introspect:Introspect object" "introspect:Introspect object"
"call:Call a method" "call:Call a method"

View File

@ -1,115 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
/*
* For details about the file format see RFC:
* https://www.ietf.org/id/draft-tuexen-opsawg-pcapng-03.html
* and
* https://github.com/pcapng/pcapng/
*/
enum pcapng_block_types {
PCAPNG_INTERFACE_BLOCK = 1,
PCAPNG_PACKET_BLOCK, /* Obsolete */
PCAPNG_SIMPLE_PACKET_BLOCK,
PCAPNG_NAME_RESOLUTION_BLOCK,
PCAPNG_INTERFACE_STATS_BLOCK,
PCAPNG_ENHANCED_PACKET_BLOCK,
PCAPNG_SECTION_BLOCK = 0x0A0D0D0A,
};
struct pcapng_option {
uint16_t code;
uint16_t length;
uint8_t data[];
};
#define PCAPNG_BYTE_ORDER_MAGIC 0x1A2B3C4D
#define PCAPNG_MAJOR_VERS 1
#define PCAPNG_MINOR_VERS 0
enum pcapng_opt {
PCAPNG_OPT_END = 0,
PCAPNG_OPT_COMMENT = 1,
};
struct pcapng_section {
uint32_t block_type;
uint32_t block_length;
uint32_t byte_order_magic;
uint16_t major_version;
uint16_t minor_version;
uint64_t section_length;
};
enum pcapng_section_opt {
PCAPNG_SHB_HARDWARE = 2,
PCAPNG_SHB_OS = 3,
PCAPNG_SHB_USERAPPL = 4,
};
struct pcapng_interface_block {
uint32_t block_type; /* 1 */
uint32_t block_length;
uint16_t link_type;
uint16_t reserved;
uint32_t snap_len;
};
enum pcapng_interface_options {
PCAPNG_IFB_NAME = 2,
PCAPNG_IFB_DESCRIPTION,
PCAPNG_IFB_IPV4ADDR,
PCAPNG_IFB_IPV6ADDR,
PCAPNG_IFB_MACADDR,
PCAPNG_IFB_EUIADDR,
PCAPNG_IFB_SPEED,
PCAPNG_IFB_TSRESOL,
PCAPNG_IFB_TZONE,
PCAPNG_IFB_FILTER,
PCAPNG_IFB_OS,
PCAPNG_IFB_FCSLEN,
PCAPNG_IFB_TSOFFSET,
PCAPNG_IFB_HARDWARE,
};
struct pcapng_enhance_packet_block {
uint32_t block_type; /* 6 */
uint32_t block_length;
uint32_t interface_id;
uint32_t timestamp_hi;
uint32_t timestamp_lo;
uint32_t capture_length;
uint32_t original_length;
};
/* Flags values */
#define PCAPNG_IFB_INBOUND 0b01
#define PCAPNG_IFB_OUTBOUND 0b10
enum pcapng_epb_options {
PCAPNG_EPB_FLAGS = 2,
PCAPNG_EPB_HASH,
PCAPNG_EPB_DROPCOUNT,
PCAPNG_EPB_PACKETID,
PCAPNG_EPB_QUEUE,
PCAPNG_EPB_VERDICT,
};
struct pcapng_statistics_block {
uint32_t block_type; /* 5 */
uint32_t block_length;
uint32_t interface_id;
uint32_t timestamp_hi;
uint32_t timestamp_lo;
};
enum pcapng_isb_options {
PCAPNG_ISB_STARTTIME = 2,
PCAPNG_ISB_ENDTIME,
PCAPNG_ISB_IFRECV,
PCAPNG_ISB_IFDROP,
PCAPNG_ISB_FILTERACCEPT,
PCAPNG_ISB_OSDROP,
PCAPNG_ISB_USRDELIV,
};

View File

@ -15,73 +15,57 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "string-util.h"
#include "strxcpyx.h" #include "strxcpyx.h"
size_t strnpcpy_full(char **dest, size_t size, const char *src, size_t len, bool *ret_truncated) { size_t strnpcpy(char **dest, size_t size, const char *src, size_t len) {
bool truncated = false;
assert(dest); assert(dest);
assert(src); assert(src);
if (size == 0) { if (size == 0)
if (ret_truncated)
*ret_truncated = len > 0;
return 0; return 0;
}
if (len >= size) { if (len >= size) {
if (size > 1) if (size > 1)
*dest = mempcpy(*dest, src, size-1); *dest = mempcpy(*dest, src, size-1);
size = 0; size = 0;
truncated = true;
} else if (len > 0) { } else if (len > 0) {
*dest = mempcpy(*dest, src, len); *dest = mempcpy(*dest, src, len);
size -= len; size -= len;
} }
if (ret_truncated)
*ret_truncated = truncated;
*dest[0] = '\0'; *dest[0] = '\0';
return size; return size;
} }
size_t strpcpy_full(char **dest, size_t size, const char *src, bool *ret_truncated) { size_t strpcpy(char **dest, size_t size, const char *src) {
assert(dest); assert(dest);
assert(src); assert(src);
return strnpcpy_full(dest, size, src, strlen(src), ret_truncated); return strnpcpy(dest, size, src, strlen(src));
} }
size_t strpcpyf_full(char **dest, size_t size, bool *ret_truncated, const char *src, ...) { size_t strpcpyf(char **dest, size_t size, const char *src, ...) {
bool truncated = false;
va_list va; va_list va;
int i; int i;
assert(dest); assert(dest);
assert(src); assert(src);
if (size == 0)
return 0;
va_start(va, src); va_start(va, src);
i = vsnprintf(*dest, size, src, va); i = vsnprintf(*dest, size, src, va);
va_end(va); if (i < (int)size) {
if (i < (int) size) {
*dest += i; *dest += i;
size -= i; size -= i;
} else { } else
size = 0; size = 0;
truncated = i > 0; va_end(va);
}
if (ret_truncated)
*ret_truncated = truncated;
return size; return size;
} }
size_t strpcpyl_full(char **dest, size_t size, bool *ret_truncated, const char *src, ...) { size_t strpcpyl(char **dest, size_t size, const char *src, ...) {
bool truncated = false;
va_list va; va_list va;
assert(dest); assert(dest);
@ -89,38 +73,31 @@ size_t strpcpyl_full(char **dest, size_t size, bool *ret_truncated, const char *
va_start(va, src); va_start(va, src);
do { do {
bool t; size = strpcpy(dest, size, src);
size = strpcpy_full(dest, size, src, &t);
truncated = truncated || t;
src = va_arg(va, char *); src = va_arg(va, char *);
} while (src); } while (src);
va_end(va); va_end(va);
if (ret_truncated)
*ret_truncated = truncated;
return size; return size;
} }
size_t strnscpy_full(char *dest, size_t size, const char *src, size_t len, bool *ret_truncated) { size_t strnscpy(char *dest, size_t size, const char *src, size_t len) {
char *s; char *s;
assert(dest); assert(dest);
assert(src); assert(src);
s = dest; s = dest;
return strnpcpy_full(&s, size, src, len, ret_truncated); return strnpcpy(&s, size, src, len);
} }
size_t strscpy_full(char *dest, size_t size, const char *src, bool *ret_truncated) { size_t strscpy(char *dest, size_t size, const char *src) {
assert(dest); assert(dest);
assert(src); assert(src);
return strnscpy_full(dest, size, src, strlen(src), ret_truncated); return strnscpy(dest, size, src, strlen(src));
} }
size_t strscpyl_full(char *dest, size_t size, bool *ret_truncated, const char *src, ...) { size_t strscpyl(char *dest, size_t size, const char *src, ...) {
bool truncated = false;
va_list va; va_list va;
char *s; char *s;
@ -130,16 +107,10 @@ size_t strscpyl_full(char *dest, size_t size, bool *ret_truncated, const char *s
va_start(va, src); va_start(va, src);
s = dest; s = dest;
do { do {
bool t; size = strpcpy(&s, size, src);
size = strpcpy_full(&s, size, src, &t);
truncated = truncated || t;
src = va_arg(va, char *); src = va_arg(va, char *);
} while (src); } while (src);
va_end(va); va_end(va);
if (ret_truncated)
*ret_truncated = truncated;
return size; return size;
} }

View File

@ -1,33 +1,14 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once #pragma once
#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include "macro.h" #include "macro.h"
size_t strnpcpy_full(char **dest, size_t size, const char *src, size_t len, bool *ret_truncated); size_t strnpcpy(char **dest, size_t size, const char *src, size_t len);
static inline size_t strnpcpy(char **dest, size_t size, const char *src, size_t len) { size_t strpcpy(char **dest, size_t size, const char *src);
return strnpcpy_full(dest, size, src, len, NULL); size_t strpcpyf(char **dest, size_t size, const char *src, ...) _printf_(3, 4);
} size_t strpcpyl(char **dest, size_t size, const char *src, ...) _sentinel_;
size_t strpcpy_full(char **dest, size_t size, const char *src, bool *ret_truncated); size_t strnscpy(char *dest, size_t size, const char *src, size_t len);
static inline size_t strpcpy(char **dest, size_t size, const char *src) { size_t strscpy(char *dest, size_t size, const char *src);
return strpcpy_full(dest, size, src, NULL); size_t strscpyl(char *dest, size_t size, const char *src, ...) _sentinel_;
}
size_t strpcpyf_full(char **dest, size_t size, bool *ret_truncated, const char *src, ...) _printf_(4, 5);
#define strpcpyf(dest, size, src, ...) \
strpcpyf_full((dest), (size), NULL, (src), ##__VA_ARGS__)
size_t strpcpyl_full(char **dest, size_t size, bool *ret_truncated, const char *src, ...) _sentinel_;
#define strpcpyl(dest, size, src, ...) \
strpcpyl_full((dest), (size), NULL, (src), ##__VA_ARGS__)
size_t strnscpy_full(char *dest, size_t size, const char *src, size_t len, bool *ret_truncated);
static inline size_t strnscpy(char *dest, size_t size, const char *src, size_t len) {
return strnscpy_full(dest, size, src, len, NULL);
}
size_t strscpy_full(char *dest, size_t size, const char *src, bool *ret_truncated);
static inline size_t strscpy(char *dest, size_t size, const char *src) {
return strscpy_full(dest, size, src, NULL);
}
size_t strscpyl_full(char *dest, size_t size, bool *ret_truncated, const char *src, ...) _sentinel_;
#define strscpyl(dest, size, src, ...) \
strscpyl_full(dest, size, NULL, src, ##__VA_ARGS__)

View File

@ -32,7 +32,7 @@ static inline void EventClosep(EFI_EVENT *event) {
* Also, multiple input protocols can be backed by the same device, but they can be out of * Also, multiple input protocols can be backed by the same device, but they can be out of
* sync. Falling back on a different protocol can end up with double input. * sync. Falling back on a different protocol can end up with double input.
* *
* Therefore, we will preferably use TextInputEx for ConIn if that is available. Additionally, * Therefore, we will perferrably use TextInputEx for ConIn if that is available. Additionally,
* we look for the first TextInputEx device the firmware gives us as a fallback option. It * we look for the first TextInputEx device the firmware gives us as a fallback option. It
* will replace ConInEx permanently if it ever reports a key press. * will replace ConInEx permanently if it ever reports a key press.
* Lastly, a timer event allows us to provide a input timeout without having to call into * Lastly, a timer event allows us to provide a input timeout without having to call into

View File

@ -99,6 +99,59 @@ if efi_lds == ''
subdir_done() subdir_done()
endif endif
efi_headers = files('''
bcd.h
console.h
cpio.h
devicetree.h
disk.h
drivers.h
graphics.h
linux.h
measure.h
missing_efi.h
pe.h
random-seed.h
shim.h
splash.h
util.h
xbootldr.h
'''.split())
common_sources = '''
assert.c
devicetree.c
disk.c
graphics.c
measure.c
pe.c
secure-boot.c
util.c
'''.split()
systemd_boot_sources = '''
bcd.c
boot.c
console.c
drivers.c
random-seed.c
shim.c
xbootldr.c
'''.split()
stub_sources = '''
cpio.c
initrd.c
splash.c
stub.c
'''.split()
if efi_arch[1] in ['ia32', 'x86_64']
stub_sources += 'linux_x86.c'
else
stub_sources += 'linux.c'
endif
conf.set10('HAVE_GNU_EFI', true) conf.set10('HAVE_GNU_EFI', true)
conf.set_quoted('EFI_MACHINE_TYPE_NAME', efi_arch[0]) conf.set_quoted('EFI_MACHINE_TYPE_NAME', efi_arch[0])
@ -130,6 +183,7 @@ elif get_option('sbat-distro') != ''
if (value == '' or value == 'auto') and not meson.is_cross_build() if (value == '' or value == 'auto') and not meson.is_cross_build()
cmd = 'if [ -e /etc/os-release ]; then . /etc/os-release; else . /usr/lib/os-release; fi; echo $@0@'.format(sbatvar[1]) cmd = 'if [ -e /etc/os-release ]; then . /etc/os-release; else . /usr/lib/os-release; fi; echo $@0@'.format(sbatvar[1])
value = run_command(sh, '-c', cmd).stdout().strip() value = run_command(sh, '-c', cmd).stdout().strip()
message('@0@ (from @1@): @2@'.format(sbatvar[0], sbatvar[1], value))
endif endif
if value == '' if value == ''
error('Required @0@ option not set and autodetection failed'.format(sbatvar[0])) error('Required @0@ option not set and autodetection failed'.format(sbatvar[0]))
@ -146,11 +200,8 @@ elif get_option('sbat-distro') != ''
pkgver = get_option('sbat-distro-version') pkgver = get_option('sbat-distro-version')
if pkgver == '' if pkgver == ''
efi_conf.set('SBAT_DISTRO_VERSION', 'GIT_VERSION') efi_conf.set('SBAT_DISTRO_VERSION', 'GIT_VERSION')
# This is determined during build, not configuration, so we can't display it yet.
sbat_distro_version_display = '(git version)'
else else
efi_conf.set_quoted('SBAT_DISTRO_VERSION', pkgver) efi_conf.set_quoted('SBAT_DISTRO_VERSION', pkgver)
sbat_distro_version_display = pkgver
endif endif
endif endif
@ -281,76 +332,6 @@ if efi_cc_version.contains('clang') and efi_cc_version.split('.')[0].split(' ')[
efi_ldflags += ['-Wl,-T,' + efi_lds, '-Wno-unused-command-line-argument'] efi_ldflags += ['-Wl,-T,' + efi_lds, '-Wno-unused-command-line-argument']
endif endif
summary({
'EFI machine type' : efi_arch[0],
'EFI CC' : '@0@'.format(' '.join(efi_cc)),
'EFI LD' : efi_ld,
'EFI lds' : efi_lds,
'EFI crt0' : efi_crt0,
'EFI include directory' : efi_incdir},
section : 'Extensible Firmware Interface')
if efi_conf.get('SBAT_DISTRO', '') != ''
summary({
'SBAT distro': efi_conf.get('SBAT_DISTRO'),
'SBAT distro generation': efi_conf.get('SBAT_DISTRO_GENERATION'),
'SBAT distro version': sbat_distro_version_display,
'SBAT distro summary': efi_conf.get('SBAT_DISTRO_SUMMARY'),
'SBAT distro URL': efi_conf.get('SBAT_DISTRO_URL')},
section : 'Extensible Firmware Interface')
endif
############################################################
efi_headers = files(
'bcd.h',
'console.h',
'cpio.h',
'devicetree.h',
'disk.h',
'drivers.h',
'graphics.h',
'linux.h',
'measure.h',
'missing_efi.h',
'pe.h',
'random-seed.h',
'shim.h',
'splash.h',
'util.h',
'xbootldr.h')
common_sources = [
'assert.c',
'devicetree.c',
'disk.c',
'graphics.c',
'measure.c',
'pe.c',
'secure-boot.c',
'util.c']
systemd_boot_sources = [
'bcd.c',
'boot.c',
'console.c',
'drivers.c',
'random-seed.c',
'shim.c',
'xbootldr.c']
stub_sources = [
'cpio.c',
'initrd.c',
'splash.c',
'stub.c']
if efi_arch[1] in ['ia32', 'x86_64']
stub_sources += 'linux_x86.c'
else
stub_sources += 'linux.c'
endif
systemd_boot_objects = [] systemd_boot_objects = []
stub_objects = [] stub_objects = []
foreach file : fundamental_source_paths + common_sources + systemd_boot_sources + stub_sources foreach file : fundamental_source_paths + common_sources + systemd_boot_sources + stub_sources

View File

@ -20,7 +20,6 @@
#include "json.h" #include "json.h"
#include "log.h" #include "log.h"
#include "main-func.h" #include "main-func.h"
#include "os-util.h"
#include "pager.h" #include "pager.h"
#include "parse-argument.h" #include "parse-argument.h"
#include "parse-util.h" #include "parse-util.h"
@ -32,7 +31,6 @@
#include "terminal-util.h" #include "terminal-util.h"
#include "user-util.h" #include "user-util.h"
#include "verbs.h" #include "verbs.h"
#include "version.h"
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
static PagerFlags arg_pager_flags = 0; static PagerFlags arg_pager_flags = 0;
@ -1331,20 +1329,13 @@ static int verb_monitor(int argc, char **argv, void *userdata) {
} }
static int verb_capture(int argc, char **argv, void *userdata) { static int verb_capture(int argc, char **argv, void *userdata) {
_cleanup_free_ char *osname = NULL;
static const char info[] =
"busctl (systemd) " STRINGIFY(PROJECT_VERSION) " (Git " GIT_VERSION ")";
int r; int r;
if (isatty(fileno(stdout)) > 0) if (isatty(fileno(stdout)) > 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Refusing to write message data to console, please redirect output to a file."); "Refusing to write message data to console, please redirect output to a file.");
r = parse_os_release(NULL, "PRETTY_NAME", &osname); bus_pcap_header(arg_snaplen, stdout);
if (r < 0)
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_INFO, r,
"Failed to read os-release file, ignoring: %m");
bus_pcap_header(arg_snaplen, osname, info, stdout);
r = monitor(argc, argv, message_pcap); r = monitor(argc, argv, message_pcap);
if (r < 0) if (r < 0)

View File

@ -370,22 +370,21 @@ static inline bool exec_context_with_rootfs(const ExecContext *c) {
} }
typedef enum ExecFlags { typedef enum ExecFlags {
EXEC_APPLY_SANDBOXING = 1 << 0, EXEC_APPLY_SANDBOXING = 1 << 0,
EXEC_APPLY_CHROOT = 1 << 1, EXEC_APPLY_CHROOT = 1 << 1,
EXEC_APPLY_TTY_STDIN = 1 << 2, EXEC_APPLY_TTY_STDIN = 1 << 2,
EXEC_PASS_LOG_UNIT = 1 << 3, /* Whether to pass the unit name to the service's journal stream connection */ EXEC_PASS_LOG_UNIT = 1 << 3, /* Whether to pass the unit name to the service's journal stream connection */
EXEC_CHOWN_DIRECTORIES = 1 << 4, /* chown() the runtime/state/cache/log directories to the user we run as, under all conditions */ EXEC_CHOWN_DIRECTORIES = 1 << 4, /* chown() the runtime/state/cache/log directories to the user we run as, under all conditions */
EXEC_NSS_BYPASS_BUS = 1 << 5, /* Set the SYSTEMD_NSS_BYPASS_BUS environment variable, to disable nss-systemd for dbus */ EXEC_NSS_BYPASS_BUS = 1 << 5, /* Set the SYSTEMD_NSS_BYPASS_BUS environment variable, to disable nss-systemd for dbus */
EXEC_CGROUP_DELEGATE = 1 << 6, EXEC_CGROUP_DELEGATE = 1 << 6,
EXEC_IS_CONTROL = 1 << 7, EXEC_IS_CONTROL = 1 << 7,
EXEC_CONTROL_CGROUP = 1 << 8, /* Place the process not in the indicated cgroup but in a subcgroup '/.control', but only EXEC_CGROUP_DELEGATE and EXEC_IS_CONTROL is set, too */ EXEC_CONTROL_CGROUP = 1 << 8, /* Place the process not in the indicated cgroup but in a subcgroup '/.control', but only EXEC_CGROUP_DELEGATE and EXEC_IS_CONTROL is set, too */
EXEC_WRITE_CREDENTIALS = 1 << 9, /* Set up the credential store logic */ EXEC_WRITE_CREDENTIALS = 1 << 9, /* Set up the credential store logic */
/* The following are not used by execute.c, but by consumers internally */ /* The following are not used by execute.c, but by consumers internally */
EXEC_PASS_FDS = 1 << 10, EXEC_PASS_FDS = 1 << 10,
EXEC_SETENV_RESULT = 1 << 11, EXEC_SETENV_RESULT = 1 << 11,
EXEC_SET_WATCHDOG = 1 << 12, EXEC_SET_WATCHDOG = 1 << 12,
EXEC_SETENV_MONITOR_RESULT = 1 << 13, /* Pass exit status to OnFailure= and OnSuccess= dependencies. */
} ExecFlags; } ExecFlags;
/* Parameters for a specific invocation of a command. This structure is put together right before a command is /* Parameters for a specific invocation of a command. This structure is put together right before a command is

View File

@ -99,13 +99,6 @@ Job* job_free(Job *j) {
assert(!j->subject_list); assert(!j->subject_list);
assert(!j->object_list); assert(!j->object_list);
do {
Unit *tu = NULL;
LIST_FOREACH(triggered_by, tu, j->triggered_by)
LIST_REMOVE(triggered_by, j->triggered_by, tu);
} while (!LIST_IS_EMPTY(j->triggered_by));
job_unlink(j); job_unlink(j);
sd_bus_track_unref(j->bus_track); sd_bus_track_unref(j->bus_track);
@ -114,13 +107,6 @@ Job* job_free(Job *j) {
return mfree(j); return mfree(j);
} }
void job_add_triggering_unit(Job *j, Unit *u) {
assert(j);
assert(u);
LIST_APPEND(triggered_by, j->triggered_by, u);
}
static void job_set_state(Job *j, JobState state) { static void job_set_state(Job *j, JobState state) {
assert(j); assert(j);
assert(state >= 0); assert(state >= 0);
@ -201,8 +187,6 @@ static void job_merge_into_installed(Job *j, Job *other) {
j->irreversible = j->irreversible || other->irreversible; j->irreversible = j->irreversible || other->irreversible;
j->ignore_order = j->ignore_order || other->ignore_order; j->ignore_order = j->ignore_order || other->ignore_order;
if (other->triggered_by)
LIST_JOIN(triggered_by, j->triggered_by, other->triggered_by);
} }
Job* job_install(Job *j) { Job* job_install(Job *j) {

View File

@ -124,8 +124,6 @@ struct Job {
LIST_HEAD(JobDependency, subject_list); LIST_HEAD(JobDependency, subject_list);
LIST_HEAD(JobDependency, object_list); LIST_HEAD(JobDependency, object_list);
LIST_HEAD(Unit, triggered_by);
/* Used for graph algs as a "I have been here" marker */ /* Used for graph algs as a "I have been here" marker */
Job* marker; Job* marker;
unsigned generation; unsigned generation;
@ -246,5 +244,3 @@ JobResult job_result_from_string(const char *s) _pure_;
const char* job_type_to_access_method(JobType t); const char* job_type_to_access_method(JobType t);
int job_compare(Job *a, Job *b, UnitDependencyAtom assume_dep); int job_compare(Job *a, Job *b, UnitDependencyAtom assume_dep);
void job_add_triggering_unit(Job *j, Unit *u);

View File

@ -167,18 +167,12 @@ load_fragment_gperf_nulstr_c = custom_target(
command : [awk, '-f', '@INPUT0@', '@INPUT1@'], command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
capture : true) capture : true)
libcore_name = 'systemd-core-@0@'.format(shared_lib_tag) libcore = static_library(
'core',
libcore = shared_library(
libcore_name,
libcore_sources, libcore_sources,
load_fragment_gperf_c, load_fragment_gperf_c,
load_fragment_gperf_nulstr_c, load_fragment_gperf_nulstr_c,
include_directories : includes, include_directories : includes,
c_args : ['-fvisibility=default'],
link_args : ['-shared',
'-Wl,--version-script=' + libshared_sym_path],
link_with : libshared,
dependencies : [versiondep, dependencies : [versiondep,
threads, threads,
libdl, libdl,
@ -190,10 +184,8 @@ libcore = shared_library(
libapparmor, libapparmor,
libselinux, libselinux,
libmount, libmount,
libblkid,
libacl], libacl],
install : true, build_by_default : false)
install_dir : rootlibexecdir)
core_includes = [includes, include_directories('.')] core_includes = [includes, include_directories('.')]

View File

@ -1440,93 +1440,6 @@ static bool service_exec_needs_notify_socket(Service *s, ExecFlags flags) {
return s->notify_access != NOTIFY_NONE; return s->notify_access != NOTIFY_NONE;
} }
static int service_create_monitor_md_env(Job *j, char **ret) {
_cleanup_free_ char *var = NULL;
const char *list_delim = ";";
bool first = true;
Unit *tu;
assert(j);
assert(ret);
/* Create an environment variable 'MONITOR_METADATA', if creation is successful
* a pointer to it is returned via ret.
*
* This variable contains a space separated set of fields which relate to
* the service(s) which triggered job 'j'. Job 'j' is the JOB_START job for
* an OnFailure= or OnSuccess= dependency. Format of the MONITOR_METADATA
* variable is as follows:
*
* MONITOR_METADATA="SERVICE_RESULT=<result-string0>,EXIT_CODE=<exit-code0>,EXIT_STATUS=<exit-status0>,
* INVOCATION_ID=<id>,UNIT=<triggering-unit0.service>;
* SERVICE_RESULT=<result-stringN>,EXIT_CODE=<exit-codeN>,EXIT_STATUS=<exit-statusN>,
* INVOCATION_ID=<id>,UNIT=<triggering-unitN.service>"
*
* Multiple results may be passed as in the above example if jobs are merged, i.e.
* some services a and b contain an OnFailure= or OnSuccess= dependency on the same
* service.
*
* For example:
*
* MONITOR_METADATA="SERVICE_RESULT=exit-code,EXIT_CODE=exited,EXIT_STATUS=1,INVOCATION_ID=02dd868af2f344b18edaf74b618b2f90,UNIT=failure.service;
* SERVICE_RESULT=exit-code,EXIT_CODE=exited,EXIT_STATUS=1,INVOCATION_ID=80cb228bd7344f77a090eda603a3cfe2,UNIT=failure2.service"
*/
LIST_FOREACH(triggered_by, tu, j->triggered_by) {
Service *env_source = SERVICE(tu);
int r;
if (!env_source)
continue;
if (first) {
/* Add the environment variable name first. */
r = strextendf(&var, "MONITOR_METADATA=");
if (r < 0)
return r;
}
r = strextendf(&var, "%sSERVICE_RESULT=%s",
!first ? list_delim : "", service_result_to_string(env_source->result));
if (r < 0)
return r;
first = false;
if (env_source->main_exec_status.pid > 0 &&
dual_timestamp_is_set(&env_source->main_exec_status.exit_timestamp)) {
r = strextendf(&var, ",EXIT_CODE=%s",
sigchld_code_to_string(env_source->main_exec_status.code));
if (r < 0)
return r;
if (env_source->main_exec_status.code == CLD_EXITED)
r = strextendf(&var, ",EXIT_STATUS=%i",
env_source->main_exec_status.status);
else
r = strextendf(&var, ",EXIT_STATUS=%s",
signal_to_string(env_source->main_exec_status.status));
if (r < 0)
return r;
}
if (!sd_id128_is_null(UNIT(env_source)->invocation_id)) {
r = strextendf(&var, ",INVOCATION_ID=" SD_ID128_FORMAT_STR,
SD_ID128_FORMAT_VAL(UNIT(env_source)->invocation_id));
if (r < 0)
return r;
}
r = strextendf(&var, ",UNIT=%s", UNIT(env_source)->id);
if (r < 0)
return r;
}
*ret = TAKE_PTR(var);
return 0;
}
static int service_spawn( static int service_spawn(
Service *s, Service *s,
ExecCommand *c, ExecCommand *c,
@ -1661,18 +1574,9 @@ static int service_spawn(
r = asprintf(our_env + n_env++, "EXIT_STATUS=%i", s->main_exec_status.status); r = asprintf(our_env + n_env++, "EXIT_STATUS=%i", s->main_exec_status.status);
else else
r = asprintf(our_env + n_env++, "EXIT_STATUS=%s", signal_to_string(s->main_exec_status.status)); r = asprintf(our_env + n_env++, "EXIT_STATUS=%s", signal_to_string(s->main_exec_status.status));
if (r < 0) if (r < 0)
return -ENOMEM; return -ENOMEM;
} }
} else if (flags & EXEC_SETENV_MONITOR_RESULT) {
Job *j = UNIT(s)->job;
if (j) {
r = service_create_monitor_md_env(j, our_env + n_env++);
if (r < 0)
return r;
}
} }
r = unit_set_exec_params(UNIT(s), &exec_params); r = unit_set_exec_params(UNIT(s), &exec_params);
@ -2260,7 +2164,7 @@ static void service_enter_start(Service *s) {
r = service_spawn(s, r = service_spawn(s,
c, c,
timeout, timeout,
EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG|EXEC_WRITE_CREDENTIALS|EXEC_SETENV_MONITOR_RESULT, EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG|EXEC_WRITE_CREDENTIALS,
&pid); &pid);
if (r < 0) if (r < 0)
goto fail; goto fail;
@ -2318,7 +2222,7 @@ static void service_enter_start_pre(Service *s) {
r = service_spawn(s, r = service_spawn(s,
s->control_command, s->control_command,
s->timeout_start_usec, s->timeout_start_usec,
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN|EXEC_SETENV_MONITOR_RESULT, EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN,
&s->control_pid); &s->control_pid);
if (r < 0) if (r < 0)
goto fail; goto fail;

View File

@ -82,15 +82,11 @@ static const UnitDependencyAtom atom_map[_UNIT_DEPENDENCY_MAX] = {
[UNIT_PROPAGATES_STOP_TO] = UNIT_ATOM_RETROACTIVE_STOP_ON_STOP | [UNIT_PROPAGATES_STOP_TO] = UNIT_ATOM_RETROACTIVE_STOP_ON_STOP |
UNIT_ATOM_PROPAGATE_STOP, UNIT_ATOM_PROPAGATE_STOP,
[UNIT_ON_FAILURE] = UNIT_ATOM_ON_FAILURE |
UNIT_ATOM_BACK_REFERENCE_IMPLIED,
[UNIT_ON_SUCCESS] = UNIT_ATOM_ON_SUCCESS |
UNIT_ATOM_BACK_REFERENCE_IMPLIED,
/* These are simple dependency types: they consist of a single atom only */ /* These are simple dependency types: they consist of a single atom only */
[UNIT_BEFORE] = UNIT_ATOM_BEFORE, [UNIT_BEFORE] = UNIT_ATOM_BEFORE,
[UNIT_AFTER] = UNIT_ATOM_AFTER, [UNIT_AFTER] = UNIT_ATOM_AFTER,
[UNIT_ON_SUCCESS] = UNIT_ATOM_ON_SUCCESS,
[UNIT_ON_FAILURE] = UNIT_ATOM_ON_FAILURE,
[UNIT_TRIGGERS] = UNIT_ATOM_TRIGGERS, [UNIT_TRIGGERS] = UNIT_ATOM_TRIGGERS,
[UNIT_TRIGGERED_BY] = UNIT_ATOM_TRIGGERED_BY, [UNIT_TRIGGERED_BY] = UNIT_ATOM_TRIGGERED_BY,
[UNIT_PROPAGATES_RELOAD_TO] = UNIT_ATOM_PROPAGATES_RELOAD_TO, [UNIT_PROPAGATES_RELOAD_TO] = UNIT_ATOM_PROPAGATES_RELOAD_TO,
@ -200,16 +196,6 @@ UnitDependency unit_dependency_from_unique_atom(UnitDependencyAtom atom) {
case UNIT_ATOM_PROPAGATE_STOP_FAILURE: case UNIT_ATOM_PROPAGATE_STOP_FAILURE:
return UNIT_CONFLICTED_BY; return UNIT_CONFLICTED_BY;
case UNIT_ATOM_ON_FAILURE |
UNIT_ATOM_BACK_REFERENCE_IMPLIED:
case UNIT_ATOM_ON_FAILURE:
return UNIT_ON_FAILURE;
case UNIT_ATOM_ON_SUCCESS |
UNIT_ATOM_BACK_REFERENCE_IMPLIED:
case UNIT_ATOM_ON_SUCCESS:
return UNIT_ON_SUCCESS;
/* And now, the simple ones */ /* And now, the simple ones */
case UNIT_ATOM_BEFORE: case UNIT_ATOM_BEFORE:
@ -218,6 +204,12 @@ UnitDependency unit_dependency_from_unique_atom(UnitDependencyAtom atom) {
case UNIT_ATOM_AFTER: case UNIT_ATOM_AFTER:
return UNIT_AFTER; return UNIT_AFTER;
case UNIT_ATOM_ON_SUCCESS:
return UNIT_ON_SUCCESS;
case UNIT_ATOM_ON_FAILURE:
return UNIT_ON_FAILURE;
case UNIT_ATOM_TRIGGERS: case UNIT_ATOM_TRIGGERS:
return UNIT_TRIGGERS; return UNIT_TRIGGERS;

View File

@ -66,27 +66,20 @@ typedef enum UnitDependencyAtom {
/* Recheck default target deps on other units (which are target units) */ /* Recheck default target deps on other units (which are target units) */
UNIT_ATOM_DEFAULT_TARGET_DEPENDENCIES = UINT64_C(1) << 21, UNIT_ATOM_DEFAULT_TARGET_DEPENDENCIES = UINT64_C(1) << 21,
/* Dependencies which include this atom automatically get a reverse
* REFERENCES/REFERENCED_BY dependency. */
UNIT_ATOM_BACK_REFERENCE_IMPLIED = UINT64_C(1) << 22,
/* Trigger a dependency on successful service exit. */
UNIT_ATOM_ON_SUCCESS = UINT64_C(1) << 23,
/* Trigger a dependency on unsuccessful service exit. */
UNIT_ATOM_ON_FAILURE = UINT64_C(1) << 24,
/* The remaining atoms map 1:1 to the equally named high-level deps */ /* The remaining atoms map 1:1 to the equally named high-level deps */
UNIT_ATOM_BEFORE = UINT64_C(1) << 25, UNIT_ATOM_BEFORE = UINT64_C(1) << 22,
UNIT_ATOM_AFTER = UINT64_C(1) << 26, UNIT_ATOM_AFTER = UINT64_C(1) << 23,
UNIT_ATOM_TRIGGERS = UINT64_C(1) << 27, UNIT_ATOM_ON_SUCCESS = UINT64_C(1) << 24,
UNIT_ATOM_TRIGGERED_BY = UINT64_C(1) << 28, UNIT_ATOM_ON_FAILURE = UINT64_C(1) << 25,
UNIT_ATOM_PROPAGATES_RELOAD_TO = UINT64_C(1) << 29, UNIT_ATOM_TRIGGERS = UINT64_C(1) << 26,
UNIT_ATOM_JOINS_NAMESPACE_OF = UINT64_C(1) << 30, UNIT_ATOM_TRIGGERED_BY = UINT64_C(1) << 27,
UNIT_ATOM_REFERENCES = UINT64_C(1) << 31, UNIT_ATOM_PROPAGATES_RELOAD_TO = UINT64_C(1) << 28,
UNIT_ATOM_REFERENCED_BY = UINT64_C(1) << 32, UNIT_ATOM_JOINS_NAMESPACE_OF = UINT64_C(1) << 29,
UNIT_ATOM_IN_SLICE = UINT64_C(1) << 33, UNIT_ATOM_REFERENCES = UINT64_C(1) << 30,
UNIT_ATOM_SLICE_OF = UINT64_C(1) << 34, UNIT_ATOM_REFERENCED_BY = UINT64_C(1) << 31,
_UNIT_DEPENDENCY_ATOM_MAX = (UINT64_C(1) << 35) - 1, UNIT_ATOM_IN_SLICE = UINT64_C(1) << 32,
UNIT_ATOM_SLICE_OF = UINT64_C(1) << 33,
_UNIT_DEPENDENCY_ATOM_MAX = (UINT64_C(1) << 34) - 1,
_UNIT_DEPENDENCY_ATOM_INVALID = -EINVAL, _UNIT_DEPENDENCY_ATOM_INVALID = -EINVAL,
} UnitDependencyAtom; } UnitDependencyAtom;

View File

@ -2222,24 +2222,17 @@ void unit_start_on_failure(
UNIT_FOREACH_DEPENDENCY(other, u, atom) { UNIT_FOREACH_DEPENDENCY(other, u, atom) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
Job *job = NULL;
if (!logged) { if (!logged) {
log_unit_info(u, "Triggering %s dependencies.", dependency_name); log_unit_info(u, "Triggering %s dependencies.", dependency_name);
logged = true; logged = true;
} }
r = manager_add_job(u->manager, JOB_START, other, job_mode, NULL, &error, &job); r = manager_add_job(u->manager, JOB_START, other, job_mode, NULL, &error, NULL);
if (r < 0) if (r < 0)
log_unit_warning_errno( log_unit_warning_errno(
u, r, "Failed to enqueue %s job, ignoring: %s", u, r, "Failed to enqueue %s job, ignoring: %s",
dependency_name, bus_error_message(&error, r)); dependency_name, bus_error_message(&error, r));
else if (job)
/* u will be kept pinned since both UNIT_ON_FAILURE and UNIT_ON_SUCCESS includes
* UNIT_ATOM_BACK_REFERENCE_IMPLIED. We save the triggering unit here since we
* want to be able to reference it when we come to run the OnFailure= or OnSuccess=
* dependency. */
job_add_triggering_unit(job, u);
} }
if (logged) if (logged)
@ -3121,20 +3114,6 @@ int unit_add_dependency(
noop = false; noop = false;
} }
if (FLAGS_SET(a, UNIT_ATOM_BACK_REFERENCE_IMPLIED)) {
r = unit_add_dependency_hashmap(&other->dependencies, UNIT_REFERENCES, u, 0, mask);
if (r < 0)
return r;
if (r)
noop = false;
r = unit_add_dependency_hashmap(&u->dependencies, UNIT_REFERENCED_BY, other, 0, mask);
if (r < 0)
return r;
if (r)
noop = false;
}
if (add_reference) { if (add_reference) {
r = unit_add_dependency_hashmap(&u->dependencies, UNIT_REFERENCES, other, mask, 0); r = unit_add_dependency_hashmap(&u->dependencies, UNIT_REFERENCES, other, mask, 0);
if (r < 0) if (r < 0)

View File

@ -242,9 +242,6 @@ typedef struct Unit {
/* Queue of units that have a BindTo= dependency on some other unit, and should possibly be shut down */ /* Queue of units that have a BindTo= dependency on some other unit, and should possibly be shut down */
LIST_FIELDS(Unit, stop_when_bound_queue); LIST_FIELDS(Unit, stop_when_bound_queue);
/* Queue of units which have triggered an OnFailure= or OnSuccess= dependency job. */
LIST_FIELDS(Unit, triggered_by);
/* PIDs we keep an eye on. Note that a unit might have many /* PIDs we keep an eye on. Note that a unit might have many
* more, but these are the ones we care enough about to * more, but these are the ones we care enough about to
* process SIGCHLD for */ * process SIGCHLD for */

View File

@ -13,7 +13,6 @@
#include "format-util.h" #include "format-util.h"
#include "glyph-util.h" #include "glyph-util.h"
#include "macro.h" #include "macro.h"
#include "pcapng.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
#include "terminal-util.h" #include "terminal-util.h"
@ -503,99 +502,57 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
return 0; return 0;
} }
static uint16_t pcapng_optlen(size_t len) { /*
return ALIGN4(len + sizeof(struct pcapng_option)); * For details about the file format, see:
} *
* http://wiki.wireshark.org/Development/LibpcapFileFormat
*/
static void pcapng_putopt(FILE *f, uint16_t code, const void *data, size_t len) { typedef struct _packed_ pcap_hdr_s {
struct pcapng_option opt = { uint32_t magic_number; /* magic number */
.code = code, uint16_t version_major; /* major version number */
.length = len, uint16_t version_minor; /* minor version number */
int32_t thiszone; /* GMT to local correction */
uint32_t sigfigs; /* accuracy of timestamps */
uint32_t snaplen; /* max length of captured packets, in octets */
uint32_t network; /* data link type */
} pcap_hdr_t ;
typedef struct _packed_ pcaprec_hdr_s {
uint32_t ts_sec; /* timestamp seconds */
uint32_t ts_usec; /* timestamp microseconds */
uint32_t incl_len; /* number of octets of packet saved in file */
uint32_t orig_len; /* actual length of packet */
} pcaprec_hdr_t;
int bus_pcap_header(size_t snaplen, FILE *f) {
pcap_hdr_t hdr = {
.magic_number = 0xa1b2c3d4U,
.version_major = 2,
.version_minor = 4,
.thiszone = 0, /* UTC */
.sigfigs = 0,
.network = 231, /* D-Bus */
}; };
assert(f);
assert((uint16_t) len == len);
assert(data || len == 0);
fwrite(&opt, 1, sizeof(opt), f);
if (len > 0) {
size_t pad = ALIGN4(len) - len;
fwrite(data, 1, len, f);
assert(pad < sizeof(uint32_t));
while (pad-- > 0)
fputc('\0', f);
}
}
static void pcapng_section_header(FILE *f, const char *os, const char *app) {
uint32_t len;
assert(f);
/* determine length of section header and options */
len = sizeof(struct pcapng_section);
if (os)
len += pcapng_optlen(strlen(os));
if (app)
len += pcapng_optlen(strlen(app));
len += pcapng_optlen(0); /* OPT_END */
len += sizeof(uint32_t); /* trailer length */
struct pcapng_section hdr = {
.block_type = PCAPNG_SECTION_BLOCK,
.block_length = len,
.byte_order_magic = PCAPNG_BYTE_ORDER_MAGIC,
.major_version = PCAPNG_MAJOR_VERS,
.minor_version = PCAPNG_MINOR_VERS,
.section_length = UINT64_MAX,
};
fwrite(&hdr, 1, sizeof(hdr), f);
if (os)
pcapng_putopt(f, PCAPNG_SHB_OS, os, strlen(os));
if (app)
pcapng_putopt(f, PCAPNG_SHB_USERAPPL, app, strlen(app));
pcapng_putopt(f, PCAPNG_OPT_END, NULL, 0);
fwrite(&len, 1, sizeof(uint32_t), f);
}
/* Only have a single instance of dbus pseudo interface */
static void pcapng_interface_header(FILE *f, size_t snaplen) {
uint32_t len;
assert(f);
assert(snaplen > 0);
assert((size_t) (uint32_t) snaplen == snaplen);
/* no options (yet) */
len = sizeof(struct pcapng_interface_block) + sizeof(uint32_t);
struct pcapng_interface_block hdr = {
.block_type = PCAPNG_INTERFACE_BLOCK,
.block_length = len,
.link_type = 231, /* D-Bus */
.snap_len = snaplen,
};
fwrite(&hdr, 1, sizeof(hdr), f);
fwrite(&len, 1, sizeof(uint32_t), f);
}
int bus_pcap_header(size_t snaplen, const char *os, const char *info, FILE *f) {
if (!f) if (!f)
f = stdout; f = stdout;
pcapng_section_header(f, os, info); assert(snaplen > 0);
pcapng_interface_header(f, snaplen); assert((size_t) (uint32_t) snaplen == snaplen);
hdr.snaplen = (uint32_t) snaplen;
fwrite(&hdr, 1, sizeof(hdr), f);
return fflush_and_check(f); return fflush_and_check(f);
} }
int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) { int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) {
struct bus_body_part *part; struct bus_body_part *part;
size_t msglen, caplen, pad; pcaprec_hdr_t hdr = {};
uint32_t length; struct timeval tv;
uint64_t ts;
unsigned i; unsigned i;
size_t w; size_t w;
@ -606,27 +563,18 @@ int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) {
assert(snaplen > 0); assert(snaplen > 0);
assert((size_t) (uint32_t) snaplen == snaplen); assert((size_t) (uint32_t) snaplen == snaplen);
ts = m->realtime ?: now(CLOCK_REALTIME); if (m->realtime != 0)
msglen = BUS_MESSAGE_SIZE(m); timeval_store(&tv, m->realtime);
caplen = MIN(msglen, snaplen); else
pad = ALIGN4(caplen) - caplen; assert_se(gettimeofday(&tv, NULL) >= 0);
/* packet block has no options */ hdr.ts_sec = tv.tv_sec;
length = sizeof(struct pcapng_enhance_packet_block) hdr.ts_usec = tv.tv_usec;
+ caplen + pad + sizeof(uint32_t); hdr.orig_len = BUS_MESSAGE_SIZE(m);
hdr.incl_len = MIN(hdr.orig_len, snaplen);
struct pcapng_enhance_packet_block epb = { /* write the pcap header */
.block_type = PCAPNG_ENHANCED_PACKET_BLOCK, fwrite(&hdr, 1, sizeof(hdr), f);
.block_length = length,
.interface_id = 0,
.timestamp_hi = (uint32_t)(ts >> 32),
.timestamp_lo = (uint32_t)ts,
.original_length = msglen,
.capture_length = caplen,
};
/* write the pcapng enhanced packet block header */
fwrite(&epb, 1, sizeof(epb), f);
/* write the dbus header */ /* write the dbus header */
w = MIN(BUS_MESSAGE_BODY_BEGIN(m), snaplen); w = MIN(BUS_MESSAGE_BODY_BEGIN(m), snaplen);
@ -643,11 +591,5 @@ int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) {
snaplen -= w; snaplen -= w;
} }
while (pad-- > 0)
fputc('\0', f);
/* trailing block length */
fwrite(&length, 1, sizeof(uint32_t), f);
return fflush_and_check(f); return fflush_and_check(f);
} }

View File

@ -8,5 +8,5 @@
int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse); int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse);
int bus_pcap_header(size_t snaplen, const char *os, const char *app, FILE *f); int bus_pcap_header(size_t snaplen, FILE *f);
int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f); int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f);

View File

@ -20,8 +20,6 @@ sources = files('''
netdev/macvlan.c netdev/macvlan.c
netdev/macvlan.h netdev/macvlan.h
netdev/netdev.c netdev/netdev.c
netdev/netdev-util.c
netdev/netdev-util.h
netdev/netdev.h netdev/netdev.h
netdev/nlmon.c netdev/nlmon.c
netdev/nlmon.h netdev/nlmon.h

View File

@ -68,8 +68,8 @@ IPVLAN.Mode, config_parse_ipvlan_mode,
IPVLAN.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags) IPVLAN.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags)
IPVTAP.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode) IPVTAP.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode)
IPVTAP.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags) IPVTAP.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags)
Tunnel.Local, config_parse_tunnel_local_address, 0, 0 Tunnel.Local, config_parse_tunnel_address, 0, offsetof(Tunnel, local)
Tunnel.Remote, config_parse_tunnel_remote_address, 0, 0 Tunnel.Remote, config_parse_tunnel_address, 0, offsetof(Tunnel, remote)
Tunnel.TOS, config_parse_unsigned, 0, offsetof(Tunnel, tos) Tunnel.TOS, config_parse_unsigned, 0, offsetof(Tunnel, tos)
Tunnel.TTL, config_parse_unsigned, 0, offsetof(Tunnel, ttl) Tunnel.TTL, config_parse_unsigned, 0, offsetof(Tunnel, ttl)
Tunnel.Key, config_parse_tunnel_key, 0, offsetof(Tunnel, key) Tunnel.Key, config_parse_tunnel_key, 0, offsetof(Tunnel, key)

View File

@ -1,97 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "netdev-util.h"
#include "networkd-address.h"
#include "networkd-link.h"
#include "string-table.h"
static const char * const netdev_local_address_type_table[_NETDEV_LOCAL_ADDRESS_TYPE_MAX] = {
[NETDEV_LOCAL_ADDRESS_IPV4LL] = "ipv4_link_local",
[NETDEV_LOCAL_ADDRESS_IPV6LL] = "ipv6_link_local",
[NETDEV_LOCAL_ADDRESS_DHCP4] = "dhcp4",
[NETDEV_LOCAL_ADDRESS_DHCP6] = "dhcp6",
[NETDEV_LOCAL_ADDRESS_SLAAC] = "slaac",
};
DEFINE_STRING_TABLE_LOOKUP(netdev_local_address_type, NetDevLocalAddressType);
int link_get_local_address(
Link *link,
NetDevLocalAddressType type,
int family,
int *ret_family,
union in_addr_union *ret_address) {
Address *a;
assert(link);
switch (type) {
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:
assert(IN_SET(family, AF_UNSPEC, AF_INET));
family = AF_INET;
break;
case NETDEV_LOCAL_ADDRESS_DHCP6:
assert(IN_SET(family, AF_UNSPEC, AF_INET6));
family = AF_INET6;
break;
case NETDEV_LOCAL_ADDRESS_SLAAC:
assert(IN_SET(family, AF_UNSPEC, AF_INET6));
family = AF_INET6;
break;
default:
assert_not_reached();
}
SET_FOREACH(a, link->addresses) {
if (!address_exists(a))
continue;
if (a->family != family)
continue;
if (in_addr_is_set(a->family, &a->in_addr_peer))
continue;
switch (type) {
case NETDEV_LOCAL_ADDRESS_IPV4LL:
if (a->source != NETWORK_CONFIG_SOURCE_IPV4LL)
continue;
break;
case NETDEV_LOCAL_ADDRESS_IPV6LL:
if (!in6_addr_is_link_local(&a->in_addr.in6))
continue;
break;
case NETDEV_LOCAL_ADDRESS_DHCP4:
if (a->source != NETWORK_CONFIG_SOURCE_DHCP4)
continue;
break;
case NETDEV_LOCAL_ADDRESS_DHCP6:
if (a->source != NETWORK_CONFIG_SOURCE_DHCP6)
continue;
break;
case NETDEV_LOCAL_ADDRESS_SLAAC:
if (a->source != NETWORK_CONFIG_SOURCE_NDISC)
continue;
break;
default:
assert_not_reached();
}
if (ret_family)
*ret_family = a->family;
if (ret_address)
*ret_address = a->in_addr;
return 1;
}
return -ENXIO;
}

View File

@ -1,27 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "in-addr-util.h"
#include "macro.h"
typedef struct Link Link;
typedef enum NetDevLocalAddressType {
NETDEV_LOCAL_ADDRESS_IPV4LL,
NETDEV_LOCAL_ADDRESS_IPV6LL,
NETDEV_LOCAL_ADDRESS_DHCP4,
NETDEV_LOCAL_ADDRESS_DHCP6,
NETDEV_LOCAL_ADDRESS_SLAAC,
_NETDEV_LOCAL_ADDRESS_TYPE_MAX,
_NETDEV_LOCAL_ADDRESS_TYPE_INVALID = -EINVAL,
} NetDevLocalAddressType;
const char *netdev_local_address_type_to_string(NetDevLocalAddressType t) _const_;
NetDevLocalAddressType netdev_local_address_type_from_string(const char *s) _pure_;
int link_get_local_address(
Link *link,
NetDevLocalAddressType type,
int family,
int *ret_family,
union in_addr_union *ret_address);

View File

@ -628,9 +628,6 @@ static bool netdev_is_ready_to_create(NetDev *netdev, Link *link) {
if (link->set_link_messages > 0) if (link->set_link_messages > 0)
return false; return false;
if (NETDEV_VTABLE(netdev)->is_ready_to_create)
return NETDEV_VTABLE(netdev)->is_ready_to_create(netdev, link);
return true; return true;
} }

View File

@ -153,9 +153,6 @@ typedef struct NetDevVTable {
/* specifies if netdev is independent, or a master device or a stacked device */ /* specifies if netdev is independent, or a master device or a stacked device */
NetDevCreateType create_type; NetDevCreateType create_type;
/* This is used for stacked netdev. Return true when the underlying link is ready. */
int (*is_ready_to_create)(NetDev *netdev, Link *link);
/* create netdev, if not done via rtnl */ /* create netdev, if not done via rtnl */
int (*create)(NetDev *netdev); int (*create)(NetDev *netdev);

View File

@ -168,20 +168,7 @@ int dhcp4_pd_create_6rd_tunnel(Link *link, link_netlink_message_handler_t callba
return 0; return 0;
} }
static int tunnel_get_local_address(Tunnel *t, Link *link, union in_addr_union *ret) {
assert(t);
if (t->local_type < 0) {
if (ret)
*ret = t->local;
return 0;
}
return link_get_local_address(link, t->local_type, t->family, NULL, ret);
}
static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
union in_addr_union local;
Tunnel *t; Tunnel *t;
int r; int r;
@ -201,11 +188,7 @@ static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_ne
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
} }
r = tunnel_get_local_address(t, link, &local); r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not find local address: %m");
r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &local.in);
if (r < 0) if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
@ -264,7 +247,6 @@ static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_ne
} }
static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
union in_addr_union local;
uint32_t ikey = 0; uint32_t ikey = 0;
uint32_t okey = 0; uint32_t okey = 0;
uint16_t iflags = 0; uint16_t iflags = 0;
@ -303,11 +285,7 @@ static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ERSPAN_INDEX attribute: %m"); return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ERSPAN_INDEX attribute: %m");
} }
r = tunnel_get_local_address(t, link, &local); r = sd_netlink_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not find local address: %m");
r = sd_netlink_message_append_in_addr(m, IFLA_GRE_LOCAL, &local.in);
if (r < 0) if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m"); return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
@ -385,7 +363,6 @@ static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_
} }
static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
union in_addr_union local;
uint32_t ikey = 0; uint32_t ikey = 0;
uint32_t okey = 0; uint32_t okey = 0;
uint16_t iflags = 0; uint16_t iflags = 0;
@ -409,11 +386,7 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m"); return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
} }
r = tunnel_get_local_address(t, link, &local); r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not find local address: %m");
r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_LOCAL, &local.in6);
if (r < 0) if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m"); return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
@ -471,7 +444,6 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl
} }
static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
union in_addr_union local;
uint32_t ikey, okey; uint32_t ikey, okey;
Tunnel *t; Tunnel *t;
int r; int r;
@ -507,11 +479,7 @@ static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink
if (r < 0) if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_OKEY attribute: %m"); return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_OKEY attribute: %m");
r = tunnel_get_local_address(t, link, &local); r = netlink_message_append_in_addr_union(m, IFLA_VTI_LOCAL, t->family, &t->local);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not find local address: %m");
r = netlink_message_append_in_addr_union(m, IFLA_VTI_LOCAL, t->family, &local);
if (r < 0) if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_LOCAL attribute: %m"); return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_LOCAL attribute: %m");
@ -523,7 +491,6 @@ static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink
} }
static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
union in_addr_union local;
uint8_t proto; uint8_t proto;
Tunnel *t; Tunnel *t;
int r; int r;
@ -541,11 +508,7 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
} }
r = tunnel_get_local_address(t, link, &local); r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not find local address: %m");
r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &local.in6);
if (r < 0) if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
@ -599,19 +562,6 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl
return r; return r;
} }
static int netdev_tunnel_is_ready_to_create(NetDev *netdev, Link *link) {
Tunnel *t;
assert(netdev);
assert(link);
t = TUNNEL(netdev);
assert(t);
return tunnel_get_local_address(t, link, NULL) >= 0;
}
static int netdev_tunnel_verify(NetDev *netdev, const char *filename) { static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
Tunnel *t; Tunnel *t;
@ -661,15 +611,10 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
if (t->assign_to_loopback) if (t->assign_to_loopback)
t->independent = true; t->independent = true;
if (t->independent && t->local_type >= 0)
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"The local address cannot be '%s' when Independent= or AssignToLoopback= is enabled, ignoring.",
strna(netdev_local_address_type_to_string(t->local_type)));
return 0; return 0;
} }
int config_parse_tunnel_local_address( int config_parse_tunnel_address(
const char *unit, const char *unit,
const char *filename, const char *filename,
unsigned line, unsigned line,
@ -681,82 +626,28 @@ int config_parse_tunnel_local_address(
void *data, void *data,
void *userdata) { void *userdata) {
union in_addr_union buffer = IN_ADDR_NULL;
NetDevLocalAddressType type;
Tunnel *t = userdata; Tunnel *t = userdata;
union in_addr_union *addr = data, buffer;
int r, f; int r, f;
assert(filename); assert(filename);
assert(lvalue); assert(lvalue);
assert(rvalue); assert(rvalue);
assert(userdata); assert(data);
if (isempty(rvalue) || streq(rvalue, "any")) { /* This is used to parse addresses on both local and remote ends of the tunnel.
/* Unset the previous assignment. */ * Address families must match.
t->local = IN_ADDR_NULL; *
t->local_type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID; * "any" is a special value which means that the address is unspecified.
*/
/* If the remote address is not specified, also clear the address family. */ if (streq(rvalue, "any")) {
if (!in_addr_is_set(t->family, &t->remote)) *addr = IN_ADDR_NULL;
t->family = AF_UNSPEC;
return 0;
}
type = netdev_local_address_type_from_string(rvalue); /* As a special case, if both the local and remote addresses are
if (IN_SET(type, NETDEV_LOCAL_ADDRESS_IPV4LL, NETDEV_LOCAL_ADDRESS_DHCP4)) * unspecified, also clear the address family. */
f = AF_INET; if (!in_addr_is_set(t->family, &t->local) &&
else if (IN_SET(type, NETDEV_LOCAL_ADDRESS_IPV6LL, NETDEV_LOCAL_ADDRESS_DHCP6, NETDEV_LOCAL_ADDRESS_SLAAC)) !in_addr_is_set(t->family, &t->remote))
f = AF_INET6;
else {
type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID;
r = in_addr_from_string_auto(rvalue, &f, &buffer);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Tunnel address \"%s\" invalid, ignoring assignment: %m", rvalue);
return 0;
}
}
if (t->family != AF_UNSPEC && t->family != f) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Address family does not match the previous assignment, ignoring assignment: %s", rvalue);
return 0;
}
t->family = f;
t->local = buffer;
t->local_type = type;
return 0;
}
int config_parse_tunnel_remote_address(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
union in_addr_union buffer;
Tunnel *t = userdata;
int r, f;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(userdata);
if (isempty(rvalue) || streq(rvalue, "any")) {
/* Unset the previous assignment. */
t->remote = IN_ADDR_NULL;
/* If the local address is not specified, also clear the address family. */
if (t->local_type == _NETDEV_LOCAL_ADDRESS_TYPE_INVALID &&
!in_addr_is_set(t->family, &t->local))
t->family = AF_UNSPEC; t->family = AF_UNSPEC;
return 0; return 0;
} }
@ -770,12 +661,12 @@ int config_parse_tunnel_remote_address(
if (t->family != AF_UNSPEC && t->family != f) { if (t->family != AF_UNSPEC && t->family != f) {
log_syntax(unit, LOG_WARNING, filename, line, 0, log_syntax(unit, LOG_WARNING, filename, line, 0,
"Address family does not match the previous assignment, ignoring assignment: %s", rvalue); "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
return 0; return 0;
} }
t->family = f; t->family = f;
t->remote = buffer; *addr = buffer;
return 0; return 0;
} }
@ -949,7 +840,6 @@ static void netdev_tunnel_init(NetDev *netdev) {
assert(t); assert(t);
t->local_type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID;
t->pmtudisc = true; t->pmtudisc = true;
t->fou_encap_type = NETDEV_FOO_OVER_UDP_ENCAP_DIRECT; t->fou_encap_type = NETDEV_FOO_OVER_UDP_ENCAP_DIRECT;
t->isatap = -1; t->isatap = -1;
@ -969,7 +859,6 @@ const NetDevVTable ipip_vtable = {
.sections = NETDEV_COMMON_SECTIONS "Tunnel\0", .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
.fill_message_create = netdev_ipip_sit_fill_message_create, .fill_message_create = netdev_ipip_sit_fill_message_create,
.create_type = NETDEV_CREATE_STACKED, .create_type = NETDEV_CREATE_STACKED,
.is_ready_to_create = netdev_tunnel_is_ready_to_create,
.config_verify = netdev_tunnel_verify, .config_verify = netdev_tunnel_verify,
.iftype = ARPHRD_TUNNEL, .iftype = ARPHRD_TUNNEL,
}; };
@ -980,7 +869,6 @@ const NetDevVTable sit_vtable = {
.sections = NETDEV_COMMON_SECTIONS "Tunnel\0", .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
.fill_message_create = netdev_ipip_sit_fill_message_create, .fill_message_create = netdev_ipip_sit_fill_message_create,
.create_type = NETDEV_CREATE_STACKED, .create_type = NETDEV_CREATE_STACKED,
.is_ready_to_create = netdev_tunnel_is_ready_to_create,
.config_verify = netdev_tunnel_verify, .config_verify = netdev_tunnel_verify,
.iftype = ARPHRD_SIT, .iftype = ARPHRD_SIT,
}; };
@ -991,7 +879,6 @@ const NetDevVTable vti_vtable = {
.sections = NETDEV_COMMON_SECTIONS "Tunnel\0", .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
.fill_message_create = netdev_vti_fill_message_create, .fill_message_create = netdev_vti_fill_message_create,
.create_type = NETDEV_CREATE_STACKED, .create_type = NETDEV_CREATE_STACKED,
.is_ready_to_create = netdev_tunnel_is_ready_to_create,
.config_verify = netdev_tunnel_verify, .config_verify = netdev_tunnel_verify,
.iftype = ARPHRD_TUNNEL, .iftype = ARPHRD_TUNNEL,
}; };
@ -1002,7 +889,6 @@ const NetDevVTable vti6_vtable = {
.sections = NETDEV_COMMON_SECTIONS "Tunnel\0", .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
.fill_message_create = netdev_vti_fill_message_create, .fill_message_create = netdev_vti_fill_message_create,
.create_type = NETDEV_CREATE_STACKED, .create_type = NETDEV_CREATE_STACKED,
.is_ready_to_create = netdev_tunnel_is_ready_to_create,
.config_verify = netdev_tunnel_verify, .config_verify = netdev_tunnel_verify,
.iftype = ARPHRD_TUNNEL6, .iftype = ARPHRD_TUNNEL6,
}; };
@ -1013,7 +899,6 @@ const NetDevVTable gre_vtable = {
.sections = NETDEV_COMMON_SECTIONS "Tunnel\0", .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
.fill_message_create = netdev_gre_erspan_fill_message_create, .fill_message_create = netdev_gre_erspan_fill_message_create,
.create_type = NETDEV_CREATE_STACKED, .create_type = NETDEV_CREATE_STACKED,
.is_ready_to_create = netdev_tunnel_is_ready_to_create,
.config_verify = netdev_tunnel_verify, .config_verify = netdev_tunnel_verify,
.iftype = ARPHRD_IPGRE, .iftype = ARPHRD_IPGRE,
}; };
@ -1024,7 +909,6 @@ const NetDevVTable gretap_vtable = {
.sections = NETDEV_COMMON_SECTIONS "Tunnel\0", .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
.fill_message_create = netdev_gre_erspan_fill_message_create, .fill_message_create = netdev_gre_erspan_fill_message_create,
.create_type = NETDEV_CREATE_STACKED, .create_type = NETDEV_CREATE_STACKED,
.is_ready_to_create = netdev_tunnel_is_ready_to_create,
.config_verify = netdev_tunnel_verify, .config_verify = netdev_tunnel_verify,
.iftype = ARPHRD_ETHER, .iftype = ARPHRD_ETHER,
.generate_mac = true, .generate_mac = true,
@ -1036,7 +920,6 @@ const NetDevVTable ip6gre_vtable = {
.sections = NETDEV_COMMON_SECTIONS "Tunnel\0", .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
.fill_message_create = netdev_ip6gre_fill_message_create, .fill_message_create = netdev_ip6gre_fill_message_create,
.create_type = NETDEV_CREATE_STACKED, .create_type = NETDEV_CREATE_STACKED,
.is_ready_to_create = netdev_tunnel_is_ready_to_create,
.config_verify = netdev_tunnel_verify, .config_verify = netdev_tunnel_verify,
.iftype = ARPHRD_IP6GRE, .iftype = ARPHRD_IP6GRE,
}; };
@ -1047,7 +930,6 @@ const NetDevVTable ip6gretap_vtable = {
.sections = NETDEV_COMMON_SECTIONS "Tunnel\0", .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
.fill_message_create = netdev_ip6gre_fill_message_create, .fill_message_create = netdev_ip6gre_fill_message_create,
.create_type = NETDEV_CREATE_STACKED, .create_type = NETDEV_CREATE_STACKED,
.is_ready_to_create = netdev_tunnel_is_ready_to_create,
.config_verify = netdev_tunnel_verify, .config_verify = netdev_tunnel_verify,
.iftype = ARPHRD_ETHER, .iftype = ARPHRD_ETHER,
.generate_mac = true, .generate_mac = true,
@ -1059,7 +941,6 @@ const NetDevVTable ip6tnl_vtable = {
.sections = NETDEV_COMMON_SECTIONS "Tunnel\0", .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
.fill_message_create = netdev_ip6tnl_fill_message_create, .fill_message_create = netdev_ip6tnl_fill_message_create,
.create_type = NETDEV_CREATE_STACKED, .create_type = NETDEV_CREATE_STACKED,
.is_ready_to_create = netdev_tunnel_is_ready_to_create,
.config_verify = netdev_tunnel_verify, .config_verify = netdev_tunnel_verify,
.iftype = ARPHRD_TUNNEL6, .iftype = ARPHRD_TUNNEL6,
}; };
@ -1070,7 +951,6 @@ const NetDevVTable erspan_vtable = {
.sections = NETDEV_COMMON_SECTIONS "Tunnel\0", .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
.fill_message_create = netdev_gre_erspan_fill_message_create, .fill_message_create = netdev_gre_erspan_fill_message_create,
.create_type = NETDEV_CREATE_STACKED, .create_type = NETDEV_CREATE_STACKED,
.is_ready_to_create = netdev_tunnel_is_ready_to_create,
.config_verify = netdev_tunnel_verify, .config_verify = netdev_tunnel_verify,
.iftype = ARPHRD_ETHER, .iftype = ARPHRD_ETHER,
.generate_mac = true, .generate_mac = true,

View File

@ -5,7 +5,6 @@
#include "conf-parser.h" #include "conf-parser.h"
#include "fou-tunnel.h" #include "fou-tunnel.h"
#include "netdev-util.h"
#include "netdev.h" #include "netdev.h"
#include "networkd-link.h" #include "networkd-link.h"
@ -43,7 +42,6 @@ typedef struct Tunnel {
uint32_t okey; uint32_t okey;
uint32_t erspan_index; uint32_t erspan_index;
NetDevLocalAddressType local_type;
union in_addr_union local; union in_addr_union local;
union in_addr_union remote; union in_addr_union remote;
@ -121,8 +119,7 @@ const char *ip6tnl_mode_to_string(Ip6TnlMode d) _const_;
Ip6TnlMode ip6tnl_mode_from_string(const char *d) _pure_; Ip6TnlMode ip6tnl_mode_from_string(const char *d) _pure_;
CONFIG_PARSER_PROTOTYPE(config_parse_ip6tnl_mode); CONFIG_PARSER_PROTOTYPE(config_parse_ip6tnl_mode);
CONFIG_PARSER_PROTOTYPE(config_parse_tunnel_local_address); CONFIG_PARSER_PROTOTYPE(config_parse_tunnel_address);
CONFIG_PARSER_PROTOTYPE(config_parse_tunnel_remote_address);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_flowlabel); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_flowlabel);
CONFIG_PARSER_PROTOTYPE(config_parse_encap_limit); CONFIG_PARSER_PROTOTYPE(config_parse_encap_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_tunnel_key); CONFIG_PARSER_PROTOTYPE(config_parse_tunnel_key);

View File

@ -2550,23 +2550,6 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
if (r < 0) if (r < 0)
log_link_debug_errno(link, r, "Failed to get driver, continuing without: %m"); log_link_debug_errno(link, r, "Failed to get driver, continuing without: %m");
if (streq_ptr(link->driver, "dsa")) {
uint32_t dsa_master_ifindex;
r = sd_netlink_message_read_u32(message, IFLA_LINK, &dsa_master_ifindex);
if (r < 0) {
dsa_master_ifindex = 0;
if (r != -ENODATA)
log_link_warning_errno(link, r, "rtnl: failed to read ifindex of the DSA master interface, ignoring: %m");
} else if (dsa_master_ifindex > INT_MAX) {
dsa_master_ifindex = 0;
log_link_warning(link, "rtnl: received too large DSA master ifindex (%"PRIu32" > INT_MAX), ignoring.",
dsa_master_ifindex);
}
link->dsa_master_ifindex = (int) dsa_master_ifindex;
}
*ret = TAKE_PTR(link); *ret = TAKE_PTR(link);
return 0; return 0;
} }

View File

@ -48,7 +48,6 @@ typedef struct Link {
int ifindex; int ifindex;
int master_ifindex; int master_ifindex;
int dsa_master_ifindex;
char *ifname; char *ifname;
char **alternative_names; char **alternative_names;
char *kind; char *kind;

View File

@ -948,42 +948,7 @@ int link_configure_mtu(Link *link) {
return link_request_to_set_mtu(link, mtu); return link_request_to_set_mtu(link, mtu);
} }
static int link_up_dsa_slave(Link *link) { static int link_up_or_down_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, bool up, bool check_ready) {
Link *master;
int r;
assert(link);
/* For older kernels (specifically, older than 9d5ef190e5615a7b63af89f88c4106a5bc127974, kernel-5.12),
* it is necessary to bring up a DSA slave that its master interface is already up. And bringing up
* the slave fails with -ENETDOWN. So, let's bring up the master even if it is not managed by us,
* and try to bring up the slave after the master becomes up. */
if (link->dsa_master_ifindex <= 0)
return 0;
if (!streq_ptr(link->driver, "dsa"))
return 0;
if (link_get_by_index(link->manager, link->dsa_master_ifindex, &master) < 0)
return 0;
if (master->state == LINK_STATE_UNMANAGED) {
/* If the DSA master interface is unmanaged, then it will never become up.
* Let's request to bring up the master. */
r = link_request_to_bring_up_or_down(master, /* up = */ true);
if (r < 0)
return r;
}
r = link_request_to_bring_up_or_down(link, /* up = */ true);
if (r < 0)
return r;
return 1;
}
static int link_up_or_down_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, bool up, bool on_activate) {
int r; int r;
assert(m); assert(m);
@ -993,19 +958,10 @@ static int link_up_or_down_handler_internal(sd_netlink *rtnl, sd_netlink_message
goto on_error; goto on_error;
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
if (r == -ENETDOWN && up && link_up_dsa_slave(link) > 0) if (r < 0)
log_link_message_debug_errno(link, m, r, "Could not bring up dsa slave, retrying again after dsa master becomes up"); log_link_message_warning_errno(link, m, r, up ?
else if (r < 0) { "Could not bring up interface, ignoring" :
const char *error_msg; "Could not bring down interface, ignoring");
error_msg = up ?
(on_activate ? "Could not bring up interface" : "Could not bring up interface, ignoring") :
(on_activate ? "Could not bring down interface" : "Could not bring down interface, ignoring");
log_link_message_warning_errno(link, m, r, error_msg);
if (on_activate)
goto on_error;
}
r = link_call_getlink(link, get_link_update_flag_handler); r = link_call_getlink(link, get_link_update_flag_handler);
if (r < 0) { if (r < 0) {
@ -1013,7 +969,7 @@ static int link_up_or_down_handler_internal(sd_netlink *rtnl, sd_netlink_message
goto on_error; goto on_error;
} }
if (on_activate) { if (check_ready) {
link->activated = true; link->activated = true;
link_check_ready(link); link_check_ready(link);
} }
@ -1028,19 +984,19 @@ on_error:
} }
static int link_activate_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int link_activate_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ true, /* on_activate = */ true); return link_up_or_down_handler_internal(rtnl, m, link, true, true);
} }
static int link_activate_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int link_activate_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ false, /* on_activate = */ true); return link_up_or_down_handler_internal(rtnl, m, link, false, true);
} }
static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ true, /* on_activate = */ false); return link_up_or_down_handler_internal(rtnl, m, link, true, false);
} }
static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ false, /* on_activate = */ false); return link_up_or_down_handler_internal(rtnl, m, link, false, false);
} }
static const char *up_or_down(bool up) { static const char *up_or_down(bool up) {
@ -1167,21 +1123,9 @@ int link_request_to_activate(Link *link) {
return 0; return 0;
} }
static bool link_is_ready_to_bring_up_or_down(Link *link, bool up) { static bool link_is_ready_to_bring_up_or_down(Link *link) {
assert(link); assert(link);
if (up && link->dsa_master_ifindex > 0) {
Link *master;
/* The master interface must be up. See comments in link_up_dsa_slave(). */
if (link_get_by_index(link->manager, link->dsa_master_ifindex, &master) < 0)
return false;
if (!FLAGS_SET(master->flags, IFF_UP))
return false;
}
if (link->state == LINK_STATE_UNMANAGED) if (link->state == LINK_STATE_UNMANAGED)
return true; return true;
@ -1209,7 +1153,7 @@ int request_process_link_up_or_down(Request *req) {
link = req->link; link = req->link;
up = PTR_TO_INT(req->userdata); up = PTR_TO_INT(req->userdata);
if (!link_is_ready_to_bring_up_or_down(link, up)) if (!link_is_ready_to_bring_up_or_down(link))
return 0; return 0;
r = link_up_or_down(link, up, req->netlink_handler); r = link_up_or_down(link, up, req->netlink_handler);

View File

@ -430,7 +430,7 @@ target2 = custom_target(
shared_generated_gperf_headers = [target1, target2] shared_generated_gperf_headers = [target1, target2]
shared_sources += shared_generated_gperf_headers shared_sources += shared_generated_gperf_headers
libshared_name = 'systemd-shared-@0@'.format(shared_lib_tag) libshared_name = 'systemd-shared-@0@'.format(meson.project_version())
libshared_deps = [threads, libshared_deps = [threads,
libacl, libacl,
@ -465,13 +465,13 @@ libshared_static = static_library(
libshared = shared_library( libshared = shared_library(
libshared_name, libshared_name,
include_directories : includes, include_directories : includes,
c_args : ['-fvisibility=default'],
link_args : ['-shared', link_args : ['-shared',
'-Wl,--version-script=' + libshared_sym_path], '-Wl,--version-script=' + libshared_sym_path],
link_whole : [libshared_static, link_whole : [libshared_static,
libbasic, libbasic,
libbasic_gcrypt, libbasic_gcrypt,
libsystemd_static], libsystemd_static],
c_args : ['-fvisibility=default'],
dependencies : libshared_deps, dependencies : libshared_deps,
install : true, install : true,
install_dir : rootlibexecdir) install_dir : rootlibexecdir)

View File

@ -419,8 +419,7 @@ tests += [
libmount, libmount,
libxz, libxz,
liblz4, liblz4,
libblkid, libblkid],
libselinux],
[core_includes, journal_includes, udev_includes]], [core_includes, journal_includes, udev_includes]],
[['src/test/test-prioq.c']], [['src/test/test-prioq.c']],

View File

@ -11,86 +11,34 @@ TEST(strpcpy) {
char target[25]; char target[25];
char *s = target; char *s = target;
size_t space_left; size_t space_left;
bool truncated;
space_left = sizeof(target); space_left = sizeof(target);
space_left = strpcpy_full(&s, space_left, "12345", &truncated); space_left = strpcpy(&s, space_left, "12345");
assert_se(!truncated); space_left = strpcpy(&s, space_left, "hey hey hey");
space_left = strpcpy_full(&s, space_left, "hey hey hey", &truncated); space_left = strpcpy(&s, space_left, "waldo");
assert_se(!truncated); space_left = strpcpy(&s, space_left, "ba");
space_left = strpcpy_full(&s, space_left, "waldo", &truncated); space_left = strpcpy(&s, space_left, "r");
assert_se(!truncated); space_left = strpcpy(&s, space_left, "foo");
space_left = strpcpy_full(&s, space_left, "ba", &truncated);
assert_se(!truncated);
space_left = strpcpy_full(&s, space_left, "r", &truncated);
assert_se(!truncated);
assert_se(space_left == 1);
assert_se(streq(target, "12345hey hey heywaldobar"));
space_left = strpcpy_full(&s, space_left, "", &truncated);
assert_se(!truncated);
assert_se(space_left == 1);
assert_se(streq(target, "12345hey hey heywaldobar")); assert_se(streq(target, "12345hey hey heywaldobar"));
space_left = strpcpy_full(&s, space_left, "f", &truncated);
assert_se(truncated);
assert_se(space_left == 0); assert_se(space_left == 0);
assert_se(streq(target, "12345hey hey heywaldobar"));
space_left = strpcpy_full(&s, space_left, "", &truncated);
assert_se(!truncated);
assert_se(space_left == 0);
assert_se(streq(target, "12345hey hey heywaldobar"));
space_left = strpcpy_full(&s, space_left, "foo", &truncated);
assert_se(truncated);
assert_se(space_left == 0);
assert_se(streq(target, "12345hey hey heywaldobar"));
} }
TEST(strpcpyf) { TEST(strpcpyf) {
char target[25]; char target[25];
char *s = target; char *s = target;
size_t space_left; size_t space_left;
bool truncated;
space_left = sizeof(target); space_left = sizeof(target);
space_left = strpcpyf_full(&s, space_left, &truncated, "space left: %zu. ", space_left); space_left = strpcpyf(&s, space_left, "space left: %zu. ", space_left);
assert_se(!truncated); space_left = strpcpyf(&s, space_left, "foo%s", "bar");
space_left = strpcpyf_full(&s, space_left, &truncated, "foo%s", "bar");
assert_se(!truncated);
assert_se(space_left == 3);
assert_se(streq(target, "space left: 25. foobar")); assert_se(streq(target, "space left: 25. foobar"));
assert_se(space_left == 3);
space_left = strpcpyf_full(&s, space_left, &truncated, "%i", 42);
assert_se(!truncated);
assert_se(space_left == 1);
assert_se(streq(target, "space left: 25. foobar42"));
space_left = strpcpyf_full(&s, space_left, &truncated, "%s", "");
assert_se(!truncated);
assert_se(space_left == 1);
assert_se(streq(target, "space left: 25. foobar42"));
space_left = strpcpyf_full(&s, space_left, &truncated, "%c", 'x');
assert_se(truncated);
assert_se(space_left == 0);
assert_se(streq(target, "space left: 25. foobar42"));
space_left = strpcpyf_full(&s, space_left, &truncated, "%s", "");
assert_se(!truncated);
assert_se(space_left == 0);
assert_se(streq(target, "space left: 25. foobar42"));
space_left = strpcpyf_full(&s, space_left, &truncated, "abc%s", "hoge");
assert_se(truncated);
assert_se(space_left == 0);
assert_se(streq(target, "space left: 25. foobar42"));
/* test overflow */ /* test overflow */
s = target; s = target;
space_left = strpcpyf_full(&s, 12, &truncated, "00 left: %i. ", 999); space_left = strpcpyf(&s, 12, "00 left: %i. ", 999);
assert_se(truncated);
assert_se(streq(target, "00 left: 99")); assert_se(streq(target, "00 left: 99"));
assert_se(space_left == 0); assert_se(space_left == 0);
assert_se(target[12] == '2'); assert_se(target[12] == '2');
@ -100,40 +48,21 @@ TEST(strpcpyl) {
char target[25]; char target[25];
char *s = target; char *s = target;
size_t space_left; size_t space_left;
bool truncated;
space_left = sizeof(target); space_left = sizeof(target);
space_left = strpcpyl_full(&s, space_left, &truncated, "waldo", " test", " waldo. ", NULL); space_left = strpcpyl(&s, space_left, "waldo", " test", " waldo. ", NULL);
assert_se(!truncated); space_left = strpcpyl(&s, space_left, "Banana", NULL);
space_left = strpcpyl_full(&s, space_left, &truncated, "Banana", NULL);
assert_se(!truncated); assert_se(streq(target, "waldo test waldo. Banana"));
assert_se(space_left == 1); assert_se(space_left == 1);
assert_se(streq(target, "waldo test waldo. Banana"));
space_left = strpcpyl_full(&s, space_left, &truncated, "", "", "", NULL);
assert_se(!truncated);
assert_se(space_left == 1);
assert_se(streq(target, "waldo test waldo. Banana"));
space_left = strpcpyl_full(&s, space_left, &truncated, "", "x", "", NULL);
assert_se(truncated);
assert_se(space_left == 0);
assert_se(streq(target, "waldo test waldo. Banana"));
space_left = strpcpyl_full(&s, space_left, &truncated, "hoge", NULL);
assert_se(truncated);
assert_se(space_left == 0);
assert_se(streq(target, "waldo test waldo. Banana"));
} }
TEST(strscpy) { TEST(strscpy) {
char target[25]; char target[25];
size_t space_left; size_t space_left;
bool truncated;
space_left = sizeof(target); space_left = sizeof(target);
space_left = strscpy_full(target, space_left, "12345", &truncated); space_left = strscpy(target, space_left, "12345");
assert_se(!truncated);
assert_se(streq(target, "12345")); assert_se(streq(target, "12345"));
assert_se(space_left == 20); assert_se(space_left == 20);
@ -142,11 +71,9 @@ TEST(strscpy) {
TEST(strscpyl) { TEST(strscpyl) {
char target[25]; char target[25];
size_t space_left; size_t space_left;
bool truncated;
space_left = sizeof(target); space_left = sizeof(target);
space_left = strscpyl_full(target, space_left, &truncated, "12345", "waldo", "waldo", NULL); space_left = strscpyl(target, space_left, "12345", "waldo", "waldo", NULL);
assert_se(!truncated);
assert_se(streq(target, "12345waldowaldo")); assert_se(streq(target, "12345waldowaldo"));
assert_se(space_left == 10); assert_se(space_left == 10);

View File

@ -9,7 +9,7 @@
#define BUF_SIZE 1024 #define BUF_SIZE 1024
static void test_event_spawn_core(bool with_pidfd, const char *cmd, char *result_buf, size_t buf_size) { static void test_event_spawn_core(bool with_pidfd, const char *cmd, char result_buf[BUF_SIZE]) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL; _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
_cleanup_(udev_event_freep) UdevEvent *event = NULL; _cleanup_(udev_event_freep) UdevEvent *event = NULL;
@ -17,12 +17,12 @@ static void test_event_spawn_core(bool with_pidfd, const char *cmd, char *result
assert_se(sd_device_new_from_syspath(&dev, "/sys/class/net/lo") >= 0); assert_se(sd_device_new_from_syspath(&dev, "/sys/class/net/lo") >= 0);
assert_se(event = udev_event_new(dev, 0, NULL, LOG_DEBUG)); assert_se(event = udev_event_new(dev, 0, NULL, LOG_DEBUG));
assert_se(udev_event_spawn(event, 5 * USEC_PER_SEC, SIGKILL, false, cmd, result_buf, buf_size, NULL) == 0); assert_se(udev_event_spawn(event, 5 * USEC_PER_SEC, SIGKILL, false, cmd, result_buf, BUF_SIZE) == 0);
assert_se(unsetenv("SYSTEMD_PIDFD") >= 0); assert_se(unsetenv("SYSTEMD_PIDFD") >= 0);
} }
static void test_event_spawn_cat(bool with_pidfd, size_t buf_size) { static void test_event_spawn_cat(bool with_pidfd) {
_cleanup_strv_free_ char **lines = NULL; _cleanup_strv_free_ char **lines = NULL;
_cleanup_free_ char *cmd = NULL; _cleanup_free_ char *cmd = NULL;
char result_buf[BUF_SIZE]; char result_buf[BUF_SIZE];
@ -32,16 +32,13 @@ static void test_event_spawn_cat(bool with_pidfd, size_t buf_size) {
assert_se(find_executable("cat", &cmd) >= 0); assert_se(find_executable("cat", &cmd) >= 0);
assert_se(strextend_with_separator(&cmd, " ", "/sys/class/net/lo/uevent")); assert_se(strextend_with_separator(&cmd, " ", "/sys/class/net/lo/uevent"));
test_event_spawn_core(with_pidfd, cmd, result_buf, test_event_spawn_core(with_pidfd, cmd, result_buf);
buf_size >= BUF_SIZE ? BUF_SIZE : buf_size);
assert_se(lines = strv_split_newlines(result_buf)); assert_se(lines = strv_split_newlines(result_buf));
strv_print(lines); strv_print(lines);
if (buf_size >= BUF_SIZE) { assert_se(strv_contains(lines, "INTERFACE=lo"));
assert_se(strv_contains(lines, "INTERFACE=lo")); assert_se(strv_contains(lines, "IFINDEX=1"));
assert_se(strv_contains(lines, "IFINDEX=1"));
}
} }
static void test_event_spawn_self(const char *self, const char *arg, bool with_pidfd) { static void test_event_spawn_self(const char *self, const char *arg, bool with_pidfd) {
@ -53,7 +50,7 @@ static void test_event_spawn_self(const char *self, const char *arg, bool with_p
assert_se(cmd = strjoin(self, " ", arg)); assert_se(cmd = strjoin(self, " ", arg));
test_event_spawn_core(with_pidfd, cmd, result_buf, BUF_SIZE); test_event_spawn_core(with_pidfd, cmd, result_buf);
assert_se(lines = strv_split_newlines(result_buf)); assert_se(lines = strv_split_newlines(result_buf));
strv_print(lines); strv_print(lines);
@ -95,10 +92,8 @@ int main(int argc, char *argv[]) {
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
test_event_spawn_cat(true, SIZE_MAX); test_event_spawn_cat(true);
test_event_spawn_cat(false, SIZE_MAX); test_event_spawn_cat(false);
test_event_spawn_cat(true, 5);
test_event_spawn_cat(false, 5);
assert_se(path_make_absolute_cwd(argv[0], &self) >= 0); assert_se(path_make_absolute_cwd(argv[0], &self) >= 0);
path_simplify(self); path_simplify(self);

View File

@ -12,7 +12,6 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "errno-util.h" #include "errno-util.h"
#include "event-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "format-util.h" #include "format-util.h"
#include "io-util.h" #include "io-util.h"
@ -106,13 +105,6 @@ static void udev_ctrl_disconnect(UdevCtrl *uctrl) {
uctrl->sock_connect = safe_close(uctrl->sock_connect); uctrl->sock_connect = safe_close(uctrl->sock_connect);
} }
int udev_ctrl_is_connected(UdevCtrl *uctrl) {
if (!uctrl)
return false;
return event_source_is_enabled(uctrl->event_source_connect);
}
static UdevCtrl *udev_ctrl_free(UdevCtrl *uctrl) { static UdevCtrl *udev_ctrl_free(UdevCtrl *uctrl) {
assert(uctrl); assert(uctrl);
@ -299,7 +291,7 @@ int udev_ctrl_start(UdevCtrl *uctrl, udev_ctrl_handler_t callback, void *userdat
return 0; return 0;
} }
int udev_ctrl_send(UdevCtrl *uctrl, UdevCtrlMessageType type, const void *data) { int udev_ctrl_send(UdevCtrl *uctrl, UdevCtrlMessageType type, int intval, const char *buf) {
UdevCtrlMessageWire ctrl_msg_wire = { UdevCtrlMessageWire ctrl_msg_wire = {
.version = "udev-" STRINGIFY(PROJECT_VERSION), .version = "udev-" STRINGIFY(PROJECT_VERSION),
.magic = UDEV_CTRL_MAGIC, .magic = UDEV_CTRL_MAGIC,
@ -309,13 +301,10 @@ int udev_ctrl_send(UdevCtrl *uctrl, UdevCtrlMessageType type, const void *data)
if (uctrl->maybe_disconnected) if (uctrl->maybe_disconnected)
return -ENOANO; /* to distinguish this from other errors. */ return -ENOANO; /* to distinguish this from other errors. */
if (type == UDEV_CTRL_SET_ENV) { if (buf)
assert(data); strscpy(ctrl_msg_wire.value.buf, sizeof(ctrl_msg_wire.value.buf), buf);
strscpy(ctrl_msg_wire.value.buf, sizeof(ctrl_msg_wire.value.buf), data); else
} else if (IN_SET(type, UDEV_CTRL_SET_LOG_LEVEL, UDEV_CTRL_SET_CHILDREN_MAX)) ctrl_msg_wire.value.intval = intval;
ctrl_msg_wire.value.intval = PTR_TO_INT(data);
else if (type == UDEV_CTRL_SENDER_PID)
ctrl_msg_wire.value.pid = PTR_TO_PID(data);
if (!uctrl->connected) { if (!uctrl->connected) {
if (connect(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0) if (connect(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0)
@ -344,7 +333,7 @@ int udev_ctrl_wait(UdevCtrl *uctrl, usec_t timeout) {
return 0; return 0;
if (!uctrl->maybe_disconnected) { if (!uctrl->maybe_disconnected) {
r = udev_ctrl_send(uctrl, _UDEV_CTRL_END_MESSAGES, NULL); r = udev_ctrl_send(uctrl, _UDEV_CTRL_END_MESSAGES, 0, NULL);
if (r < 0) if (r < 0)
return r; return r;
} }

View File

@ -4,7 +4,6 @@
#include "sd-event.h" #include "sd-event.h"
#include "macro.h" #include "macro.h"
#include "process-util.h"
#include "time-util.h" #include "time-util.h"
typedef struct UdevCtrl UdevCtrl; typedef struct UdevCtrl UdevCtrl;
@ -19,12 +18,10 @@ typedef enum UdevCtrlMessageType {
UDEV_CTRL_SET_CHILDREN_MAX, UDEV_CTRL_SET_CHILDREN_MAX,
UDEV_CTRL_PING, UDEV_CTRL_PING,
UDEV_CTRL_EXIT, UDEV_CTRL_EXIT,
UDEV_CTRL_SENDER_PID,
} UdevCtrlMessageType; } UdevCtrlMessageType;
typedef union UdevCtrlMessageValue { typedef union UdevCtrlMessageValue {
int intval; int intval;
pid_t pid;
char buf[256]; char buf[256];
} UdevCtrlMessageValue; } UdevCtrlMessageValue;
@ -42,45 +39,40 @@ UdevCtrl *udev_ctrl_unref(UdevCtrl *uctrl);
int udev_ctrl_attach_event(UdevCtrl *uctrl, sd_event *event); int udev_ctrl_attach_event(UdevCtrl *uctrl, sd_event *event);
int udev_ctrl_start(UdevCtrl *uctrl, udev_ctrl_handler_t callback, void *userdata); int udev_ctrl_start(UdevCtrl *uctrl, udev_ctrl_handler_t callback, void *userdata);
sd_event_source *udev_ctrl_get_event_source(UdevCtrl *uctrl); sd_event_source *udev_ctrl_get_event_source(UdevCtrl *uctrl);
int udev_ctrl_is_connected(UdevCtrl *uctrl);
int udev_ctrl_wait(UdevCtrl *uctrl, usec_t timeout); int udev_ctrl_wait(UdevCtrl *uctrl, usec_t timeout);
int udev_ctrl_send(UdevCtrl *uctrl, UdevCtrlMessageType type, const void *data); int udev_ctrl_send(UdevCtrl *uctrl, UdevCtrlMessageType type, int intval, const char *buf);
static inline int udev_ctrl_send_set_log_level(UdevCtrl *uctrl, int priority) { static inline int udev_ctrl_send_set_log_level(UdevCtrl *uctrl, int priority) {
return udev_ctrl_send(uctrl, UDEV_CTRL_SET_LOG_LEVEL, INT_TO_PTR(priority)); return udev_ctrl_send(uctrl, UDEV_CTRL_SET_LOG_LEVEL, priority, NULL);
} }
static inline int udev_ctrl_send_stop_exec_queue(UdevCtrl *uctrl) { static inline int udev_ctrl_send_stop_exec_queue(UdevCtrl *uctrl) {
return udev_ctrl_send(uctrl, UDEV_CTRL_STOP_EXEC_QUEUE, NULL); return udev_ctrl_send(uctrl, UDEV_CTRL_STOP_EXEC_QUEUE, 0, NULL);
} }
static inline int udev_ctrl_send_start_exec_queue(UdevCtrl *uctrl) { static inline int udev_ctrl_send_start_exec_queue(UdevCtrl *uctrl) {
return udev_ctrl_send(uctrl, UDEV_CTRL_START_EXEC_QUEUE, NULL); return udev_ctrl_send(uctrl, UDEV_CTRL_START_EXEC_QUEUE, 0, NULL);
} }
static inline int udev_ctrl_send_reload(UdevCtrl *uctrl) { static inline int udev_ctrl_send_reload(UdevCtrl *uctrl) {
return udev_ctrl_send(uctrl, UDEV_CTRL_RELOAD, NULL); return udev_ctrl_send(uctrl, UDEV_CTRL_RELOAD, 0, NULL);
} }
static inline int udev_ctrl_send_set_env(UdevCtrl *uctrl, const char *key) { static inline int udev_ctrl_send_set_env(UdevCtrl *uctrl, const char *key) {
return udev_ctrl_send(uctrl, UDEV_CTRL_SET_ENV, key); return udev_ctrl_send(uctrl, UDEV_CTRL_SET_ENV, 0, key);
} }
static inline int udev_ctrl_send_set_children_max(UdevCtrl *uctrl, int count) { static inline int udev_ctrl_send_set_children_max(UdevCtrl *uctrl, int count) {
return udev_ctrl_send(uctrl, UDEV_CTRL_SET_CHILDREN_MAX, INT_TO_PTR(count)); return udev_ctrl_send(uctrl, UDEV_CTRL_SET_CHILDREN_MAX, count, NULL);
} }
static inline int udev_ctrl_send_ping(UdevCtrl *uctrl) { static inline int udev_ctrl_send_ping(UdevCtrl *uctrl) {
return udev_ctrl_send(uctrl, UDEV_CTRL_PING, NULL); return udev_ctrl_send(uctrl, UDEV_CTRL_PING, 0, NULL);
} }
static inline int udev_ctrl_send_exit(UdevCtrl *uctrl) { static inline int udev_ctrl_send_exit(UdevCtrl *uctrl) {
return udev_ctrl_send(uctrl, UDEV_CTRL_EXIT, NULL); return udev_ctrl_send(uctrl, UDEV_CTRL_EXIT, 0, NULL);
}
static inline int udev_ctrl_send_pid(UdevCtrl *uctrl) {
return udev_ctrl_send(uctrl, UDEV_CTRL_SENDER_PID, PID_TO_PTR(getpid_cached()));
} }
DEFINE_TRIVIAL_CLEANUP_FUNC(UdevCtrl*, udev_ctrl_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(UdevCtrl*, udev_ctrl_unref);

View File

@ -50,7 +50,6 @@ typedef struct Spawn {
char *result; char *result;
size_t result_size; size_t result_size;
size_t result_len; size_t result_len;
bool truncated;
} Spawn; } Spawn;
UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl, int log_level) { UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl, int log_level) {
@ -238,12 +237,9 @@ static ssize_t udev_event_subst_format(
FormatSubstitutionType type, FormatSubstitutionType type,
const char *attr, const char *attr,
char *dest, char *dest,
size_t l, size_t l) {
bool *ret_truncated) {
sd_device *parent, *dev = event->dev; sd_device *parent, *dev = event->dev;
const char *val = NULL; const char *val = NULL;
bool truncated = false;
char *s = dest; char *s = dest;
int r; int r;
@ -252,13 +248,13 @@ static ssize_t udev_event_subst_format(
r = sd_device_get_devpath(dev, &val); r = sd_device_get_devpath(dev, &val);
if (r < 0) if (r < 0)
return r; return r;
strpcpy_full(&s, l, val, &truncated); strpcpy(&s, l, val);
break; break;
case FORMAT_SUBST_KERNEL: case FORMAT_SUBST_KERNEL:
r = sd_device_get_sysname(dev, &val); r = sd_device_get_sysname(dev, &val);
if (r < 0) if (r < 0)
return r; return r;
strpcpy_full(&s, l, val, &truncated); strpcpy(&s, l, val);
break; break;
case FORMAT_SUBST_KERNEL_NUMBER: case FORMAT_SUBST_KERNEL_NUMBER:
r = sd_device_get_sysnum(dev, &val); r = sd_device_get_sysnum(dev, &val);
@ -266,7 +262,7 @@ static ssize_t udev_event_subst_format(
goto null_terminate; goto null_terminate;
if (r < 0) if (r < 0)
return r; return r;
strpcpy_full(&s, l, val, &truncated); strpcpy(&s, l, val);
break; break;
case FORMAT_SUBST_ID: case FORMAT_SUBST_ID:
if (!event->dev_parent) if (!event->dev_parent)
@ -274,7 +270,7 @@ static ssize_t udev_event_subst_format(
r = sd_device_get_sysname(event->dev_parent, &val); r = sd_device_get_sysname(event->dev_parent, &val);
if (r < 0) if (r < 0)
return r; return r;
strpcpy_full(&s, l, val, &truncated); strpcpy(&s, l, val);
break; break;
case FORMAT_SUBST_DRIVER: case FORMAT_SUBST_DRIVER:
if (!event->dev_parent) if (!event->dev_parent)
@ -284,7 +280,7 @@ static ssize_t udev_event_subst_format(
goto null_terminate; goto null_terminate;
if (r < 0) if (r < 0)
return r; return r;
strpcpy_full(&s, l, val, &truncated); strpcpy(&s, l, val);
break; break;
case FORMAT_SUBST_MAJOR: case FORMAT_SUBST_MAJOR:
case FORMAT_SUBST_MINOR: { case FORMAT_SUBST_MINOR: {
@ -293,7 +289,7 @@ static ssize_t udev_event_subst_format(
r = sd_device_get_devnum(dev, &devnum); r = sd_device_get_devnum(dev, &devnum);
if (r < 0 && r != -ENOENT) if (r < 0 && r != -ENOENT)
return r; return r;
strpcpyf_full(&s, l, &truncated, "%u", r < 0 ? 0 : type == FORMAT_SUBST_MAJOR ? major(devnum) : minor(devnum)); strpcpyf(&s, l, "%u", r < 0 ? 0 : type == FORMAT_SUBST_MAJOR ? major(devnum) : minor(devnum));
break; break;
} }
case FORMAT_SUBST_RESULT: { case FORMAT_SUBST_RESULT: {
@ -312,7 +308,7 @@ static ssize_t udev_event_subst_format(
} }
if (index == 0) if (index == 0)
strpcpy_full(&s, l, event->program_result, &truncated); strpcpy(&s, l, event->program_result);
else { else {
const char *start, *p; const char *start, *p;
unsigned i; unsigned i;
@ -334,11 +330,11 @@ static ssize_t udev_event_subst_format(
start = p; start = p;
/* %c{2+} copies the whole string from the second part on */ /* %c{2+} copies the whole string from the second part on */
if (has_plus) if (has_plus)
strpcpy_full(&s, l, start, &truncated); strpcpy(&s, l, start);
else { else {
while (*p && !strchr(WHITESPACE, *p)) while (*p && !strchr(WHITESPACE, *p))
p++; p++;
strnpcpy_full(&s, l, start, p - start, &truncated); strnpcpy(&s, l, start, p - start);
} }
} }
break; break;
@ -346,7 +342,6 @@ static ssize_t udev_event_subst_format(
case FORMAT_SUBST_ATTR: { case FORMAT_SUBST_ATTR: {
char vbuf[UDEV_NAME_SIZE]; char vbuf[UDEV_NAME_SIZE];
int count; int count;
bool t;
if (isempty(attr)) if (isempty(attr))
return -EINVAL; return -EINVAL;
@ -368,13 +363,12 @@ static ssize_t udev_event_subst_format(
/* strip trailing whitespace, and replace unwanted characters */ /* strip trailing whitespace, and replace unwanted characters */
if (val != vbuf) if (val != vbuf)
strscpy_full(vbuf, sizeof(vbuf), val, &truncated); strscpy(vbuf, sizeof(vbuf), val);
delete_trailing_chars(vbuf, NULL); delete_trailing_chars(vbuf, NULL);
count = udev_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT); count = udev_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT);
if (count > 0) if (count > 0)
log_device_debug(dev, "%i character(s) replaced", count); log_device_debug(dev, "%i character(s) replaced", count);
strpcpy_full(&s, l, vbuf, &t); strpcpy(&s, l, vbuf);
truncated = truncated || t;
break; break;
} }
case FORMAT_SUBST_PARENT: case FORMAT_SUBST_PARENT:
@ -388,7 +382,7 @@ static ssize_t udev_event_subst_format(
goto null_terminate; goto null_terminate;
if (r < 0) if (r < 0)
return r; return r;
strpcpy_full(&s, l, val + STRLEN("/dev/"), &truncated); strpcpy(&s, l, val + STRLEN("/dev/"));
break; break;
case FORMAT_SUBST_DEVNODE: case FORMAT_SUBST_DEVNODE:
r = sd_device_get_devname(dev, &val); r = sd_device_get_devname(dev, &val);
@ -396,37 +390,34 @@ static ssize_t udev_event_subst_format(
goto null_terminate; goto null_terminate;
if (r < 0) if (r < 0)
return r; return r;
strpcpy_full(&s, l, val, &truncated); strpcpy(&s, l, val);
break; break;
case FORMAT_SUBST_NAME: case FORMAT_SUBST_NAME:
if (event->name) if (event->name)
strpcpy_full(&s, l, event->name, &truncated); strpcpy(&s, l, event->name);
else if (sd_device_get_devname(dev, &val) >= 0) else if (sd_device_get_devname(dev, &val) >= 0)
strpcpy_full(&s, l, val + STRLEN("/dev/"), &truncated); strpcpy(&s, l, val + STRLEN("/dev/"));
else { else {
r = sd_device_get_sysname(dev, &val); r = sd_device_get_sysname(dev, &val);
if (r < 0) if (r < 0)
return r; return r;
strpcpy_full(&s, l, val, &truncated); strpcpy(&s, l, val);
} }
break; break;
case FORMAT_SUBST_LINKS: case FORMAT_SUBST_LINKS:
FOREACH_DEVICE_DEVLINK(dev, val) { FOREACH_DEVICE_DEVLINK(dev, val)
if (s == dest) if (s == dest)
strpcpy_full(&s, l, val + STRLEN("/dev/"), &truncated); strpcpy(&s, l, val + STRLEN("/dev/"));
else else
strpcpyl_full(&s, l, &truncated, " ", val + STRLEN("/dev/"), NULL); strpcpyl(&s, l, " ", val + STRLEN("/dev/"), NULL);
if (truncated)
break;
}
if (s == dest) if (s == dest)
goto null_terminate; goto null_terminate;
break; break;
case FORMAT_SUBST_ROOT: case FORMAT_SUBST_ROOT:
strpcpy_full(&s, l, "/dev", &truncated); strpcpy(&s, l, "/dev");
break; break;
case FORMAT_SUBST_SYS: case FORMAT_SUBST_SYS:
strpcpy_full(&s, l, "/sys", &truncated); strpcpy(&s, l, "/sys");
break; break;
case FORMAT_SUBST_ENV: case FORMAT_SUBST_ENV:
if (isempty(attr)) if (isempty(attr))
@ -436,34 +427,22 @@ static ssize_t udev_event_subst_format(
goto null_terminate; goto null_terminate;
if (r < 0) if (r < 0)
return r; return r;
strpcpy_full(&s, l, val, &truncated); strpcpy(&s, l, val);
break; break;
default: default:
assert_not_reached(); assert_not_reached();
} }
if (ret_truncated)
*ret_truncated = truncated;
return s - dest; return s - dest;
null_terminate: null_terminate:
if (ret_truncated)
*ret_truncated = truncated;
*s = '\0'; *s = '\0';
return 0; return 0;
} }
size_t udev_event_apply_format( size_t udev_event_apply_format(UdevEvent *event,
UdevEvent *event, const char *src, char *dest, size_t size,
const char *src, bool replace_whitespace) {
char *dest,
size_t size,
bool replace_whitespace,
bool *ret_truncated) {
bool truncated = false;
const char *s = src; const char *s = src;
int r; int r;
@ -477,24 +456,20 @@ size_t udev_event_apply_format(
FormatSubstitutionType type; FormatSubstitutionType type;
char attr[UDEV_PATH_SIZE]; char attr[UDEV_PATH_SIZE];
ssize_t subst_len; ssize_t subst_len;
bool t;
r = get_subst_type(&s, false, &type, attr); r = get_subst_type(&s, false, &type, attr);
if (r < 0) { if (r < 0) {
log_device_warning_errno(event->dev, r, "Invalid format string, ignoring: %s", src); log_device_warning_errno(event->dev, r, "Invalid format string, ignoring: %s", src);
break; break;
} else if (r == 0) { } else if (r == 0) {
if (size < 2) { if (size < 2) /* need space for this char and the terminating NUL */
/* need space for this char and the terminating NUL */
truncated = true;
break; break;
}
*dest++ = *s++; *dest++ = *s++;
size--; size--;
continue; continue;
} }
subst_len = udev_event_subst_format(event, type, attr, dest, size, &t); subst_len = udev_event_subst_format(event, type, attr, dest, size);
if (subst_len < 0) { if (subst_len < 0) {
log_device_warning_errno(event->dev, subst_len, log_device_warning_errno(event->dev, subst_len,
"Failed to substitute variable '$%s' or apply format '%%%c', ignoring: %m", "Failed to substitute variable '$%s' or apply format '%%%c', ignoring: %m",
@ -502,8 +477,6 @@ size_t udev_event_apply_format(
break; break;
} }
truncated = truncated || t;
/* FORMAT_SUBST_RESULT handles spaces itself */ /* FORMAT_SUBST_RESULT handles spaces itself */
if (replace_whitespace && type != FORMAT_SUBST_RESULT) if (replace_whitespace && type != FORMAT_SUBST_RESULT)
/* udev_replace_whitespace can replace in-place, /* udev_replace_whitespace can replace in-place,
@ -515,10 +488,6 @@ size_t udev_event_apply_format(
} }
assert(size >= 1); assert(size >= 1);
if (ret_truncated)
*ret_truncated = truncated;
*dest = '\0'; *dest = '\0';
return size; return size;
} }
@ -586,7 +555,7 @@ static int on_spawn_io(sd_event_source *s, int fd, uint32_t revents, void *userd
size = sizeof(buf); size = sizeof(buf);
} }
l = read(fd, p, size - (p == buf)); l = read(fd, p, size - 1);
if (l < 0) { if (l < 0) {
if (errno == EAGAIN) if (errno == EAGAIN)
goto reenable; goto reenable;
@ -597,13 +566,6 @@ static int on_spawn_io(sd_event_source *s, int fd, uint32_t revents, void *userd
return 0; return 0;
} }
if ((size_t) l == size) {
log_device_warning(spawn->device, "Truncating stdout of '%s' up to %zu byte.",
spawn->cmd, spawn->result_size);
l--;
spawn->truncated = true;
}
p[l] = '\0'; p[l] = '\0';
if (fd == spawn->fd_stdout && spawn->result) if (fd == spawn->fd_stdout && spawn->result)
spawn->result_len += l; spawn->result_len += l;
@ -624,7 +586,7 @@ static int on_spawn_io(sd_event_source *s, int fd, uint32_t revents, void *userd
fd == spawn->fd_stdout ? "out" : "err", *q); fd == spawn->fd_stdout ? "out" : "err", *q);
} }
if (l == 0 || spawn->truncated) if (l == 0)
return 0; return 0;
reenable: reenable:
@ -763,16 +725,12 @@ static int spawn_wait(Spawn *spawn) {
return sd_event_loop(e); return sd_event_loop(e);
} }
int udev_event_spawn( int udev_event_spawn(UdevEvent *event,
UdevEvent *event, usec_t timeout_usec,
usec_t timeout_usec, int timeout_signal,
int timeout_signal, bool accept_failure,
bool accept_failure, const char *cmd,
const char *cmd, char *result, size_t ressize) {
char *result,
size_t ressize,
bool *ret_truncated) {
_cleanup_close_pair_ int outpipe[2] = {-1, -1}, errpipe[2] = {-1, -1}; _cleanup_close_pair_ int outpipe[2] = {-1, -1}, errpipe[2] = {-1, -1};
_cleanup_strv_free_ char **argv = NULL; _cleanup_strv_free_ char **argv = NULL;
char **envp = NULL; char **envp = NULL;
@ -863,9 +821,6 @@ int udev_event_spawn(
if (result) if (result)
result[spawn.result_len] = '\0'; result[spawn.result_len] = '\0';
if (ret_truncated)
*ret_truncated = spawn.truncated;
return r; /* 0 for success, and positive if the program failed */ return r; /* 0 for success, and positive if the program failed */
} }
@ -1140,7 +1095,7 @@ void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_s
log_device_debug(event->dev, "Running command \"%s\"", command); log_device_debug(event->dev, "Running command \"%s\"", command);
r = udev_event_spawn(event, timeout_usec, timeout_signal, false, command, NULL, 0, NULL); r = udev_event_spawn(event, timeout_usec, timeout_signal, false, command, NULL, 0);
if (r < 0) if (r < 0)
log_device_warning_errno(event->dev, r, "Failed to execute '%s', ignoring: %m", command); log_device_warning_errno(event->dev, r, "Failed to execute '%s', ignoring: %m", command);
else if (r > 0) /* returned value is positive when program fails */ else if (r > 0) /* returned value is positive when program fails */

View File

@ -56,8 +56,7 @@ size_t udev_event_apply_format(
const char *src, const char *src,
char *dest, char *dest,
size_t size, size_t size,
bool replace_whitespace, bool replace_whitespace);
bool *ret_truncated);
int udev_check_format(const char *value, size_t *offset, const char **hint); int udev_check_format(const char *value, size_t *offset, const char **hint);
int udev_event_spawn( int udev_event_spawn(
UdevEvent *event, UdevEvent *event,
@ -66,8 +65,7 @@ int udev_event_spawn(
bool accept_failure, bool accept_failure,
const char *cmd, const char *cmd,
char *result, char *result,
size_t ressize, size_t ressize);
bool *ret_truncated);
int udev_event_execute_rules( int udev_event_execute_rules(
UdevEvent *event, UdevEvent *event,
int inotify_fd, int inotify_fd,

View File

@ -1381,14 +1381,11 @@ static bool token_match_string(UdevRuleToken *token, const char *str) {
return token->op == (match ? OP_MATCH : OP_NOMATCH); return token->op == (match ? OP_MATCH : OP_NOMATCH);
} }
static bool token_match_attr(UdevRules *rules, UdevRuleToken *token, sd_device *dev, UdevEvent *event) { static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *event) {
char nbuf[UDEV_NAME_SIZE], vbuf[UDEV_NAME_SIZE]; char nbuf[UDEV_NAME_SIZE], vbuf[UDEV_NAME_SIZE];
const char *name, *value; const char *name, *value;
bool truncated;
assert(rules);
assert(token); assert(token);
assert(IN_SET(token->type, TK_M_ATTR, TK_M_PARENTS_ATTR));
assert(dev); assert(dev);
assert(event); assert(event);
@ -1396,15 +1393,7 @@ static bool token_match_attr(UdevRules *rules, UdevRuleToken *token, sd_device *
switch (token->attr_subst_type) { switch (token->attr_subst_type) {
case SUBST_TYPE_FORMAT: case SUBST_TYPE_FORMAT:
(void) udev_event_apply_format(event, name, nbuf, sizeof(nbuf), false, &truncated); (void) udev_event_apply_format(event, name, nbuf, sizeof(nbuf), false);
if (truncated) {
log_rule_debug(dev, rules,
"The sysfs attribute name '%s' is truncated while substituting into '%s', "
"assuming the %s key does not match.", nbuf, name,
token->type == TK_M_ATTR ? "ATTR" : "ATTRS");
return false;
}
name = nbuf; name = nbuf;
_fallthrough_; _fallthrough_;
case SUBST_TYPE_PLAIN: case SUBST_TYPE_PLAIN:
@ -1508,22 +1497,19 @@ static int attr_subst_subdir(char attr[static UDEV_PATH_SIZE]) {
char buf[UDEV_PATH_SIZE], *p; char buf[UDEV_PATH_SIZE], *p;
const char *tail; const char *tail;
size_t len, size; size_t len, size;
bool truncated;
assert(attr); assert(attr);
tail = strstr(attr, "/*/"); tail = strstr(attr, "/*/");
if (!tail) if (!tail)
return 0; return 0;
len = tail - attr + 1; /* include slash at the end */ len = tail - attr + 1; /* include slash at the end */
tail += 2; /* include slash at the beginning */ tail += 2; /* include slash at the beginning */
p = buf; p = buf;
size = sizeof(buf); size = sizeof(buf);
size -= strnpcpy_full(&p, size, attr, len, &truncated); size -= strnpcpy(&p, size, attr, len);
if (truncated)
return -ENOENT;
dir = opendir(buf); dir = opendir(buf);
if (!dir) if (!dir)
@ -1533,10 +1519,7 @@ static int attr_subst_subdir(char attr[static UDEV_PATH_SIZE]) {
if (de->d_name[0] == '.') if (de->d_name[0] == '.')
continue; continue;
strscpyl_full(p, size, &truncated, de->d_name, tail, NULL); strscpyl(p, size, de->d_name, tail, NULL);
if (truncated)
continue;
if (faccessat(dirfd(dir), p, F_OK, 0) < 0) if (faccessat(dirfd(dir), p, F_OK, 0) < 0)
continue; continue;
@ -1662,19 +1645,12 @@ static int udev_rule_apply_token_to_event(
} }
case TK_M_ATTR: case TK_M_ATTR:
case TK_M_PARENTS_ATTR: case TK_M_PARENTS_ATTR:
return token_match_attr(rules, token, dev, event); return token_match_attr(token, dev, event);
case TK_M_SYSCTL: { case TK_M_SYSCTL: {
_cleanup_free_ char *value = NULL; _cleanup_free_ char *value = NULL;
char buf[UDEV_PATH_SIZE]; char buf[UDEV_PATH_SIZE];
bool truncated;
(void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_rule_debug(dev, rules, "The sysctl entry name '%s' is truncated while substituting into '%s', "
"assuming the SYSCTL key does not match.", buf, (const char*) token->data);
return false;
}
(void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false);
r = sysctl_read(sysctl_normalize(buf), &value); r = sysctl_read(sysctl_normalize(buf), &value);
if (r < 0 && r != -ENOENT) if (r < 0 && r != -ENOENT)
return log_rule_error_errno(dev, rules, r, "Failed to read sysctl '%s': %m", buf); return log_rule_error_errno(dev, rules, r, "Failed to read sysctl '%s': %m", buf);
@ -1685,15 +1661,9 @@ static int udev_rule_apply_token_to_event(
mode_t mode = PTR_TO_MODE(token->data); mode_t mode = PTR_TO_MODE(token->data);
char buf[UDEV_PATH_SIZE]; char buf[UDEV_PATH_SIZE];
struct stat statbuf; struct stat statbuf;
bool match, truncated; bool match;
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_rule_debug(dev, rules, "The file name '%s' is truncated while substituting into '%s', "
"assuming the TEST key does not match", buf, token->value);
return false;
}
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
if (!path_is_absolute(buf) && if (!path_is_absolute(buf) &&
udev_resolve_subsys_kernel(buf, buf, sizeof(buf), false) < 0) { udev_resolve_subsys_kernel(buf, buf, sizeof(buf), false) < 0) {
char tmp[UDEV_PATH_SIZE]; char tmp[UDEV_PATH_SIZE];
@ -1703,11 +1673,8 @@ static int udev_rule_apply_token_to_event(
if (r < 0) if (r < 0)
return log_rule_error_errno(dev, rules, r, "Failed to get syspath: %m"); return log_rule_error_errno(dev, rules, r, "Failed to get syspath: %m");
strscpy_full(tmp, sizeof(tmp), buf, &truncated); strscpy(tmp, sizeof(tmp), buf);
assert(!truncated); strscpyl(buf, sizeof(buf), val, "/", tmp, NULL);
strscpyl_full(buf, sizeof(buf), &truncated, val, "/", tmp, NULL);
if (truncated)
return false;
} }
r = attr_subst_subdir(buf); r = attr_subst_subdir(buf);
@ -1727,20 +1694,13 @@ static int udev_rule_apply_token_to_event(
} }
case TK_M_PROGRAM: { case TK_M_PROGRAM: {
char buf[UDEV_PATH_SIZE], result[UDEV_LINE_SIZE]; char buf[UDEV_PATH_SIZE], result[UDEV_LINE_SIZE];
bool truncated;
size_t count; size_t count;
event->program_result = mfree(event->program_result); event->program_result = mfree(event->program_result);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
if (truncated) {
log_rule_debug(dev, rules, "The command '%s' is truncated while substituting into '%s', "
"assuming the PROGRAM key does not match.", buf, token->value);
return false;
}
log_rule_debug(dev, rules, "Running PROGRAM '%s'", buf); log_rule_debug(dev, rules, "Running PROGRAM '%s'", buf);
r = udev_event_spawn(event, timeout_usec, timeout_signal, true, buf, result, sizeof(result), NULL); r = udev_event_spawn(event, timeout_usec, timeout_signal, true, buf, result, sizeof(result));
if (r != 0) { if (r != 0) {
if (r < 0) if (r < 0)
log_rule_warning_errno(dev, rules, r, "Failed to execute \"%s\": %m", buf); log_rule_warning_errno(dev, rules, r, "Failed to execute \"%s\": %m", buf);
@ -1761,15 +1721,8 @@ static int udev_rule_apply_token_to_event(
case TK_M_IMPORT_FILE: { case TK_M_IMPORT_FILE: {
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
char buf[UDEV_PATH_SIZE]; char buf[UDEV_PATH_SIZE];
bool truncated;
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_rule_debug(dev, rules, "The file name '%s' to be imported is truncated while substituting into '%s', "
"assuming the IMPORT key does not match.", buf, token->value);
return false;
}
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
log_rule_debug(dev, rules, "Importing properties from '%s'", buf); log_rule_debug(dev, rules, "Importing properties from '%s'", buf);
f = fopen(buf, "re"); f = fopen(buf, "re");
@ -1815,18 +1768,11 @@ static int udev_rule_apply_token_to_event(
case TK_M_IMPORT_PROGRAM: { case TK_M_IMPORT_PROGRAM: {
_cleanup_strv_free_ char **lines = NULL; _cleanup_strv_free_ char **lines = NULL;
char buf[UDEV_PATH_SIZE], result[UDEV_LINE_SIZE], **line; char buf[UDEV_PATH_SIZE], result[UDEV_LINE_SIZE], **line;
bool truncated;
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_rule_debug(dev, rules, "The command '%s' is truncated while substituting into '%s', "
"assuming the IMPORT key does not match.", buf, token->value);
return false;
}
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
log_rule_debug(dev, rules, "Importing properties from results of '%s'", buf); log_rule_debug(dev, rules, "Importing properties from results of '%s'", buf);
r = udev_event_spawn(event, timeout_usec, timeout_signal, true, buf, result, sizeof result, &truncated); r = udev_event_spawn(event, timeout_usec, timeout_signal, true, buf, result, sizeof result);
if (r != 0) { if (r != 0) {
if (r < 0) if (r < 0)
log_rule_warning_errno(dev, rules, r, "Failed to execute '%s', ignoring: %m", buf); log_rule_warning_errno(dev, rules, r, "Failed to execute '%s', ignoring: %m", buf);
@ -1835,26 +1781,10 @@ static int udev_rule_apply_token_to_event(
return token->op == OP_NOMATCH; return token->op == OP_NOMATCH;
} }
if (truncated) {
bool found = false;
/* Drop the last line. */
for (char *p = buf + strlen(buf) - 1; p >= buf; p--)
if (strchr(NEWLINE, *p)) {
*p = '\0';
found = true;
} else if (found)
break;
}
r = strv_split_newlines_full(&lines, result, EXTRACT_RETAIN_ESCAPE); r = strv_split_newlines_full(&lines, result, EXTRACT_RETAIN_ESCAPE);
if (r == -ENOMEM) if (r < 0)
return log_oom();
if (r < 0) {
log_rule_warning_errno(dev, rules, r, log_rule_warning_errno(dev, rules, r,
"Failed to extract lines from result of command \"%s\", ignoring: %m", buf); "Failed to extract lines from result of command \"%s\", ignoring: %m", buf);
return false;
}
STRV_FOREACH(line, lines) { STRV_FOREACH(line, lines) {
char *key, *value; char *key, *value;
@ -1883,7 +1813,6 @@ static int udev_rule_apply_token_to_event(
assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX); assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX);
unsigned mask = 1U << (int) cmd; unsigned mask = 1U << (int) cmd;
char buf[UDEV_PATH_SIZE]; char buf[UDEV_PATH_SIZE];
bool truncated;
if (udev_builtin_run_once(cmd)) { if (udev_builtin_run_once(cmd)) {
/* check if we ran already */ /* check if we ran already */
@ -1897,13 +1826,7 @@ static int udev_rule_apply_token_to_event(
event->builtin_run |= mask; event->builtin_run |= mask;
} }
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
if (truncated) {
log_rule_debug(dev, rules, "The builtin command '%s' is truncated while substituting into '%s', "
"assuming the IMPORT key does not match", buf, token->value);
return false;
}
log_rule_debug(dev, rules, "Importing properties from results of builtin command '%s'", buf); log_rule_debug(dev, rules, "Importing properties from results of builtin command '%s'", buf);
r = udev_builtin_run(dev, &event->rtnl, cmd, buf, false); r = udev_builtin_run(dev, &event->rtnl, cmd, buf, false);
@ -1952,15 +1875,8 @@ static int udev_rule_apply_token_to_event(
} }
case TK_M_IMPORT_PARENT: { case TK_M_IMPORT_PARENT: {
char buf[UDEV_PATH_SIZE]; char buf[UDEV_PATH_SIZE];
bool truncated;
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_rule_debug(dev, rules, "The property name '%s' is truncated while substituting into '%s', "
"assuming the IMPORT key does not match.", buf, token->value);
return false;
}
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
r = import_parent_into_properties(dev, buf); r = import_parent_into_properties(dev, buf);
if (r < 0) if (r < 0)
return log_rule_error_errno(dev, rules, r, return log_rule_error_errno(dev, rules, r,
@ -2009,20 +1925,13 @@ static int udev_rule_apply_token_to_event(
case TK_A_OWNER: { case TK_A_OWNER: {
char owner[UDEV_NAME_SIZE]; char owner[UDEV_NAME_SIZE];
const char *ow = owner; const char *ow = owner;
bool truncated;
if (event->owner_final) if (event->owner_final)
break; break;
if (token->op == OP_ASSIGN_FINAL) if (token->op == OP_ASSIGN_FINAL)
event->owner_final = true; event->owner_final = true;
(void) udev_event_apply_format(event, token->value, owner, sizeof(owner), false, &truncated); (void) udev_event_apply_format(event, token->value, owner, sizeof(owner), false);
if (truncated) {
log_rule_warning(dev, rules, "The user name '%s' is truncated while substituting into '%s', "
"refusing to apply the OWNER key.", owner, token->value);
break;
}
r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
if (r < 0) if (r < 0)
log_unknown_owner(dev, rules, r, "user", owner); log_unknown_owner(dev, rules, r, "user", owner);
@ -2033,20 +1942,13 @@ static int udev_rule_apply_token_to_event(
case TK_A_GROUP: { case TK_A_GROUP: {
char group[UDEV_NAME_SIZE]; char group[UDEV_NAME_SIZE];
const char *gr = group; const char *gr = group;
bool truncated;
if (event->group_final) if (event->group_final)
break; break;
if (token->op == OP_ASSIGN_FINAL) if (token->op == OP_ASSIGN_FINAL)
event->group_final = true; event->group_final = true;
(void) udev_event_apply_format(event, token->value, group, sizeof(group), false, &truncated); (void) udev_event_apply_format(event, token->value, group, sizeof(group), false);
if (truncated) {
log_rule_warning(dev, rules, "The group name '%s' is truncated while substituting into '%s', "
"refusing to apply the GROUP key.", group, token->value);
break;
}
r = get_group_creds(&gr, &event->gid, USER_CREDS_ALLOW_MISSING); r = get_group_creds(&gr, &event->gid, USER_CREDS_ALLOW_MISSING);
if (r < 0) if (r < 0)
log_unknown_owner(dev, rules, r, "group", group); log_unknown_owner(dev, rules, r, "group", group);
@ -2056,20 +1958,13 @@ static int udev_rule_apply_token_to_event(
} }
case TK_A_MODE: { case TK_A_MODE: {
char mode_str[UDEV_NAME_SIZE]; char mode_str[UDEV_NAME_SIZE];
bool truncated;
if (event->mode_final) if (event->mode_final)
break; break;
if (token->op == OP_ASSIGN_FINAL) if (token->op == OP_ASSIGN_FINAL)
event->mode_final = true; event->mode_final = true;
(void) udev_event_apply_format(event, token->value, mode_str, sizeof(mode_str), false, &truncated); (void) udev_event_apply_format(event, token->value, mode_str, sizeof(mode_str), false);
if (truncated) {
log_rule_warning(dev, rules, "The mode '%s' is truncated while substituting into %s, "
"refusing to apply the MODE key.", mode_str, token->value);
break;
}
r = parse_mode(mode_str, &event->mode); r = parse_mode(mode_str, &event->mode);
if (r < 0) if (r < 0)
log_rule_error_errno(dev, rules, r, "Failed to parse mode '%s', ignoring: %m", mode_str); log_rule_error_errno(dev, rules, r, "Failed to parse mode '%s', ignoring: %m", mode_str);
@ -2110,19 +2005,12 @@ static int udev_rule_apply_token_to_event(
case TK_A_SECLABEL: { case TK_A_SECLABEL: {
_cleanup_free_ char *name = NULL, *label = NULL; _cleanup_free_ char *name = NULL, *label = NULL;
char label_str[UDEV_LINE_SIZE] = {}; char label_str[UDEV_LINE_SIZE] = {};
bool truncated;
name = strdup(token->data); name = strdup(token->data);
if (!name) if (!name)
return log_oom(); return log_oom();
(void) udev_event_apply_format(event, token->value, label_str, sizeof(label_str), false, &truncated); (void) udev_event_apply_format(event, token->value, label_str, sizeof(label_str), false);
if (truncated) {
log_rule_warning(dev, rules, "The security label '%s' is truncated while substituting into '%s', "
"refusing to apply the SECLABEL key.", label_str, token->value);
break;
}
if (!isempty(label_str)) if (!isempty(label_str))
label = strdup(label_str); label = strdup(label_str);
else else
@ -2149,7 +2037,6 @@ static int udev_rule_apply_token_to_event(
const char *val, *name = token->data; const char *val, *name = token->data;
char value_new[UDEV_NAME_SIZE], *p = value_new; char value_new[UDEV_NAME_SIZE], *p = value_new;
size_t count, l = sizeof(value_new); size_t count, l = sizeof(value_new);
bool truncated;
if (isempty(token->value)) { if (isempty(token->value)) {
if (token->op == OP_ADD) if (token->op == OP_ADD)
@ -2161,22 +2048,10 @@ static int udev_rule_apply_token_to_event(
} }
if (token->op == OP_ADD && if (token->op == OP_ADD &&
sd_device_get_property_value(dev, name, &val) >= 0) { sd_device_get_property_value(dev, name, &val) >= 0)
l = strpcpyl_full(&p, l, &truncated, val, " ", NULL); l = strpcpyl(&p, l, val, " ", NULL);
if (truncated) {
log_rule_warning(dev, rules, "The buffer for the property '%s' is full, "
"refusing to append the new value '%s'.", name, token->value);
break;
}
}
(void) udev_event_apply_format(event, token->value, p, l, false, &truncated);
if (truncated) {
log_rule_warning(dev, rules, "The property value '%s' is truncated while substituting into '%s', "
"refusing to add property '%s'.", p, token->value, name);
break;
}
(void) udev_event_apply_format(event, token->value, p, l, false);
if (event->esc == ESCAPE_REPLACE) { if (event->esc == ESCAPE_REPLACE) {
count = udev_replace_chars(p, NULL); count = udev_replace_chars(p, NULL);
if (count > 0) if (count > 0)
@ -2191,16 +2066,8 @@ static int udev_rule_apply_token_to_event(
} }
case TK_A_TAG: { case TK_A_TAG: {
char buf[UDEV_PATH_SIZE]; char buf[UDEV_PATH_SIZE];
bool truncated;
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_rule_warning(dev, rules, "The tag name '%s' is truncated while substituting into '%s',"
"refusing to %s the tag.", buf, token->value,
token->op == OP_REMOVE ? "remove" : "add");
break;
}
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
if (token->op == OP_ASSIGN) if (token->op == OP_ASSIGN)
device_cleanup_tags(dev); device_cleanup_tags(dev);
@ -2219,7 +2086,6 @@ static int udev_rule_apply_token_to_event(
} }
case TK_A_NAME: { case TK_A_NAME: {
char buf[UDEV_PATH_SIZE]; char buf[UDEV_PATH_SIZE];
bool truncated;
size_t count; size_t count;
if (event->name_final) if (event->name_final)
@ -2234,13 +2100,7 @@ static int udev_rule_apply_token_to_event(
break; break;
} }
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
if (truncated) {
log_rule_warning(dev, rules, "The network interface name '%s' is truncated while substituting into '%s', "
"refusing to set the name.", buf, token->value);
break;
}
if (IN_SET(event->esc, ESCAPE_UNSET, ESCAPE_REPLACE)) { if (IN_SET(event->esc, ESCAPE_UNSET, ESCAPE_REPLACE)) {
if (naming_scheme_has(NAMING_REPLACE_STRICTLY)) if (naming_scheme_has(NAMING_REPLACE_STRICTLY))
count = udev_replace_ifname(buf); count = udev_replace_ifname(buf);
@ -2259,7 +2119,6 @@ static int udev_rule_apply_token_to_event(
} }
case TK_A_DEVLINK: { case TK_A_DEVLINK: {
char buf[UDEV_PATH_SIZE], *p; char buf[UDEV_PATH_SIZE], *p;
bool truncated;
size_t count; size_t count;
if (event->devlink_final) if (event->devlink_final)
@ -2272,13 +2131,7 @@ static int udev_rule_apply_token_to_event(
device_cleanup_devlinks(dev); device_cleanup_devlinks(dev);
/* allow multiple symlinks separated by spaces */ /* allow multiple symlinks separated by spaces */
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), event->esc != ESCAPE_NONE, &truncated); (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), event->esc != ESCAPE_NONE);
if (truncated) {
log_rule_warning(dev, rules, "The symbolic link path '%s' is truncated while substituting into '%s', "
"refusing to add the device symbolic link.", buf, token->value);
break;
}
if (event->esc == ESCAPE_UNSET) if (event->esc == ESCAPE_UNSET)
count = udev_replace_chars(buf, "/ "); count = udev_replace_chars(buf, "/ ");
else if (event->esc == ESCAPE_REPLACE) else if (event->esc == ESCAPE_REPLACE)
@ -2299,10 +2152,7 @@ static int udev_rule_apply_token_to_event(
next = skip_leading_chars(next, NULL); next = skip_leading_chars(next, NULL);
} }
strscpyl_full(filename, sizeof(filename), &truncated, "/dev/", p, NULL); strscpyl(filename, sizeof(filename), "/dev/", p, NULL);
if (truncated)
continue;
r = device_add_devlink(dev, filename); r = device_add_devlink(dev, filename);
if (r < 0) if (r < 0)
return log_rule_error_errno(dev, rules, r, "Failed to add devlink '%s': %m", filename); return log_rule_error_errno(dev, rules, r, "Failed to add devlink '%s': %m", filename);
@ -2315,30 +2165,17 @@ static int udev_rule_apply_token_to_event(
case TK_A_ATTR: { case TK_A_ATTR: {
char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE]; char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE];
const char *val, *key_name = token->data; const char *val, *key_name = token->data;
bool truncated;
if (udev_resolve_subsys_kernel(key_name, buf, sizeof(buf), false) < 0 && if (udev_resolve_subsys_kernel(key_name, buf, sizeof(buf), false) < 0 &&
sd_device_get_syspath(dev, &val) >= 0) { sd_device_get_syspath(dev, &val) >= 0)
strscpyl_full(buf, sizeof(buf), &truncated, val, "/", key_name, NULL); strscpyl(buf, sizeof(buf), val, "/", key_name, NULL);
if (truncated) {
log_rule_warning(dev, rules,
"The path to the attribute '%s/%s' is too long, refusing to set the attribute.",
val, key_name);
break;
}
}
r = attr_subst_subdir(buf); r = attr_subst_subdir(buf);
if (r < 0) { if (r < 0) {
log_rule_error_errno(dev, rules, r, "Could not find file matches '%s', ignoring: %m", buf); log_rule_error_errno(dev, rules, r, "Could not find file matches '%s', ignoring: %m", buf);
break; break;
} }
(void) udev_event_apply_format(event, token->value, value, sizeof(value), false, &truncated); (void) udev_event_apply_format(event, token->value, value, sizeof(value), false);
if (truncated) {
log_rule_warning(dev, rules, "The attribute value '%s' is truncated while substituting into '%s', "
"refusing to set the attribute '%s'", value, token->value, buf);
break;
}
log_rule_debug(dev, rules, "ATTR '%s' writing '%s'", buf, value); log_rule_debug(dev, rules, "ATTR '%s' writing '%s'", buf, value);
r = write_string_file(buf, value, r = write_string_file(buf, value,
@ -2352,22 +2189,9 @@ static int udev_rule_apply_token_to_event(
} }
case TK_A_SYSCTL: { case TK_A_SYSCTL: {
char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE]; char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE];
bool truncated;
(void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, &truncated);
if (truncated) {
log_rule_warning(dev, rules, "The sysctl entry name '%s' is truncated while substituting into '%s', "
"refusing to set the sysctl entry.", buf, (const char*) token->data);
break;
}
(void) udev_event_apply_format(event, token->value, value, sizeof(value), false, &truncated);
if (truncated) {
log_rule_warning(dev, rules, "The sysctl value '%s' is truncated while substituting into '%s', "
"refusing to set the sysctl entry '%s'", value, token->value, buf);
break;
}
(void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false);
(void) udev_event_apply_format(event, token->value, value, sizeof(value), false);
sysctl_normalize(buf); sysctl_normalize(buf);
log_rule_debug(dev, rules, "SYSCTL '%s' writing '%s'", buf, value); log_rule_debug(dev, rules, "SYSCTL '%s' writing '%s'", buf, value);
r = sysctl_write(buf, value); r = sysctl_write(buf, value);
@ -2379,7 +2203,6 @@ static int udev_rule_apply_token_to_event(
case TK_A_RUN_PROGRAM: { case TK_A_RUN_PROGRAM: {
_cleanup_free_ char *cmd = NULL; _cleanup_free_ char *cmd = NULL;
char buf[UDEV_PATH_SIZE]; char buf[UDEV_PATH_SIZE];
bool truncated;
if (event->run_final) if (event->run_final)
break; break;
@ -2389,12 +2212,7 @@ static int udev_rule_apply_token_to_event(
if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL)) if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL))
ordered_hashmap_clear_free_key(event->run_list); ordered_hashmap_clear_free_key(event->run_list);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated); (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
if (truncated) {
log_rule_warning(dev, rules, "The command '%s' is truncated while substituting into '%s', "
"refusing to invoke the command.", buf, token->value);
break;
}
cmd = strdup(buf); cmd = strdup(buf);
if (!cmd) if (!cmd)

View File

@ -87,11 +87,6 @@ int control_main(int argc, char *argv[], void *userdata) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to initialize udev control: %m"); return log_error_errno(r, "Failed to initialize udev control: %m");
/* See comments in on_post() in udevd.c. */
r = udev_ctrl_send_pid(uctrl);
if (r < 0)
return log_error_errno(r, "Failed to send pid of this process: %m");
while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0) while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0)
switch (c) { switch (c) {
case 'e': case 'e':

View File

@ -135,11 +135,8 @@ int test_main(int argc, char *argv[], void *userdata) {
ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list) { ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list) {
char program[UDEV_PATH_SIZE]; char program[UDEV_PATH_SIZE];
bool truncated;
(void) udev_event_apply_format(event, cmd, program, sizeof(program), false, &truncated); (void) udev_event_apply_format(event, cmd, program, sizeof(program), false);
if (truncated)
log_warning("The command '%s' is truncated while substituting into '%s'.", program, cmd);
printf("run: '%s'\n", program); printf("run: '%s'\n", program);
} }

View File

@ -108,8 +108,6 @@ typedef struct Manager {
bool stop_exec_queue; bool stop_exec_queue;
bool exit; bool exit;
pid_t pid_udevadm; /* pid of 'udevadm control' */
} Manager; } Manager;
typedef enum EventState { typedef enum EventState {
@ -1217,10 +1215,6 @@ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrl
log_debug("Received udev control message (EXIT)"); log_debug("Received udev control message (EXIT)");
manager_exit(manager); manager_exit(manager);
break; break;
case UDEV_CTRL_SENDER_PID:
log_debug("Received udev control message (SENDER_PID)");
manager->pid_udevadm = value->pid;
break;
default: default:
log_debug("Received unknown udev control message, ignoring"); log_debug("Received unknown udev control message, ignoring");
} }
@ -1496,35 +1490,9 @@ static int on_post(sd_event_source *s, void *userdata) {
if (manager->exit) if (manager->exit)
return sd_event_exit(manager->event, 0); return sd_event_exit(manager->event, 0);
if (!manager->cgroup) if (manager->cgroup)
return 1; /* cleanup possible left-over processes in our cgroup */
(void) cg_kill(SYSTEMD_CGROUP_CONTROLLER, manager->cgroup, SIGKILL, CGROUP_IGNORE_SELF, NULL, NULL, NULL);
/* Cleanup possible left-over processes in our cgroup. But do not kill udevadm called by
* ExecReload= in systemd-udevd.service. See #16867. To protect it, the following two ways are
* introduced:
*
* 1. After the connection is accepted, but the PID of udevadm is not received, do not call
* cg_kill(). So, in this period, unwanted process or threads may exist in our cgroup.
* But, it is expected that the PID of the udevadm will be received soon. So, this time
* period should be short enough.
* 2. After the PID of udevadm is received, check the process is active or not, and if it is
* still active, set the PID to the deny list for cg_kill(). Why udev_ctrl_is_connected() is
* not enough? Because the udevadm may be still active after the control socket is
* disconnected. If the process is not active, then clear the PID for later connections.
*/
if (udev_ctrl_is_connected(manager->ctrl) >= 0 && !pid_is_valid(manager->pid_udevadm))
return 1;
_cleanup_set_free_ Set *pids = NULL;
if (pid_is_valid(manager->pid_udevadm)) {
if (pid_is_alive(manager->pid_udevadm))
(void) set_ensure_put(&pids, NULL, PID_TO_PTR(manager->pid_udevadm));
else
manager->pid_udevadm = 0;
}
(void) cg_kill(SYSTEMD_CGROUP_CONTROLLER, manager->cgroup, SIGKILL, CGROUP_IGNORE_SELF, pids, NULL, NULL);
return 1; return 1;
} }

View File

@ -1 +0,0 @@
../TEST-01-BASIC/Makefile

View File

@ -1,11 +0,0 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -e
TEST_DESCRIPTION="Test propagation of exit status to On{Failure,Success}= dependencies"
TEST_NO_QEMU=1
# shellcheck source=test/test-functions
. "$TEST_BASE_DIR/test-functions"
do_test "$@"

View File

@ -1932,9 +1932,11 @@ inst_libs() {
while read -r line; do while read -r line; do
[[ "$line" = 'not a dynamic executable' ]] && break [[ "$line" = 'not a dynamic executable' ]] && break
# Ignore errors about our own stuff missing. This is most likely caused # Skip a harmless error when running the tests on a system with a significantly
# by ldd attempting to use the unprefixed RPATH. # older systemd version (ldd tries to resolve the unprefixed RPATH for libsystemd.so.0,
[[ "$line" =~ libsystemd.*\ not\ found ]] && continue # which is in this case older than the already installed libsystemd.so.0 in $initdir).
# The issue is triggered by installing test dependencies in install_missing_libraries().
[[ "$line" =~ libsystemd.so.*:\ version\ .*\ not\ found ]] && continue
if [[ "$line" =~ $so_regex ]]; then if [[ "$line" =~ $so_regex ]]; then
file="${BASH_REMATCH[1]}" file="${BASH_REMATCH[1]}"
@ -2307,7 +2309,7 @@ inst_binary() {
# In certain cases we might attempt to install a binary which is already # In certain cases we might attempt to install a binary which is already
# present in the test image, yet it's missing from the host system. # present in the test image, yet it's missing from the host system.
# In such cases, let's check if the binary indeed exists in the image # In such cases, let's check if the binary indeed exists in the image
# before doing any other checks. If it does, immediately return with # before doing any other chcecks. If it does, immediately return with
# success. # success.
if [[ $# -eq 1 ]]; then if [[ $# -eq 1 ]]; then
for path in "" bin sbin usr/bin usr/sbin; do for path in "" bin sbin usr/bin usr/sbin; do
@ -2326,10 +2328,6 @@ inst_binary() {
while read -r line; do while read -r line; do
[[ "$line" = 'not a dynamic executable' ]] && break [[ "$line" = 'not a dynamic executable' ]] && break
# Ignore errors about our own stuff missing. This is most likely caused
# by ldd attempting to use the unprefixed RPATH.
[[ "$line" =~ libsystemd.*\ not\ found ]] && continue
if [[ "$line" =~ $so_regex ]]; then if [[ "$line" =~ $so_regex ]]; then
file="${BASH_REMATCH[1]}" file="${BASH_REMATCH[1]}"
[[ -e "${initdir}/$file" ]] && continue [[ -e "${initdir}/$file" ]] && continue

View File

@ -1,9 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[NetDev]
Name=ip6tnl-slaac
Kind=ip6tnl
[Tunnel]
Mode=ip6ip6
Local=slaac
Remote=2001:473:fece:cafe::5179

View File

@ -1,10 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Match]
Name=ip6tnl-slaac
[Network]
IPv6AcceptRA=no
LinkLocalAddressing=yes
[Route]
Destination=0.0.0.0/0

View File

@ -1,10 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Match]
Name=veth99
[Network]
IPv6AcceptRA=yes
Tunnel=ip6tnl-slaac
[IPv6AcceptRA]
PrefixAllowList=2002:da8:1::/64

View File

@ -900,7 +900,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'ip6gretun97', 'ip6gretun97',
'ip6gretun98', 'ip6gretun98',
'ip6gretun99', 'ip6gretun99',
'ip6tnl-slaac',
'ip6tnl97', 'ip6tnl97',
'ip6tnl98', 'ip6tnl98',
'ip6tnl99', 'ip6tnl99',
@ -987,8 +986,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-ip6gre-tunnel.netdev', '25-ip6gre-tunnel.netdev',
'25-ip6tnl-tunnel-any-any.netdev', '25-ip6tnl-tunnel-any-any.netdev',
'25-ip6tnl-tunnel-local-any.netdev', '25-ip6tnl-tunnel-local-any.netdev',
'25-ip6tnl-tunnel-local-slaac.netdev',
'25-ip6tnl-tunnel-local-slaac.network',
'25-ip6tnl-tunnel-remote-any.netdev', '25-ip6tnl-tunnel-remote-any.netdev',
'25-ip6tnl-tunnel.netdev', '25-ip6tnl-tunnel.netdev',
'25-ipip-tunnel-any-any.netdev', '25-ipip-tunnel-any-any.netdev',
@ -1047,10 +1044,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'gretun.network', 'gretun.network',
'ip6gretap.network', 'ip6gretap.network',
'ip6gretun.network', 'ip6gretun.network',
'ip6tnl-slaac.network',
'ip6tnl.network', 'ip6tnl.network',
'ipip.network', 'ipip.network',
'ipv6-prefix.network',
'ipvlan.network', 'ipvlan.network',
'ipvtap.network', 'ipvtap.network',
'isatap.network', 'isatap.network',
@ -1669,33 +1664,19 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network', copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
'25-ip6tnl-tunnel.netdev', '25-tunnel.network', '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
'25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network', '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
'25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
'25-veth.netdev', 'ip6tnl-slaac.network', 'ipv6-prefix.network',
'25-ip6tnl-tunnel-local-slaac.netdev', '25-ip6tnl-tunnel-local-slaac.network')
start_networkd() start_networkd()
self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'ip6tnl-slaac:degraded', self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
'dummy98:degraded', 'veth99:routable', 'veth-peer:degraded'])
output = check_output('ip -d link show ip6tnl99') output = check_output('ip -d link show ip6tnl99')
print(output) print(output)
self.assertIn('ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98', output) self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
output = check_output('ip -d link show ip6tnl98') output = check_output('ip -d link show ip6tnl98')
print(output) print(output)
self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98') self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
output = check_output('ip -d link show ip6tnl97') output = check_output('ip -d link show ip6tnl97')
print(output) print(output)
self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98') self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
output = check_output('ip -d link show ip6tnl-slaac')
print(output)
self.assertIn('ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2002:da8:1:0:1034:56ff:fe78:9abc dev veth99', output)
output = check_output('ip -6 address show veth99')
print(output)
self.assertIn('inet6 2002:da8:1:0:1034:56ff:fe78:9abc/64 scope global dynamic', output)
output = check_output('ip -4 route show default')
print(output)
self.assertIn('default dev ip6tnl-slaac proto static', output)
def test_sit_tunnel(self): def test_sit_tunnel(self):
copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network', copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',

View File

@ -1,7 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Unit]
Description=TEST-68-PROPAGATE-EXIT-STATUS
[Service]
Type=oneshot
ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh

View File

@ -1,230 +0,0 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -ex
set -o pipefail
# Wait for a service to enter a state within a timeout period, if it doesn't
# enter the desired state within the timeout period then this function will
# exit the test case with a non zero exit code.
wait_on_state_or_fail () {
service=$1
expected_state=$2
timeout=$3
state=$(systemctl show "$service" --property=ActiveState --value)
while [ "$state" != "$expected_state" ]; do
if [ "$timeout" = "0" ]; then
systemd-analyze log-level info
exit 1
fi
timeout=$((timeout - 1))
sleep 1
state=$(systemctl show "$service" --property=ActiveState --value)
done
}
systemd-analyze log-level debug
systemd-analyze log-target console
# Trigger testservice-failure-exit-handler-68.service
cat >/run/systemd/system/testservice-failure-68.service <<EOF
[Unit]
Description=TEST-68-PROPAGATE-EXIT-STATUS with OnFailure= trigger
OnFailure=testservice-failure-exit-handler-68.service
[Service]
ExecStart=/bin/bash -c "exit 1"
EOF
# Another service which triggers testservice-failure-exit-handler-68.service
cat >/run/systemd/system/testservice-failure-68-additional.service <<EOF
[Unit]
Description=TEST-68-PROPAGATE-EXIT-STATUS Additional service with OnFailure= trigger
OnFailure=testservice-failure-exit-handler-68.service
[Service]
ExecStart=/bin/bash -c "exit 1"
EOF
# Trigger testservice-success-exit-handler-68.service
cat >/run/systemd/system/testservice-success-68.service <<EOF
[Unit]
Description=TEST-68-PROPAGATE-EXIT-STATUS with OnSuccess= trigger
OnSuccess=testservice-success-exit-handler-68.service
[Service]
ExecStart=/bin/bash -c "exit 0"
EOF
# Trigger testservice-success-exit-handler-68.service
cat >/run/systemd/system/testservice-success-68-additional.service <<EOF
[Unit]
Description=TEST-68-PROPAGATE-EXIT-STATUS Addition service with OnSuccess= trigger
OnSuccess=testservice-success-exit-handler-68.service
[Service]
ExecStart=/bin/bash -c "exit 0"
EOF
# Script to check that when an OnSuccess= dependency fires, the correct
# MONITOR* env variables are passed. This script handles the case where
# multiple services triggered the unit that calls this script. In this
# case we need to check the MONITOR_METADATA variable for >= 1 service
# details since jobs may merge.
cat >/tmp/check_on_success.sh <<EOF
#!/usr/bin/env bash
set -ex
echo "MONITOR_METADATA=\$MONITOR_METADATA"
IFS=';' read -ra ALL_SERVICE_MD <<< "\$MONITOR_METADATA"
for SERVICE_MD in "\${ALL_SERVICE_MD[@]}"; do
IFS=',' read -ra METADATA <<< "\$SERVICE_MD"
IFS='=' read -ra SERVICE_RESULT <<< "\${METADATA[0]}"
SERVICE_RESULT=\${SERVICE_RESULT[1]}
IFS='=' read -ra EXIT_CODE <<< "\${METADATA[1]}"
EXIT_CODE=\${EXIT_CODE[1]}
IFS='=' read -ra EXIT_STATUS <<< "\${METADATA[2]}"
EXIT_STATUS=\${EXIT_STATUS[1]}
IFS='=' read -ra INVOCATION_ID <<< "\${METADATA[3]}"
INVOCATION_ID=\${INVOCATION_ID[1]}
IFS='=' read -ra UNIT <<< "\${METADATA[4]}"
UNIT=\${UNIT[1]}
if [ "\$SERVICE_RESULT" != "success" ]; then
echo 'SERVICE_RESULT was "\$SERVICE_RESULT", expected "success"';
exit 1;
fi
if [ "\$EXIT_CODE" != "exited" ]; then
echo 'EXIT_CODE was "\$EXIT_CODE", expected "exited"';
exit 1;
fi
if [ "\$EXIT_STATUS" != "0" ]; then
echo 'EXIT_STATUS was "\$EXIT_STATUS", expected "0"';
exit 1;
fi
if [ -z "\$INVOCATION_ID" ]; then
echo 'INVOCATION_ID unset';
exit 1;
fi
if [[ "\$UNIT" != "testservice-success-68.service" && "\$UNIT" != "testservice-success-68-additional.service" && "\$UNIT" != "testservice-transient-success-68.service" ]]; then
echo 'UNIT was "\$UNIT", expected "testservice-success-68{-additional,-transient}.service"';
exit 1;
fi
done
exit 0;
EOF
chmod +x /tmp/check_on_success.sh
# Handle testservice-failure-exit-handler-68.service exiting with success.
cat >/run/systemd/system/testservice-success-exit-handler-68.service <<EOF
[Unit]
Description=TEST-68-PROPAGATE-EXIT-STATUS handle service exiting in success
[Service]
ExecStartPre=/tmp/check_on_success.sh
ExecStart=/tmp/check_on_success.sh
EOF
# Script to check that when an OnFailure= dependency fires, the correct
# MONITOR* env variables are passed. This script handles the case where
# multiple services triggered the unit that calls this script. In this
# case we need to check the MONITOR_METADATA variable for >=1 service
# details since jobs may merge.
cat >/tmp/check_on_failure.sh <<EOF
#!/usr/bin/env bash
set -ex
echo "MONITOR_METADATA=\$MONITOR_METADATA"
IFS=';' read -ra ALL_SERVICE_MD <<< "\$MONITOR_METADATA"
for SERVICE_MD in "\${ALL_SERVICE_MD[@]}"; do
IFS=',' read -ra METADATA <<< "\$SERVICE_MD"
IFS='=' read -ra SERVICE_RESULT <<< "\${METADATA[0]}"
SERVICE_RESULT=\${SERVICE_RESULT[1]}
IFS='=' read -ra EXIT_CODE <<< "\${METADATA[1]}"
EXIT_CODE=\${EXIT_CODE[1]}
IFS='=' read -ra EXIT_STATUS <<< "\${METADATA[2]}"
EXIT_STATUS=\${EXIT_STATUS[1]}
IFS='=' read -ra INVOCATION_ID <<< "\${METADATA[3]}"
INVOCATION_ID=\${INVOCATION_ID[1]}
IFS='=' read -ra UNIT <<< "\${METADATA[4]}"
UNIT=\${UNIT[1]}
if [ "\$SERVICE_RESULT" != "exit-code" ]; then
echo 'SERVICE_RESULT was "\$SERVICE_RESULT", expected "exit-code"';
exit 1;
fi
if [ "\$EXIT_CODE" != "exited" ]; then
echo 'EXIT_CODE was "\$EXIT_CODE", expected "exited"';
exit 1;
fi
if [ "\$EXIT_STATUS" != "1" ]; then
echo 'EXIT_STATUS was "\$EXIT_STATUS", expected "1"';
exit 1;
fi
if [ -z "\$INVOCATION_ID" ]; then
echo 'INVOCATION_ID unset';
exit 1;
fi
if [[ "\$UNIT" != "testservice-failure-68.service" && "\$UNIT" != "testservice-failure-68-additional.service" && "\$UNIT" != "testservice-transient-failure-68.service" ]]; then
echo 'UNIT was "\$UNIT", expected "testservice-failure-68{-additional,-transient}.service"';
exit 1;
fi
done
exit 0;
EOF
chmod +x /tmp/check_on_failure.sh
# Handle testservice-failure-exit-handler-68.service exiting with failure.
cat >/run/systemd/system/testservice-failure-exit-handler-68.service <<EOF
[Unit]
Description=TEST-68-PROPAGATE-EXIT-STATUS handle service exiting in failure
[Service]
ExecStartPre=/tmp/check_on_failure.sh
ExecStart=/tmp/check_on_failure.sh
EOF
systemctl daemon-reload
# The running of the OnFailure= and OnSuccess= jobs for all of these services
# may result in jobs being merged.
systemctl start testservice-failure-68.service
wait_on_state_or_fail "testservice-failure-exit-handler-68.service" "inactive" "10"
systemctl start testservice-failure-68-additional.service
wait_on_state_or_fail "testservice-failure-exit-handler-68.service" "inactive" "10"
systemctl start testservice-success-68.service
wait_on_state_or_fail "testservice-success-exit-handler-68.service" "inactive" "10"
systemctl start testservice-success-68-additional.service
wait_on_state_or_fail "testservice-success-exit-handler-68.service" "inactive" "10"
# Test some transient units since these exit very quickly.
systemd-run --unit=testservice-transient-success-68 --property=OnSuccess=testservice-success-exit-handler-68.service /bin/bash -c "exit 0;"
wait_on_state_or_fail "testservice-success-exit-handler-68.service" "inactive" "10"
systemd-run --unit=testservice-transient-failure-68 --property=OnFailure=testservice-failure-exit-handler-68.service /bin/bash -c "exit 1;"
wait_on_state_or_fail "testservice-failure-exit-handler-68.service" "inactive" "10"
# These yield a higher chance of resulting in jobs merging.
systemctl start testservice-failure-68.service testservice-failure-68-additional.service --no-block
wait_on_state_or_fail "testservice-failure-exit-handler-68.service" "inactive" "10"
systemctl start testservice-success-68.service testservice-success-68-additional.service --no-block
wait_on_state_or_fail "testservice-success-exit-handler-68.service" "inactive" "10"
systemd-analyze log-level info
echo OK >/testok
exit 0

View File

@ -12,7 +12,6 @@ L+ /etc/mtab - - - - ../proc/self/mounts
{% if HAVE_SMACK_RUN_LABEL %} {% if HAVE_SMACK_RUN_LABEL %}
t /etc/mtab - - - - security.SMACK64=_ t /etc/mtab - - - - security.SMACK64=_
{% endif %} {% endif %}
C! /etc/locale.conf - - - -
C! /etc/nsswitch.conf - - - - C! /etc/nsswitch.conf - - - -
{% if HAVE_PAM %} {% if HAVE_PAM %}
C! /etc/pam.d - - - - C! /etc/pam.d - - - -

View File

@ -67,9 +67,7 @@ df="$build/dns-fuzzing"
git clone --depth 1 https://github.com/CZ-NIC/dns-fuzzing "$df" git clone --depth 1 https://github.com/CZ-NIC/dns-fuzzing "$df"
zip -jqr "$OUT/fuzz-dns-packet_seed_corpus.zip" "$df/packet" zip -jqr "$OUT/fuzz-dns-packet_seed_corpus.zip" "$df/packet"
install -Dt "$OUT/src/shared/" \ install -Dt "$OUT/src/shared/" "$build"/src/shared/libsystemd-shared-*.so
"$build"/src/shared/libsystemd-shared-*.so \
"$build"/src/core/libsystemd-core-*.so
wget -O "$OUT/fuzz-json.dict" https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/json.dict wget -O "$OUT/fuzz-json.dict" https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/json.dict