diff options
73 files changed, 595 insertions, 385 deletions
diff --git a/.semaphore/semaphore-runner.sh b/.semaphore/semaphore-runner.sh index 6ccf271a82..ec95f65315 100755 --- a/.semaphore/semaphore-runner.sh +++ b/.semaphore/semaphore-runner.sh @@ -21,7 +21,7 @@ UBUNTU_RELEASE="$(lsb_release -cs)" create_container() { # Create autopkgtest LXC image; this sometimes fails with "Unable to fetch # GPG key from keyserver", so retry a few times with different keyservers. - for keyserver in "" "keys.gnupg.net" "keys.openpgp.org" "keyserver.ubuntu.com"; do + for keyserver in "keys.openpgp.org" "" "keyserver.ubuntu.com" "keys.gnupg.net"; do for retry in {1..5}; do sudo lxc-create -n "$CONTAINER" -t download -- -d "$DISTRO" -r "$RELEASE" -a "$ARCH" ${keyserver:+--keyserver "$keyserver"} && break 2 sleep $((retry*retry)) @@ -36,8 +36,16 @@ create_container() { # enable source repositories so that apt-get build-dep works sudo lxc-attach -n "$CONTAINER" -- sh -ex <<EOF sed 's/^deb/deb-src/' /etc/apt/sources.list >> /etc/apt/sources.list.d/sources.list -# wait until online -while [ -z "\$(ip route list 0/0)" ]; do sleep 1; done +# We might attach the console too soon +while ! systemctl --quiet --wait is-system-running; do sleep 1; done +# Manpages database trigger takes a lot of time and is not useful in a CI +echo 'man-db man-db/auto-update boolean false' | debconf-set-selections +# Speed up dpkg, image is thrown away after the test +mkdir -p /etc/dpkg/dpkg.cfg.d/ +echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/unsafe_io +# For some reason, it is necessary to run this manually or the interface won't be configured +# Note that we avoid networkd, as some of the tests will break it later on +dhclient apt-get -q --allow-releaseinfo-change update apt-get -y dist-upgrade apt-get install -y eatmydata @@ -88,6 +96,10 @@ EOF rm -rf debian/patches # disable autopkgtests which are not for upstream sed -i '/# NOUPSTREAM/ q' debian/tests/control + # TODO: rebooting via autopkgtest-reboot seems to be broken, disable these tests for now + sed -i -n '1,/Tests: boot-and-services/p;/Tests: udev/,$p' debian/tests/control + sed -i '/Tests: boot-and-services/d' debian/tests/control + sed -i '/Tests: boot-smoke/,$d' debian/tests/control # enable more unit tests sed -i '/^CONFFLAGS =/ s/=/= --werror -Dtests=unsafe -Dsplit-usr=true -Dslow-tests=true -Dfuzz-tests=true -Dman=true /' debian/rules # no orig tarball diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index bd5d135e9e..07742337e8 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -7,7 +7,7 @@ name: Debian autopkgtest (LXC) agent: machine: type: e1-standard-2 - os_image: ubuntu1804 + os_image: ubuntu2004 # Cancel any running or queued job for the same ref auto_cancel: @@ -30,14 +30,21 @@ LICENSE: LGPL-2.1-or-later for all code, exceptions noted in LICENSES/README.md REQUIREMENTS: - Linux kernel >= 3.15 - Linux kernel >= 4.2 for unified cgroup hierarchy support - Linux kernel >= 4.10 for cgroup-bpf egress and ingress hooks - Linux kernel >= 4.15 for cgroup-bpf device hook - Linux kernel >= 4.17 for cgroup-bpf socket address hooks - Linux kernel >= 5.3 for bounded-loops in BPF program - Linux kernel >= 5.4 for signed Verity images support - Linux kernel >= 5.7 for BPF links and the BPF LSM hook + Linux kernel ≥ 3.15 + ≥ 4.5 for pids controller in cgroup v2 + ≥ 4.6 for cgroup namespaces + ≥ 4.9 for RENAME_NOREPLACE support in vfat + ≥ 4.10 for cgroup-bpf egress and ingress hooks + ≥ 4.15 for cgroup-bpf device hook and cpu controller in cgroup v2 + ≥ 4.17 for cgroup-bpf socket address hooks + ≥ 5.3 for bounded loops in BPF program + ≥ 5.4 for signed Verity images + ≥ 5.7 for BPF links and the BPF LSM hook + + Kernel versions below 4.15 have significant gaps in functionality and + are not recommended for use with this version of systemd. Taint flag + 'old-kernel' will be set. Systemd will most likely still function, but + upstream support and testing are limited. Kernel Config Options: CONFIG_DEVTMPFS @@ -330,24 +337,48 @@ SYSV INIT.D SCRIPTS: Please see src/systemctl/systemd-sysv-install.SKELETON for how this needs to look like, and provide an implementation at the marked places. -WARNINGS: +WARNINGS and TAINT FLAGS: systemd will warn during early boot if /usr is not already mounted at this point (that means: either located on the same file system as / or already mounted in the initrd). While in systemd itself very little - will break if /usr is on a separate, late-mounted partition, many of - its dependencies very likely will break sooner or later in one form or + will break if /usr is on a separate late-mounted partition, many of its + dependencies very likely will break sooner or later in one form or another. For example, udev rules tend to refer to binaries in /usr, binaries that link to libraries in /usr or binaries that refer to data files in /usr. Since these breakages are not always directly visible, - systemd will warn about this, since this kind of file system setup is - not really supported anymore by the basic set of Linux OS components. - - systemd requires that the /run mount point exists. systemd also - requires that /var/run is a symlink to /run. + systemd will warn about this. Such setups are not really supported by + the basic set of Linux OS components. Taint flag 'split-usr' will be + set when this condition is detected. For more information on this issue consult https://www.freedesktop.org/wiki/Software/systemd/separate-usr-is-broken + systemd will warn if the filesystem is not usr-merged (i.e.: /bin, /sbin + and /lib* are not symlinks to their counterparts under /usr). Taint flag + 'unmerged-usr' will be set when this condition is detected. + + For more information on this issue consult + https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge + + systemd requires that the /run mount point exists. systemd also + requires that /var/run is a symlink to /run. Taint flag 'var-run-bad' + will be set when this condition is detected. + + Systemd will also warn when the cgroup support is unavailable in the + kernel (taint flag 'cgroups-missing'), the system is using the old + cgroup hierarchy (taint flag 'cgroupsv1'), the hardware clock is + running in non-UTC mode (taint flag 'local-hwclock'), the kernel + overflow UID or GID are not 65534 (taint flags 'overflowuid-not-65534' + and 'overflowgid-not-65534'), the UID or GID range assigned to the + running systemd instance covers less than 0…65534 (taint flags + 'short-uid-range' and 'short-gid-range'). + + Taint conditions are logged during boot, but may also be checked at any + time with: + + busctl get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager Tainted + +VALGRIND: To run systemd under valgrind, compile with meson option -Dvalgrind=true and have valgrind development headers installed (i.e. valgrind-devel or equivalent). Otherwise, false positives will be @@ -13,6 +13,7 @@ System and Service Manager [![CentOS CI - CentOS 8](https://jenkins-systemd.apps.ocp.ci.centos.org/buildStatus/icon?subject=CentOS%20CI%20-%20CentOS%208&job=upstream-centos8)](https://jenkins-systemd.apps.ocp.ci.centos.org/job/upstream-centos8/)<br/> [![CentOS CI - Arch](https://jenkins-systemd.apps.ocp.ci.centos.org/buildStatus/icon?subject=CentOS%20CI%20-%20Arch&job=upstream-vagrant-archlinux)](https://jenkins-systemd.apps.ocp.ci.centos.org/job/upstream-vagrant-archlinux/)<br/> [![CentOS CI - Arch (sanitizers)](https://jenkins-systemd.apps.ocp.ci.centos.org/buildStatus/icon?subject=CentOS%20CI%20-%20Arch%20(sanitizers)&job=upstream-vagrant-archlinux-sanitizers)](https://jenkins-systemd.apps.ocp.ci.centos.org/job/upstream-vagrant-archlinux-sanitizers/)<br/> +[![CentOS CI - Rawhide (SELinux)](https://jenkins-systemd.apps.ocp.ci.centos.org/buildStatus/icon?subject=CentOS%20CI%20-%20Rawhide%20(SELinux)&job=upstream-vagrant-rawhide-selinux)](https://jenkins-systemd.apps.ocp.ci.centos.org/view/Upstream/job/upstream-vagrant-rawhide-selinux/)<br/> [![Fossies codespell report](https://fossies.org/linux/test/systemd-main.tar.gz/codespell.svg)](https://fossies.org/linux/test/systemd-main.tar.gz/codespell.html)</br> [![Coverage Status](https://coveralls.io/repos/github/systemd/systemd/badge.svg?branch=main)](https://coveralls.io/github/systemd/systemd?branch=main)</br> [![Packaging status](https://repology.org/badge/tiny-repos/systemd.svg)](https://repology.org/project/systemd/versions) @@ -78,6 +78,13 @@ Janitorial Clean-ups: Features: +* get_color_mode() should probably check the $COLORTERM environment variable + which most terminal environments appear to set. + +* firstboot: maybe just default to C.UTF-8 locale if nothing is set, so that we + don't query this unnecessarily in entirely uninitialized + containers. (i.e. containers with empty /etc). + * systemd creds hookup with qemu fw_cfg. (Quite possibly might not need any code at all, given the fw_cfg stuff are just files, but we should then document how to use it). Goal: provide symmetric ways to pass creds to nspawn diff --git a/docs/sysvinit/meson.build b/docs/sysvinit/meson.build index cd3015ca4b..64476a5d76 100644 --- a/docs/sysvinit/meson.build +++ b/docs/sysvinit/meson.build @@ -4,6 +4,6 @@ custom_target( 'README', input : 'README.in', output : 'README', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : conf.get('HAVE_SYSV_COMPAT') == 1, install_dir : sysvinit_path) diff --git a/factory/templates/meson.build b/factory/templates/meson.build index 821f176a74..ece2c644ff 100644 --- a/factory/templates/meson.build +++ b/factory/templates/meson.build @@ -6,6 +6,6 @@ custom_target( 'locale.conf', input : 'locale.conf.in', output : 'locale.conf', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : true, install_dir : factory_etc_dir) diff --git a/hwdb.d/60-evdev.hwdb b/hwdb.d/60-evdev.hwdb index 9fcb4a3ddf..c97cd13557 100644 --- a/hwdb.d/60-evdev.hwdb +++ b/hwdb.d/60-evdev.hwdb @@ -3,11 +3,6 @@ # The lookup keys are composed in: # 60-evdev.rules # -# Note: The format of the "evdev:" prefix match key is a contract between the -# rules file and the hardware data, it might change in later revisions to -# support more or better matches, it is not necessarily expected to be a stable -# ABI. -# # Match string formats: # evdev:<modalias> # evdev:name:<device name>:dmi:<dmi string> diff --git a/hwdb.d/60-input-id.hwdb b/hwdb.d/60-input-id.hwdb index 2d5681dea6..802ed9a1e7 100644 --- a/hwdb.d/60-input-id.hwdb +++ b/hwdb.d/60-input-id.hwdb @@ -3,11 +3,6 @@ # The lookup keys are composed in: # 60-input-id.rules # -# Note: The format of the "input-id:" prefix match key is a contract between -# the rules file and the hardware data, it might change in later revisions to -# support more or better matches, it is not necessarily expected to be a stable -# ABI. -# # Match string formats: # id-input:modalias:<modalias> # diff --git a/hwdb.d/60-keyboard.hwdb b/hwdb.d/60-keyboard.hwdb index c196a1fd64..7c830fb9b1 100644 --- a/hwdb.d/60-keyboard.hwdb +++ b/hwdb.d/60-keyboard.hwdb @@ -13,11 +13,6 @@ # The lookup keys are composed in: # 60-evdev.rules # -# Note: The format of the "evdev:" prefix match key is a contract between the -# rules file and the hardware data, it might change in later revisions to -# support more or better matches, it is not necessarily expected to be a stable -# ABI. -# # Supported hardware matches are: # - Generic input devices match: # evdev:input:bZZZZvYYYYpXXXXeWWWW-VVVV diff --git a/hwdb.d/60-sensor.hwdb b/hwdb.d/60-sensor.hwdb index ea278913bc..b54539bf53 100644 --- a/hwdb.d/60-sensor.hwdb +++ b/hwdb.d/60-sensor.hwdb @@ -3,11 +3,6 @@ # The lookup keys are composed in: # 60-sensor.rules # -# Note: The format of the "sensor:" prefix match key is a contract between the -# rules file and the hardware data, it might change in later revisions to -# support more or better matches, it is not necessarily expected to be a stable -# ABI. -# # Match string formats: # sensor:modalias:<parent modalias pattern>:dmi:<dmi pattern> # diff --git a/hwdb.d/70-mouse.hwdb b/hwdb.d/70-mouse.hwdb index 723d145e34..4084019bde 100644 --- a/hwdb.d/70-mouse.hwdb +++ b/hwdb.d/70-mouse.hwdb @@ -6,11 +6,6 @@ # The lookup keys are composed in: # 70-mouse.rules # -# Note: The format of the "mouse:" prefix match key is a contract between the -# rules file and the hardware data, it might change in later revisions to -# support more or better matches, it is not necessarily expected to be a stable -# ABI. -# # Match key format: # mouse:<subsystem>:v<vid>p<pid>:name:<name>: # diff --git a/hwdb.d/70-pointingstick.hwdb b/hwdb.d/70-pointingstick.hwdb index 6039119b6a..00f28c6034 100644 --- a/hwdb.d/70-pointingstick.hwdb +++ b/hwdb.d/70-pointingstick.hwdb @@ -7,10 +7,6 @@ # The lookup keys are composed in: # 60-evdev.rules # -# Note: The format of the "evdev:" prefix match key is a contract between the -# rules file and the hardware data, it might change in later revisions to -# support more or better matches, it is not necessarily a stable ABI. -# # Supported hardware matches are: # - Generic input devices match: # evdev:input:bZZZZvYYYYpXXXXeWWWW-VVVV diff --git a/man/kernel-install.xml b/man/kernel-install.xml index 974d6984de..5ae86aca18 100644 --- a/man/kernel-install.xml +++ b/man/kernel-install.xml @@ -166,6 +166,7 @@ </varlistentry> <xi:include href="standard-options.xml" xpointer="help" /> + <xi:include href="standard-options.xml" xpointer="version" /> </variablelist> </refsect1> diff --git a/man/logind.conf.xml b/man/logind.conf.xml index 3045c1b9ba..fc838abee2 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml @@ -205,47 +205,34 @@ <term><varname>HandleLidSwitchExternalPower=</varname></term> <term><varname>HandleLidSwitchDocked=</varname></term> - <listitem><para>Controls how logind shall handle the - system power, reboot and sleep keys and the lid switch to trigger - actions such as system power-off, reboot or suspend. Can be one of - <literal>ignore</literal>, - <literal>poweroff</literal>, - <literal>reboot</literal>, - <literal>halt</literal>, - <literal>kexec</literal>, - <literal>suspend</literal>, - <literal>hibernate</literal>, - <literal>hybrid-sleep</literal>, - <literal>suspend-then-hibernate</literal>, - <literal>lock</literal>, and - <literal>factory-reset</literal>. - If <literal>ignore</literal>, logind will never handle these - keys. If <literal>lock</literal>, all running sessions will be - screen-locked; otherwise, the specified action will be taken - in the respective event. Only input devices with the - <literal>power-switch</literal> udev tag will be watched for - key/lid switch events. <varname>HandlePowerKey=</varname> - defaults to <literal>poweroff</literal>, <varname>HandleRebootKey=</varname> - defaults to <literal>reboot</literal>, <varname>HandleSuspendKey=</varname> - defaults to <literal>suspend</literal>, <varname>HandleHibernateKey=</varname> - defaults to <literal>hibernate</literal>, <varname>HandlePowerKeyLongPress=</varname> - defaults to <literal>ignore</literal>, <varname>HandleRebootKeyLongPress=</varname> - defaults to <literal>poweroff</literal>, <varname>HandleSuspendKeyLongPress=</varname> - defaults to <literal>hibernate</literal>, <varname>HandleHibernateKeyLongPress=</varname> - defaults to <literal>ignore</literal>. - <varname>HandleLidSwitch=</varname> defaults to - <literal>suspend</literal>. - <varname>HandleLidSwitchExternalPower=</varname> is completely - ignored by default (for backwards compatibility) — an explicit - value must be set before it will be used to determine - behaviour. <varname>HandleLidSwitchDocked=</varname> defaults - to <literal>ignore</literal>. If the system is inserted in a - docking station, or if more than one display is connected, the - action specified by <varname>HandleLidSwitchDocked=</varname> - occurs; if the system is on external power the action (if any) - specified by <varname>HandleLidSwitchExternalPower=</varname> - occurs; otherwise the <varname>HandleLidSwitch=</varname> - action occurs.</para> + <listitem><para>Controls how logind shall handle the system power, reboot and sleep keys and the lid + switch to trigger actions such as system power-off, reboot or suspend. Can be one of + <literal>ignore</literal>, <literal>poweroff</literal>, <literal>reboot</literal>, + <literal>halt</literal>, <literal>kexec</literal>, <literal>suspend</literal>, + <literal>hibernate</literal>, <literal>hybrid-sleep</literal>, + <literal>suspend-then-hibernate</literal>, <literal>lock</literal>, and + <literal>factory-reset</literal>. If <literal>ignore</literal>, <command>systemd-logind</command> + will never handle these keys. If <literal>lock</literal>, all running sessions will be screen-locked; + otherwise, the specified action will be taken in the respective event. Only input devices with the + <literal>power-switch</literal> udev tag will be watched for key/lid switch + events.</para> + + <para><varname>HandlePowerKey=</varname> defaults to <literal>poweroff</literal>, + <varname>HandleRebootKey=</varname> defaults to <literal>reboot</literal>, + <varname>HandleSuspendKey=</varname> defaults to <literal>suspend</literal>, + <varname>HandleHibernateKey=</varname> defaults to <literal>hibernate</literal>, + <varname>HandlePowerKeyLongPress=</varname> defaults to <literal>ignore</literal>, + <varname>HandleRebootKeyLongPress=</varname> defaults to <literal>poweroff</literal>, + <varname>HandleSuspendKeyLongPress=</varname> defaults to <literal>hibernate</literal>, + <varname>HandleHibernateKeyLongPress=</varname> defaults to <literal>ignore</literal>. + <varname>HandleLidSwitch=</varname> defaults to <literal>suspend</literal>. + <varname>HandleLidSwitchExternalPower=</varname> is completely ignored by default (for backwards + compatibility) — an explicit value must be set before it will be used to determine + behaviour. <varname>HandleLidSwitchDocked=</varname> defaults to <literal>ignore</literal>. If the + system is inserted in a docking station, or if more than one display is connected, the action + specified by <varname>HandleLidSwitchDocked=</varname> occurs; if the system is on external power the + action (if any) specified by <varname>HandleLidSwitchExternalPower=</varname> occurs; otherwise the + <varname>HandleLidSwitch=</varname> action occurs.</para> <para>A different application may disable logind's handling of system power and sleep keys and the lid switch by taking a low-level inhibitor lock diff --git a/man/meson.build b/man/meson.build index 83b368115b..d9c706b4ab 100644 --- a/man/meson.build +++ b/man/meson.build @@ -30,7 +30,7 @@ custom_entities_ent = custom_target( 'custom-entities.ent', input : 'custom-entities.ent.in', output : 'custom-entities.ent', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@']) + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@']) man_pages = [] html_pages = [] diff --git a/man/org.freedesktop.login1.xml b/man/org.freedesktop.login1.xml index d25287b18b..8fc145d771 100644 --- a/man/org.freedesktop.login1.xml +++ b/man/org.freedesktop.login1.xml @@ -194,10 +194,20 @@ node /org/freedesktop/login1 { @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s HandlePowerKey = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly s HandlePowerKeyLongPress = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly s HandleRebootKey = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly s HandleRebootKeyLongPress = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s HandleSuspendKey = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly s HandleSuspendKeyLongPress = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s HandleHibernateKey = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly s HandleHibernateKeyLongPress = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s HandleLidSwitch = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s HandleLidSwitchExternalPower = '...'; @@ -242,6 +252,16 @@ node /org/freedesktop/login1 { }; </programlisting> + <!--property HandlePowerKeyLongPress is not documented!--> + + <!--property HandleRebootKey is not documented!--> + + <!--property HandleRebootKeyLongPress is not documented!--> + + <!--property HandleSuspendKeyLongPress is not documented!--> + + <!--property HandleHibernateKeyLongPress is not documented!--> + <!--Autogenerated cross-references for systemd.directives, do not edit--> <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.login1.Manager"/> @@ -418,10 +438,20 @@ node /org/freedesktop/login1 { <variablelist class="dbus-property" generated="True" extra-ref="HandlePowerKey"/> + <variablelist class="dbus-property" generated="True" extra-ref="HandlePowerKeyLongPress"/> + + <variablelist class="dbus-property" generated="True" extra-ref="HandleRebootKey"/> + + <variablelist class="dbus-property" generated="True" extra-ref="HandleRebootKeyLongPress"/> + <variablelist class="dbus-property" generated="True" extra-ref="HandleSuspendKey"/> + <variablelist class="dbus-property" generated="True" extra-ref="HandleSuspendKeyLongPress"/> + <variablelist class="dbus-property" generated="True" extra-ref="HandleHibernateKey"/> + <variablelist class="dbus-property" generated="True" extra-ref="HandleHibernateKeyLongPress"/> + <variablelist class="dbus-property" generated="True" extra-ref="HandleLidSwitch"/> <variablelist class="dbus-property" generated="True" extra-ref="HandleLidSwitchExternalPower"/> diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml index 7baa1794d7..97290d479b 100644 --- a/man/systemd-analyze.xml +++ b/man/systemd-analyze.xml @@ -819,10 +819,12 @@ $ systemd-analyze verify /tmp/source:alias.service <listitem><para>Control verification of units and their dependencies and whether <command>systemd-analyze verify</command> exits with a non-zero process exit status or not. With <command>yes</command>, return a non-zero process exit status when warnings arise during verification - of either the specified unit or any of its associated dependencies. This is the default. With - <command>no</command>, return a non-zero process exit status when warnings arise during verification - of only the specified unit. With <command>one</command>, return a non-zero process exit status when - warnings arise during verification of either the specified unit or its immediate dependencies. </para></listitem> + of either the specified unit or any of its associated dependencies. With <command>no</command>, + return a non-zero process exit status when warnings arise during verification of only the specified + unit. With <command>one</command>, return a non-zero process exit status when warnings arise during + verification of either the specified unit or its immediate dependencies. If this option is not + specified, zero is returned as the exit status regardless whether warnings arise during verification + or not.</para></listitem> </varlistentry> <varlistentry> diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml index 41408411fc..e5a3d7a313 100644 --- a/man/systemd.net-naming-scheme.xml +++ b/man/systemd.net-naming-scheme.xml @@ -403,6 +403,18 @@ </listitem> </varlistentry> + <varlistentry> + <term><constant>v251</constant></term> + + <listitem><para>Since version <constant>v247</constant> we no longer set + <varname>ID_NET_NAME_SLOT</varname> if we detect that a PCI device associated with a slot is a PCI + bridge as that would create naming conflict when there are more child devices on that bridge. Now, + this is relaxed and we will use slot information to generate the name based on it but only if + the PCI device has multiple functions. This is safe because distinct function number is a part of + the device name for multifunction devices.</para> + </listitem> + </varlistentry> + </variablelist> <para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this diff --git a/meson.build b/meson.build index 0455d89b78..4a154850db 100644 --- a/meson.build +++ b/meson.build @@ -1826,6 +1826,8 @@ config_h = configure_file( add_project_arguments('-include', 'config.h', language : 'c') +jinja2_cmdline = [meson_render_jinja2, config_h, version_h] + ############################################################ # binaries that have --help and are intended for use by humans, @@ -2113,7 +2115,7 @@ endforeach ############################################################ -dbus_programs += executable( +exe = executable( 'systemd', systemd_sources, include_directories : includes, @@ -2124,6 +2126,8 @@ dbus_programs += executable( install_rpath : rootlibexecdir, install : true, install_dir : rootlibexecdir) +dbus_programs += exe +public_programs += exe meson.add_install_script(meson_make_symlink, rootlibexecdir / 'systemd', @@ -2680,7 +2684,7 @@ if conf.get('HAVE_LIBCRYPTSETUP') == 1 install : true, install_dir : systemgeneratordir) - executable( + public_programs += executable( 'systemd-cryptenroll', systemd_cryptenroll_sources, include_directories : includes, @@ -3115,7 +3119,7 @@ if conf.get('ENABLE_RANDOMSEED') == 1 endif if conf.get('ENABLE_FIRSTBOOT') == 1 - executable( + public_programs += executable( 'systemd-firstboot', 'src/firstboot/firstboot.c', include_directories : includes, @@ -3605,7 +3609,7 @@ if conf.get('ENABLE_NETWORKD') == 1 install : true, install_dir : rootlibexecdir) - executable( + public_programs += executable( 'systemd-networkd-wait-online', systemd_networkd_wait_online_sources, include_directories : includes, @@ -3651,6 +3655,15 @@ executable( install : true, install_dir : rootlibexecdir) +public_programs += custom_target( + 'kernel-install', + input : kernel_install_in, + output : 'kernel-install', + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], + install : want_kernel_install, + install_mode : 'rwxr-xr-x', + install_dir : bindir) + ############################################################ runtest_env = custom_target( @@ -3891,6 +3904,7 @@ endif ############################################################ check_help = find_program('tools/check-help.sh') +check_version = find_program('tools/check-version.sh') foreach exec : public_programs name = exec.full_path().split('/')[-1] @@ -3899,6 +3913,12 @@ foreach exec : public_programs check_help, args : exec.full_path(), depends: exec) + + test('check-version-' + name, + check_version, + args : [exec.full_path(), + meson.project_version()], + depends: exec) endif endforeach diff --git a/rules.d/meson.build b/rules.d/meson.build index e6533e001a..f725e14d95 100644 --- a/rules.d/meson.build +++ b/rules.d/meson.build @@ -51,7 +51,7 @@ foreach file : rules_in file, input : file + '.in', output: file, - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : true, install_dir : udevrulesdir) endforeach diff --git a/shell-completion/bash/meson.build b/shell-completion/bash/meson.build index ae6a61e555..fb7314348a 100644 --- a/shell-completion/bash/meson.build +++ b/shell-completion/bash/meson.build @@ -14,7 +14,7 @@ custom_target( 'systemctl', input : 'systemctl.in', output : 'systemctl', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : bashcompletiondir != 'no', install_dir : bashcompletiondir) diff --git a/shell-completion/zsh/meson.build b/shell-completion/zsh/meson.build index bac531798c..b39f933ea4 100644 --- a/shell-completion/zsh/meson.build +++ b/shell-completion/zsh/meson.build @@ -9,7 +9,7 @@ custom_target( '_systemctl', input : '_systemctl.in', output : '_systemctl', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : zshcompletiondir != 'no', install_dir : zshcompletiondir) diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 905ff2c27f..cb83e73877 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -90,7 +90,7 @@ PagerFlags arg_pager_flags = 0; BusTransport arg_transport = BUS_TRANSPORT_LOCAL; const char *arg_host = NULL; LookupScope arg_scope = LOOKUP_SCOPE_SYSTEM; -RecursiveErrors arg_recursive_errors = RECURSIVE_ERRORS_YES; +RecursiveErrors arg_recursive_errors = _RECURSIVE_ERRORS_INVALID; bool arg_man = true; bool arg_generators = false; char *arg_root = NULL; diff --git a/src/basic/def.h b/src/basic/def.h index 54a82c7c49..0a1ae023a3 100644 --- a/src/basic/def.h +++ b/src/basic/def.h @@ -74,4 +74,4 @@ /* Path where systemd-oomd listens for varlink connections from user managers to report changes in ManagedOOM settings. */ #define VARLINK_ADDR_PATH_MANAGED_OOM_USER "/run/systemd/oom/io.system.ManagedOOM" -#define KERNEL_BASELINE_VERSION "3.15" +#define KERNEL_BASELINE_VERSION "4.15" diff --git a/src/basic/strv.c b/src/basic/strv.c index c4e3dad446..22f5402575 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -351,7 +351,7 @@ int strv_split_colon_pairs(char ***t, const char *s) { return (int) n; } -char* strv_join_full(char * const *l, const char *separator, const char *prefix, bool unescape_separators) { +char* strv_join_full(char * const *l, const char *separator, const char *prefix, bool escape_separator) { char *r, *e; size_t n, k, m; @@ -361,7 +361,7 @@ char* strv_join_full(char * const *l, const char *separator, const char *prefix, k = strlen(separator); m = strlen_ptr(prefix); - if (unescape_separators) /* If there separator is multi-char, we won't know how to escape it. */ + if (escape_separator) /* If the separator was multi-char, we wouldn't know how to escape it. */ assert(k == 1); n = 0; @@ -369,7 +369,7 @@ char* strv_join_full(char * const *l, const char *separator, const char *prefix, if (s != l) n += k; - bool needs_escaping = unescape_separators && strchr(*s, separator[0]); + bool needs_escaping = escape_separator && strchr(*s, *separator); n += m + strlen(*s) * (1 + needs_escaping); } @@ -386,11 +386,11 @@ char* strv_join_full(char * const *l, const char *separator, const char *prefix, if (prefix) e = stpcpy(e, prefix); - bool needs_escaping = unescape_separators && strchr(*s, separator[0]); + bool needs_escaping = escape_separator && strchr(*s, *separator); if (needs_escaping) for (size_t i = 0; (*s)[i]; i++) { - if ((*s)[i] == separator[0]) + if ((*s)[i] == *separator) *(e++) = '\\'; *(e++) = (*s)[i]; } diff --git a/src/basic/strv.h b/src/basic/strv.h index 2a858326c6..6295058876 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -101,7 +101,7 @@ static inline char** strv_split_newlines(const char *s) { * string in the vector is an empty string. */ int strv_split_colon_pairs(char ***t, const char *s); -char* strv_join_full(char * const *l, const char *separator, const char *prefix, bool escape_separtor); +char* strv_join_full(char * const *l, const char *separator, const char *prefix, bool escape_separator); static inline char *strv_join(char * const *l, const char *separator) { return strv_join_full(l, separator, NULL, false); } diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index e0dc47ecd8..66e0c01c23 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -1000,7 +1000,7 @@ int config_parse_exec( if (r < 0) return ignore ? 0 : -ENOEXEC; - r = unit_path_printf(u, word, &resolved); + r = unit_full_printf(u, word, &resolved); if (r < 0) { log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s%s: %m", diff --git a/src/core/main.c b/src/core/main.c index 6567cdfb28..c6e9e9b034 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1075,9 +1075,8 @@ static int help(void) { " -h --help Show this help\n" " --version Show version\n" " --test Determine initial transaction, dump it and exit\n" - " --system In combination with --test: operate as system service manager\n" - " --user In combination with --test: operate as per-user service manager\n" - " --no-pager Do not pipe output into a pager\n" + " --system Combined with --test: operate in system mode\n" + " --user Combined with --test: operate in user mode\n" " --dump-configuration-items Dump understood unit configuration items\n" " --dump-bus-properties Dump exposed bus properties\n" " --bus-introspect=PATH Write XML introspection data\n" @@ -1087,14 +1086,17 @@ static int help(void) { " --crash-reboot[=BOOL] Reboot on crash\n" " --crash-shell[=BOOL] Run shell on crash\n" " --confirm-spawn[=BOOL] Ask for confirmation when spawning processes\n" - " --show-status[=BOOL] Show status updates on the console during bootup\n" - " --log-target=TARGET Set log target (console, journal, kmsg, journal-or-kmsg, null)\n" - " --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n" + " --show-status[=BOOL] Show status updates on the console during boot\n" + " --log-target=TARGET Set log target (console, journal, kmsg,\n" + " journal-or-kmsg, null)\n" + " --log-level=LEVEL Set log level (debug, info, notice, warning,\n" + " err, crit, alert, emerg)\n" " --log-color[=BOOL] Highlight important log messages\n" " --log-location[=BOOL] Include code location in log messages\n" " --log-time[=BOOL] Prefix log messages with current time\n" " --default-standard-output= Set default standard output for services\n" " --default-standard-error= Set default standard error output for services\n" + " --no-pager Do not pipe output into a pager\n" "\nSee the %s for details.\n", program_invocation_short_name, ansi_highlight(), diff --git a/src/core/manager.c b/src/core/manager.c index e92004edf3..2f60b14159 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -4370,71 +4370,58 @@ static int short_uid_range(const char *path) { return !uid_range_covers(p, n, 0, 65535); } -char *manager_taint_string(Manager *m) { - _cleanup_free_ char *destination = NULL, *overflowuid = NULL, *overflowgid = NULL; - struct utsname uts; - char *buf, *e; - int r; - - /* Returns a "taint string", e.g. "local-hwclock:var-run-bad". Only things that are detected at - * runtime should be tagged here. For stuff that is set during compilation, emit a warning in the +char* manager_taint_string(const Manager *m) { + /* Returns a "taint string", e.g. "local-hwclock:var-run-bad". Only things that are detected at + * runtime should be tagged here. For stuff that is known during compilation, emit a warning in the * configuration phase. */ assert(m); - buf = new(char, sizeof("split-usr:" - "cgroups-missing:" - "cgrousv1:" - "local-hwclock:" - "var-run-bad:" - "overflowuid-not-65534:" - "overflowgid-not-65534:" - "old-kernel:" - "short-uid-range:" - "short-gid-range:")); - if (!buf) - return NULL; - - e = buf; - buf[0] = 0; + const char* stage[12] = {}; + size_t n = 0; if (m->taint_usr) - e = stpcpy(e, "split-usr:"); + stage[n++] = "split-usr"; + + _cleanup_free_ char *usrbin = NULL; + if (readlink_malloc("/bin", &usrbin) < 0 || !PATH_IN_SET(usrbin, "usr/bin", "/usr/bin")) + stage[n++] = "unmerged-usr"; if (access("/proc/cgroups", F_OK) < 0) - e = stpcpy(e, "cgroups-missing:"); + stage[n++] = "cgroups-missing"; if (cg_all_unified() == 0) - e = stpcpy(e, "cgroupsv1:"); + stage[n++] = "cgroupsv1"; if (clock_is_localtime(NULL) > 0) - e = stpcpy(e, "local-hwclock:"); + stage[n++] = "local-hwclock"; - r = readlink_malloc("/var/run", &destination); - if (r < 0 || !PATH_IN_SET(destination, "../run", "/run")) - e = stpcpy(e, "var-run-bad:"); + _cleanup_free_ char *destination = NULL; + if (readlink_malloc("/var/run", &destination) < 0 || + !PATH_IN_SET(destination, "../run", "/run")) + stage[n++] = "var-run-bad"; - r = read_one_line_file("/proc/sys/kernel/overflowuid", &overflowuid); - if (r >= 0 && !streq(overflowuid, "65534")) - e = stpcpy(e, "overflowuid-not-65534:"); - r = read_one_line_file("/proc/sys/kernel/overflowgid", &overflowgid); - if (r >= 0 && !streq(overflowgid, "65534")) - e = stpcpy(e, "overflowgid-not-65534:"); + _cleanup_free_ char *overflowuid = NULL, *overflowgid = NULL; + if (read_one_line_file("/proc/sys/kernel/overflowuid", &overflowuid) >= 0 && + !streq(overflowuid, "65534")) + stage[n++] = "overflowuid-not-65534"; + if (read_one_line_file("/proc/sys/kernel/overflowgid", &overflowgid) >= 0 && + !streq(overflowgid, "65534")) + stage[n++] = "overflowgid-not-65534"; + struct utsname uts; assert_se(uname(&uts) >= 0); if (strverscmp_improved(uts.release, KERNEL_BASELINE_VERSION) < 0) - e = stpcpy(e, "old-kernel:"); + stage[n++] = "old-kernel"; if (short_uid_range("/proc/self/uid_map") > 0) - e = stpcpy(e, "short-uid-range:"); + stage[n++] = "short-uid-range"; if (short_uid_range("/proc/self/gid_map") > 0) - e = stpcpy(e, "short-gid-range:"); + stage[n++] = "short-gid-range"; - /* remove the last ':' */ - if (e != buf) - e[-1] = 0; + assert(n < ELEMENTSOF(stage) - 1); /* One extra for NULL terminator */ - return buf; + return strv_join((char**) stage, ":"); } void manager_ref_console(Manager *m) { diff --git a/src/core/manager.h b/src/core/manager.h index dc6718ada1..6f4bbb36ab 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -551,7 +551,7 @@ int manager_ref_uid(Manager *m, uid_t uid, bool clean_ipc); void manager_unref_gid(Manager *m, gid_t gid, bool destroy_now); int manager_ref_gid(Manager *m, gid_t gid, bool clean_ipc); -char *manager_taint_string(Manager *m); +char* manager_taint_string(const Manager *m); void manager_ref_console(Manager *m); void manager_unref_console(Manager *m); diff --git a/src/core/meson.build b/src/core/meson.build index f5e04b37ca..ee2f8774bf 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -151,7 +151,7 @@ load_fragment_gperf_gperf = custom_target( 'load-fragment-gperf.gperf', input : 'load-fragment-gperf.gperf.in', output: 'load-fragment-gperf.gperf', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@']) + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@']) load_fragment_gperf_c = custom_target( 'load-fragment-gperf.c', @@ -217,7 +217,7 @@ foreach item : in_files file, input : file + '.in', output: file, - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : (dir == pkgsysconfdir) ? install_sysconfdir_samples : (dir != 'no'), install_dir : dir) endforeach diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index d28a416e5d..39160182ef 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -984,37 +984,37 @@ static int help(void) { printf("%s [OPTIONS...]\n\n" "Configures basic settings of the system.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --root=PATH Operate on an alternate filesystem root\n" - " --image=PATH Operate on an alternate filesystem image\n" - " --locale=LOCALE Set primary locale (LANG=)\n" - " --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n" - " --keymap=KEYMAP Set keymap\n" - " --timezone=TIMEZONE Set timezone\n" - " --hostname=NAME Set hostname\n" - " --machine-ID=ID Set machine ID\n" - " --root-password=PASSWORD Set root password from plaintext password\n" - " --root-password-file=FILE Set root password from file\n" - " --root-password-hashed=HASHED_PASSWORD Set root password from hashed password\n" - " --root-shell=SHELL Set root shell\n" - " --prompt-locale Prompt the user for locale settings\n" - " --prompt-keymap Prompt the user for keymap settings\n" - " --prompt-timezone Prompt the user for timezone\n" - " --prompt-hostname Prompt the user for hostname\n" - " --prompt-root-password Prompt the user for root password\n" - " --prompt-root-shell Prompt the user for root shell\n" - " --prompt Prompt for all of the above\n" - " --copy-locale Copy locale from host\n" - " --copy-keymap Copy keymap from host\n" - " --copy-timezone Copy timezone from host\n" - " --copy-root-password Copy root password from host\n" - " --copy-root-shell Copy root shell from host\n" - " --copy Copy locale, keymap, timezone, root password\n" - " --setup-machine-id Generate a new random machine ID\n" - " --force Overwrite existing files\n" - " --delete-root-password Delete root password\n" - " --welcome=no Disable the welcome text\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --root=PATH Operate on an alternate filesystem root\n" + " --image=PATH Operate on an alternate filesystem image\n" + " --locale=LOCALE Set primary locale (LANG=)\n" + " --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n" + " --keymap=KEYMAP Set keymap\n" + " --timezone=TIMEZONE Set timezone\n" + " --hostname=NAME Set hostname\n" + " --machine-ID=ID Set machine ID\n" + " --root-password=PASSWORD Set root password from plaintext password\n" + " --root-password-file=FILE Set root password from file\n" + " --root-password-hashed=HASH Set root password from hashed password\n" + " --root-shell=SHELL Set root shell\n" + " --prompt-locale Prompt the user for locale settings\n" + " --prompt-keymap Prompt the user for keymap settings\n" + " --prompt-timezone Prompt the user for timezone\n" + " --prompt-hostname Prompt the user for hostname\n" + " --prompt-root-password Prompt the user for root password\n" + " --prompt-root-shell Prompt the user for root shell\n" + " --prompt Prompt for all of the above\n" + " --copy-locale Copy locale from host\n" + " --copy-keymap Copy keymap from host\n" + " --copy-timezone Copy timezone from host\n" + " --copy-root-password Copy root password from host\n" + " --copy-root-shell Copy root shell from host\n" + " --copy Copy locale, keymap, timezone, root password\n" + " --setup-machine-id Generate a new random machine ID\n" + " --force Overwrite existing files\n" + " --delete-root-password Delete root password\n" + " --welcome=no Disable the welcome text\n" "\nSee the %s for details.\n", program_invocation_short_name, link); diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c index e70354e444..17ac7e4fbe 100644 --- a/src/hwdb/hwdb.c +++ b/src/hwdb/hwdb.c @@ -73,7 +73,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "ust:r:h", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "sr:h", options, NULL)) >= 0) switch (c) { case 'h': diff --git a/src/journal-remote/meson.build b/src/journal-remote/meson.build index 4bbbc1431f..f81d906616 100644 --- a/src/journal-remote/meson.build +++ b/src/journal-remote/meson.build @@ -54,7 +54,7 @@ foreach tuple : in_files file, input : file + '.in', output: file, - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : tuple[1], install_dir : pkgsysconfdir) endforeach diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install.in index a09b998362..f6d262f522 100755 --- a/src/kernel-install/kernel-install +++ b/src/kernel-install/kernel-install.in @@ -23,11 +23,12 @@ skip_remaining=77 usage() { echo "Usage:" - echo " $0 [OPTIONS...] add KERNEL-VERSION KERNEL-IMAGE [INITRD-FILE ...]" - echo " $0 [OPTIONS...] remove KERNEL-VERSION" - echo " $0 [OPTIONS...] inspect" + echo " kernel-install [OPTIONS...] add KERNEL-VERSION KERNEL-IMAGE [INITRD-FILE...]" + echo " kernel-install [OPTIONS...] remove KERNEL-VERSION" + echo " kernel-install [OPTIONS...] inspect" echo "Options:" - echo " -h, --help Print this help" + echo " -h, --help Print this help and exit" + echo " --version Print version string and exit" echo " -v, --verbose Increase verbosity" } @@ -59,6 +60,13 @@ for i; do fi done +for i; do + if [ "$i" = "--version" ]; then + echo "kernel-install {{PROJECT_VERSION}} ({{GIT_VERSION}})" + exit 0 + fi +done + export KERNEL_INSTALL_VERBOSE=0 if [ "$1" = "--verbose" ] || [ "$1" = "-v" ]; then shift diff --git a/src/kernel-install/meson.build b/src/kernel-install/meson.build index abc3520b62..06c1c3aafb 100644 --- a/src/kernel-install/meson.build +++ b/src/kernel-install/meson.build @@ -1,10 +1,8 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -if want_kernel_install - install_data('kernel-install', - install_mode : 'rwxr-xr-x', - install_dir : bindir) +kernel_install_in = files('kernel-install.in') +if want_kernel_install install_data('50-depmod.install', '90-loaderentry.install', install_mode : 'rwxr-xr-x', diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build index 67b439a5dd..a86b8f896b 100644 --- a/src/libsystemd/meson.build +++ b/src/libsystemd/meson.build @@ -186,7 +186,7 @@ custom_target( 'libsystemd.pc', input : 'libsystemd.pc.in', output : 'libsystemd.pc', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : pkgconfiglibdir != 'no', install_dir : pkgconfiglibdir) diff --git a/src/libudev/meson.build b/src/libudev/meson.build index 2d51ff7c58..a831391cc1 100644 --- a/src/libudev/meson.build +++ b/src/libudev/meson.build @@ -38,7 +38,7 @@ custom_target( 'libudev.pc', input : 'libudev.pc.in', output : 'libudev.pc', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : pkgconfiglibdir != 'no', install_dir : pkgconfiglibdir) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 1212a1ac53..a9da1e7731 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -3378,8 +3378,13 @@ static const sd_bus_vtable manager_vtable[] = { SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("UserStopDelayUSec", "t", NULL, offsetof(Manager, user_stop_delay), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandlePowerKeyLongPress", "s", property_get_handle_action, offsetof(Manager, handle_power_key_long_press), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandleRebootKey", "s", property_get_handle_action, offsetof(Manager, handle_reboot_key), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandleRebootKeyLongPress", "s", property_get_handle_action, offsetof(Manager, handle_reboot_key_long_press), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandleSuspendKeyLongPress", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key_long_press), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandleHibernateKeyLongPress", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key_long_press), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST), diff --git a/src/login/logind.conf.in b/src/login/logind.conf.in index 926bd6cfe9..8ec979e0e8 100644 --- a/src/login/logind.conf.in +++ b/src/login/logind.conf.in @@ -23,13 +23,16 @@ #InhibitDelayMaxSec=5 #UserStopDelaySec=10 #HandlePowerKey=poweroff +#HandlePowerKeyLongPress=ignore +#HandleRebootKey=reboot +#HandleRebootKeyLongPress=poweroff #HandleSuspendKey=suspend +#HandleSuspendKeyLongPress=hibernate #HandleHibernateKey=hibernate +#HandleHibernateKeyLongPress=ignore #HandleLidSwitch=suspend #HandleLidSwitchExternalPower=suspend #HandleLidSwitchDocked=ignore -#HandleRebootKey=reboot -#HandleRebootKeyLongPress=poweroff #PowerKeyIgnoreInhibited=no #SuspendKeyIgnoreInhibited=no #HibernateKeyIgnoreInhibited=no diff --git a/src/login/meson.build b/src/login/meson.build index 1a2d738e84..bd350569d5 100644 --- a/src/login/meson.build +++ b/src/login/meson.build @@ -80,7 +80,7 @@ foreach tuple : in_files file, input : file + '.in', output: file, - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : tuple[2] and install, install_dir : dir) endforeach diff --git a/src/partition/test-repart.sh b/src/partition/test-repart.sh index 88b696ba01..89f6266539 100755 --- a/src/partition/test-repart.sh +++ b/src/partition/test-repart.sh @@ -201,7 +201,7 @@ $D/zzz7 : start= 6291416, size= 98304, type=0FC63DAF-8483-4772-8E79-3D EOF LOOP="$(losetup -P --show --find "$D/zzz")" - "${udevadm:?}" wait --timeout 60 --initialized=yes --settle "${LOOP:?}" + "${udevadm:?}" wait --timeout 60 --settle "${LOOP:?}" VOLUME="test-repart-$RANDOM" diff --git a/src/resolve/meson.build b/src/resolve/meson.build index b2da249c87..e11aefce7a 100644 --- a/src/resolve/meson.build +++ b/src/resolve/meson.build @@ -168,7 +168,7 @@ custom_target( 'resolved.conf', input : 'resolved.conf.in', output : 'resolved.conf', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : conf.get('ENABLE_RESOLVE') == 1 and install_sysconfdir_samples, install_dir : pkgsysconfdir) diff --git a/src/rpm/meson.build b/src/rpm/meson.build index 4bfeda8883..817665912a 100644 --- a/src/rpm/meson.build +++ b/src/rpm/meson.build @@ -18,7 +18,7 @@ foreach tuple : in_files file, input : file + '.in', output : file, - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : tuple[1], install_dir : tuple.length() > 2 ? tuple[2] : '', build_by_default : true) diff --git a/src/shared/devnode-acl.c b/src/shared/devnode-acl.c index d2b78f392a..357efc1930 100644 --- a/src/shared/devnode-acl.c +++ b/src/shared/devnode-acl.c @@ -9,9 +9,9 @@ #include "device-util.h" #include "devnode-acl.h" #include "dirent-util.h" -#include "escape.h" #include "fd-util.h" #include "format-util.h" +#include "fs-util.h" #include "set.h" #include "string-util.h" #include "util.h" @@ -195,21 +195,18 @@ int devnode_acl_all(const char *seat, dir = opendir("/run/udev/static_node-tags/uaccess"); if (dir) { FOREACH_DIRENT(de, dir, return -errno) { - _cleanup_free_ char *unescaped_devname = NULL; - ssize_t l; - - l = cunescape(de->d_name, UNESCAPE_RELAX, &unescaped_devname); - if (l < 0) - return l; - - n = path_join("/dev", unescaped_devname); - if (!n) - return -ENOMEM; + r = readlinkat_malloc(dirfd(dir), de->d_name, &n); + if (r == -ENOENT) + continue; + if (r < 0) { + log_debug_errno(r, + "Unable to read symlink '/run/udev/static_node-tags/uaccess/%s', ignoring: %m", + de->d_name); + continue; + } log_debug("Found static node %s for seat %s", n, seat); r = set_consume(nodes, n); - if (r == -EEXIST) - continue; if (r < 0) return r; } diff --git a/src/shared/netif-naming-scheme.c b/src/shared/netif-naming-scheme.c index a2bc4fa55a..e95072e048 100644 --- a/src/shared/netif-naming-scheme.c +++ b/src/shared/netif-naming-scheme.c @@ -23,6 +23,7 @@ static const NamingScheme naming_schemes[] = { { "v247", NAMING_V247 }, { "v249", NAMING_V249 }, { "v250", NAMING_V250 }, + { "v251", NAMING_V251 }, /* … add more schemes here, as the logic to name devices is updated … */ EXTRA_NET_NAMING_MAP diff --git a/src/shared/netif-naming-scheme.h b/src/shared/netif-naming-scheme.h index 16b304ce10..5303348e06 100644 --- a/src/shared/netif-naming-scheme.h +++ b/src/shared/netif-naming-scheme.h @@ -22,20 +22,21 @@ * OS versions, but not fully stabilize them. */ typedef enum NamingSchemeFlags { /* First, the individual features */ - NAMING_SR_IOV_V = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a */ - NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6ea */ - NAMING_INFINIBAND = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df */ - NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Use zero acpi_index field, see d81186ef4f6a */ - NAMING_ALLOW_RERENAMES = 1 << 4, /* Allow re-renaming of devices, see #9006 */ - NAMING_STABLE_VIRTUAL_MACS = 1 << 5, /* Use device name to generate MAC, see 6d3646406560 */ - NAMING_NETDEVSIM = 1 << 6, /* Generate names for netdevsim devices, see eaa9d507d855 */ - NAMING_LABEL_NOPREFIX = 1 << 7, /* Don't prepend ID_NET_LABEL_ONBOARD with interface type prefix */ - NAMING_NSPAWN_LONG_HASH = 1 << 8, /* Shorten nspawn interfaces by including 24bit hash, instead of simple truncation */ - NAMING_BRIDGE_NO_SLOT = 1 << 9, /* Don't use PCI hotplug slot information if the corresponding device is a PCI bridge */ - NAMING_SLOT_FUNCTION_ID = 1 << 10, /* Use function_id if present to identify PCI hotplug slots */ - NAMING_16BIT_INDEX = 1 << 11, /* Allow full 16-bit for the onboard index */ - NAMING_REPLACE_STRICTLY = 1 << 12, /* Use udev_replace_ifname() for NAME= rule */ - NAMING_XEN_VIF = 1 << 13, /* GEnerate names for Xen netfront devices */ + NAMING_SR_IOV_V = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a */ + NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6ea */ + NAMING_INFINIBAND = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df */ + NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Use zero acpi_index field, see d81186ef4f6a */ + NAMING_ALLOW_RERENAMES = 1 << 4, /* Allow re-renaming of devices, see #9006 */ + NAMING_STABLE_VIRTUAL_MACS = 1 << 5, /* Use device name to generate MAC, see 6d3646406560 */ + NAMING_NETDEVSIM = 1 << 6, /* Generate names for netdevsim devices, see eaa9d507d855 */ + NAMING_LABEL_NOPREFIX = 1 << 7, /* Don't prepend ID_NET_LABEL_ONBOARD with interface type prefix */ + NAMING_NSPAWN_LONG_HASH = 1 << 8, /* Shorten nspawn interfaces by including 24bit hash, instead of simple truncation */ + NAMING_BRIDGE_NO_SLOT = 1 << 9, /* Don't use PCI hotplug slot information if the corresponding device is a PCI bridge */ + NAMING_SLOT_FUNCTION_ID = 1 << 10, /* Use function_id if present to identify PCI hotplug slots */ + NAMING_16BIT_INDEX = 1 << 11, /* Allow full 16-bit for the onboard index */ + NAMING_REPLACE_STRICTLY = 1 << 12, /* Use udev_replace_ifname() for NAME= rule */ + NAMING_XEN_VIF = 1 << 13, /* Generate names for Xen netfront devices */ + NAMING_BRIDGE_MULTIFUNCTION_SLOT = 1 << 14, /* Use PCI hotplug slot information associated with bridge, but only if PCI device is multifunction */ /* And now the masks that combine the features above */ NAMING_V238 = 0, @@ -47,6 +48,7 @@ typedef enum NamingSchemeFlags { NAMING_V247 = NAMING_V245 | NAMING_BRIDGE_NO_SLOT, NAMING_V249 = NAMING_V247 | NAMING_SLOT_FUNCTION_ID | NAMING_16BIT_INDEX | NAMING_REPLACE_STRICTLY, NAMING_V250 = NAMING_V249 | NAMING_XEN_VIF, + NAMING_V251 = NAMING_V250 | NAMING_BRIDGE_MULTIFUNCTION_SLOT, EXTRA_NET_NAMING_SCHEMES diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c index 3e9e241499..820aa8e286 100644 --- a/src/shutdown/umount.c +++ b/src/shutdown/umount.c @@ -352,9 +352,14 @@ static int md_list_get(MountPoint **head) { if (r < 0) return r; + /* Filter out partitions. */ + r = sd_device_enumerator_add_match_property(e, "DEVTYPE", "disk"); + if (r < 0) + return r; + FOREACH_DEVICE(e, d) { _cleanup_free_ char *p = NULL; - const char *dn; + const char *dn, *md_level; MountPoint *m; dev_t devnum; @@ -362,6 +367,17 @@ static int md_list_get(MountPoint **head) { sd_device_get_devname(d, &dn) < 0) continue; + r = sd_device_get_property_value(d, "MD_LEVEL", &md_level); + if (r < 0) { + log_warning_errno(r, "Failed to get MD_LEVEL property for %s, ignoring: %m", dn); + continue; + } + + /* MD "containers" are a special type of MD devices, used for external metadata. + * Since it doesn't provide RAID functionality in itself we don't need to stop it. */ + if (streq(md_level, "container")) + continue; + p = strdup(dn); if (!p) return -ENOMEM; diff --git a/src/test/meson.build b/src/test/meson.build index 297a65d9af..11517c990b 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -56,6 +56,12 @@ tests += [ libblkid], core_includes], + [files('test-manager.c'), + [libcore, + libshared], + [], + core_includes], + [files('test-emergency-action.c'), [libcore, libshared], diff --git a/src/test/test-load-fragment.c b/src/test/test-load-fragment.c index c3206e1e7a..9cbf22312f 100644 --- a/src/test/test-load-fragment.c +++ b/src/test/test-load-fragment.c @@ -10,6 +10,7 @@ #include "capability-util.h" #include "conf-parser.h" #include "fd-util.h" +#include "fileio.h" #include "format-util.h" #include "fs-util.h" #include "hashmap.h" @@ -416,6 +417,21 @@ TEST(config_parse_exec) { assert_se(r == 0); assert_se(c1->command_next == NULL); + log_info("/* long arg */"); /* See issue #22957. */ + + char x[LONG_LINE_MAX-100], *y; + y = mempcpy(x, "/bin/echo ", STRLEN("/bin/echo ")); + memset(y, 'x', sizeof(x) - STRLEN("/bin/echo ") - 1); + x[sizeof(x) - 1] = '\0'; + + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, x, + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, + "/bin/echo", NULL, y, NULL, false); + log_info("/* empty argument, reset */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "", diff --git a/src/test/test-manager.c b/src/test/test-manager.c new file mode 100644 index 0000000000..89f9277b28 --- /dev/null +++ b/src/test/test-manager.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "manager.h" +#include "tests.h" + +TEST(manager_taint_string) { + Manager m = {}; + + _cleanup_free_ char *a = manager_taint_string(&m); + assert_se(a); + log_debug("taint string w/o split-usr: '%s'", a); + /* split-usr is the only one that is cached in Manager, so we know it's not present. + * The others are queried dynamically, so we'd need to duplicate the logic here + * to test for them. Let's do just one. */ + assert_se(!strstr(a, "split-usr")); + + if (cg_all_unified() == 0) + assert_se(strstr(a, "cgroupsv1")); + else + assert_se(!strstr(a, "cgroupsv1")); + + m.taint_usr = true; + _cleanup_free_ char *b = manager_taint_string(&m); + assert_se(b); + log_debug("taint string w/ split-usr: '%s'", b); + assert_se(strstr(b, "split-usr")); +} + +DEFINE_TEST_MAIN(LOG_DEBUG); diff --git a/src/timesync/meson.build b/src/timesync/meson.build index 8ecfbfab82..35467026a8 100644 --- a/src/timesync/meson.build +++ b/src/timesync/meson.build @@ -39,7 +39,7 @@ custom_target( 'timesyncd.conf', input : 'timesyncd.conf.in', output : 'timesyncd.conf', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : conf.get('ENABLE_TIMESYNCD') == 1 and install_sysconfdir_samples, install_dir : pkgsysconfdir) diff --git a/src/udev/meson.build b/src/udev/meson.build index 354b923291..79964a7d8e 100644 --- a/src/udev/meson.build +++ b/src/udev/meson.build @@ -166,7 +166,7 @@ custom_target( 'udev.pc', input : 'udev.pc.in', output : 'udev.pc', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : pkgconfigdatadir != 'no', install_dir : pkgconfigdatadir) diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c index 9e4297adaf..114fda663e 100644 --- a/src/udev/udev-builtin-net_id.c +++ b/src/udev/udev-builtin-net_id.c @@ -451,8 +451,15 @@ static int dev_pci_slot(sd_device *dev, const LinkInfo *info, NetNames *names) { * devices that will try to claim the same index and that would create name * collision. */ if (naming_scheme_has(NAMING_BRIDGE_NO_SLOT) && is_pci_bridge(hotplug_slot_dev)) { - log_device_debug(dev, "Not using slot information because the PCI device is a bridge."); - return 0; + if (naming_scheme_has(NAMING_BRIDGE_MULTIFUNCTION_SLOT) && !is_pci_multifunction(names->pcidev)) { + log_device_debug(dev, "Not using slot information because the PCI device associated with the hotplug slot is a bridge and the PCI device has single function."); + return 0; + } + + if (!naming_scheme_has(NAMING_BRIDGE_MULTIFUNCTION_SLOT)) { + log_device_debug(dev, "Not using slot information because the PCI device is a bridge."); + return 0; + } } break; diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index d9af8bfd20..78e8f3018c 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -966,9 +966,6 @@ static int update_devnode(UdevEvent *event) { if (r < 0 && r != -ENOENT) return log_device_error_errno(dev, r, "Failed to get devnode mode: %m"); } - if (event->mode == MODE_INVALID && gid_is_valid(event->gid) && event->gid > 0) - /* If group is set, but mode is not set, "upgrade" mode for the group. */ - event->mode = 0660; bool apply_mac = device_for_action(dev, SD_DEVICE_ADD); diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c index c313181041..deacbc31c5 100644 --- a/src/udev/udev-node.c +++ b/src/udev/udev-node.c @@ -13,6 +13,7 @@ #include "device-private.h" #include "device-util.h" #include "dirent-util.h" +#include "escape.h" #include "fd-util.h" #include "format-util.h" #include "fs-util.h" @@ -590,51 +591,30 @@ int udev_node_remove(sd_device *dev) { return 0; } -int udev_node_apply_permissions( - sd_device *dev, +static int udev_node_apply_permissions_impl( + sd_device *dev, /* can be NULL, only used for logging. */ + int node_fd, + const char *devnode, bool apply_mac, mode_t mode, uid_t uid, gid_t gid, OrderedHashmap *seclabel_list) { - const char *devnode, *subsystem; bool apply_mode, apply_uid, apply_gid; - _cleanup_close_ int node_fd = -1; struct stat stats; - dev_t devnum; int r; - assert(dev); - - r = sd_device_get_devname(dev, &devnode); - if (r < 0) - return log_device_debug_errno(dev, r, "Failed to get devname: %m"); - r = sd_device_get_subsystem(dev, &subsystem); - if (r < 0) - return log_device_debug_errno(dev, r, "Failed to get subsystem: %m"); - r = sd_device_get_devnum(dev, &devnum); - if (r < 0) - return log_device_debug_errno(dev, r, "Failed to get devnum: %m"); - - if (streq(subsystem, "block")) - mode |= S_IFBLK; - else - mode |= S_IFCHR; - - node_fd = sd_device_open(dev, O_PATH|O_CLOEXEC); - if (node_fd < 0) { - if (ERRNO_IS_DEVICE_ABSENT(node_fd)) { - log_device_debug_errno(dev, node_fd, "Device node %s is missing, skipping handling.", devnode); - return 0; /* This is necessarily racey, so ignore missing the device */ - } - - return log_device_debug_errno(dev, node_fd, "Cannot open node %s: %m", devnode); - } + assert(node_fd >= 0); + assert(devnode); if (fstat(node_fd, &stats) < 0) return log_device_debug_errno(dev, errno, "cannot stat() node %s: %m", devnode); + /* If group is set, but mode is not set, "upgrade" mode for the group. */ + if (mode == MODE_INVALID && gid_is_valid(gid) && gid > 0) + mode = 0660; + apply_mode = mode != MODE_INVALID && (stats.st_mode & 0777) != (mode & 0777); apply_uid = uid_is_valid(uid) && stats.st_uid != uid; apply_gid = gid_is_valid(gid) && stats.st_gid != gid; @@ -708,3 +688,95 @@ int udev_node_apply_permissions( return 0; } + +int udev_node_apply_permissions( + sd_device *dev, + bool apply_mac, + mode_t mode, + uid_t uid, + gid_t gid, + OrderedHashmap *seclabel_list) { + + const char *devnode; + _cleanup_close_ int node_fd = -1; + int r; + + assert(dev); + + r = sd_device_get_devname(dev, &devnode); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get devname: %m"); + + node_fd = sd_device_open(dev, O_PATH|O_CLOEXEC); + if (node_fd < 0) { + if (ERRNO_IS_DEVICE_ABSENT(node_fd)) { + log_device_debug_errno(dev, node_fd, "Device node %s is missing, skipping handling.", devnode); + return 0; /* This is necessarily racey, so ignore missing the device */ + } + + return log_device_debug_errno(dev, node_fd, "Cannot open node %s: %m", devnode); + } + + return udev_node_apply_permissions_impl(dev, node_fd, devnode, apply_mac, mode, uid, gid, seclabel_list); +} + +int static_node_apply_permissions( + const char *name, + mode_t mode, + uid_t uid, + gid_t gid, + char **tags) { + + _cleanup_free_ char *unescaped_filename = NULL; + _cleanup_close_ int node_fd = -1; + const char *devnode; + struct stat stats; + int r; + + assert(name); + + if (uid == UID_INVALID && gid == GID_INVALID && mode == MODE_INVALID && !tags) + return 0; + + devnode = strjoina("/dev/", name); + + node_fd = open(devnode, O_PATH|O_CLOEXEC); + if (node_fd < 0) { + if (errno != ENOENT) + return log_error_errno(errno, "Failed to open %s: %m", devnode); + return 0; + } + + if (fstat(node_fd, &stats) < 0) + return log_error_errno(errno, "Failed to stat %s: %m", devnode); + + if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode)) { + log_warning("%s is neither block nor character device, ignoring.", devnode); + return 0; + } + + if (!strv_isempty(tags)) { + unescaped_filename = xescape(name, "/."); + if (!unescaped_filename) + return log_oom(); + } + + /* export the tags to a directory as symlinks, allowing otherwise dead nodes to be tagged */ + STRV_FOREACH(t, tags) { + _cleanup_free_ char *p = NULL; + + p = path_join("/run/udev/static_node-tags/", *t, unescaped_filename); + if (!p) + return log_oom(); + + r = mkdir_parents(p, 0755); + if (r < 0) + return log_error_errno(r, "Failed to create parent directory for %s: %m", p); + + r = symlink(devnode, p); + if (r < 0 && errno != EEXIST) + return log_error_errno(errno, "Failed to create symlink %s -> %s: %m", p, devnode); + } + + return udev_node_apply_permissions_impl(NULL, node_fd, devnode, false, mode, uid, gid, NULL); +} diff --git a/src/udev/udev-node.h b/src/udev/udev-node.h index a34af77146..86a829545a 100644 --- a/src/udev/udev-node.h +++ b/src/udev/udev-node.h @@ -15,6 +15,13 @@ int udev_node_apply_permissions( uid_t uid, gid_t gid, OrderedHashmap *seclabel_list); +int static_node_apply_permissions( + const char *name, + mode_t mode, + uid_t uid, + gid_t gid, + char **tags); + int udev_node_remove(sd_device *dev); int udev_node_update(sd_device *dev, sd_device *dev_old); diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index b46cb0f906..1c20775f08 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -9,7 +9,6 @@ #include "device-private.h" #include "device-util.h" #include "dirent-util.h" -#include "escape.h" #include "fd-util.h" #include "fileio.h" #include "format-util.h" @@ -30,6 +29,7 @@ #include "udev-builtin.h" #include "udev-event.h" #include "udev-netlink.h" +#include "udev-node.h" #include "udev-rules.h" #include "udev-util.h" #include "user-util.h" @@ -2536,72 +2536,6 @@ int udev_rules_apply_to_event( return 0; } -static int apply_static_dev_perms(const char *devnode, uid_t uid, gid_t gid, mode_t mode, char **tags) { - char device_node[UDEV_PATH_SIZE], tags_dir[UDEV_PATH_SIZE], tag_symlink[UDEV_PATH_SIZE]; - _cleanup_free_ char *unescaped_filename = NULL; - struct stat stats; - int r; - - assert(devnode); - - if (uid == UID_INVALID && gid == GID_INVALID && mode == MODE_INVALID && !tags) - return 0; - - strscpyl(device_node, sizeof(device_node), "/dev/", devnode, NULL); - if (stat(device_node, &stats) < 0) { - if (errno != ENOENT) - return log_error_errno(errno, "Failed to stat %s: %m", device_node); - return 0; - } - - if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode)) { - log_warning("%s is neither block nor character device, ignoring.", device_node); - return 0; - } - - if (!strv_isempty(tags)) { - unescaped_filename = xescape(devnode, "/."); - if (!unescaped_filename) - return log_oom(); - } - - /* export the tags to a directory as symlinks, allowing otherwise dead nodes to be tagged */ - STRV_FOREACH(t, tags) { - strscpyl(tags_dir, sizeof(tags_dir), "/run/udev/static_node-tags/", *t, "/", NULL); - r = mkdir_p(tags_dir, 0755); - if (r < 0) - return log_error_errno(r, "Failed to create %s: %m", tags_dir); - - strscpyl(tag_symlink, sizeof(tag_symlink), tags_dir, unescaped_filename, NULL); - r = symlink(device_node, tag_symlink); - if (r < 0 && errno != EEXIST) - return log_error_errno(errno, "Failed to create symlink %s -> %s: %m", - tag_symlink, device_node); - } - - /* don't touch the permissions if only the tags were set */ - if (uid == UID_INVALID && gid == GID_INVALID && mode == MODE_INVALID) - return 0; - - if (mode == MODE_INVALID) - mode = gid_is_valid(gid) ? 0660 : 0600; - if (!uid_is_valid(uid)) - uid = 0; - if (!gid_is_valid(gid)) - gid = 0; - - r = chmod_and_chown(device_node, mode, uid, gid); - if (r == -ENOENT) - return 0; - if (r < 0) - return log_error_errno(r, "Failed to chown '%s' %u %u: %m", device_node, uid, gid); - else - log_debug("chown '%s' %u:%u with mode %#o", device_node, uid, gid, mode); - - (void) utimensat(AT_FDCWD, device_node, NULL, 0); - return 0; -} - static int udev_rule_line_apply_static_dev_perms(UdevRuleLine *rule_line) { _cleanup_strv_free_ char **tags = NULL; uid_t uid = UID_INVALID; @@ -2626,7 +2560,7 @@ static int udev_rule_line_apply_static_dev_perms(UdevRuleLine *rule_line) { if (r < 0) return log_oom(); } else if (token->type == TK_A_OPTIONS_STATIC_NODE) { - r = apply_static_dev_perms(token->value, uid, gid, mode, tags); + r = static_node_apply_permissions(token->value, mode, uid, gid, tags); if (r < 0) return r; } diff --git a/src/udev/udevadm-lock.c b/src/udev/udevadm-lock.c index 3e5d7b356f..951711f120 100644 --- a/src/udev/udevadm-lock.c +++ b/src/udev/udevadm-lock.c @@ -144,6 +144,7 @@ static int find_devno( const char *device, bool backing) { + _cleanup_close_ int fd = -1; dev_t devt, whole_devt; struct stat st; int r; @@ -153,7 +154,11 @@ static int find_devno( assert(*devnos || *n_devnos == 0); assert(device); - if (stat(device, &st) < 0) + fd = open(device, O_CLOEXEC|O_PATH); + if (fd < 0) + return log_error_errno(errno, "Failed to open '%s': %m", device); + + if (fstat(fd, &st) < 0) return log_error_errno(errno, "Failed to stat '%s': %m", device); if (S_ISBLK(st.st_mode)) @@ -166,20 +171,13 @@ static int find_devno( devt = st.st_dev; else { _cleanup_close_ int regfd = -1; - struct stat st2; /* If major(st.st_dev) is zero, this might mean we are backed by btrfs, which needs special * handing, to get the backing device node. */ - regfd = open(device, O_RDONLY|O_CLOEXEC|O_NONBLOCK); + regfd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK); if (regfd < 0) - return log_error_errno(errno, "Failed to open '%s': %m", device); - - /* Extra safety: let's check we are still looking at the same file */ - if (fstat(regfd, &st2) < 0) - return log_error_errno(errno, "Failed to stat '%s': %m", device); - if (!stat_inode_same(&st, &st2)) - return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "File '%s' was replaced while we were looking at it.", device); + return log_error_errno(regfd, "Failed to open '%s': %m", device); r = btrfs_get_block_device_fd(regfd, &devt); if (r == -ENOTTY) diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 4a37a76924..078cd960b4 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -442,6 +442,12 @@ static int device_get_whole_disk(sd_device *dev, sd_device **ret_device, const c if (r < 0) return log_device_debug_errno(dev, r, "Failed to get sysname: %m"); + /* Exclude the following devices: + * For "dm-", see the comment added by e918a1b5a94f270186dca59156354acd2a596494. + * For "md", see the commit message of 2e5b17d01347d3c3118be2b8ad63d20415dbb1f0, + * but not sure the assumption is still valid even when partitions are created on the md + * devices, surprisingly which seems to be possible, see PR #22973. + * For "drbd", see the commit message of fee854ee8ccde0cd28e0f925dea18cce35f3993d. */ if (STARTSWITH_SET(val, "dm-", "md", "drbd")) goto irrelevant; diff --git a/src/vconsole/meson.build b/src/vconsole/meson.build index eb22358c20..bb3c3c5a03 100644 --- a/src/vconsole/meson.build +++ b/src/vconsole/meson.build @@ -4,6 +4,6 @@ custom_target( '90-vconsole.rules', input : '90-vconsole.rules.in', output : '90-vconsole.rules', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : conf.get('ENABLE_VCONSOLE') == 1, install_dir : udevrulesdir) diff --git a/sysctl.d/meson.build b/sysctl.d/meson.build index 1745a13bfb..ecec903d1b 100644 --- a/sysctl.d/meson.build +++ b/sysctl.d/meson.build @@ -16,7 +16,7 @@ custom_target( '50-coredump.conf', input : '50-coredump.conf.in', output : '50-coredump.conf', - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : conf.get('ENABLE_COREDUMP') == 1, install_dir : sysctldir) diff --git a/sysusers.d/meson.build b/sysusers.d/meson.build index 73d507f1f1..608c4b744a 100644 --- a/sysusers.d/meson.build +++ b/sysusers.d/meson.build @@ -33,7 +33,7 @@ foreach tuple : in_files file, input : file + '.in', output: file, - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : tuple[1], install_dir : sysusersdir) endforeach diff --git a/test/test-network/conf/25-ip6tnl-external.netdev b/test/test-network/conf/25-ip6tnl-tunnel-external.netdev index 68926cdd1e..68926cdd1e 100644 --- a/test/test-network/conf/25-ip6tnl-external.netdev +++ b/test/test-network/conf/25-ip6tnl-tunnel-external.netdev diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 0a8349fd5b..d626e4b641 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -1711,7 +1711,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', '25-veth.netdev', '25-ip6tnl-slaac.network', '25-ipv6-prefix.network', '25-ip6tnl-tunnel-local-slaac.netdev', '25-ip6tnl-tunnel-local-slaac.network', - '25-ip6tnl-external.netdev', '26-netdev-link-local-addressing-yes.network') + '25-ip6tnl-tunnel-external.netdev', '26-netdev-link-local-addressing-yes.network') start_networkd() self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'ip6tnl-slaac:degraded', 'ip6tnl-external:degraded', diff --git a/test/units/testsuite-58.sh b/test/units/testsuite-58.sh index 21f762d399..8dadcc0a95 100755 --- a/test/units/testsuite-58.sh +++ b/test/units/testsuite-58.sh @@ -173,20 +173,22 @@ rm -r /tmp/testsuite-58.3-defs/ # testcase for #21817 mkdir -p /tmp/testsuite-58-issue-21817-defs/ truncate -s 100m /var/tmp/testsuite-58-issue-21817.img -LOOP=$(losetup -P --show -f /var/tmp/testsuite-58-issue-21817.img) -udevadm wait --timeout 60 --initialized=yes --settle "${LOOP:?}" -printf 'size=50M,type=%s\n,\n' "${root_guid}" | sfdisk -X gpt "$LOOP" +sfdisk /var/tmp/testsuite-58-issue-21817.img <<EOF +label: gpt + +size=50M, type=${root_guid} +, +EOF cat >/tmp/testsuite-58-issue-21817-defs/test.conf <<EOF [Partition] Type=root EOF -systemd-repart --pretty=yes --definitions /tmp/testsuite-58-issue-21817-defs/ "$LOOP" -sfdisk --dump "$LOOP" | tee /tmp/testsuite-58-issue-21817.dump -losetup -d "$LOOP" +systemd-repart --pretty=yes --definitions /tmp/testsuite-58-issue-21817-defs/ --dry-run=no /var/tmp/testsuite-58-issue-21817.img +sfdisk --dump /var/tmp/testsuite-58-issue-21817.img | tee /tmp/testsuite-58-issue-21817.dump -grep -qiF "p1 : start= 2048, size= 102400, type=${root_guid}," /tmp/testsuite-58-issue-21817.dump +grep -qiF "/var/tmp/testsuite-58-issue-21817.img1 : start= 2048, size= 102400, type=${root_guid}," /tmp/testsuite-58-issue-21817.dump # Accept both unpadded (pre-v2.38 util-linux) and padded (v2.38+ util-linux) sizes -grep -qE "p2 : start= 104448, size= (100319| 98304)," /tmp/testsuite-58-issue-21817.dump +grep -qE "/var/tmp/testsuite-58-issue-21817.img2 : start= 104448, size= (100319| 98304)," /tmp/testsuite-58-issue-21817.dump rm /var/tmp/testsuite-58-issue-21817.img /tmp/testsuite-58-issue-21817.dump rm -r /tmp/testsuite-58-issue-21817-defs/ @@ -216,7 +218,7 @@ EOF truncate -s 100m "/tmp/testsuite-58-sector-$1.img" LOOP=$(losetup -b "$1" -P --show -f "/tmp/testsuite-58-sector-$1.img" ) - udevadm wait --timeout 60 --initialized=yes --settle "${LOOP:?}" + udevadm wait --timeout 60 --settle "${LOOP:?}" systemd-repart --pretty=yes --definitions=/tmp/testsuite-58-sector/ --seed=750b6cd5c4ae4012a15e7be3c29e6a47 --empty=require --dry-run=no "$LOOP" rm -rf /tmp/testsuite-58-sector sfdisk --verify "$LOOP" diff --git a/test/units/testsuite-64.sh b/test/units/testsuite-64.sh index 44f362ec6f..5f50131dd5 100755 --- a/test/units/testsuite-64.sh +++ b/test/units/testsuite-64.sh @@ -168,7 +168,7 @@ $(printf 'name="test%d", size=2M\n' {1..50}) EOF # Initial partition table - sfdisk -q -X gpt "$blockdev" <"$partscript" + udevadm lock --device="$blockdev" sfdisk -q -X gpt "$blockdev" <"$partscript" # Delete the partitions, immediately recreate them, wait for udev to settle # down, and then check if we have any dangling symlinks in /dev/disk/. Rinse @@ -177,8 +177,8 @@ EOF # On unpatched udev versions the delete-recreate cycle may trigger a race # leading to dead symlinks in /dev/disk/ for i in {1..100}; do - sfdisk -q --delete "$blockdev" - sfdisk -q -X gpt "$blockdev" <"$partscript" + udevadm lock --device="$blockdev" sfdisk -q --delete "$blockdev" + udevadm lock --device="$blockdev" sfdisk -q -X gpt "$blockdev" <"$partscript" if ((i % 10 == 0)); then udevadm wait --settle --timeout=30 "$blockdev" @@ -281,7 +281,7 @@ testcase_btrfs_basic() { echo "Multiple devices: using partitions, data: single, metadata: raid1" uuid="deadbeef-dead-dead-beef-000000000001" label="btrfs_mpart" - sfdisk --wipe=always "${devices[0]}" <<EOF + udevadm lock --device="${devices[0]}" sfdisk --wipe=always "${devices[0]}" <<EOF label: gpt name="diskpart1", size=85M diff --git a/tmpfiles.d/meson.build b/tmpfiles.d/meson.build index b8d3919025..306e066f22 100644 --- a/tmpfiles.d/meson.build +++ b/tmpfiles.d/meson.build @@ -41,7 +41,7 @@ foreach pair : in_files pair[0], input : pair[0] + '.in', output: pair[0], - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : enable_tmpfiles, install_dir : tmpfilesdir) else diff --git a/tools/check-help.sh b/tools/check-help.sh index 76ac292675..f97429364e 100755 --- a/tools/check-help.sh +++ b/tools/check-help.sh @@ -3,8 +3,8 @@ set -eu set -o pipefail -# Note: `grep ... >/dev/null` instead of just `grep -q` is used intentionally -# here, since `grep -q` exits on the first match causing SIGPIPE being +# Note: 'grep ... >/dev/null' instead of just 'grep -q' is used intentionally +# here, since 'grep -q' exits on the first match causing SIGPIPE being # sent to the sender. BINARY="${1:?}" @@ -24,11 +24,11 @@ fi # --help prints something. Also catches case where args are ignored. if ! "$BINARY" --help | grep . >/dev/null; then - echo "$(basename "$BINARY") --help output is empty." + echo "$(basename "$BINARY") --help output is empty" exit 2 fi -# no --help output to stdout +# no --help output to stderr if "$BINARY" --help 2>&1 1>/dev/null | grep .; then echo "$(basename "$BINARY") --help prints to stderr" exit 3 @@ -39,3 +39,9 @@ if ! ("$BINARY" --no-such-parameter 2>&1 1>/dev/null || :) | grep . >/dev/null; echo "$(basename "$BINARY") with an unknown parameter does not print to stderr" exit 4 fi + +# --help and -h are equivalent +if ! diff <("$BINARY" -h) <("$BINARY" --help); then + echo "$(basename "$BINARY") --help and -h are not identical" + exit 5 +fi diff --git a/tools/check-version.sh b/tools/check-version.sh new file mode 100755 index 0000000000..faefb46883 --- /dev/null +++ b/tools/check-version.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later +set -eu +set -o pipefail + +# Note: 'grep ... >/dev/null' instead of just 'grep -q' is used intentionally +# here, since 'grep -q' exits on the first match causing SIGPIPE being +# sent to the sender. + +BINARY="${1:?}" +VERSION="${2:?}" +export SYSTEMD_LOG_LEVEL=info + +if [[ ! -x "$BINARY" ]]; then + echo "$BINARY is not an executable" + exit 1 +fi + +# --version prints something. Also catches case where args are ignored. +if ! "$BINARY" --version | grep . >/dev/null; then + echo "$(basename "$BINARY") --version output is empty" + exit 2 +fi + +# no --version output to stderr +if "$BINARY" --version 2>&1 1>/dev/null | grep .; then + echo "$(basename "$BINARY") --version prints to stderr" + exit 3 +fi + +# project version appears in version output +out="$("$BINARY" --version)" +if ! grep -F "$VERSION" >/dev/null <<<"$out"; then + echo "$(basename "$BINARY") --version output does not match '$VERSION': $out" + exit 4 +fi diff --git a/tools/meson-render-jinja2.py b/tools/meson-render-jinja2.py index 89735c70ed..fbaae596de 100755 --- a/tools/meson-render-jinja2.py +++ b/tools/meson-render-jinja2.py @@ -28,9 +28,10 @@ def render(filename, defines): if __name__ == '__main__': defines = parse_config_h(sys.argv[1]) - output = render(sys.argv[2], defines) - with open(sys.argv[3], 'w') as f: + defines.update(parse_config_h(sys.argv[2])) + output = render(sys.argv[3], defines) + with open(sys.argv[4], 'w') as f: f.write(output) f.write('\n') - info = os.stat(sys.argv[2]) - os.chmod(sys.argv[3], info.st_mode) + info = os.stat(sys.argv[3]) + os.chmod(sys.argv[4], info.st_mode) diff --git a/units/meson.build b/units/meson.build index 8a3bd0da51..e8f81f2230 100644 --- a/units/meson.build +++ b/units/meson.build @@ -276,7 +276,7 @@ foreach tuple : in_units file, input : file + '.in', output : file, - command : [meson_render_jinja2, config_h, '@INPUT@', '@OUTPUT@'], + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], install : install, install_dir : systemunitdir) |