summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.github/workflows/ubuntu-build-check.sh2
-rw-r--r--.travis.yml187
-rw-r--r--NEWS10
-rw-r--r--coccinelle/set_ensure_put.cocci18
-rw-r--r--docs/RANDOM_SEEDS.md2
-rw-r--r--hwdb.d/60-autosuspend.hwdb44
-rw-r--r--hwdb.d/70-mouse.hwdb2
-rw-r--r--hwdb.d/meson.build36
-rwxr-xr-xhwdb.d/parse_hwdb.py18
-rw-r--r--man/bootup.xml2
-rw-r--r--man/custom-html.xsl12
-rw-r--r--man/homectl.xml3
-rw-r--r--man/repart.d.xml42
-rw-r--r--man/resolved.conf.xml59
-rw-r--r--man/systemd-makefs@.service.xml6
-rw-r--r--man/systemd-modules-load.service.xml13
-rw-r--r--man/systemd-resolved.service.xml18
-rw-r--r--man/systemd.exec.xml37
-rw-r--r--man/systemd.network.xml151
-rw-r--r--man/systemd.resource-control.xml4
-rw-r--r--meson.build38
-rw-r--r--meson_options.txt2
-rw-r--r--rules.d/50-udev-default.rules.in3
-rw-r--r--rules.d/60-autosuspend.rules14
-rw-r--r--rules.d/60-serial.rules5
-rw-r--r--rules.d/61-autosuspend-manual.rules19
-rw-r--r--rules.d/meson.build10
-rw-r--r--src/analyze/analyze.c4
-rw-r--r--src/basic/dlfcn-util.h8
-rw-r--r--src/basic/hashmap.c64
-rw-r--r--src/basic/hashmap.h13
-rw-r--r--src/basic/log.c51
-rw-r--r--src/basic/log.h4
-rw-r--r--src/basic/memory-util.h1
-rw-r--r--src/basic/meson.build4
-rw-r--r--src/basic/selinux-util.c158
-rw-r--r--src/basic/set.h18
-rw-r--r--src/boot/efi/boot.c8
-rw-r--r--src/busctl/busctl.c4
-rw-r--r--src/cgls/cgls.c4
-rw-r--r--src/cgtop/cgtop.c4
-rw-r--r--src/core/automount.c32
-rw-r--r--src/core/bpf-firewall.c16
-rw-r--r--src/core/dbus-cgroup.c164
-rw-r--r--src/core/dbus-execute.c77
-rw-r--r--src/core/dbus-manager.c38
-rw-r--r--src/core/emergency-action.c35
-rw-r--r--src/core/execute.c19
-rw-r--r--src/core/execute.h4
-rw-r--r--src/core/job.c51
-rw-r--r--src/core/job.h3
-rw-r--r--src/core/load-fragment-gperf.gperf.m42
-rw-r--r--src/core/load-fragment.c71
-rw-r--r--src/core/load-fragment.h1
-rw-r--r--src/core/main.c7
-rw-r--r--src/core/manager.c132
-rw-r--r--src/core/manager.h6
-rw-r--r--src/core/namespace.c16
-rw-r--r--src/core/namespace.h4
-rw-r--r--src/core/org.freedesktop.systemd1.conf4
-rw-r--r--src/core/transaction.c8
-rw-r--r--src/core/unit.c7
-rw-r--r--src/coredump/coredumpctl.c4
-rw-r--r--src/delta/delta.c4
-rw-r--r--src/detect-virt/detect-virt.c4
-rw-r--r--src/dissect/dissect.c2
-rw-r--r--src/escape/escape.c4
-rw-r--r--src/home/homectl.c4
-rw-r--r--src/hostname/hostnamectl.c4
-rw-r--r--src/hostname/hostnamed.c5
-rw-r--r--src/hwdb/hwdb.c4
-rw-r--r--src/id128/id128.c4
-rw-r--r--src/journal-remote/journal-remote-main.c2
-rw-r--r--src/journal-remote/journal-upload.c2
-rw-r--r--src/journal/cat.c4
-rw-r--r--src/journal/journalctl.c11
-rw-r--r--src/libsystemd-network/dhcp-lease-internal.h3
-rw-r--r--src/libsystemd-network/network-internal.h4
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c2
-rw-r--r--src/libsystemd/sd-bus/bus-message.c13
-rw-r--r--src/libsystemd/sd-device/device-monitor.c25
-rw-r--r--src/libsystemd/sd-event/sd-event.c7
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.c29
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.h1
-rw-r--r--src/libsystemd/sd-network/sd-network.c28
-rw-r--r--src/locale/localectl.c4
-rw-r--r--src/locale/localed.c9
-rw-r--r--src/locale/meson.build2
-rw-r--r--src/login/loginctl.c4
-rw-r--r--src/login/logind-brightness.c10
-rw-r--r--src/login/logind.c2
-rw-r--r--src/login/user-runtime-dir.c6
-rw-r--r--src/machine/machinectl.c4
-rw-r--r--src/network/meson.build2
-rw-r--r--src/network/netdev/wireguard.c40
-rw-r--r--src/network/networkctl.c106
-rw-r--r--src/network/networkd-address.c16
-rw-r--r--src/network/networkd-dhcp-common.c13
-rw-r--r--src/network/networkd-dhcp-server.c371
-rw-r--r--src/network/networkd-dhcp-server.h7
-rw-r--r--src/network/networkd-dhcp4.c9
-rw-r--r--src/network/networkd-dhcp6.c2
-rw-r--r--src/network/networkd-link.c72
-rw-r--r--src/network/networkd-link.h3
-rw-r--r--src/network/networkd-manager.c61
-rw-r--r--src/network/networkd-ndisc.c40
-rw-r--r--src/network/networkd-neighbor.c15
-rw-r--r--src/network/networkd-network-gperf.gperf27
-rw-r--r--src/network/networkd-network.c27
-rw-r--r--src/network/networkd-network.h33
-rw-r--r--src/network/networkd-nexthop.c12
-rw-r--r--src/network/networkd-route.c12
-rw-r--r--src/network/networkd-routing-policy-rule.c18
-rw-r--r--src/network/tc/ets.c338
-rw-r--r--src/network/tc/ets.h25
-rw-r--r--src/network/tc/qdisc.c1
-rw-r--r--src/network/tc/qdisc.h2
-rw-r--r--src/nspawn/nspawn-mount.c4
-rw-r--r--src/nspawn/nspawn.c2
-rw-r--r--src/nss-systemd/nss-systemd.c71
-rw-r--r--src/nss-systemd/nss-systemd.h13
-rw-r--r--src/nss-systemd/nss-systemd.sym4
-rw-r--r--src/nss-systemd/userdb-glue.c52
-rw-r--r--src/partition/repart.c49
-rwxr-xr-xsrc/partition/test-repart.sh9
-rw-r--r--src/portable/portable.c14
-rw-r--r--src/portable/portablectl.c4
-rw-r--r--src/resolve/resolvectl.c4
-rw-r--r--src/resolve/resolved-dns-query.c50
-rw-r--r--src/resolve/resolved-dns-query.h2
-rw-r--r--src/resolve/resolved-dns-scope.c33
-rw-r--r--src/resolve/resolved-dns-scope.h2
-rw-r--r--src/resolve/resolved-dns-stub.c35
-rw-r--r--src/resolve/resolved-dns-transaction.c38
-rw-r--r--src/resolve/resolved-dns-transaction.h2
-rw-r--r--src/resolve/resolved-dns-trust-anchor.c14
-rw-r--r--src/resolve/resolved-dns-zone.c23
-rw-r--r--src/resolve/resolved-etc-hosts.c7
-rw-r--r--src/resolve/resolved-gperf.gperf21
-rw-r--r--src/resolve/resolved-manager.h5
-rw-r--r--src/resolve/resolved.c2
-rw-r--r--src/resolve/resolved.conf.in1
-rw-r--r--src/shared/bus-unit-util.c41
-rw-r--r--src/shared/bus-util.c6
-rw-r--r--src/shared/dissect-image.c37
-rw-r--r--src/shared/dissect-image.h2
-rw-r--r--src/shared/seccomp-util.c15
-rw-r--r--src/shared/seccomp-util.h2
-rw-r--r--src/shared/userdb.c213
-rw-r--r--src/shared/userdb.h3
-rw-r--r--src/shared/wifi-util.c45
-rw-r--r--src/socket-proxy/socket-proxyd.c30
-rw-r--r--src/systemctl/systemctl.c2
-rw-r--r--src/systemd/sd-dhcp-server.h4
-rw-r--r--src/systemd/sd-network.h22
-rw-r--r--src/sysusers/sysusers.c2
-rw-r--r--src/sysv-generator/sysv-generator.c19
-rw-r--r--src/test/test-chase-symlinks.c4
-rw-r--r--src/test/test-namespace.c4
-rw-r--r--src/test/test-ns.c4
-rw-r--r--src/test/test-set.c46
-rw-r--r--src/timedate/timedatectl.c4
-rw-r--r--src/timedate/timedated.c5
-rw-r--r--src/tmpfiles/meson.build7
-rw-r--r--src/tmpfiles/tmpfiles.c10
-rw-r--r--src/udev/udev-event.c25
-rw-r--r--src/udev/udev-event.h6
-rw-r--r--src/udev/udevadm-monitor.c21
-rw-r--r--src/udev/udevadm-test.c2
-rw-r--r--src/udev/udevadm.c5
-rw-r--r--src/udev/udevd.c2
-rw-r--r--src/update-done/update-done.c4
-rw-r--r--src/user-sessions/user-sessions.c4
-rw-r--r--src/userdb/userdbctl.c4
-rw-r--r--src/userdb/userwork.c5
-rw-r--r--src/xdg-autostart-generator/xdg-autostart-service.c12
-rwxr-xr-xtest/TEST-21-SYSUSERS/test.sh4
-rw-r--r--test/TEST-52-HONORFIRSTSHUTDOWN/Makefile16
-rwxr-xr-xtest/TEST-52-HONORFIRSTSHUTDOWN/fini.sh10
-rwxr-xr-xtest/TEST-52-HONORFIRSTSHUTDOWN/test.sh19
-rw-r--r--test/fuzz/fuzz-bus-message/zero-offset-to-null-pointerbin0 -> 64 bytes
-rw-r--r--test/fuzz/fuzz-netdev-parser/wireguard-duplicated-endpoint6
-rw-r--r--test/fuzz/fuzz-network-parser/directives.network16
-rw-r--r--test/fuzz/fuzz-network-parser/dns-trust-anchor-duplicate.network2
-rw-r--r--test/fuzz/fuzz-unit-file/directives.service2
-rw-r--r--test/meson.build2
-rw-r--r--test/test-functions2
-rw-r--r--test/test-network/conf/25-qdisc-ets.network20
-rwxr-xr-xtest/test-network/systemd-networkd-tests.py26
-rwxr-xr-xtest/testsuite-52.units/testsuite-52.service6
-rwxr-xr-xtest/testsuite-52.units/testsuite-52.sh18
-rw-r--r--test/units/test-honor-first-shutdown.service11
-rwxr-xr-xtest/units/test-honor-first-shutdown.sh3
-rwxr-xr-xtools/make-autosuspend-rules.py24
-rwxr-xr-xtravis-ci/managers/debian.sh34
-rwxr-xr-xtravis-ci/managers/fedora.sh84
196 files changed, 2504 insertions, 2141 deletions
diff --git a/.github/workflows/ubuntu-build-check.sh b/.github/workflows/ubuntu-build-check.sh
index fb7c71ecb8..75fc36fffb 100755
--- a/.github/workflows/ubuntu-build-check.sh
+++ b/.github/workflows/ubuntu-build-check.sh
@@ -102,7 +102,7 @@ for args in "${ARGS[@]}"; do
SECONDS=0
info "Checking build with $args"
- if ! AR="$AR" CC="$CC" CXX="$CXX" meson -Dtests=unsafe -Dslow-tests=true --werror $args build; then
+ if ! AR="$AR" CC="$CC" CXX="$CXX" CFLAGS="-Werror" CXXFLAGS="-Werror" meson -Dtests=unsafe -Dslow-tests=true --werror $args build; then
fatal "meson failed with $args"
fi
diff --git a/.travis.yml b/.travis.yml
index d933ccce06..a72e81552f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,127 +1,82 @@
-sudo: required
+---
+# vi: ts=2 sw=2 et:
+
+language: bash
dist: bionic
services:
- - docker
+ - docker
env:
- global:
- - AUTHOR_EMAIL="$(git log -1 $TRAVIS_COMMIT --pretty=\"%aE\")"
- - CI_MANAGERS="$TRAVIS_BUILD_DIR/travis-ci/managers"
- - CI_TOOLS="$TRAVIS_BUILD_DIR/travis-ci/tools"
- - REPO_ROOT="$TRAVIS_BUILD_DIR"
+ global:
+ - AUTHOR_EMAIL="$(git log -1 $TRAVIS_COMMIT --pretty=\"%aE\")"
+ - CI_MANAGERS="$TRAVIS_BUILD_DIR/travis-ci/managers"
+ - CI_TOOLS="$TRAVIS_BUILD_DIR/travis-ci/tools"
+ - REPO_ROOT="$TRAVIS_BUILD_DIR"
+ jobs:
+ - DEBIAN_RELEASE=testing PHASE="RUN_GCC"
+ - DEBIAN_RELEASE=testing PHASE="RUN_GCC_ASAN_UBSAN"
+ - DEBIAN_RELEASE=testing PHASE="RUN_CLANG"
+ - DEBIAN_RELEASE=testing PHASE="RUN_CLANG_ASAN_UBSAN"
stages:
- - name: Build & test
- if: type != cron
+ # 'Test' is the default stage (for matrix jobs)
+ - name: Test
+ if: type != cron
# Run Coverity periodically instead of for each commit/PR
- - name: Coverity
- if: type = cron
-
-jobs:
- include:
- - stage: Build & test
- name: Debian Testing
- language: bash
- env:
- - DEBIAN_RELEASE="testing"
- - CONT_NAME="systemd-debian-$DEBIAN_RELEASE"
- - DOCKER_EXEC="docker exec -ti $CONT_NAME"
- before_install:
- - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- - docker --version
- install:
- - $CI_MANAGERS/debian.sh SETUP
- script:
- - $CI_MANAGERS/debian.sh RUN || travis_terminate 1
- after_script:
- - $CI_MANAGERS/debian.sh CLEANUP
+ - name: Coverity
+ if: type = cron
- - name: Debian Testing (ASan+UBSan)
- language: bash
- env:
- - DEBIAN_RELEASE="testing"
- - CONT_NAME="systemd-debian-$DEBIAN_RELEASE"
- - DOCKER_EXEC="docker exec -ti $CONT_NAME"
- before_install:
- - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- - docker --version
- install:
- - $CI_MANAGERS/debian.sh SETUP
- script:
- - $CI_MANAGERS/debian.sh RUN_ASAN || travis_terminate 1
- after_script:
- - $CI_MANAGERS/debian.sh CLEANUP
+# Matrix job definition - this is run for each combination of env variables
+# from the env.jobs array above
+before_install:
+ - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
+ - docker --version
+install:
+ - $CI_MANAGERS/debian.sh SETUP
+script:
+ - $CI_MANAGERS/debian.sh $PHASE || travis_terminate 1
+after_script:
+ - $CI_MANAGERS/debian.sh CLEANUP
- - name: Debian Testing (clang)
- language: bash
- env:
- - DEBIAN_RELEASE="testing"
- - CONT_NAME="systemd-debian-$DEBIAN_RELEASE"
- - DOCKER_EXEC="docker exec -ti $CONT_NAME"
- before_install:
- - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- - docker --version
- install:
- - $CI_MANAGERS/debian.sh SETUP
- script:
- - $CI_MANAGERS/debian.sh RUN_CLANG || travis-travis_terminate 1
- after_script:
- - $CI_MANAGERS/debian.sh CLEANUP
-
- - name: Debian Testing (clang ASan+UBSan)
- language: bash
- env:
- - DEBIAN_RELEASE="testing"
- - CONT_NAME="systemd-debian-$DEBIAN_RELEASE"
- - DOCKER_EXEC="docker exec -ti $CONT_NAME"
- before_install:
- - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- - docker --version
- install:
- - $CI_MANAGERS/debian.sh SETUP
- script:
- - $CI_MANAGERS/debian.sh RUN_CLANG_ASAN || travis_terminate 1
- after_script:
- - $CI_MANAGERS/debian.sh CLEANUP
-
- - stage: Coverity
- language: bash
- env:
- - FEDORA_RELEASE="latest"
- - CONT_NAME="coverity-fedora-$FEDORA_RELEASE"
- - DOCKER_EXEC="docker exec -ti $CONT_NAME"
- - TOOL_BASE="/var/tmp/coverity-scan-analysis"
- - DOCKER_RUN="docker run -v $TOOL_BASE:$TOOL_BASE:rw --env-file .cov-env"
- # Coverity env variables
- - PLATFORM="$(uname)"
- - TOOL_ARCHIVE="/var/tmp/cov-analysis-$PLATFORM.tgz"
- - SCAN_URL="https://scan.coverity.com"
- - UPLOAD_URL="https://scan.coverity.com/builds"
- - COVERITY_SCAN_PROJECT_NAME="$TRAVIS_REPO_SLUG"
- - COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}"
- - COVERITY_SCAN_BRANCH_PATTERN="$TRAVIS_BRANCH"
- # Encrypted COVERITY_SCAN_TOKEN env variable
- # Generated using `travis encrypt -r systemd/systemd COVERITY_SCAN_TOKEN=xxxx`
- - secure: "jKSz+Y1Mv8xMpQHh7g5lzW7E6HQGndFz/vKDJQ1CVShwFoyjV3Zu+MFS3UYKlh1236zL0Z4dvsYFx/b3Hq8nxZWCrWeZs2NdXgy/wh8LZhxwzcGYigp3sIA/cYdP5rDjFJO0MasNkl25/rml8+eZWz+8/xQic98UQHjSco/EOWtssoRcg0J0c4eDM7bGLfIQWE73NNY1Q1UtWjKmx1kekVrM8dPmHXJ9aERka7bmcbJAcKd6vabs6DQ5AfWccUPIn/EsRYqIJTRxJrFYU6XizANZ1a7Vwk/DWHZUEn2msxcZw5BbAMDTMx0TbfrNkKSHMHuvQUCu6KCBAq414i+LgkMfmQ2SWwKiIUsud1kxXX3ZPl9bxDv1HkvVdcniC/EM7lNEEVwm4meOnjuhI2lhOyOjmP3FTSlMHGP7xlK8DS2k9fqL58vn0BaSjwWgd+2+HuL2+nJmxcK1eLGzKqaostFxrk2Xs2vPZkUdV2nWY/asUrcWHml6YlWDn2eP83pfwxHYsMiEHY/rTKvxeVY+iirO/AphoO+eaYu7LvjKZU1Yx5Z4u/SnGWAiCH0yhMis0bWmgi7SCbw+sDd2uya+aoiLIGiB2ChW7hXHXCue/dif6/gLU7b+L8R00pQwnWdvKUPoIJCmZJYCluTeib4jpW+EmARB2+nR8wms2K9FGKM="
- before_install:
- - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- - docker --version
- install:
- # Install Coverity on the host
- - $CI_TOOLS/get-coverity.sh
- # Export necessary env variables for Coverity
- - env | grep -E "TRAVIS|COV|TOOL|URL" > .cov-env
- # Pull a Docker image and start a new container
- - $CI_MANAGERS/fedora.sh SETUP
- script:
- - set -e
- # Preconfigure with meson to prevent Coverity from capturing meson metadata
- - $DOCKER_EXEC meson cov-build -Dman=false
- # Run Coverity
- - $DOCKER_EXEC tools/coverity.sh build
- - $DOCKER_EXEC tools/coverity.sh upload
+# Inject another (single) job into the matrix for Coverity
+jobs:
+ include:
+ - stage: Coverity
+ language: bash
+ env:
+ - FEDORA_RELEASE="latest"
+ - TOOL_BASE="/var/tmp/coverity-scan-analysis"
+ - DOCKER_RUN="docker run -v $TOOL_BASE:$TOOL_BASE:rw --env-file .cov-env"
+ # Coverity env variables
+ - PLATFORM="$(uname)"
+ - TOOL_ARCHIVE="/var/tmp/cov-analysis-$PLATFORM.tgz"
+ - SCAN_URL="https://scan.coverity.com"
+ - UPLOAD_URL="https://scan.coverity.com/builds"
+ - COVERITY_SCAN_PROJECT_NAME="$TRAVIS_REPO_SLUG"
+ - COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}"
+ - COVERITY_SCAN_BRANCH_PATTERN="$TRAVIS_BRANCH"
+ # Encrypted COVERITY_SCAN_TOKEN env variable
+ # Generated using `travis encrypt -r systemd/systemd COVERITY_SCAN_TOKEN=xxxx`
+ - secure: "jKSz+Y1Mv8xMpQHh7g5lzW7E6HQGndFz/vKDJQ1CVShwFoyjV3Zu+MFS3UYKlh1236zL0Z4dvsYFx/b3Hq8nxZWCrWeZs2NdXgy/wh8LZhxwzcGYigp3sIA/cYdP5rDjFJO0MasNkl25/rml8+eZWz+8/xQic98UQHjSco/EOWtssoRcg0J0c4eDM7bGLfIQWE73NNY1Q1UtWjKmx1kekVrM8dPmHXJ9aERka7bmcbJAcKd6vabs6DQ5AfWccUPIn/EsRYqIJTRxJrFYU6XizANZ1a7Vwk/DWHZUEn2msxcZw5BbAMDTMx0TbfrNkKSHMHuvQUCu6KCBAq414i+LgkMfmQ2SWwKiIUsud1kxXX3ZPl9bxDv1HkvVdcniC/EM7lNEEVwm4meOnjuhI2lhOyOjmP3FTSlMHGP7xlK8DS2k9fqL58vn0BaSjwWgd+2+HuL2+nJmxcK1eLGzKqaostFxrk2Xs2vPZkUdV2nWY/asUrcWHml6YlWDn2eP83pfwxHYsMiEHY/rTKvxeVY+iirO/AphoO+eaYu7LvjKZU1Yx5Z4u/SnGWAiCH0yhMis0bWmgi7SCbw+sDd2uya+aoiLIGiB2ChW7hXHXCue/dif6/gLU7b+L8R00pQwnWdvKUPoIJCmZJYCluTeib4jpW+EmARB2+nR8wms2K9FGKM="
+ before_install:
+ - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
+ - docker --version
+ install:
+ # Install Coverity on the host
+ - $CI_TOOLS/get-coverity.sh
+ # Export necessary env variables for Coverity
+ - env | grep -E "TRAVIS|COV|TOOL|URL" > .cov-env
+ # Pull a Docker image and start a new container
+ - $CI_MANAGERS/fedora.sh SETUP
+ script:
+ - set -e
+ # Preconfigure with meson to prevent Coverity from capturing meson metadata
+ - $DOCKER_EXEC meson cov-build -Dman=false
+ # Run Coverity
+ - $DOCKER_EXEC tools/coverity.sh build
+ - $DOCKER_EXEC tools/coverity.sh upload
- - set +e
- after_script:
- - $CI_MANAGERS/fedora.sh CLEANUP
+ - set +e
+ after_script:
+ - $CI_MANAGERS/fedora.sh CLEANUP
diff --git a/NEWS b/NEWS
index 6e65c637c8..8d93d0c813 100644
--- a/NEWS
+++ b/NEWS
@@ -76,7 +76,7 @@ CHANGES WITH 246 in spe:
field.
* systemd-networkd's [DHCPServer] section gained a new set of options
- POP3Servers=, SMTPServers=, LPRServers= for including server
+ EmitPOP3=/POP3=, EmitSMTP=/SMTP=, EmitLPR=/LPR= for including server
information about these three protocols in the DHCP lease. It also
gained support for including "MUD" URLs ("Manufacturer Usage
Description"). Support for "MUD" URLs was also added to the LLDP
@@ -87,6 +87,12 @@ CHANGES WITH 246 in spe:
used, the DNS-over-TLS certificate is validated to match the
specified hostname.
+ * systemd-resolved may be configured to forward single-label DNS names.
+ This is not standard-conformant, but may make sense in setups where
+ public DNS servers are not used.
+
+ * systemd-resolved's DNS-over-TLS support gained SNI validation.
+
* The fs.suid_dumpable sysctl is set to 2 / "suidsafe". This allows
systemd-coredump to save core files for suid processes. When saving
the core file, systemd-coredump will use the effective uid and gid of
@@ -538,8 +544,6 @@ CHANGES WITH 245:
* systemd-sysusers gained support for creating users with the primary
group named differently than the user.
- * systemd-resolved's DNS-over-TLS support gained SNI validation.
-
* systemd-growfs (i.e. the x-systemd.growfs mount option in /etc/fstab)
gained support for growing XFS partitions. Previously it supported
only ext4 and btrfs partitions.
diff --git a/coccinelle/set_ensure_put.cocci b/coccinelle/set_ensure_put.cocci
new file mode 100644
index 0000000000..92d7970ade
--- /dev/null
+++ b/coccinelle/set_ensure_put.cocci
@@ -0,0 +1,18 @@
+@@
+local idexpression r;
+expression p, k, x;
+@@
+- r = set_ensure_allocated(&p, k);
+- if (r < 0)
+- return ...;
+- r = set_put(p, x);
++ r = set_ensure_put(&p, k, x);
+@@
+local idexpression r;
+expression p, k, x;
+@@
+- r = set_ensure_allocated(p, k);
+- if (r < 0)
+- return ...;
+- r = set_put(*p, x);
++ r = set_ensure_put(p, k, x);
diff --git a/docs/RANDOM_SEEDS.md b/docs/RANDOM_SEEDS.md
index d3b68e967a..c1735b1ac9 100644
--- a/docs/RANDOM_SEEDS.md
+++ b/docs/RANDOM_SEEDS.md
@@ -118,7 +118,7 @@ requires random numbers as well, including for the following uses:
* systemd maintains various hash tables internally. In order to harden them
against [collision
- attacks](https://rt.perl.org/Public/Bug/Display.html?CSRF_Token=165691af9ddaa95f653402f1b68de728)
+ attacks](https://www.cs.auckland.ac.nz/~mcw/Teaching/refs/misc/denial-of-service.pdf)
they are seeded with random numbers.
* At various places systemd needs random bytes for temporary file name
diff --git a/hwdb.d/60-autosuspend.hwdb b/hwdb.d/60-autosuspend.hwdb
new file mode 100644
index 0000000000..0de49afa6c
--- /dev/null
+++ b/hwdb.d/60-autosuspend.hwdb
@@ -0,0 +1,44 @@
+# This file is part of systemd.
+#
+# The lookup keys are $MODALIAS strings, see udev's hwdb builtin.
+#
+# Match string formats:
+# <subsystem>:<modalias>
+#
+# pci:v<vendor>d<device>
+# usb:v<vendor>p<product>
+#
+# To add local entries, create a new file
+# /etc/udev/hwdb.d/61-autosuspend-local.hwdb
+# and add your rules there. To load the new rules execute (as root):
+# systemd-hwdb update
+# udevadm trigger /dev/…
+#
+# If your changes are generally applicable, preferably send them as a pull
+# request to
+# https://github.com/systemd/systemd
+# or create a bug report on https://github.com/systemd/systemd/issues and
+# include your new rules, a description of the device, and the output of
+# udevadm info
+# the device.
+#
+# Allowed properties are:
+# ID_AUTOSUSPEND=1
+
+#
+# Sort by brand, model
+
+#########################################
+# Alcor
+#########################################
+
+# AU9540 Smartcard Reader
+usb:v058Fp9540*
+ ID_AUTOSUSPEND=1
+
+#########################################
+# Wacom
+#########################################
+
+usb:v056Ap51A0*
+ ID_AUTOSUSPEND=1
diff --git a/hwdb.d/70-mouse.hwdb b/hwdb.d/70-mouse.hwdb
index ef5a473e87..63ef1fba12 100644
--- a/hwdb.d/70-mouse.hwdb
+++ b/hwdb.d/70-mouse.hwdb
@@ -349,6 +349,8 @@ mouse:usb:v046dpc068:name:Logitech G500:
mouse:usb:v046dpc332:name:Logitech Gaming Mouse G502:
# Logitech G502 HERO SE
mouse:usb:v046dpc08b:name:Logitech G502 HERO SE:
+# Logitech G502 Hero
+mouse:usb:v046dpc08b:name:Logitech G502 HERO Gaming Mouse:
MOUSE_DPI=1200@1000 *2400@1000 3200@1000 6400@1000
# Logitech G700 Laser Mouse (Wired)
diff --git a/hwdb.d/meson.build b/hwdb.d/meson.build
index 4df6dabf89..5c77387a26 100644
--- a/hwdb.d/meson.build
+++ b/hwdb.d/meson.build
@@ -1,6 +1,9 @@
# SPDX-License-Identifier: LGPL-2.1+
-hwdb_files = files('''
+# Those files right now are not supported by the grammar. Also,
+# they are very long but quite repetitive and the parser is not very fast.
+# So we don't "test" them.
+hwdb_files_notest = files('''
20-pci-vendor-model.hwdb
20-pci-classes.hwdb
20-usb-vendor-model.hwdb
@@ -12,6 +15,10 @@ hwdb_files = files('''
20-OUI.hwdb
20-net-ifname.hwdb
20-vmbus-class.hwdb
+'''.split())
+
+hwdb_files_test = files('''
+ 60-autosuspend.hwdb
60-evdev.hwdb
60-input-id.hwdb
60-keyboard.hwdb
@@ -23,7 +30,16 @@ hwdb_files = files('''
'''.split())
if conf.get('ENABLE_HWDB') == 1
- install_data(hwdb_files,
+ auto_suspend_rules = custom_target(
+ '60-autosuspend-chromiumos.hwdb',
+ output : '60-autosuspend-chromiumos.hwdb',
+ command : make_autosuspend_rules_py,
+ capture : true,
+ install : true,
+ install_dir: udevhwdbdir)
+
+ install_data(hwdb_files_notest,
+ hwdb_files_test,
install_dir : udevhwdbdir)
meson.add_install_script('sh', '-c',
@@ -32,15 +48,15 @@ if conf.get('ENABLE_HWDB') == 1
meson.add_install_script('sh', '-c',
'test -n "$DESTDIR" || @0@/systemd-hwdb update'
.format(rootbindir))
-endif
-
-############################################################
-parse_hwdb_py = find_program('parse_hwdb.py')
-if want_tests != 'false'
- test('parse-hwdb',
- parse_hwdb_py,
- timeout : 90)
+ if want_tests != 'false'
+ parse_hwdb_py = find_program('parse_hwdb.py')
+ test('parse-hwdb',
+ parse_hwdb_py,
+ args : [hwdb_files_test,
+ auto_suspend_rules],
+ timeout : 90)
+ endif
endif
############################################################
diff --git a/hwdb.d/parse_hwdb.py b/hwdb.d/parse_hwdb.py
index abef56728f..8e1b5fdafa 100755
--- a/hwdb.d/parse_hwdb.py
+++ b/hwdb.d/parse_hwdb.py
@@ -59,6 +59,7 @@ REAL = Combine((INTEGER + Optional('.' + Optional(INTEGER))) ^ ('.' + INTEGER))
SIGNED_REAL = Combine(Optional(Word('-+')) + REAL)
UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_')
+# Those patterns are used in type-specific matches
TYPES = {'mouse': ('usb', 'bluetooth', 'ps2', '*'),
'evdev': ('name', 'atkbd', 'input'),
'id-input': ('modalias'),
@@ -68,13 +69,27 @@ TYPES = {'mouse': ('usb', 'bluetooth', 'ps2', '*'),
'sensor': ('modalias', ),
}
+# Patterns that are used to set general properties on a device
+GENERAL_MATCHES = {'acpi',
+ 'bluetooth',
+ 'usb',
+ 'pci',
+ 'sdio',
+ 'vmbus',
+ 'OUI',
+ }
+
@lru_cache()
def hwdb_grammar():
ParserElement.setDefaultWhitespaceChars('')
prefix = Or(category + ':' + Or(conn) + ':'
for category, conn in TYPES.items())
- matchline = Combine(prefix + Word(printables + ' ' + '®')) + EOL
+
+ matchline_typed = Combine(prefix + Word(printables + ' ' + '®'))
+ matchline_general = Combine(Or(GENERAL_MATCHES) + ':' + Word(printables))
+ matchline = (matchline_typed | matchline_general) + EOL
+
propertyline = (White(' ', exact=1).suppress() +
Combine(UDEV_TAG - '=' - Word(alphanums + '_=:@*.!-;, "') - Optional(pythonStyleComment)) +
EOL)
@@ -102,6 +117,7 @@ def property_grammar():
('MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL', INTEGER),
('MOUSE_WHEEL_CLICK_COUNT', INTEGER),
('MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL', INTEGER),
+ ('ID_AUTOSUSPEND', Literal('1')),
('ID_INPUT', Literal('1')),
('ID_INPUT_ACCELEROMETER', Literal('1')),
('ID_INPUT_JOYSTICK', Literal('1')),
diff --git a/man/bootup.xml b/man/bootup.xml
index 8cee4b419e..5770e7828d 100644
--- a/man/bootup.xml
+++ b/man/bootup.xml
@@ -192,7 +192,7 @@ emergency.service | | |
v graphical-session-pre.target
(various user services) | (printers)
| v |
- | (services for the graphical sesion) v
+ | (services for the graphical session) v
| | printer.target
v v
<emphasis>default.target</emphasis> graphical-session.target</programlisting>
diff --git a/man/custom-html.xsl b/man/custom-html.xsl
index 7eebfdb5a1..57a9cc97d2 100644
--- a/man/custom-html.xsl
+++ b/man/custom-html.xsl
@@ -19,7 +19,8 @@
<xsl:template match="citerefentry[not(@project)]">
<a>
<xsl:attribute name="href">
- <xsl:value-of select="refentrytitle"/><xsl:text>.html#</xsl:text>
+ <xsl:value-of select="refentrytitle"/>
+ <xsl:text>.html#</xsl:text>
<xsl:value-of select="refentrytitle/@target"/>
</xsl:attribute>
<xsl:call-template name="inline.charseq"/>
@@ -133,6 +134,15 @@
</a>
</xsl:template>
+<xsl:template match="citerefentry[@project='url']">
+ <a>
+ <xsl:attribute name="href">
+ <xsl:value-of select="refentrytitle/@url"/>
+ </xsl:attribute>
+ <xsl:call-template name="inline.charseq"/>
+ </a>
+</xsl:template>
+
<!--
- helper template to do conflict resolution between various headings with the same inferred ID attribute/tag from the headerlink template
- this conflict resolution is necessary to prevent malformed HTML output (multiple ID attributes with the same value)
diff --git a/man/homectl.xml b/man/homectl.xml
index 14877a0cde..3a4c6e5f5b 100644
--- a/man/homectl.xml
+++ b/man/homectl.xml
@@ -268,7 +268,8 @@
independently, for example with <citerefentry
project='man-pages'><refentrytitle>groupadd</refentrytitle><manvolnum>8</manvolnum></citerefentry>. If
non-existent groups that are listed there are ignored. This option may be used more than once, in
- which case all specified group lists are combined.</para></listitem>
+ which case all specified group lists are combined. If the user is currently a member of a group
+ which is not listed, the user will be removed from the group.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/repart.d.xml b/man/repart.d.xml
index f2c155e200..32df1e3d7f 100644
--- a/man/repart.d.xml
+++ b/man/repart.d.xml
@@ -1,7 +1,8 @@
<?xml version='1.0'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-<refentry id="repart.d" conditional='ENABLE_REPART'>
+<refentry id="repart.d" conditional='ENABLE_REPART'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>repart.d</title>
@@ -214,7 +215,7 @@
setting is not used for matching. It is also not used when a label is already set for an existing
partition. It is thus only used when a partition is newly created or when an existing one had a no
label set (that is: an empty label). If not specified a label derived from the partition type is
- automatically used.</para></listitem>
+ automatically used. Simple specifier expansion is supported, see below.</para></listitem>
</varlistentry>
<varlistentry>
@@ -291,7 +292,8 @@
<varname>SizeMaxBytes=</varname>) otherwise. If the backing device does not provide enough space to
fulfill the constraints placing the partition will fail. For partitions that shall be created,
depending on the setting of <varname>Priority=</varname> (see above) the partition might be dropped
- and the placing algorithm restarted. By default no size constraints are set.</para></listitem>
+ and the placing algorithm restarted. By default a minimum size constraint of 10M and no maximum size
+ constraint is set.</para></listitem>
</varlistentry>
<varlistentry>
@@ -316,6 +318,40 @@
</refsect1>
<refsect1>
+ <title>Specifiers</title>
+
+ <para>Specifiers may be used in the <varname>Label=</varname> setting. The following expansions are understood:</para>
+ <table class='specifiers'>
+ <title>Specifiers available</title>
+ <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+ <colspec colname="spec" />
+ <colspec colname="mean" />
+ <colspec colname="detail" />
+ <thead>
+ <row>
+ <entry>Specifier</entry>
+ <entry>Meaning</entry>
+ <entry>Details</entry>
+ </row>
+ </thead>
+ <tbody>
+ <xi:include href="standard-specifiers.xml" xpointer="a"/>
+ <xi:include href="standard-specifiers.xml" xpointer="b"/>
+ <xi:include href="standard-specifiers.xml" xpointer="B"/>
+ <xi:include href="standard-specifiers.xml" xpointer="H"/>
+ <xi:include href="standard-specifiers.xml" xpointer="l"/>
+ <xi:include href="standard-specifiers.xml" xpointer="m"/>
+ <xi:include href="standard-specifiers.xml" xpointer="o"/>
+ <xi:include href="standard-specifiers.xml" xpointer="v"/>
+ <xi:include href="standard-specifiers.xml" xpointer="w"/>
+ <xi:include href="standard-specifiers.xml" xpointer="W"/>
+ <xi:include href="standard-specifiers.xml" xpointer="percent"/>
+ </tbody>
+ </tgroup>
+ </table>
+ </refsect1>
+
+ <refsect1>
<title>Examples</title>
<example>
diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml
index 9be41baaa5..0e9b90c1cd 100644
--- a/man/resolved.conf.xml
+++ b/man/resolved.conf.xml
@@ -67,20 +67,28 @@
<varlistentry>
<term><varname>Domains=</varname></term>
- <listitem><para>A space-separated list of domains. These domains are used as search suffixes when resolving
- single-label hostnames (domain names which contain no dot), in order to qualify them into fully-qualified
- domain names (FQDNs). Search domains are strictly processed in the order they are specified, until the name
- with the suffix appended is found. For compatibility reasons, if this setting is not specified, the search
- domains listed in <filename>/etc/resolv.conf</filename> are used instead, if that file exists and any domains
- are configured in it. This setting defaults to the empty list.</para>
-
- <para>Specified domain names may optionally be prefixed with <literal>~</literal>. In this case they do not
- define a search path, but preferably direct DNS queries for the indicated domains to the DNS servers configured
- with the system <varname>DNS=</varname> setting (see above), in case additional, suitable per-link DNS servers
- are known. If no per-link DNS servers are known using the <literal>~</literal> syntax has no effect. Use the
- construct <literal>~.</literal> (which is composed of <literal>~</literal> to indicate a routing domain and
- <literal>.</literal> to indicate the DNS root domain that is the implied suffix of all DNS domains) to use the
- system DNS server defined with <varname>DNS=</varname> preferably for all domains.</para></listitem>
+ <listitem><para>A space-separated list of domains optionally prefixed with <literal>~</literal>,
+ used for two distinct purposes described below. Defaults to the empty list.</para>
+
+ <para>Any domains <emphasis>not</emphasis> prefixed with <literal>~</literal> are used as search
+ suffixes when resolving single-label hostnames (domain names which contain no dot), in order to
+ qualify them into fully-qualified domain names (FQDNs). These "search domains" are strictly processed
+ in the order they are specified in, until the name with the suffix appended is found. For
+ compatibility reasons, if this setting is not specified, the search domains listed in
+ <filename>/etc/resolv.conf</filename> with the <varname>search</varname> keyword are used instead, if
+ that file exists and any domains are configured in it.</para>
+
+ <para>The domains prefixed with <literal>~</literal> are called "routing domains". All domains listed
+ here (both search domains and routing domains after removing the <literal>~</literal> prefix) define
+ a search path that preferably directs DNS queries to this inteface. This search path has an effect
+ only when suitable per-link DNS servers are known. Such servers may be defined through the
+ <varname>DNS=</varname> setting (see above) and dynamically at run time, for example from DHCP
+ leases. If no per-link DNS servers are known, routing domains have no effect.</para>
+
+ <para>Use the construct <literal>~.</literal> (which is composed from <literal>~</literal> to
+ indicate a routing domain and <literal>.</literal> to indicate the DNS root domain that is the
+ implied suffix of all DNS domains) to use the DNS servers defined for this link preferably for all
+ domains.</para></listitem>
</varlistentry>
<varlistentry>
@@ -258,11 +266,28 @@
<varlistentry>
<term><varname>ReadEtcHosts=</varname></term>
- <listitem><para>Takes a boolean argument. If <literal>yes</literal> (the default), the DNS stub resolver will read
- <filename>/etc/hosts</filename>, and try to resolve hosts or address by using the entries in the file before
- sending query to DNS servers.</para></listitem>
+ <listitem><para>Takes a boolean argument. If <literal>yes</literal> (the default),
+ <command>systemd-resolved</command> will read <filename>/etc/hosts</filename>, and try to resolve
+ hosts or address by using the entries in the file before sending query to DNS servers.
+ </para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>ResolveUnicastSingleLabel=</varname></term>
+ <listitem><para>Takes a boolean argument. When false (the default),
+ <command>systemd-resolved</command> will not resolve A and AAAA queries for single-label names over
+ classic DNS. Note that such names may still be resolved if search domains are specified (see
+ <varname>Domains=</varname> above), or using other mechanisms, in particular via LLMNR or from
+ <filename>/etc/hosts</filename>. When true, queries for single-label names will be forwarded to
+ global DNS servers even if no search domains are defined.
+ </para>
+
+ <para>This option is provided for compatibility with configurations where <emphasis>public DNS
+ servers are not used</emphasis>. Forwarding single-label names to servers not under your control is
+ not standard-conformant, see <ulink
+ url="https://www.iab.org/documents/correspondence-reports-documents/2013-2/iab-statement-dotless-domains-considered-harmful/">IAB
+ Statement</ulink>, and may create a privacy and security risk.</para></listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/man/systemd-makefs@.service.xml b/man/systemd-makefs@.service.xml
index d07d90315a..9aa058588e 100644
--- a/man/systemd-makefs@.service.xml
+++ b/man/systemd-makefs@.service.xml
@@ -51,7 +51,8 @@
<para><filename>systemd-makefs</filename> knows very little about specific file
systems and swap devices, and after checking that the block device does not already
contain a file system or other content, it will execute binaries specific to
- each filesystem type (<filename>/sbin/mkfs.<replaceable>type</replaceable></filename>).</para>
+ each filesystem type (<filename>/sbin/mkfs.<replaceable>type</replaceable></filename>
+ or <filename>/sbin/mkswap</filename>).</para>
<para><filename>systemd-growfs</filename> knows very little about specific file
systems and swap devices, and will instruct the kernel to grow the mounted
@@ -61,8 +62,7 @@
number specific to each file system, so only certain types are supported.
Currently:
<citerefentry project='man-pages'><refentrytitle>ext4</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- btrfs (see
- <citerefentry project='man-pages'><refentrytitle>btrfs-man5</refentrytitle><manvolnum>5</manvolnum></citerefentry>),
+ <citerefentry project='url'><refentrytitle url='https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)'>btrfs</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>xfs</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<!-- yes, that's what the man page is called. -->
and dm-crypt partitions (see
diff --git a/man/systemd-modules-load.service.xml b/man/systemd-modules-load.service.xml
index ca9edef367..e960609c6c 100644
--- a/man/systemd-modules-load.service.xml
+++ b/man/systemd-modules-load.service.xml
@@ -29,14 +29,15 @@
<refsect1>
<title>Description</title>
- <para><filename>systemd-modules-load.service</filename> is an
- early boot service that loads kernel modules based on static
- configuration.</para>
+ <para><filename>systemd-modules-load.service</filename> is an early boot service that loads kernel
+ modules. It reads static configuration from files in <filename>/usr</filename> and
+ <filename>/etc</filename>, but also runtime configuration from <filename>/run</filename> and the kernel
+ command line (see below).</para>
<para>See
- <citerefentry><refentrytitle>modules-load.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for information about the configuration of this service.</para>
-
+ <citerefentry><refentrytitle>modules-load.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+ information about the configuration format of this service and paths where configuration files can be
+ created.</para>
</refsect1>
<refsect1>
diff --git a/man/systemd-resolved.service.xml b/man/systemd-resolved.service.xml
index 6e1ee9f4a5..914607e3f8 100644
--- a/man/systemd-resolved.service.xml
+++ b/man/systemd-resolved.service.xml
@@ -135,14 +135,16 @@
IPv6.</para></listitem>
<listitem><para>Resolution of address records (A and AAAA) via unicast DNS (i.e. not LLMNR or
- MulticastDNS) for non-synthesized single-label names is only allowed for non-top-level domains. This
- means that such records can only be resolved when search domains are defined. For any interface which
- defines search domains, such look-ups are routed to that interface, suffixed with each of the search
- domains defined on that interface in turn. When global search domains are defined, such look-ups are
- routed to all interfaces, suffixed by each of the global search domains in turn. The details of which
- servers are queried and how the final reply is chosen are described below. Note that this means that
- address queries for single-label names are never sent out to remote DNS servers, and if no search
- domains are defined, resolution will fail.</para></listitem>
+ MulticastDNS) for non-synthesized single-label names is allowed for non-top-level domains. This means
+ that such records can be resolved when search domains are defined. For any interface which defines
+ search domains, such look-ups are routed to that interface, suffixed with each of the search domains
+ defined on that interface in turn. When global search domains are defined, such look-ups are routed to
+ all interfaces, suffixed by each of the global search domains in turn. Additionally, lookup of
+ single-label names via unicast DNS may be enabled with the
+ <varname>ResolveUnicastSingleLabel=yes</varname> setting. The details of which servers are queried and
+ how the final reply is chosen are described below. Note that this means that address queries for
+ single-label names are never sent out to remote DNS servers by default, and if no search domains are
+ defined, resolution will fail.</para></listitem>
<listitem><para>Other multi-label names are routed to all local interfaces that have a DNS server
configured, plus the globally configured DNS servers if there are any. Note that by default, lookups for
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index f5db55511f..aa8a3f75bc 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -146,6 +146,43 @@
</varlistentry>
<varlistentry>
+ <term><varname>RootHash=</varname></term>
+
+ <listitem><para>Takes a data integrity (dm-verity) root hash specified in hexadecimal, or the path to a file
+ containing a root hash in ASCII hexadecimal format. This option enables data integrity checks using dm-verity,
+ if the used image contains the appropriate integrity data (see above) or if <varname>RootVerity=</varname> is used.
+ The specified hash must match the root hash of integrity data, and is usually at least 256 bits (and hence 64
+ formatted hexadecimal characters) long (in case of SHA256 for example). If this option is not specified, but
+ the image file carries the <literal>user.verity.roothash</literal> extended file attribute (see <citerefentry
+ project='man-pages'><refentrytitle>xattr</refentrytitle><manvolnum>7</manvolnum></citerefentry>), then the root
+ hash is read from it, also as formatted hexadecimal characters. If the extended file attribute is not found (or
+ is not supported by the underlying file system), but a file with the <filename>.roothash</filename> suffix is
+ found next to the image file, bearing otherwise the same name (except if the image has the
+ <filename>.raw</filename> suffix, in which case the root hash file must not have it in its name), the root hash
+ is read from it and automatically used, also as formatted hexadecimal characters.</para>
+
+ <xi:include href="system-only.xml" xpointer="singular"/></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>RootVerity=</varname></term>
+
+ <listitem><para>Takes the path to a data integrity (dm-verity) file. This option enables data integrity checks
+ using dm-verity, if <varname>RootImage=</varname> is used and a root-hash is passed and if the used image itself
+ does not contains the integrity data. The integrity data must be matched by the root hash. If this option is not
+ specified, but a file with the <filename>.verity</filename> suffix is found next to the image file, bearing otherwise
+ the same name (except if the image has the <filename>.raw</filename> suffix, in which case the verity data file must
+ not have it in its name), the verity data is read from it and automatically used.</para>
+
+ <para>This option is supported only for disk images that contain a single file system, without an enveloping partition
+ table. Images that contain a GPT partition table should instead include both root file system and matching Verity
+ data in the same image, implementing the
+ [Discoverable Partition Specification](https://systemd.io/DISCOVERABLE_PARTITIONS)</para>
+
+ <xi:include href="system-only.xml" xpointer="singular"/></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>MountAPIVFS=</varname></term>
<listitem><para>Takes a boolean argument. If on, a private mount namespace for the unit's processes is created
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 515cfe23cd..241c780457 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -578,7 +578,7 @@
<varlistentry>
<term><varname>NTP=</varname></term>
<listitem>
- <para>An NTP server address. This option may be specified more than once. This setting is read by
+ <para>An NTP server address (either an IP address, or a hostname). This option may be specified more than once. This setting is read by
<citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -1412,17 +1412,16 @@
<varlistentry>
<term><varname>UseNTP=</varname></term>
<listitem>
- <para>When true (the default), the NTP servers received
- from the DHCP server will be used by systemd-timesyncd
- and take precedence over any statically configured ones.</para>
+ <para>When true (the default), the NTP servers received from the DHCP server will be used by
+ <filename>systemd-timesyncd.service</filename> and take precedence over any statically configured
+ ones.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseSIP=</varname></term>
<listitem>
- <para>When true (the default), the SIP servers received
- from the DHCP server will be saved at the state files and can be
- read via <function>sd_network_link_get_sip_servers()</function> function.</para>
+ <para>When true (the default), the SIP servers received from the DHCP server will be collected
+ and made available to client programs.</para>
</listitem>
</varlistentry>
@@ -2010,79 +2009,37 @@
<term><varname>EmitDNS=</varname></term>
<term><varname>DNS=</varname></term>
- <listitem><para>Takes a boolean. Configures whether the DHCP leases handed out
- to clients shall contain DNS server information. Defaults to <literal>yes</literal>.
- The DNS servers to pass to clients may be configured with the
- <varname>DNS=</varname> option, which takes a list of IPv4
- addresses. If the <varname>EmitDNS=</varname> option is
- enabled but no servers configured, the servers are
- automatically propagated from an "uplink" interface that has
- appropriate servers set. The "uplink" interface is determined
- by the default route of the system with the highest
- priority. Note that this information is acquired at the time
- the lease is handed out, and does not take uplink interfaces
- into account that acquire DNS or NTP server information at a
- later point. DNS server propagation does not take
- <filename>/etc/resolv.conf</filename> into account. Also, note
- that the leases are not refreshed if the uplink network
- configuration changes. To ensure clients regularly acquire the
- most current uplink DNS server information, it is thus
- advisable to shorten the DHCP lease time via
- <varname>MaxLeaseTimeSec=</varname> described
+ <listitem><para><varname>EmitDNS=</varname> takes a boolean. Configures whether the DHCP leases
+ handed out to clients shall contain DNS server information. Defaults to <literal>yes</literal>. The
+ DNS servers to pass to clients may be configured with the <varname>DNS=</varname> option, which takes
+ a list of IPv4 addresses. If the <varname>EmitDNS=</varname> option is enabled but no servers
+ configured, the servers are automatically propagated from an "uplink" interface that has appropriate
+ servers set. The "uplink" interface is determined by the default route of the system with the highest
+ priority. Note that this information is acquired at the time the lease is handed out, and does not
+ take uplink interfaces into account that acquire DNS server information at a later point. If no
+ suitable uplinkg interface is found the DNS server data from <filename>/etc/resolv.conf</filename> is
+ used. Also, note that the leases are not refreshed if the uplink network configuration changes. To
+ ensure clients regularly acquire the most current uplink DNS server information, it is thus advisable
+ to shorten the DHCP lease time via <varname>MaxLeaseTimeSec=</varname> described
above.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>EmitNTP=</varname></term>
<term><varname>NTP=</varname></term>
-
- <listitem><para>Similar to the <varname>EmitDNS=</varname> and
- <varname>DNS=</varname> settings described above, these
- settings configure whether and what NTP server information
- shall be emitted as part of the DHCP lease. The same syntax,
- propagation semantics and defaults apply as for
- <varname>EmitDNS=</varname> and
- <varname>DNS=</varname>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
<term><varname>EmitSIP=</varname></term>
<term><varname>SIP=</varname></term>
+ <term><varname>EmitPOP3=</varname></term>
+ <term><varname>POP3=</varname></term>
+ <term><varname>EmitSMTP=</varname></term>
+ <term><varname>SMTP=</varname></term>
+ <term><varname>EmitLPR=</varname></term>
+ <term><varname>LPR=</varname></term>
- <listitem><para>Similar to the <varname>EmitDNS=</varname> and
- <varname>DNS=</varname> settings described above, these
- settings configure whether and what SIP server information
- shall be emitted as part of the DHCP lease. The same syntax,
- propagation semantics and defaults apply as for
- <varname>EmitDNS=</varname> and
- <varname>DNS=</varname>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>POP3Servers=</varname></term>
-
- <listitem><para>Similar to the <varname>DNS=</varname> setting described above, this setting
- configures whether and what POP3 server information shall be emitted as part of the DHCP lease. The
- same syntax, propagation semantics and defaults apply as for
- <varname>DNS=</varname>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>SMTPServers=</varname></term>
-
- <listitem><para>Similar to the <varname>DNS=</varname> setting described above, this
- setting configures whether and what SMTP server information shall be emitted as part of
- the DHCP lease. The same syntax, propagation semantics and defaults apply as for
- <varname>DNS=</varname>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>LPRServers=</varname></term>
-
- <listitem><para>Similar to the <varname>DNS=</varname> setting described above, this
- setting configures whether and what LPR (line printer) server information shall be emitted
- as part of the DHCP lease. The same syntax, propagation semantics and defaults apply as for
- <varname>DNS=</varname>.</para></listitem>
+ <listitem><para>Similar to the <varname>EmitDNS=</varname> and <varname>DNS=</varname> settings
+ described above, these settings configure whether and what server information for the indicate
+ protocol shall be emitted as part of the DHCP lease. The same syntax, propagation semantics and
+ defaults apply as for <varname>EmitDNS=</varname> and <varname>DNS=</varname>.</para></listitem>
</varlistentry>
<varlistentry>
@@ -2973,6 +2930,58 @@
</refsect1>
<refsect1>
+ <title>[EnhancedTransmissionSelection] Section Options</title>
+ <para>The <literal>[EnhancedTransmissionSelection]</literal> section manages the queueing discipline (qdisc) of
+ Enhanced Transmission Selection (ETS).</para>
+
+ <variablelist class='network-directives'>
+ <xi:include href="tc.xml" xpointer="qdisc-parent" />
+ <xi:include href="tc.xml" xpointer="qdisc-handle" />
+
+ <varlistentry>
+ <term><varname>Bands=</varname></term>
+ <listitem>
+ <para>Specifies the number of bands. An unsigned integer ranges 1 to 16. This value has to be
+ at least large enough to cover the strict bands specified through the
+ <varname>StrictBands=</varname> and bandwidth-sharing bands specified in
+ <varname>QuantumBytes=</varname>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>StrictBands=</varname></term>
+ <listitem>
+ <para>Specifies the number of bands that should be created in strict mode. An unsigned integer
+ ranges 1 to 16.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>QuantumBytes=</varname></term>
+ <listitem>
+ <para>Specifies the white-space separated list of quantum used in band-sharing bands. When
+ suffixed with K, M, or G, the specified size is parsed as Kilobytes, Megabytes, or Gigabytes,
+ respectively, to the base of 1024. This setting can be specified multiple times. If an empty
+ string is assigned, then the all previous assignments are cleared.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>PriorityMap=</varname></term>
+ <listitem>
+ <para>The priority map maps the priority of a packet to a band. The argument is a white-space
+ separated list of numbers. The first number indicates which band the packets with priority
+ 0 should be put to, the second is for priority 1, and so on. There can be up to 16 numbers in
+ the list. If there are fewer, the default band that traffic with one of the unmentioned
+ priorities goes to is the last one. Each band number must be 0..255. This setting can be
+ specified multiple times. If an empty string is assigned, then the all previous assignments
+ are cleared.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
<title>[GenericRandomEarlyDetection] Section Options</title>
<para>The <literal>[GenericRandomEarlyDetection]</literal> section manages the queueing discipline
(qdisc) of Generic Random Early Detection (GRED).</para>
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
index 6d3568576c..aa368732fb 100644
--- a/man/systemd.resource-control.xml
+++ b/man/systemd.resource-control.xml
@@ -670,8 +670,8 @@
</varlistentry>
<varlistentry>
- <term><varname>IPIngressFilterPath=<replaceable>BPF_FS_PROGRAMM_PATH</replaceable></varname></term>
- <term><varname>IPEgressFilterPath=<replaceable>BPF_FS_PROGRAMM_PATH</replaceable></varname></term>
+ <term><varname>IPIngressFilterPath=<replaceable>BPF_FS_PROGRAM_PATH</replaceable></varname></term>
+ <term><varname>IPEgressFilterPath=<replaceable>BPF_FS_PROGRAM_PATH</replaceable></varname></term>
<listitem>
<para>Add custom network traffic filters implemented as BPF programs, applying to all IP packets
diff --git a/meson.build b/meson.build
index fbb4090f18..8f1d1b5897 100644
--- a/meson.build
+++ b/meson.build
@@ -85,6 +85,8 @@ if rootprefixdir == ''
endif
rootprefixdir_noslash = rootprefixdir == '/' ? '' : rootprefixdir
+have_standalone_binaries = get_option('standalone-binaries')
+
sysvinit_path = get_option('sysvinit-path')
sysvrcnd_path = get_option('sysvrcnd-path')
conf.set10('HAVE_SYSV_COMPAT', sysvinit_path != '' and sysvrcnd_path != '',
@@ -1635,6 +1637,7 @@ subdir('src/nspawn')
subdir('src/resolve')
subdir('src/timedate')
subdir('src/timesync')
+subdir('src/tmpfiles')
subdir('src/vconsole')
subdir('src/boot/efi')
@@ -1657,7 +1660,7 @@ test_dlopen = executable(
build_by_default : want_tests != 'false')
foreach tuple : [['myhostname', 'ENABLE_NSS_MYHOSTNAME'],
- ['systemd', 'ENABLE_NSS_SYSTEMD', 'src/nss-systemd/userdb-glue.c src/nss-systemd/userdb-glue.h'],
+ ['systemd', 'ENABLE_NSS_SYSTEMD', 'src/nss-systemd/userdb-glue.c src/nss-systemd/userdb-glue.h src/nss-systemd/nss-systemd.h'],
['mymachines', 'ENABLE_NSS_MYMACHINES'],
['resolve', 'ENABLE_NSS_RESOLVE']]
@@ -2931,14 +2934,26 @@ if conf.get('ENABLE_SYSUSERS') == 1
install_rpath : rootlibexecdir,
install : true,
install_dir : rootbindir)
+
+ if have_standalone_binaries
+ public_programs += executable(
+ 'systemd-sysusers.standalone',
+ 'src/sysusers/sysusers.c',
+ include_directories : includes,
+ link_with : [libshared_static,
+ libbasic,
+ libbasic_gcrypt,
+ libsystemd_static,
+ libjournal_client],
+ install : true,
+ install_dir : rootbindir)
+ endif
endif
if conf.get('ENABLE_TMPFILES') == 1
exe = executable(
'systemd-tmpfiles',
- 'src/tmpfiles/tmpfiles.c',
- 'src/tmpfiles/offline-passwd.c',
- 'src/tmpfiles/offline-passwd.h',
+ systemd_tmpfiles_sources,
include_directories : includes,
link_with : [libshared],
dependencies : [libacl],
@@ -2953,6 +2968,21 @@ if conf.get('ENABLE_TMPFILES') == 1
# https://github.com/mesonbuild/meson/issues/2681
args : exe.full_path())
endif
+
+ if have_standalone_binaries
+ public_programs += executable(
+ 'systemd-tmpfiles.standalone',
+ systemd_tmpfiles_sources,
+ include_directories : includes,
+ link_with : [libshared_static,
+ libbasic,
+ libbasic_gcrypt,
+ libsystemd_static,
+ libjournal_client],
+ dependencies : [libacl],
+ install : true,
+ install_dir : rootbindir)
+ endif
endif
if conf.get('ENABLE_HWDB') == 1
diff --git a/meson_options.txt b/meson_options.txt
index 5e6842f9d6..e13bfb0c4b 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -26,6 +26,8 @@ option('static-libsystemd', type : 'combo',
option('static-libudev', type : 'combo',
choices : ['false', 'true', 'pic', 'no-pic'],
description : '''install a static library for libudev''')
+option('standalone-binaries', type : 'boolean', value : 'false',
+ description : '''also build standalone versions of supported binaries''')
option('sysvinit-path', type : 'string', value : '/etc/init.d',
description : 'the directory where the SysV init scripts are located')
diff --git a/rules.d/50-udev-default.rules.in b/rules.d/50-udev-default.rules.in
index 50747a1988..cef78f9d68 100644
--- a/rules.d/50-udev-default.rules.in
+++ b/rules.d/50-udev-default.rules.in
@@ -10,8 +10,9 @@ SUBSYSTEM=="virtio-ports", KERNEL=="vport*", ATTR{name}=="?*", SYMLINK+="virtio-
SUBSYSTEM=="rtc", ATTR{hctosys}=="1", SYMLINK+="rtc"
SUBSYSTEM=="rtc", KERNEL=="rtc0", SYMLINK+="rtc", OPTIONS+="link_priority=-100"
-SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
+SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb", GOTO="default_hwdb_imported"
ENV{MODALIAS}!="", IMPORT{builtin}="hwdb --subsystem=$env{SUBSYSTEM}"
+LABEL="default_hwdb_imported"
ACTION!="add", GOTO="default_end"
diff --git a/rules.d/60-autosuspend.rules b/rules.d/60-autosuspend.rules
new file mode 100644
index 0000000000..1f9ebef631
--- /dev/null
+++ b/rules.d/60-autosuspend.rules
@@ -0,0 +1,14 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION!="add", GOTO="autosuspend_end"
+
+# I2C rules
+SUBSYSTEM=="i2c", ATTR{name}=="cyapa", \
+ ATTR{power/control}="on", GOTO="autosuspend_end"
+
+# Enable autosuspend if hwdb says so. Here we are relying on
+# the hwdb import done earlier based on MODALIAS.
+ENV{ID_AUTOSUSPEND}=="1", TEST=="power/control", \
+ ATTR{power/control}="auto"
+
+LABEL="autosuspend_end"
diff --git a/rules.d/60-serial.rules b/rules.d/60-serial.rules
index f303e27fd5..b1626650b7 100644
--- a/rules.d/60-serial.rules
+++ b/rules.d/60-serial.rules
@@ -4,8 +4,9 @@ ACTION=="remove", GOTO="serial_end"
SUBSYSTEM!="tty", GOTO="serial_end"
SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}"
-SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci"
-SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
+# We already ran the hwdb builtin for devices with MODALIAS in 50-default.rules.
+# Let's cover the remaining case here, where we walk up the tree to find a node with $MODALIAS.
+ENV{MODALIAS}=="", SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci"
# /dev/serial/by-path/, /dev/serial/by-id/ for USB devices
KERNEL!="ttyUSB[0-9]*|ttyACM[0-9]*", GOTO="serial_end"
diff --git a/rules.d/61-autosuspend-manual.rules b/rules.d/61-autosuspend-manual.rules
deleted file mode 100644
index 2b973af960..0000000000
--- a/rules.d/61-autosuspend-manual.rules
+++ /dev/null
@@ -1,19 +0,0 @@
-# This udev rule is for any devices that should enter automatic suspend
-# but are not already included in generated rules from Chromium OS via
-# tools/make-autosuspend-rules.py
-#
-
-ACTION!="add", GOTO="autosuspend_manual_end"
-SUBSYSTEM!="usb", GOTO="autosuspend_manual_end"
-
-SUBSYSTEM=="usb", GOTO="autosuspend_manual_usb"
-
-# USB rules
-LABEL="autosuspend_manual_usb"
-GOTO="autosuspend_manual_end"
-
-# Enable autosuspend
-LABEL="autosuspend_manual_enable"
-TEST=="power/control", ATTR{power/control}="auto", GOTO="autosuspend_manual_end"
-
-LABEL="autosuspend_manual_end"
diff --git a/rules.d/meson.build b/rules.d/meson.build
index 13d1d330cf..ca4445d774 100644
--- a/rules.d/meson.build
+++ b/rules.d/meson.build
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1+
rules = files('''
+ 60-autosuspend.rules
60-block.rules
60-cdrom_id.rules
60-drm.rules
@@ -14,7 +15,6 @@ rules = files('''
60-persistent-v4l.rules
60-sensor.rules
60-serial.rules
- 61-autosuspend-manual.rules
70-joystick.rules
70-mouse.rules
70-touchpad.rules
@@ -45,11 +45,3 @@ foreach file : rules_in
install_dir : udevrulesdir)
all_rules += gen
endforeach
-
-auto_suspend_rules = custom_target(
- '60-autosuspend-chromiumos.rules',
- output : '60-autosuspend-chromiumos.rules',
- command : make_autosuspend_rules_py,
- capture : true,
- install : true,
- install_dir: [udevrulesdir])
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index faf50d2ac3..a8bd993cbe 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -2376,9 +2376,7 @@ static int run(int argc, char *argv[]) {
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C"); /* we want to format/parse floats in C style */
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/basic/dlfcn-util.h b/src/basic/dlfcn-util.h
new file mode 100644
index 0000000000..d254afb68b
--- /dev/null
+++ b/src/basic/dlfcn-util.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <dlfcn.h>
+
+#include "macro.h"
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(void*, dlclose);
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index 15c8c4723c..67c4391230 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -768,7 +768,7 @@ static void reset_direct_storage(HashmapBase *h) {
memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
}
-static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
+static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
HashmapBase *h;
const struct hashmap_type_info *hi = &hashmap_type_info[type];
bool up;
@@ -808,19 +808,19 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu
}
Hashmap *_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return (Hashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
+ return (Hashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
}
OrderedHashmap *_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return (OrderedHashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
+ return (OrderedHashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
}
Set *_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return (Set*) hashmap_base_new(hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
+ return (Set*) hashmap_base_new(hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
}
static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops *hash_ops,
- enum HashmapType type HASHMAP_DEBUG_PARAMS) {
+ enum HashmapType type HASHMAP_DEBUG_PARAMS) {
HashmapBase *q;
assert(h);
@@ -828,7 +828,7 @@ static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops
if (*h)
return 0;
- q = hashmap_base_new(hash_ops, type HASHMAP_DEBUG_PASS_ARGS);
+ q = hashmap_base_new(hash_ops, type HASHMAP_DEBUG_PASS_ARGS);
if (!q)
return -ENOMEM;
@@ -837,15 +837,15 @@ static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops
}
int _hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
+ return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
}
int _ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
+ return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
}
int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
+ return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
}
static void hashmap_free_no_clear(HashmapBase *h) {
@@ -1247,6 +1247,30 @@ int set_put(Set *s, const void *key) {
return hashmap_put_boldly(s, hash, &swap, true);
}
+int _set_ensure_put(Set **s, const struct hash_ops *hash_ops, const void *key HASHMAP_DEBUG_PARAMS) {
+ int r;
+
+ r = _set_ensure_allocated(s, hash_ops HASHMAP_DEBUG_PASS_ARGS);
+ if (r < 0)
+ return r;
+
+ return set_put(*s, key);
+}
+
+int _set_ensure_consume(Set **s, const struct hash_ops *hash_ops, void *key HASHMAP_DEBUG_PARAMS) {
+ int r;
+
+ r = _set_ensure_put(s, hash_ops, key HASHMAP_DEBUG_PASS_ARGS);
+ if (r <= 0) {
+ if (hash_ops && hash_ops->free_key)
+ hash_ops->free_key(key);
+ else
+ free(key);
+ }
+
+ return r;
+}
+
int hashmap_replace(Hashmap *h, const void *key, void *value) {
struct swap_entries swap;
struct plain_hashmap_entry *e;
@@ -1687,13 +1711,13 @@ int _hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) {
return 0;
}
-HashmapBase *_hashmap_copy(HashmapBase *h) {
+HashmapBase *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS) {
HashmapBase *copy;
int r;
assert(h);
- copy = hashmap_base_new(h->hash_ops, h->type HASHMAP_DEBUG_SRC_ARGS);
+ copy = hashmap_base_new(h->hash_ops, h->type HASHMAP_DEBUG_PASS_ARGS);
if (!copy)
return NULL;
@@ -1709,10 +1733,8 @@ HashmapBase *_hashmap_copy(HashmapBase *h) {
assert_not_reached("Unknown hashmap type");
}
- if (r < 0) {
- _hashmap_free(copy, false, false);
- return NULL;
- }
+ if (r < 0)
+ return _hashmap_free(copy, false, false);
return copy;
}
@@ -1765,10 +1787,10 @@ int set_consume(Set *s, void *value) {
return r;
}
-int hashmap_put_strdup(Hashmap **h, const char *k, const char *v) {
+int _hashmap_put_strdup(Hashmap **h, const char *k, const char *v HASHMAP_DEBUG_PARAMS) {
int r;
- r = hashmap_ensure_allocated(h, &string_hash_ops_free_free);
+ r = _hashmap_ensure_allocated(h, &string_hash_ops_free_free HASHMAP_DEBUG_PASS_ARGS);
if (r < 0)
return r;
@@ -1799,14 +1821,14 @@ int hashmap_put_strdup(Hashmap **h, const char *k, const char *v) {
return r;
}
-int set_put_strdup(Set **s, const char *p) {
+int _set_put_strdup(Set **s, const char *p HASHMAP_DEBUG_PARAMS) {
char *c;
int r;
assert(s);
assert(p);
- r = set_ensure_allocated(s, &string_hash_ops_free);
+ r = _set_ensure_allocated(s, &string_hash_ops_free HASHMAP_DEBUG_PASS_ARGS);
if (r < 0)
return r;
@@ -1820,14 +1842,14 @@ int set_put_strdup(Set **s, const char *p) {
return set_consume(*s, c);
}
-int set_put_strdupv(Set **s, char **l) {
+int _set_put_strdupv(Set **s, char **l HASHMAP_DEBUG_PARAMS) {
int n = 0, r;
char **i;
assert(s);
STRV_FOREACH(i, l) {
- r = set_put_strdup(s, *i);
+ r = _set_put_strdup(s, *i HASHMAP_DEBUG_PASS_ARGS);
if (r < 0)
return r;
diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h
index 230d322213..6009441621 100644
--- a/src/basic/hashmap.h
+++ b/src/basic/hashmap.h
@@ -128,13 +128,9 @@ static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h)
IteratedCache *iterated_cache_free(IteratedCache *cache);
int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries);
-HashmapBase *_hashmap_copy(HashmapBase *h);
-static inline Hashmap *hashmap_copy(Hashmap *h) {
- return (Hashmap*) _hashmap_copy(HASHMAP_BASE(h));
-}
-static inline OrderedHashmap *ordered_hashmap_copy(OrderedHashmap *h) {
- return (OrderedHashmap*) _hashmap_copy(HASHMAP_BASE(h));
-}
+HashmapBase *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS);
+#define hashmap_copy(h) ((Hashmap*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS))
+#define ordered_hashmap_copy(h) ((OrderedHashmap*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS))
int _hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
int _ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
@@ -154,7 +150,8 @@ static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *
return hashmap_put(PLAIN_HASHMAP(h), key, value);
}
-int hashmap_put_strdup(Hashmap **h, const char *k, const char *v);
+int _hashmap_put_strdup(Hashmap **h, const char *k, const char *v HASHMAP_DEBUG_PARAMS);
+#define hashmap_put_strdup(h, k, v) _hashmap_put_strdup(h, k, v HASHMAP_DEBUG_SRC_ARGS)
int hashmap_update(Hashmap *h, const void *key, void *value);
static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) {
diff --git a/src/basic/log.c b/src/basic/log.c
index ca024d970e..c6fe203808 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -7,6 +7,7 @@
#include <stdarg.h>
#include <stddef.h>
#include <sys/signalfd.h>
+#include <sys/stat.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/un.h>
@@ -219,6 +220,32 @@ fail:
return r;
}
+static bool stderr_is_journal(void) {
+ _cleanup_free_ char *w = NULL;
+ const char *e;
+ uint64_t dev, ino;
+ struct stat st;
+
+ e = getenv("JOURNAL_STREAM");
+ if (!e)
+ return false;
+
+ if (extract_first_word(&e, &w, ":", EXTRACT_DONT_COALESCE_SEPARATORS) <= 0)
+ return false;
+ if (!e)
+ return false;
+
+ if (safe_atou64(w, &dev) < 0)
+ return false;
+ if (safe_atou64(e, &ino) < 0)
+ return false;
+
+ if (fstat(STDERR_FILENO, &st) < 0)
+ return false;
+
+ return st.st_dev == dev && st.st_ino == ino;
+}
+
int log_open(void) {
int r;
@@ -238,9 +265,7 @@ int log_open(void) {
return 0;
}
- if (log_target != LOG_TARGET_AUTO ||
- getpid_cached() == 1 ||
- isatty(STDERR_FILENO) <= 0) {
+ if (log_target != LOG_TARGET_AUTO || getpid_cached() == 1 || stderr_is_journal()) {
if (!prohibit_ipc &&
IN_SET(log_target, LOG_TARGET_AUTO,
@@ -1121,16 +1146,20 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
}
void log_parse_environment_realm(LogRealm realm) {
- /* Do not call from library code. */
-
- const char *e;
-
if (getpid_cached() == 1 || get_ctty_devnr(0, NULL) < 0)
/* Only try to read the command line in daemons. We assume that anything that has a
* controlling tty is user stuff. For PID1 we do a special check in case it hasn't
* closed the console yet. */
(void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
+ log_parse_environment_cli_realm(realm);
+}
+
+void log_parse_environment_cli_realm(LogRealm realm) {
+ /* Do not call from library code. */
+
+ const char *e;
+
e = getenv("SYSTEMD_LOG_TARGET");
if (e && log_set_target_from_string(e) < 0)
log_warning("Failed to parse log target '%s'. Ignoring.", e);
@@ -1405,3 +1434,11 @@ void log_setup_service(void) {
log_parse_environment();
(void) log_open();
}
+
+void log_setup_cli(void) {
+ /* Sets up logging the way it is most appropriate for running a program as a CLI utility. */
+
+ log_show_color(true);
+ log_parse_environment_cli();
+ (void) log_open();
+}
diff --git a/src/basic/log.h b/src/basic/log.h
index 2c1b00fb88..15807d3029 100644
--- a/src/basic/log.h
+++ b/src/basic/log.h
@@ -84,8 +84,11 @@ void log_close(void);
void log_forget_fds(void);
void log_parse_environment_realm(LogRealm realm);
+void log_parse_environment_cli_realm(LogRealm realm);
#define log_parse_environment() \
log_parse_environment_realm(LOG_REALM)
+#define log_parse_environment_cli() \
+ log_parse_environment_cli_realm(LOG_REALM)
int log_dispatch_internal(
int level,
@@ -341,3 +344,4 @@ int log_syntax_invalid_utf8_internal(
#define DEBUG_LOGGING _unlikely_(log_get_max_level() >= LOG_DEBUG)
void log_setup_service(void);
+void log_setup_cli(void);
diff --git a/src/basic/memory-util.h b/src/basic/memory-util.h
index a6a2ccdbc2..4f596cffb7 100644
--- a/src/basic/memory-util.h
+++ b/src/basic/memory-util.h
@@ -13,6 +13,7 @@
size_t page_size(void) _pure_;
#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
#define PAGE_ALIGN_DOWN(l) ((l) & ~(page_size() - 1))
+#define PAGE_OFFSET(l) ((l) & (page_size() - 1))
/* Normal memcpy requires src to be nonnull. We do nothing if n is 0. */
static inline void memcpy_safe(void *dst, const void *src, size_t n) {
diff --git a/src/basic/meson.build b/src/basic/meson.build
index 5bb49ef401..90924d6cb8 100644
--- a/src/basic/meson.build
+++ b/src/basic/meson.build
@@ -39,6 +39,7 @@ basic_sources = files('''
device-nodes.h
dirent-util.c
dirent-util.h
+ dlfcn-util.h
efivars.c
efivars.h
env-file.c
@@ -328,7 +329,8 @@ libbasic = static_library(
threads,
libcap,
libselinux,
- libm],
+ libm,
+ libdl],
c_args : ['-fvisibility=default'],
install : false)
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
index 33ff427ae7..80bd65b155 100644
--- a/src/basic/selinux-util.c
+++ b/src/basic/selinux-util.c
@@ -39,7 +39,18 @@ static int cached_enforcing = -1;
static struct selabel_handle *label_hnd = NULL;
#define log_enforcing(...) log_full(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, __VA_ARGS__)
-#define log_enforcing_errno(r, ...) log_full_errno(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, r, __VA_ARGS__)
+
+#define log_enforcing_errno(error, ...) \
+ ({ \
+ bool _enforcing = mac_selinux_enforcing(); \
+ int _level = _enforcing ? LOG_ERR : LOG_WARNING; \
+ int _e = (error); \
+ \
+ int _r = (log_get_max_level() >= LOG_PRI(_level)) \
+ ? log_internal_realm(_level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
+ : -ERRNO_VALUE(_e); \
+ _enforcing ? _r : 0; \
+ })
#endif
bool mac_selinux_use(void) {
@@ -59,14 +70,15 @@ bool mac_selinux_enforcing(void) {
#if HAVE_SELINUX
if (_unlikely_(cached_enforcing < 0)) {
cached_enforcing = security_getenforce();
- if (cached_enforcing == -1)
- log_error_errno(errno, "Failed to get SELinux enforced status, continue in enforcing mode: %m");
- else
- log_debug("SELinux enforcing state cached to: %s", cached_enforcing ? "enforcing" : "permissive");
+ if (cached_enforcing < 0) {
+ log_debug_errno(errno, "Failed to get SELinux enforced status, continuing in enforcing mode: %m");
+ return true; /* treat failure as enforcing mode */
+ }
+
+ log_debug("SELinux enforcing state cached to: %s", cached_enforcing ? "enforcing" : "permissive");
}
- /* treat failure as enforcing mode */
- return (cached_enforcing != 0);
+ return cached_enforcing > 0;
#else
return false;
#endif
@@ -90,11 +102,11 @@ static int setenforce_callback(int enforcing) {
#endif
int mac_selinux_init(void) {
- int r = 0;
-
#if HAVE_SELINUX
usec_t before_timestamp, after_timestamp;
struct mallinfo before_mallinfo, after_mallinfo;
+ char timespan[FORMAT_TIMESPAN_MAX];
+ int l;
selinux_set_callback(SELINUX_CB_POLICYLOAD, (union selinux_callback) mac_selinux_reload);
selinux_set_callback(SELINUX_CB_SETENFORCE, (union selinux_callback) setenforce_callback);
@@ -109,25 +121,20 @@ int mac_selinux_init(void) {
before_timestamp = now(CLOCK_MONOTONIC);
label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
- if (!label_hnd) {
- log_enforcing_errno(errno, "Failed to initialize SELinux context: %m");
- r = mac_selinux_enforcing() ? -errno : 0;
- } else {
- char timespan[FORMAT_TIMESPAN_MAX];
- int l;
+ if (!label_hnd)
+ return log_enforcing_errno(errno, "Failed to initialize SELinux labeling handle: %m");
- after_timestamp = now(CLOCK_MONOTONIC);
- after_mallinfo = mallinfo();
+ after_timestamp = now(CLOCK_MONOTONIC);
+ after_mallinfo = mallinfo();
- l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
+ l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
- log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.",
- format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0),
- (l+1023)/1024);
- }
-#endif
+ log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.",
+ format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0),
+ (l+1023)/1024);
- return r;
+#endif
+ return 0;
}
void mac_selinux_finish(void) {
@@ -226,9 +233,7 @@ int mac_selinux_fix_container(const char *path, const char *inside_path, LabelFi
return 0;
fail:
- log_enforcing_errno(r, "Unable to fix SELinux security context of %s (%s): %m", path, inside_path);
- if (mac_selinux_enforcing())
- return r;
+ return log_enforcing_errno(r, "Unable to fix SELinux security context of %s (%s): %m", path, inside_path);
#endif
return 0;
@@ -243,21 +248,17 @@ int mac_selinux_apply(const char *path, const char *label) {
assert(path);
assert(label);
- if (setfilecon(path, label) < 0) {
- log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path);
- if (mac_selinux_enforcing())
- return -errno;
- }
+ if (setfilecon(path, label) < 0)
+ return log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path);
#endif
return 0;
}
int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
- int r = -EOPNOTSUPP;
-
#if HAVE_SELINUX
_cleanup_freecon_ char *mycon = NULL, *fcon = NULL;
security_class_t sclass;
+ int r;
assert(exe);
assert(label);
@@ -280,36 +281,39 @@ int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
r = security_compute_create_raw(mycon, fcon, sclass, label);
if (r < 0)
return -errno;
-#endif
- return r;
+ return 0;
+#else
+ return -EOPNOTSUPP;
+#endif
}
int mac_selinux_get_our_label(char **label) {
- int r = -EOPNOTSUPP;
+#if HAVE_SELINUX
+ int r;
assert(label);
-#if HAVE_SELINUX
if (!mac_selinux_use())
return -EOPNOTSUPP;
r = getcon_raw(label);
if (r < 0)
return -errno;
-#endif
- return r;
+ return 0;
+#else
+ return -EOPNOTSUPP;
+#endif
}
int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) {
- int r = -EOPNOTSUPP;
-
#if HAVE_SELINUX
_cleanup_freecon_ char *mycon = NULL, *peercon = NULL, *fcon = NULL;
_cleanup_context_free_ context_t pcon = NULL, bcon = NULL;
security_class_t sclass;
const char *range = NULL;
+ int r;
assert(socket_fd >= 0);
assert(exe);
@@ -362,21 +366,19 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
r = security_compute_create_raw(mycon, fcon, sclass, label);
if (r < 0)
return -errno;
-#endif
- return r;
+ return 0;
+#else
+ return -EOPNOTSUPP;
+#endif
}
char* mac_selinux_free(char *label) {
#if HAVE_SELINUX
- if (!label)
- return NULL;
-
- if (!mac_selinux_use())
- return NULL;
-
freecon(label);
+#else
+ assert(!label);
#endif
return NULL;
@@ -399,26 +401,21 @@ static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode)
if (errno == ENOENT)
return 0;
- log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", abspath);
- } else {
- if (setfscreatecon_raw(filecon) >= 0)
- return 0; /* Success! */
-
- log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath);
+ return log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", abspath);
}
- if (mac_selinux_enforcing())
- return -errno;
+ if (setfscreatecon_raw(filecon) < 0)
+ return log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath);
return 0;
}
#endif
int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode) {
- int r = 0;
-
#if HAVE_SELINUX
_cleanup_free_ char *abspath = NULL;
+ int r;
+
assert(path);
@@ -440,15 +437,16 @@ int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode)
return -ENOMEM;
}
- r = selinux_create_file_prepare_abspath(path, mode);
+ return selinux_create_file_prepare_abspath(path, mode);
+#else
+ return 0;
#endif
- return r;
}
int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
- int r = 0;
-
#if HAVE_SELINUX
+ int r;
+
_cleanup_free_ char *abspath = NULL;
assert(path);
@@ -460,9 +458,10 @@ int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
if (r < 0)
return r;
- r = selinux_create_file_prepare_abspath(abspath, mode);
+ return selinux_create_file_prepare_abspath(abspath, mode);
+#else
+ return 0;
#endif
- return r;
}
void mac_selinux_create_file_clear(void) {
@@ -480,17 +479,13 @@ void mac_selinux_create_file_clear(void) {
int mac_selinux_create_socket_prepare(const char *label) {
#if HAVE_SELINUX
- if (!mac_selinux_use())
- return 0;
-
assert(label);
- if (setsockcreatecon(label) < 0) {
- log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label);
+ if (!mac_selinux_use())
+ return 0;
- if (mac_selinux_enforcing())
- return -errno;
- }
+ if (setsockcreatecon(label) < 0)
+ return log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label);
#endif
return 0;
@@ -561,15 +556,14 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
if (errno == ENOENT)
goto skipped;
- log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
- if (mac_selinux_enforcing())
- return -errno;
-
+ r = log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
+ if (r < 0)
+ return r;
} else {
if (setfscreatecon_raw(fcon) < 0) {
- log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path);
- if (mac_selinux_enforcing())
- return -errno;
+ r = log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path);
+ if (r < 0)
+ return r;
} else
context_changed = true;
}
@@ -577,7 +571,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
r = bind(fd, addr, addrlen) < 0 ? -errno : 0;
if (context_changed)
- setfscreatecon_raw(NULL);
+ (void) setfscreatecon_raw(NULL);
return r;
diff --git a/src/basic/set.h b/src/basic/set.h
index 621e83bf27..e4fc1e3c4a 100644
--- a/src/basic/set.h
+++ b/src/basic/set.h
@@ -26,9 +26,7 @@ static inline Set *set_free_free(Set *s) {
/* no set_free_free_free */
-static inline Set *set_copy(Set *s) {
- return (Set*) _hashmap_copy(HASHMAP_BASE(s));
-}
+#define set_copy(s) ((Set*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS))
int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
#define set_ensure_allocated(h, ops) _set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
@@ -120,9 +118,19 @@ static inline char **set_get_strv(Set *s) {
return _hashmap_get_strv(HASHMAP_BASE(s));
}
+int _set_ensure_put(Set **s, const struct hash_ops *hash_ops, const void *key HASHMAP_DEBUG_PARAMS);
+#define set_ensure_put(s, hash_ops, key) _set_ensure_put(s, hash_ops, key HASHMAP_DEBUG_SRC_ARGS)
+
+int _set_ensure_consume(Set **s, const struct hash_ops *hash_ops, void *key HASHMAP_DEBUG_PARAMS);
+#define set_ensure_consume(s, hash_ops, key) _set_ensure_consume(s, hash_ops, key HASHMAP_DEBUG_SRC_ARGS)
+
int set_consume(Set *s, void *value);
-int set_put_strdup(Set **s, const char *p);
-int set_put_strdupv(Set **s, char **l);
+
+int _set_put_strdup(Set **s, const char *p HASHMAP_DEBUG_PARAMS);
+#define set_put_strdup(s, p) _set_put_strdup(s, p HASHMAP_DEBUG_SRC_ARGS)
+int _set_put_strdupv(Set **s, char **l HASHMAP_DEBUG_PARAMS);
+#define set_put_strdupv(s, l) _set_put_strdupv(s, l HASHMAP_DEBUG_SRC_ARGS)
+
int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags);
#define SET_FOREACH(e, s, i) \
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index 952c3f62c2..5189d86d1a 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -272,8 +272,8 @@ static BOOLEAN line_edit(
case KEYPRESS(0, 0, CHAR_LINEFEED):
case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN):
- case KEYPRESS(0, CHAR_CARRIAGE_RETURN, 0):
- case KEYPRESS(0, CHAR_CARRIAGE_RETURN, CHAR_CARRIAGE_RETURN):
+ case KEYPRESS(0, CHAR_CARRIAGE_RETURN, 0): /* EZpad Mini 4s firmware sends malformed events */
+ case KEYPRESS(0, CHAR_CARRIAGE_RETURN, CHAR_CARRIAGE_RETURN): /* Teclast X98+ II firmware sends malformed events */
if (StrCmp(line, line_in) != 0)
*line_out = TAKE_PTR(line);
enter = TRUE;
@@ -744,8 +744,8 @@ static BOOLEAN menu_run(
case KEYPRESS(0, 0, CHAR_LINEFEED):
case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN):
- case KEYPRESS(0, CHAR_CARRIAGE_RETURN, 0):
- case KEYPRESS(0, CHAR_CARRIAGE_RETURN, CHAR_CARRIAGE_RETURN):
+ case KEYPRESS(0, CHAR_CARRIAGE_RETURN, 0): /* EZpad Mini 4s firmware sends malformed events */
+ case KEYPRESS(0, CHAR_CARRIAGE_RETURN, CHAR_CARRIAGE_RETURN): /* Teclast X98+ II firmware sends malformed events */
case KEYPRESS(0, SCAN_RIGHT, 0):
exit = TRUE;
break;
diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c
index 8e000ee119..3ab90de63e 100644
--- a/src/busctl/busctl.c
+++ b/src/busctl/busctl.c
@@ -2598,9 +2598,7 @@ static int busctl_main(int argc, char *argv[]) {
static int run(int argc, char *argv[]) {
int r;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c
index b55d7299ca..939a391e21 100644
--- a/src/cgls/cgls.c
+++ b/src/cgls/cgls.c
@@ -164,9 +164,7 @@ static void show_cg_info(const char *controller, const char *path) {
static int run(int argc, char *argv[]) {
int r, output_flags;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c
index de25aaae5d..e6c09d1b38 100644
--- a/src/cgtop/cgtop.c
+++ b/src/cgtop/cgtop.c
@@ -908,9 +908,7 @@ static int run(int argc, char *argv[]) {
CGroupMask mask;
int r;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/core/automount.c b/src/core/automount.c
index 566b56eb34..77420b929f 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -912,13 +912,7 @@ static int automount_deserialize_item(Unit *u, const char *key, const char *valu
if (safe_atou(value, &token) < 0)
log_unit_debug(u, "Failed to parse token value: %s", value);
else {
- r = set_ensure_allocated(&a->tokens, NULL);
- if (r < 0) {
- log_oom();
- return 0;
- }
-
- r = set_put(a->tokens, UINT_TO_PTR(token));
+ r = set_ensure_put(&a->tokens, NULL, UINT_TO_PTR(token));
if (r < 0)
log_unit_error_errno(u, r, "Failed to add token to set: %m");
}
@@ -928,13 +922,7 @@ static int automount_deserialize_item(Unit *u, const char *key, const char *valu
if (safe_atou(value, &token) < 0)
log_unit_debug(u, "Failed to parse token value: %s", value);
else {
- r = set_ensure_allocated(&a->expire_tokens, NULL);
- if (r < 0) {
- log_oom();
- return 0;
- }
-
- r = set_put(a->expire_tokens, UINT_TO_PTR(token));
+ r = set_ensure_put(&a->expire_tokens, NULL, UINT_TO_PTR(token));
if (r < 0)
log_unit_error_errno(u, r, "Failed to add expire token to set: %m");
}
@@ -1010,13 +998,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
} else
log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where);
- r = set_ensure_allocated(&a->tokens, NULL);
- if (r < 0) {
- log_unit_error(UNIT(a), "Failed to allocate token set.");
- goto fail;
- }
-
- r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
+ r = set_ensure_put(&a->tokens, NULL, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
if (r < 0) {
log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
goto fail;
@@ -1030,13 +1012,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
automount_stop_expire(a);
- r = set_ensure_allocated(&a->expire_tokens, NULL);
- if (r < 0) {
- log_unit_error(UNIT(a), "Failed to allocate token set.");
- goto fail;
- }
-
- r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
+ r = set_ensure_put(&a->expire_tokens, NULL, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
if (r < 0) {
log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
goto fail;
diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c
index 96c1a28b4f..2ec274df01 100644
--- a/src/core/bpf-firewall.c
+++ b/src/core/bpf-firewall.c
@@ -595,7 +595,7 @@ static int load_bpf_progs_from_fs_to_set(Unit *u, char **filter_paths, Set **set
set_clear(*set);
STRV_FOREACH(bpf_fs_path, filter_paths) {
- _cleanup_free_ BPFProgram *prog = NULL;
+ _cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL;
int r;
r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, &prog);
@@ -606,14 +606,9 @@ static int load_bpf_progs_from_fs_to_set(Unit *u, char **filter_paths, Set **set
if (r < 0)
return log_unit_error_errno(u, r, "Loading of ingress BPF program %s failed: %m", *bpf_fs_path);
- r = set_ensure_allocated(set, &filter_prog_hash_ops);
- if (r < 0)
- return log_unit_error_errno(u, r, "Can't allocate BPF program set: %m");
-
- r = set_put(*set, prog);
+ r = set_ensure_consume(set, &filter_prog_hash_ops, TAKE_PTR(prog));
if (r < 0)
return log_unit_error_errno(u, r, "Can't add program to BPF program set: %m");
- TAKE_PTR(prog);
}
return 0;
@@ -662,12 +657,9 @@ static int attach_custom_bpf_progs(Unit *u, const char *path, int attach_type, S
r = bpf_program_cgroup_attach(prog, attach_type, path, BPF_F_ALLOW_MULTI);
if (r < 0)
return log_unit_error_errno(u, r, "Attaching custom egress BPF program to cgroup %s failed: %m", path);
- /* Remember that these BPF programs are installed now. */
- r = set_ensure_allocated(set_installed, &filter_prog_hash_ops);
- if (r < 0)
- return log_unit_error_errno(u, r, "Can't allocate BPF program set: %m");
- r = set_put(*set_installed, prog);
+ /* Remember that these BPF programs are installed now. */
+ r = set_ensure_put(set_installed, &filter_prog_hash_ops, prog);
if (r < 0)
return log_unit_error_errno(u, r, "Can't add program to BPF program set: %m");
bpf_program_ref(prog);
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
index 8587a712e2..080f6fb1ae 100644
--- a/src/core/dbus-cgroup.c
+++ b/src/core/dbus-cgroup.c
@@ -707,112 +707,14 @@ static int bus_cgroup_set_boolean(
return 1; \
}
-#define BUS_DEFINE_SET_CGROUP_PROTECTION(function, mask, scale) \
- static int bus_cgroup_set_##function( \
- Unit *u, \
- const char *name, \
- uint64_t *p, \
- bool *s, \
- sd_bus_message *message, \
- UnitWriteFlags flags, \
- sd_bus_error *error) { \
- \
- uint64_t v = CGROUP_LIMIT_MIN; \
- bool nonempty = true; \
- char type; \
- int r; \
- \
- assert(p); \
- assert(s); \
- \
- r = sd_bus_message_peek_type(message, &type, NULL); \
- if (r < 0) \
- return r; \
- if (type == SD_BUS_TYPE_BOOLEAN) { \
- r = sd_bus_message_read(message, "b", &nonempty); \
- if (r < 0) \
- return r; \
- /* Bool is used to denote empty value only */ \
- if (nonempty) \
- return -EINVAL; \
- } else if (type != SD_BUS_TYPE_UINT64) { \
- return -EINVAL; \
- } else { \
- r = sd_bus_message_read(message, "t", &v); \
- if (r < 0) \
- return r; \
- } \
- \
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
- *p = v; \
- unit_invalidate_cgroup(u, mask); \
- if (!nonempty) { \
- *s = false; \
- unit_write_settingf(u, flags, name, \
- "%s=", name); \
- } else if (v == CGROUP_LIMIT_MAX) { \
- *s = true; \
- unit_write_settingf(u, flags, name, \
- "%s=infinity", name); \
- } else { \
- *s = true; \
- unit_write_settingf(u, flags, name, \
- "%s=%" PRIu64, name, v); \
- } \
- } \
- \
- return 1; \
- } \
- static int bus_cgroup_set_##function##_scale( \
- Unit *u, \
- const char *name, \
- uint64_t *p, \
- bool *s, \
- sd_bus_message *message, \
- UnitWriteFlags flags, \
- sd_bus_error *error) { \
- \
- uint64_t v; \
- uint32_t raw; \
- int r; \
- \
- assert(p); \
- assert(s); \
- \
- r = sd_bus_message_read(message, "u", &raw); \
- if (r < 0) \
- return r; \
- \
- v = scale(raw, UINT32_MAX); \
- if (v >= UINT64_MAX) \
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
- "Value specified in %s is out of range", name); \
- \
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
- *p = v; \
- unit_invalidate_cgroup(u, mask); \
- \
- /* Prepare to chop off suffix */ \
- assert_se(endswith(name, "Scale")); \
- \
- uint32_t scaled = DIV_ROUND_UP((uint64_t) raw * 1000, (uint64_t) UINT32_MAX); \
- unit_write_settingf(u, flags, name, "%.*s=%" PRIu32 ".%" PRIu32 "%%", \
- (int)(strlen(name) - strlen("Scale")), name, \
- scaled / 10, scaled % 10); \
- } \
- \
- *s = true; \
- return 1; \
- }
-
DISABLE_WARNING_TYPE_LIMITS;
BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight, CGROUP_MASK_CPU, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID);
BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID);
BUS_DEFINE_SET_CGROUP_LIMIT(memory, CGROUP_MASK_MEMORY, physical_memory_scale, 1);
+BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
BUS_DEFINE_SET_CGROUP_LIMIT(swap, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
-BUS_DEFINE_SET_CGROUP_PROTECTION(memory_protection, CGROUP_MASK_MEMORY, physical_memory_scale);
REENABLE_WARNING;
static int bus_cgroup_set_tasks_max(
@@ -938,17 +840,33 @@ int bus_cgroup_set_property(
if (streq(name, "MemoryAccounting"))
return bus_cgroup_set_boolean(u, name, &c->memory_accounting, CGROUP_MASK_MEMORY, message, flags, error);
- if (streq(name, "MemoryMin"))
- return bus_cgroup_set_memory_protection(u, name, &c->memory_min, &c->memory_min_set, message, flags, error);
+ if (streq(name, "MemoryMin")) {
+ r = bus_cgroup_set_memory_protection(u, name, &c->memory_min, message, flags, error);
+ if (r > 0)
+ c->memory_min_set = true;
+ return r;
+ }
- if (streq(name, "MemoryLow"))
- return bus_cgroup_set_memory_protection(u, name, &c->memory_low, &c->memory_low_set, message, flags, error);
+ if (streq(name, "MemoryLow")) {
+ r = bus_cgroup_set_memory_protection(u, name, &c->memory_low, message, flags, error);
+ if (r > 0)
+ c->memory_low_set = true;
+ return r;
+ }
- if (streq(name, "DefaultMemoryMin"))
- return bus_cgroup_set_memory_protection(u, name, &c->default_memory_min, &c->default_memory_min_set, message, flags, error);
+ if (streq(name, "DefaultMemoryMin")) {
+ r = bus_cgroup_set_memory_protection(u, name, &c->default_memory_min, message, flags, error);
+ if (r > 0)
+ c->default_memory_min_set = true;
+ return r;
+ }
- if (streq(name, "DefaultMemoryLow"))
- return bus_cgroup_set_memory_protection(u, name, &c->default_memory_low, &c->default_memory_low_set, message, flags, error);
+ if (streq(name, "DefaultMemoryLow")) {
+ r = bus_cgroup_set_memory_protection(u, name, &c->default_memory_low, message, flags, error);
+ if (r > 0)
+ c->default_memory_low_set = true;
+ return r;
+ }
if (streq(name, "MemoryHigh"))
return bus_cgroup_set_memory(u, name, &c->memory_high, message, flags, error);
@@ -962,17 +880,33 @@ int bus_cgroup_set_property(
if (streq(name, "MemoryLimit"))
return bus_cgroup_set_memory(u, name, &c->memory_limit, message, flags, error);
- if (streq(name, "MemoryMinScale"))
- return bus_cgroup_set_memory_protection_scale(u, name, &c->memory_min, &c->memory_min_set, message, flags, error);
+ if (streq(name, "MemoryMinScale")) {
+ r = bus_cgroup_set_memory_protection_scale(u, name, &c->memory_min, message, flags, error);
+ if (r > 0)
+ c->memory_min_set = true;
+ return r;
+ }
- if (streq(name, "MemoryLowScale"))
- return bus_cgroup_set_memory_protection_scale(u, name, &c->memory_low, &c->memory_low_set, message, flags, error);
+ if (streq(name, "MemoryLowScale")) {
+ r = bus_cgroup_set_memory_protection_scale(u, name, &c->memory_low, message, flags, error);
+ if (r > 0)
+ c->memory_low_set = true;
+ return r;
+ }
- if (streq(name, "DefaultMemoryMinScale"))
- return bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_min, &c->default_memory_min_set, message, flags, error);
+ if (streq(name, "DefaultMemoryMinScale")) {
+ r = bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_min, message, flags, error);
+ if (r > 0)
+ c->default_memory_min_set = true;
+ return r;
+ }
- if (streq(name, "DefaultMemoryLowScale"))
- return bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_low, &c->default_memory_low_set, message, flags, error);
+ if (streq(name, "DefaultMemoryLowScale")) {
+ r = bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_low, message, flags, error);
+ if (r > 0)
+ c->default_memory_low_set = true;
+ return r;
+ }
if (streq(name, "MemoryHighScale"))
return bus_cgroup_set_memory_scale(u, name, &c->memory_high, message, flags, error);
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 06b6b95d69..68ce395c56 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -746,6 +746,25 @@ static int property_get_log_extra_fields(
return sd_bus_message_close_container(reply);
}
+static int property_get_root_hash(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ ExecContext *c = userdata;
+
+ assert(bus);
+ assert(c);
+ assert(property);
+ assert(reply);
+
+ return sd_bus_message_append_array(reply, 'y', c->root_hash, c->root_hash_size);
+}
+
const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -788,6 +807,9 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RootHash", "ay", property_get_root_hash, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RootHashPath", "s", NULL, offsetof(ExecContext, root_hash_path), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RootVerity", "s", NULL, offsetof(ExecContext, root_verity), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CoredumpFilter", "t", property_get_coredump_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -1258,6 +1280,55 @@ int bus_exec_context_set_transient_property(
if (streq(name, "RootImage"))
return bus_set_transient_path(u, name, &c->root_image, message, flags, error);
+ if (streq(name, "RootHash")) {
+ const void *roothash_decoded;
+ size_t roothash_decoded_size;
+
+ r = sd_bus_message_read_array(message, 'y', &roothash_decoded, &roothash_decoded_size);
+ if (r < 0)
+ return r;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ _cleanup_free_ char *encoded = NULL;
+
+ if (roothash_decoded_size == 0) {
+ c->root_hash_path = mfree(c->root_hash_path);
+ c->root_hash = mfree(c->root_hash);
+ c->root_hash_size = 0;
+
+ unit_write_settingf(u, flags, name, "RootHash=");
+ } else {
+ _cleanup_free_ void *p;
+
+ encoded = hexmem(roothash_decoded, roothash_decoded_size);
+ if (!encoded)
+ return -ENOMEM;
+
+ p = memdup(roothash_decoded, roothash_decoded_size);
+ if (!p)
+ return -ENOMEM;
+
+ free_and_replace(c->root_hash, p);
+ c->root_hash_size = roothash_decoded_size;
+ c->root_hash_path = mfree(c->root_hash_path);
+
+ unit_write_settingf(u, flags, name, "RootHash=%s", encoded);
+ }
+ }
+
+ return 1;
+ }
+
+ if (streq(name, "RootHashPath")) {
+ c->root_hash_size = 0;
+ c->root_hash = mfree(c->root_hash);
+
+ return bus_set_transient_path(u, "RootHash", &c->root_hash_path, message, flags, error);
+ }
+
+ if (streq(name, "RootVerity"))
+ return bus_set_transient_path(u, name, &c->root_verity, message, flags, error);
+
if (streq(name, "RootDirectory"))
return bus_set_transient_path(u, name, &c->root_directory, message, flags, error);
@@ -1697,10 +1768,6 @@ int bus_exec_context_set_transient_property(
else {
char **s;
- r = set_ensure_allocated(&c->syscall_archs, NULL);
- if (r < 0)
- return r;
-
STRV_FOREACH(s, l) {
uint32_t a;
@@ -1708,7 +1775,7 @@ int bus_exec_context_set_transient_property(
if (r < 0)
return r;
- r = set_put(c->syscall_archs, UINT32_TO_PTR(a + 1));
+ r = set_ensure_put(&c->syscall_archs, NULL, UINT32_TO_PTR(a + 1));
if (r < 0)
return r;
}
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 2a3c8e776a..5cb06867cb 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -234,14 +234,12 @@ static int property_get_show_status(
sd_bus_error *error) {
Manager *m = userdata;
- int b;
+ assert(m);
assert(bus);
assert(reply);
- assert(m);
- b = IN_SET(m->show_status, SHOW_STATUS_TEMPORARY, SHOW_STATUS_YES);
- return sd_bus_message_append_basic(reply, 'b', &b);
+ return sd_bus_message_append(reply, "b", manager_get_show_status_on(m));
}
static int property_get_runtime_watchdog(
@@ -311,7 +309,7 @@ static int property_set_watchdog(Manager *m, WatchdogType type, sd_bus_message *
if (r < 0)
return r;
- return manager_set_watchdog_overridden(m, type, timeout);
+ return manager_override_watchdog(m, type, timeout);
}
static int property_set_runtime_watchdog(
@@ -2452,6 +2450,30 @@ static int method_abandon_scope(sd_bus_message *message, void *userdata, sd_bus_
return bus_scope_method_abandon(message, u, error);
}
+static int method_set_show_status(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+ ShowStatus mode = _SHOW_STATUS_INVALID;
+ const char *t;
+ int r;
+
+ assert(m);
+ assert(message);
+
+ r = sd_bus_message_read(message, "s", &t);
+ if (r < 0)
+ return r;
+
+ if (!isempty(t)) {
+ mode = show_status_from_string(t);
+ if (mode < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid show status '%s'", t);
+ }
+
+ manager_override_show_status(m, mode, "bus");
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_VTABLE_START(0),
@@ -2786,6 +2808,12 @@ const sd_bus_vtable bus_manager_vtable[] = {
NULL,
method_reset_failed,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("SetShowStatus",
+ "s",
+ SD_BUS_PARAM(mode),
+ NULL,,
+ method_set_show_status,
+ SD_BUS_VTABLE_CAPABILITY(CAP_SYS_ADMIN)),
SD_BUS_METHOD_WITH_NAMES("ListUnits",
NULL,,
"a(ssssssouso)",
diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c
index 4330c0f2c1..1565a79927 100644
--- a/src/core/emergency-action.c
+++ b/src/core/emergency-action.c
@@ -12,6 +12,18 @@
#include "terminal-util.h"
#include "virt.h"
+static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = {
+ [EMERGENCY_ACTION_NONE] = "none",
+ [EMERGENCY_ACTION_REBOOT] = "reboot",
+ [EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force",
+ [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
+ [EMERGENCY_ACTION_POWEROFF] = "poweroff",
+ [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force",
+ [EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate",
+ [EMERGENCY_ACTION_EXIT] = "exit",
+ [EMERGENCY_ACTION_EXIT_FORCE] = "exit-force",
+};
+
static void log_and_status(Manager *m, bool warn, const char *message, const char *reason) {
log_full(warn ? LOG_WARNING : LOG_DEBUG, "%s: %s", message, reason);
if (warn)
@@ -28,10 +40,22 @@ void emergency_action(
int exit_status,
const char *reason) {
+ Unit *u;
+
assert(m);
assert(action >= 0);
assert(action < _EMERGENCY_ACTION_MAX);
+ /* Is the special shutdown target active or queued? If so, we are in shutdown state */
+ if (IN_SET(action, EMERGENCY_ACTION_REBOOT, EMERGENCY_ACTION_POWEROFF, EMERGENCY_ACTION_EXIT)) {
+ u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET);
+ if (u && unit_active_or_pending(u)) {
+ log_notice("Shutdown is already active. Skipping emergency action request %s.",
+ emergency_action_table[action]);
+ return;
+ }
+ }
+
if (action == EMERGENCY_ACTION_NONE)
return;
@@ -126,17 +150,6 @@ void emergency_action(
}
}
-static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = {
- [EMERGENCY_ACTION_NONE] = "none",
- [EMERGENCY_ACTION_REBOOT] = "reboot",
- [EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force",
- [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
- [EMERGENCY_ACTION_POWEROFF] = "poweroff",
- [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force",
- [EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate",
- [EMERGENCY_ACTION_EXIT] = "exit",
- [EMERGENCY_ACTION_EXIT_FORCE] = "exit-force",
-};
DEFINE_STRING_TABLE_LOOKUP(emergency_action, EmergencyAction);
int parse_emergency_action(
diff --git a/src/core/execute.c b/src/core/execute.c
index aa253a5ddf..e0835f9b92 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -54,6 +54,7 @@
#include "format-util.h"
#include "fs-util.h"
#include "glob-util.h"
+#include "hexdecoct.h"
#include "io-util.h"
#include "ioprio.h"
#include "label.h"
@@ -2666,6 +2667,7 @@ static int apply_mount_namespace(
needs_sandboxing ? context->protect_home : PROTECT_HOME_NO,
needs_sandboxing ? context->protect_system : PROTECT_SYSTEM_NO,
context->mount_flags,
+ context->root_hash, context->root_hash_size, context->root_hash_path, context->root_verity,
DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
error_path);
@@ -4195,6 +4197,10 @@ void exec_context_done(ExecContext *c) {
c->working_directory = mfree(c->working_directory);
c->root_directory = mfree(c->root_directory);
c->root_image = mfree(c->root_image);
+ c->root_hash = mfree(c->root_hash);
+ c->root_hash_size = 0;
+ c->root_hash_path = mfree(c->root_hash_path);
+ c->root_verity = mfree(c->root_verity);
c->tty_path = mfree(c->tty_path);
c->syslog_identifier = mfree(c->syslog_identifier);
c->user = mfree(c->user);
@@ -4599,6 +4605,19 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
if (c->root_image)
fprintf(f, "%sRootImage: %s\n", prefix, c->root_image);
+ if (c->root_hash) {
+ _cleanup_free_ char *encoded = NULL;
+ encoded = hexmem(c->root_hash, c->root_hash_size);
+ if (encoded)
+ fprintf(f, "%sRootHash: %s\n", prefix, encoded);
+ }
+
+ if (c->root_hash_path)
+ fprintf(f, "%sRootHash: %s\n", prefix, c->root_hash_path);
+
+ if (c->root_verity)
+ fprintf(f, "%sRootVerity: %s\n", prefix, c->root_verity);
+
STRV_FOREACH(e, c->environment)
fprintf(f, "%sEnvironment: %s\n", prefix, *e);
diff --git a/src/core/execute.h b/src/core/execute.h
index 7e1015631f..7c9d63c5e4 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -155,7 +155,9 @@ struct ExecContext {
char **unset_environment;
struct rlimit *rlimit[_RLIMIT_MAX];
- char *working_directory, *root_directory, *root_image;
+ char *working_directory, *root_directory, *root_image, *root_verity, *root_hash_path;
+ void *root_hash;
+ size_t root_hash_size;
bool working_directory_missing_ok:1;
bool working_directory_home:1;
diff --git a/src/core/job.c b/src/core/job.c
index d518ac8969..ff49136d70 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -387,62 +387,25 @@ JobType job_type_lookup_merge(JobType a, JobType b) {
return job_merging_table[(a - 1) * a / 2 + b];
}
-bool job_later_link_matters(Job *j, JobType type, unsigned generation) {
- JobDependency *l;
-
- assert(j);
-
- j->generation = generation;
-
- LIST_FOREACH(subject, l, j->subject_list) {
- UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID;
-
- /* Have we seen this before? */
- if (l->object->generation == generation)
- continue;
-
- state = unit_active_state(l->object->unit);
- switch (type) {
-
- case JOB_START:
- return IN_SET(state, UNIT_INACTIVE, UNIT_FAILED) ||
- job_later_link_matters(l->object, type, generation);
-
- case JOB_STOP:
- return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING) ||
- job_later_link_matters(l->object, type, generation);
-
- default:
- assert_not_reached("Invalid job type");
- }
- }
-
- return false;
-}
-
-bool job_is_redundant(Job *j, unsigned generation) {
-
- assert(j);
-
- UnitActiveState state = unit_active_state(j->unit);
- switch (j->type) {
+bool job_type_is_redundant(JobType a, UnitActiveState b) {
+ switch (a) {
case JOB_START:
- return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING) && !job_later_link_matters(j, JOB_START, generation);
+ return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
case JOB_STOP:
- return IN_SET(state, UNIT_INACTIVE, UNIT_FAILED) && !job_later_link_matters(j, JOB_STOP, generation);
+ return IN_SET(b, UNIT_INACTIVE, UNIT_FAILED);
case JOB_VERIFY_ACTIVE:
- return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING);
+ return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
case JOB_RELOAD:
return
- state == UNIT_RELOADING;
+ b == UNIT_RELOADING;
case JOB_RESTART:
return
- state == UNIT_ACTIVATING;
+ b == UNIT_ACTIVATING;
case JOB_NOP:
return true;
diff --git a/src/core/job.h b/src/core/job.h
index 02b057ee06..03ad640618 100644
--- a/src/core/job.h
+++ b/src/core/job.h
@@ -196,8 +196,7 @@ _pure_ static inline bool job_type_is_superset(JobType a, JobType b) {
return a == job_type_lookup_merge(a, b);
}
-bool job_later_link_matters(Job *j, JobType type, unsigned generation);
-bool job_is_redundant(Job *j, unsigned generation);
+bool job_type_is_redundant(JobType a, UnitActiveState b) _pure_;
/* Collapses a state-dependent job type into a simpler type by observing
* the state of the unit which it is going to be applied to. */
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 69598e8430..9cf959edd5 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -23,6 +23,8 @@ m4_define(`EXEC_CONTEXT_CONFIG_ITEMS',
`$1.WorkingDirectory, config_parse_working_directory, 0, offsetof($1, exec_context)
$1.RootDirectory, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_directory)
$1.RootImage, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_image)
+$1.RootHash, config_parse_exec_root_hash, 0, offsetof($1, exec_context)
+$1.RootVerity, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_verity)
$1.User, config_parse_user_group_compat, 0, offsetof($1, exec_context.user)
$1.Group, config_parse_user_group_compat, 0, offsetof($1, exec_context.group)
$1.SupplementaryGroups, config_parse_user_group_strv_compat, 0, offsetof($1, exec_context.supplementary_groups)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index c1a4eb96cb..c3186f3824 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -29,6 +29,7 @@
#include "errno-list.h"
#include "escape.h"
#include "fd-util.h"
+#include "fileio.h"
#include "fs-util.h"
#include "hexdecoct.h"
#include "io-util.h"
@@ -1413,6 +1414,64 @@ int config_parse_exec_cpu_sched_prio(const char *unit,
return 0;
}
+int config_parse_exec_root_hash(
+ 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) {
+
+ _cleanup_free_ void *roothash_decoded = NULL;
+ ExecContext *c = data;
+ size_t roothash_decoded_size = 0;
+ int r;
+
+ assert(data);
+ assert(filename);
+ assert(line);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ /* Reset if the empty string is assigned */
+ c->root_hash_path = mfree(c->root_hash_path);
+ c->root_hash = mfree(c->root_hash);
+ c->root_hash_size = 0;
+ return 0;
+ }
+
+ if (path_is_absolute(rvalue)) {
+ /* We have the path to a roothash to load and decode, eg: RootHash=/foo/bar.roothash */
+ _cleanup_free_ char *p = NULL;
+
+ p = strdup(rvalue);
+ if (!p)
+ return -ENOMEM;
+
+ free_and_replace(c->root_hash_path, p);
+ c->root_hash = mfree(c->root_hash);
+ c->root_hash_size = 0;
+ return 0;
+ }
+
+ /* We have a roothash to decode, eg: RootHash=012345789abcdef */
+ r = unhexmem(rvalue, strlen(rvalue), &roothash_decoded, &roothash_decoded_size);
+ if (r < 0)
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode RootHash=, ignoring: %s", rvalue);
+ if (roothash_decoded_size < sizeof(sd_id128_t))
+ return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "RootHash= is too short, ignoring: %s", rvalue);
+
+ free_and_replace(c->root_hash, roothash_decoded);
+ c->root_hash_size = roothash_decoded_size;
+ c->root_hash_path = mfree(c->root_hash_path);
+
+ return 0;
+}
+
int config_parse_exec_cpu_affinity(const char *unit,
const char *filename,
unsigned line,
@@ -3043,10 +3102,6 @@ int config_parse_syscall_archs(
return 0;
}
- r = set_ensure_allocated(archs, NULL);
- if (r < 0)
- return log_oom();
-
for (;;) {
_cleanup_free_ char *word = NULL;
uint32_t a;
@@ -3069,7 +3124,7 @@ int config_parse_syscall_archs(
continue;
}
- r = set_put(*archs, UINT32_TO_PTR(a + 1));
+ r = set_ensure_put(archs, NULL, UINT32_TO_PTR(a + 1));
if (r < 0)
return log_oom();
}
@@ -3397,8 +3452,6 @@ int config_parse_memory_limit(
}
}
- /* Keep Memory{Low,Min} unset with empty assignment so that we fall back to DefaultMemory* which in
- * contrast means zeroing the property. */
if (streq(lvalue, "DefaultMemoryLow")) {
c->default_memory_low = bytes;
c->default_memory_low_set = true;
@@ -3407,10 +3460,10 @@ int config_parse_memory_limit(
c->default_memory_min_set = true;
} else if (streq(lvalue, "MemoryMin")) {
c->memory_min = bytes;
- c->memory_min_set = !isempty(rvalue);
+ c->memory_min_set = true;
} else if (streq(lvalue, "MemoryLow")) {
c->memory_low = bytes;
- c->memory_low_set = !isempty(rvalue);
+ c->memory_low_set = true;
} else if (streq(lvalue, "MemoryHigh"))
c->memory_high = bytes;
else if (streq(lvalue, "MemoryMax"))
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index 9c30b6f882..f0e109da3a 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -44,6 +44,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_prio);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_affinity);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_secure_bits);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_root_hash);
CONFIG_PARSER_PROTOTYPE(config_parse_capability_set);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_mount_flags);
CONFIG_PARSER_PROTOTYPE(config_parse_timer);
diff --git a/src/core/main.c b/src/core/main.c
index 6e606d412a..a2ff71fa71 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -2559,7 +2559,7 @@ int main(int argc, char *argv[]) {
}
if (mac_selinux_init() < 0) {
- error_message = "Failed to initialize SELinux policy";
+ error_message = "Failed to initialize SELinux support";
goto finish;
}
@@ -2603,6 +2603,11 @@ int main(int argc, char *argv[]) {
/* clear the kernel timestamp,
* because we are not PID 1 */
kernel_timestamp = DUAL_TIMESTAMP_NULL;
+
+ if (mac_selinux_init() < 0) {
+ error_message = "Failed to initialize SELinux support";
+ goto finish;
+ }
}
if (arg_system) {
diff --git a/src/core/manager.c b/src/core/manager.c
index 72dd93fa95..ab3d0b1192 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -779,6 +779,8 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager
.watchdog_overridden[WATCHDOG_REBOOT] = USEC_INFINITY,
.watchdog_overridden[WATCHDOG_KEXEC] = USEC_INFINITY,
+ .show_status_overridden = _SHOW_STATUS_INVALID,
+
.notify_fd = -1,
.cgroups_agent_fd = -1,
.signal_fd = -1,
@@ -2759,11 +2761,11 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
switch (sfsi.ssi_signo - SIGRTMIN) {
case 20:
- manager_set_show_status(m, SHOW_STATUS_YES, "signal");
+ manager_override_show_status(m, SHOW_STATUS_YES, "signal");
break;
case 21:
- manager_set_show_status(m, SHOW_STATUS_NO, "signal");
+ manager_override_show_status(m, SHOW_STATUS_NO, "signal");
break;
case 22:
@@ -3219,9 +3221,9 @@ int manager_serialize(
/* After switching root, udevd has not been started yet. So, enumeration results should not be emitted. */
(void) serialize_bool(f, "honor-device-enumeration", !switching_root);
- t = show_status_to_string(m->show_status);
- if (t)
- (void) serialize_item(f, "show-status", t);
+ if (m->show_status_overridden != _SHOW_STATUS_INVALID)
+ (void) serialize_item(f, "show-status-overridden",
+ show_status_to_string(m->show_status_overridden));
if (m->log_level_overridden)
(void) serialize_item_format(f, "log-level-override", "%i", log_get_max_level());
@@ -3399,7 +3401,7 @@ void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
m->watchdog[t] = timeout;
}
-int manager_set_watchdog_overridden(Manager *m, WatchdogType t, usec_t timeout) {
+int manager_override_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
int r = 0;
assert(m);
@@ -3568,14 +3570,14 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
else
m->honor_device_enumeration = b;
- } else if ((val = startswith(l, "show-status="))) {
+ } else if ((val = startswith(l, "show-status-overridden="))) {
ShowStatus s;
s = show_status_from_string(val);
if (s < 0)
- log_notice("Failed to parse show-status flag '%s', ignoring.", val);
+ log_notice("Failed to parse show-status-overridden flag '%s', ignoring.", val);
else
- manager_set_show_status(m, s, "deserialization");
+ manager_override_show_status(m, s, "deserialize");
} else if ((val = startswith(l, "log-level-override="))) {
int level;
@@ -3601,7 +3603,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse runtime-watchdog-overridden value '%s', ignoring.", val);
else
- manager_set_watchdog_overridden(m, WATCHDOG_RUNTIME, t);
+ manager_override_watchdog(m, WATCHDOG_RUNTIME, t);
} else if ((val = startswith(l, "reboot-watchdog-overridden="))) {
usec_t t;
@@ -3609,7 +3611,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse reboot-watchdog-overridden value '%s', ignoring.", val);
else
- manager_set_watchdog_overridden(m, WATCHDOG_REBOOT, t);
+ manager_override_watchdog(m, WATCHDOG_REBOOT, t);
} else if ((val = startswith(l, "kexec-watchdog-overridden="))) {
usec_t t;
@@ -3617,7 +3619,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse kexec-watchdog-overridden value '%s', ignoring.", val);
else
- manager_set_watchdog_overridden(m, WATCHDOG_KEXEC, t);
+ manager_override_watchdog(m, WATCHDOG_KEXEC, t);
} else if (startswith(l, "env=")) {
r = deserialize_environment(l + 4, &m->client_environment);
@@ -4264,49 +4266,78 @@ void manager_recheck_journal(Manager *m) {
log_open();
}
+static ShowStatus manager_get_show_status(Manager *m) {
+ assert(m);
+
+ if (MANAGER_IS_USER(m))
+ return _SHOW_STATUS_INVALID;
+
+ if (m->show_status_overridden != _SHOW_STATUS_INVALID)
+ return m->show_status_overridden;
+
+ return m->show_status;
+}
+
+bool manager_get_show_status_on(Manager *m) {
+ assert(m);
+
+ return show_status_on(manager_get_show_status(m));
+}
+
+static void set_show_status_marker(bool b) {
+ if (b)
+ (void) touch("/run/systemd/show-status");
+ else
+ (void) unlink("/run/systemd/show-status");
+}
+
void manager_set_show_status(Manager *m, ShowStatus mode, const char *reason) {
assert(m);
+ assert(reason);
assert(mode >= 0 && mode < _SHOW_STATUS_MAX);
- if (!MANAGER_IS_SYSTEM(m))
+ if (MANAGER_IS_USER(m))
return;
if (mode == m->show_status)
return;
- bool enabled = IN_SET(mode, SHOW_STATUS_TEMPORARY, SHOW_STATUS_YES);
- log_debug("%s (%s) showing of status (%s).",
- enabled ? "Enabling" : "Disabling",
- strna(show_status_to_string(mode)),
- reason);
- m->show_status = mode;
+ if (m->show_status_overridden == _SHOW_STATUS_INVALID) {
+ bool enabled;
- if (enabled)
- (void) touch("/run/systemd/show-status");
- else
- (void) unlink("/run/systemd/show-status");
+ enabled = show_status_on(mode);
+ log_debug("%s (%s) showing of status (%s).",
+ enabled ? "Enabling" : "Disabling",
+ strna(show_status_to_string(mode)),
+ reason);
+
+ set_show_status_marker(enabled);
+ }
+
+ m->show_status = mode;
}
-static bool manager_get_show_status(Manager *m, StatusType type) {
+void manager_override_show_status(Manager *m, ShowStatus mode, const char *reason) {
assert(m);
+ assert(mode < _SHOW_STATUS_MAX);
- if (!MANAGER_IS_SYSTEM(m))
- return false;
+ if (MANAGER_IS_USER(m))
+ return;
- if (m->no_console_output)
- return false;
+ if (mode == m->show_status_overridden)
+ return;
- if (!IN_SET(manager_state(m), MANAGER_INITIALIZING, MANAGER_STARTING, MANAGER_STOPPING))
- return false;
+ m->show_status_overridden = mode;
- /* If we cannot find out the status properly, just proceed. */
- if (type != STATUS_TYPE_EMERGENCY && manager_check_ask_password(m) > 0)
- return false;
+ if (mode == _SHOW_STATUS_INVALID)
+ mode = m->show_status;
- if (type == STATUS_TYPE_NOTICE && m->show_status != SHOW_STATUS_NO)
- return true;
+ log_debug("%s (%s) showing of status (%s).",
+ m->show_status_overridden != _SHOW_STATUS_INVALID ? "Overriding" : "Restoring",
+ strna(show_status_to_string(mode)),
+ reason);
- return show_status_on(m->show_status);
+ set_show_status_marker(show_status_on(mode));
}
const char *manager_get_confirm_spawn(Manager *m) {
@@ -4381,12 +4412,34 @@ bool manager_is_confirm_spawn_disabled(Manager *m) {
return access("/run/systemd/confirm_spawn_disabled", F_OK) >= 0;
}
+static bool manager_should_show_status(Manager *m, StatusType type) {
+ assert(m);
+
+ if (!MANAGER_IS_SYSTEM(m))
+ return false;
+
+ if (m->no_console_output)
+ return false;
+
+ if (!IN_SET(manager_state(m), MANAGER_INITIALIZING, MANAGER_STARTING, MANAGER_STOPPING))
+ return false;
+
+ /* If we cannot find out the status properly, just proceed. */
+ if (type != STATUS_TYPE_EMERGENCY && manager_check_ask_password(m) > 0)
+ return false;
+
+ if (type == STATUS_TYPE_NOTICE && m->show_status != SHOW_STATUS_NO)
+ return true;
+
+ return manager_get_show_status_on(m);
+}
+
void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) {
va_list ap;
/* If m is NULL, assume we're after shutdown and let the messages through. */
- if (m && !manager_get_show_status(m, type))
+ if (m && !manager_should_show_status(m, type))
return;
/* XXX We should totally drop the check for ephemeral here
@@ -4421,12 +4474,9 @@ int manager_update_failed_units(Manager *m, Unit *u, bool failed) {
size = set_size(m->failed_units);
if (failed) {
- r = set_ensure_allocated(&m->failed_units, NULL);
+ r = set_ensure_put(&m->failed_units, NULL, u);
if (r < 0)
return log_oom();
-
- if (set_put(m->failed_units, u) < 0)
- return log_oom();
} else
(void) set_remove(m->failed_units, u);
diff --git a/src/core/manager.h b/src/core/manager.h
index a29d976eae..2cd0dacdb0 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -335,6 +335,7 @@ struct Manager {
uint8_t return_value;
ShowStatus show_status;
+ ShowStatus show_status_overridden;
StatusUnitFormat status_unit_format;
char *confirm_spawn;
bool no_console_output;
@@ -512,7 +513,10 @@ void disable_printk_ratelimit(void);
void manager_recheck_dbus(Manager *m);
void manager_recheck_journal(Manager *m);
+bool manager_get_show_status_on(Manager *m);
void manager_set_show_status(Manager *m, ShowStatus mode, const char *reason);
+void manager_override_show_status(Manager *m, ShowStatus mode, const char *reason);
+
void manager_set_first_boot(Manager *m, bool b);
void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) _printf_(4,5);
@@ -553,7 +557,7 @@ ManagerTimestamp manager_timestamp_initrd_mangle(ManagerTimestamp s);
usec_t manager_get_watchdog(Manager *m, WatchdogType t);
void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout);
-int manager_set_watchdog_overridden(Manager *m, WatchdogType t, usec_t timeout);
+int manager_override_watchdog(Manager *m, WatchdogType t, usec_t timeout);
const char* oom_policy_to_string(OOMPolicy i) _const_;
OOMPolicy oom_policy_from_string(const char *s) _pure_;
diff --git a/src/core/namespace.c b/src/core/namespace.c
index 6bfc266dc0..423a47c7b8 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -1257,16 +1257,20 @@ int setup_namespace(
ProtectHome protect_home,
ProtectSystem protect_system,
unsigned long mount_flags,
+ const void *root_hash,
+ size_t root_hash_size,
+ const char *root_hash_path,
+ const char *root_verity,
DissectImageFlags dissect_image_flags,
char **error_path) {
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
- _cleanup_free_ void *root_hash = NULL;
+ _cleanup_free_ void *root_hash_decoded = NULL;
_cleanup_free_ char *verity_data = NULL;
MountEntry *m = NULL, *mounts = NULL;
- size_t n_mounts, root_hash_size = 0;
+ size_t n_mounts;
bool require_prefix = false;
const char *root;
int r = 0;
@@ -1295,16 +1299,16 @@ int setup_namespace(
if (r < 0)
return log_debug_errno(r, "Failed to create loop device for root image: %m");
- r = verity_metadata_load(root_image, &root_hash, &root_hash_size, &verity_data);
+ r = verity_metadata_load(root_image, root_hash_path, root_hash ? NULL : &root_hash_decoded, root_hash ? NULL : &root_hash_size, root_verity ? NULL : &verity_data);
if (r < 0)
return log_debug_errno(r, "Failed to load root hash: %m");
- dissect_image_flags |= verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
+ dissect_image_flags |= root_verity || verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
- r = dissect_image(loop_device->fd, root_hash, root_hash_size, verity_data, dissect_image_flags, &dissected_image);
+ r = dissect_image(loop_device->fd, root_hash ?: root_hash_decoded, root_hash_size, root_verity ?: verity_data, dissect_image_flags, &dissected_image);
if (r < 0)
return log_debug_errno(r, "Failed to dissect image: %m");
- r = dissected_image_decrypt(dissected_image, NULL, root_hash, root_hash_size, verity_data, dissect_image_flags, &decrypted_image);
+ r = dissected_image_decrypt(dissected_image, NULL, root_hash ?: root_hash_decoded, root_hash_size, root_verity ?: verity_data, dissect_image_flags, &decrypted_image);
if (r < 0)
return log_debug_errno(r, "Failed to decrypt dissected image: %m");
}
diff --git a/src/core/namespace.h b/src/core/namespace.h
index ef6c9bdc9b..a687be5bfd 100644
--- a/src/core/namespace.h
+++ b/src/core/namespace.h
@@ -88,6 +88,10 @@ int setup_namespace(
ProtectHome protect_home,
ProtectSystem protect_system,
unsigned long mount_flags,
+ const void *root_hash,
+ size_t root_hash_size,
+ const char *root_hash_path,
+ const char *root_verity,
DissectImageFlags dissected_image_flags,
char **error_path);
diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf
index 415b3f5d84..9a5912c10f 100644
--- a/src/core/org.freedesktop.systemd1.conf
+++ b/src/core/org.freedesktop.systemd1.conf
@@ -318,6 +318,10 @@
send_interface="org.freedesktop.systemd1.Manager"
send_member="AddDependencyUnitFiles"/>
+ <allow send_destination="org.freedesktop.systemd1"
+ send_interface="org.freedesktop.systemd1.Manager"
+ send_member="SetShowStatus"/>
+
<!-- Managed via polkit or other criteria: org.freedesktop.systemd1.Job interface -->
<allow send_destination="org.freedesktop.systemd1"
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 0fb52372f1..ef6470656c 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -279,7 +279,7 @@ static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
return 0;
}
-static void transaction_drop_redundant(Transaction *tr, unsigned generation) {
+static void transaction_drop_redundant(Transaction *tr) {
bool again;
/* Goes through the transaction and removes all jobs of the units whose jobs are all noops. If not
@@ -299,7 +299,7 @@ static void transaction_drop_redundant(Transaction *tr, unsigned generation) {
LIST_FOREACH(transaction, k, j)
if (tr->anchor_job == k ||
- !job_is_redundant(k, generation) ||
+ !job_type_is_redundant(k->type, unit_active_state(k->unit)) ||
(k->unit->job && job_type_is_conflicting(k->type, k->unit->job->type))) {
keep = true;
break;
@@ -735,7 +735,7 @@ int transaction_activate(
transaction_minimize_impact(tr);
/* Third step: Drop redundant jobs */
- transaction_drop_redundant(tr, generation++);
+ transaction_drop_redundant(tr);
for (;;) {
/* Fourth step: Let's remove unneeded jobs that might
@@ -777,7 +777,7 @@ int transaction_activate(
}
/* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */
- transaction_drop_redundant(tr, generation++);
+ transaction_drop_redundant(tr);
/* Ninth step: check whether we can actually apply this */
r = transaction_is_destructive(tr, mode, e);
diff --git a/src/core/unit.c b/src/core/unit.c
index e50080cd97..8e59fafc11 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1591,7 +1591,6 @@ static int unit_add_mount_dependencies(Unit *u) {
static int unit_add_startup_units(Unit *u) {
CGroupContext *c;
- int r;
c = unit_get_cgroup_context(u);
if (!c)
@@ -1602,11 +1601,7 @@ static int unit_add_startup_units(Unit *u) {
c->startup_blockio_weight == CGROUP_BLKIO_WEIGHT_INVALID)
return 0;
- r = set_ensure_allocated(&u->manager->startup_units, NULL);
- if (r < 0)
- return r;
-
- return set_put(u->manager->startup_units, u);
+ return set_ensure_put(&u->manager->startup_units, NULL, u);
}
int unit_load(Unit *u) {
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c
index ed4d06e986..eceb7927af 100644
--- a/src/coredump/coredumpctl.c
+++ b/src/coredump/coredumpctl.c
@@ -1091,9 +1091,7 @@ static int run(int argc, char *argv[]) {
int r, units_active;
setlocale(LC_ALL, "");
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
/* The journal merging logic potentially needs a lot of fds. */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
diff --git a/src/delta/delta.c b/src/delta/delta.c
index 2d80d3a664..29e5120375 100644
--- a/src/delta/delta.c
+++ b/src/delta/delta.c
@@ -643,9 +643,7 @@ static int parse_argv(int argc, char *argv[]) {
static int run(int argc, char *argv[]) {
int r, k, n_found = 0;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/detect-virt/detect-virt.c b/src/detect-virt/detect-virt.c
index 7fb80ca138..4f38de8e29 100644
--- a/src/detect-virt/detect-virt.c
+++ b/src/detect-virt/detect-virt.c
@@ -128,9 +128,7 @@ static int run(int argc, char *argv[]) {
* to detect whether we are being run in a virtualized
* environment or not */
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c
index 9ae632f226..2a8eaca5bd 100644
--- a/src/dissect/dissect.c
+++ b/src/dissect/dissect.c
@@ -201,7 +201,7 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to set up loopback device: %m");
- r = verity_metadata_load(arg_image, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
+ r = verity_metadata_load(arg_image, NULL, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
arg_verity_data ? NULL : &arg_verity_data);
if (r < 0)
return log_error_errno(r, "Failed to read verity artefacts for %s: %m", arg_image);
diff --git a/src/escape/escape.c b/src/escape/escape.c
index 9066c30853..0c543a90f6 100644
--- a/src/escape/escape.c
+++ b/src/escape/escape.c
@@ -159,9 +159,7 @@ static int run(int argc, char *argv[]) {
char **i;
int r;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/home/homectl.c b/src/home/homectl.c
index f7237d22d8..7a473b791b 100644
--- a/src/home/homectl.c
+++ b/src/home/homectl.c
@@ -3489,9 +3489,7 @@ static int run(int argc, char *argv[]) {
int r;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c
index 5596846ed2..e08ab15acd 100644
--- a/src/hostname/hostnamectl.c
+++ b/src/hostname/hostnamectl.c
@@ -436,9 +436,7 @@ static int run(int argc, char *argv[]) {
int r;
setlocale(LC_ALL, "");
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index e694a95a04..36229f3c9b 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -801,7 +801,10 @@ static int run(int argc, char *argv[]) {
return r;
umask(0022);
- mac_selinux_init();
+
+ r = mac_selinux_init();
+ if (r < 0)
+ return r;
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c
index 651647b3f0..eb038a8b55 100644
--- a/src/hwdb/hwdb.c
+++ b/src/hwdb/hwdb.c
@@ -125,7 +125,9 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
return r;
- mac_selinux_init();
+ r = mac_selinux_init();
+ if (r < 0)
+ return r;
return hwdb_main(argc, argv);
}
diff --git a/src/id128/id128.c b/src/id128/id128.c
index 19435f80fe..13996573ab 100644
--- a/src/id128/id128.c
+++ b/src/id128/id128.c
@@ -249,9 +249,7 @@ static int id128_main(int argc, char *argv[]) {
static int run(int argc, char *argv[]) {
int r;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c
index 948b2d2fce..69a111afea 100644
--- a/src/journal-remote/journal-remote-main.c
+++ b/src/journal-remote/journal-remote-main.c
@@ -1110,7 +1110,7 @@ static int run(int argc, char **argv) {
int r;
log_show_color(true);
- log_parse_environment();
+ log_parse_environment_cli();
/* The journal merging logic potentially needs a lot of fds. */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
index bd58fdbcdf..e169a27eb3 100644
--- a/src/journal-remote/journal-upload.c
+++ b/src/journal-remote/journal-upload.c
@@ -821,7 +821,7 @@ static int run(int argc, char **argv) {
int r;
log_show_color(true);
- log_parse_environment();
+ log_parse_environment_cli();
/* The journal merging logic potentially needs a lot of fds. */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
diff --git a/src/journal/cat.c b/src/journal/cat.c
index 500b674505..2faaa2e284 100644
--- a/src/journal/cat.c
+++ b/src/journal/cat.c
@@ -129,9 +129,7 @@ static int run(int argc, char *argv[]) {
_cleanup_close_ int outfd = -1, errfd = -1, saved_stderr = -1;
int r;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 859f4bbd44..8d4897b942 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -875,12 +875,7 @@ static int parse_argv(int argc, char *argv[]) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Bad --facility= argument \"%s\".", fac);
- r = set_ensure_allocated(&arg_facilities, NULL);
- if (r < 0)
- return log_oom();
-
- r = set_put(arg_facilities, INT_TO_PTR(num));
- if (r < 0)
+ if (set_ensure_put(&arg_facilities, NULL, INT_TO_PTR(num)) < 0)
return log_oom();
}
@@ -2115,9 +2110,7 @@ int main(int argc, char *argv[]) {
int n_shown = 0, r, poll_fd = -1;
setlocale(LC_ALL, "");
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
/* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
* split up into many files. */
diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h
index aed30d6118..66222eaddb 100644
--- a/src/libsystemd-network/dhcp-lease-internal.h
+++ b/src/libsystemd-network/dhcp-lease-internal.h
@@ -82,6 +82,3 @@ int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const vo
int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease);
int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len);
-
-int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
-int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index aa61bc2614..e4c11235b6 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -61,9 +61,13 @@ int deserialize_in6_addrs(struct in6_addr **addresses, const char *string);
/* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */
struct sd_dhcp_route;
+struct sd_dhcp_lease;
void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size);
int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string);
/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */
int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
+
+int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
+int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index 8582302cb4..0bc5fa3210 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -1076,7 +1076,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
"ADDRESS", &address,
"ROUTER", &router,
"NETMASK", &netmask,
- "SERVER_IDENTIFIER", &server_address,
+ "SERVER_ADDRESS", &server_address,
"NEXT_SERVER", &next_server,
"BROADCAST", &broadcast,
"DNS", &dns,
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
index 97b732ae42..55e35cd902 100644
--- a/src/libsystemd/sd-bus/bus-message.c
+++ b/src/libsystemd/sd-bus/bus-message.c
@@ -451,7 +451,7 @@ int bus_message_from_header(
if (!IN_SET(h->version, 1, 2))
return -EBADMSG;
- if (h->type <= _SD_BUS_MESSAGE_TYPE_INVALID || h->type >= _SD_BUS_MESSAGE_TYPE_MAX)
+ if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
return -EBADMSG;
if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
@@ -589,7 +589,8 @@ _public_ int sd_bus_message_new(
assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state != BUS_UNSET, -ENOTCONN);
assert_return(m, -EINVAL);
- assert_return(type > _SD_BUS_MESSAGE_TYPE_INVALID && type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
+ /* Creation of messages with _SD_BUS_MESSAGE_TYPE_INVALID is allowed. */
+ assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
sd_bus_message *t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
if (!t)
@@ -3021,7 +3022,7 @@ int bus_body_part_map(struct bus_body_part *part) {
return 0;
}
- shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
+ shift = PAGE_OFFSET(part->memfd_offset);
psz = PAGE_ALIGN(part->size + shift);
if (part->memfd >= 0)
@@ -3158,7 +3159,8 @@ static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t s
return NULL;
if (p)
- *p = (uint8_t*) part->data + index - begin;
+ *p = part->data ? (uint8_t*) part->data + index - begin
+ : NULL; /* Avoid dereferencing a NULL pointer. */
m->cached_rindex_part = part;
m->cached_rindex_part_begin = begin;
@@ -5497,9 +5499,6 @@ int bus_message_parse_fields(sd_bus_message *m) {
if (m->reply_cookie == 0 || !m->error.name)
return -EBADMSG;
break;
-
- default:
- assert_not_reached("Bad message type");
}
/* Refuse non-local messages that claim they are local */
diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c
index ee8005833d..ffec11bbd3 100644
--- a/src/libsystemd/sd-device/device-monitor.c
+++ b/src/libsystemd/sd-device/device-monitor.c
@@ -759,30 +759,13 @@ _public_ int sd_device_monitor_filter_add_match_subsystem_devtype(sd_device_moni
}
_public_ int sd_device_monitor_filter_add_match_tag(sd_device_monitor *m, const char *tag) {
- _cleanup_free_ char *t = NULL;
- int r;
-
assert_return(m, -EINVAL);
assert_return(tag, -EINVAL);
- t = strdup(tag);
- if (!t)
- return -ENOMEM;
-
- r = set_ensure_allocated(&m->tag_filter, &string_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(m->tag_filter, t);
- if (r == -EEXIST)
- return 0;
- if (r < 0)
- return r;
-
- TAKE_PTR(t);
- m->filter_uptodate = false;
-
- return 0;
+ int r = set_put_strdup(&m->tag_filter, tag);
+ if (r > 0)
+ m->filter_uptodate = false;
+ return r;
}
_public_ int sd_device_monitor_filter_remove(sd_device_monitor *m) {
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index fb9db47105..860eb048ff 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -1450,10 +1450,6 @@ _public_ int sd_event_add_post(
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
- r = set_ensure_allocated(&e->post_sources, NULL);
- if (r < 0)
- return r;
-
s = source_new(e, !ret, SOURCE_POST);
if (!s)
return -ENOMEM;
@@ -1462,9 +1458,10 @@ _public_ int sd_event_add_post(
s->userdata = userdata;
s->enabled = SD_EVENT_ON;
- r = set_put(e->post_sources, s);
+ r = set_ensure_put(&e->post_sources, NULL, s);
if (r < 0)
return r;
+ assert(r > 0);
if (ret)
*ret = s;
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index d9810b2298..488bfb5f4f 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -762,6 +762,32 @@ static const NLType rtnl_tca_option_data_drr_types[] = {
[TCA_DRR_QUANTUM] = { .type = NETLINK_TYPE_U32 },
};
+static const NLType rtnl_tca_option_data_ets_quanta_types[] = {
+ [TCA_ETS_QUANTA_BAND] = { .type = NETLINK_TYPE_U32, },
+};
+
+static const NLTypeSystem rtnl_tca_option_data_ets_quanta_type_system = {
+ .count = ELEMENTSOF(rtnl_tca_option_data_ets_quanta_types),
+ .types = rtnl_tca_option_data_ets_quanta_types,
+};
+
+static const NLType rtnl_tca_option_data_ets_prio_types[] = {
+ [TCA_ETS_PRIOMAP_BAND] = { .type = NETLINK_TYPE_U8, },
+};
+
+static const NLTypeSystem rtnl_tca_option_data_ets_prio_type_system = {
+ .count = ELEMENTSOF(rtnl_tca_option_data_ets_prio_types),
+ .types = rtnl_tca_option_data_ets_prio_types,
+};
+
+static const NLType rtnl_tca_option_data_ets_types[] = {
+ [TCA_ETS_NBANDS] = { .type = NETLINK_TYPE_U8 },
+ [TCA_ETS_NSTRICT] = { .type = NETLINK_TYPE_U8 },
+ [TCA_ETS_QUANTA] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_option_data_ets_quanta_type_system },
+ [TCA_ETS_PRIOMAP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_option_data_ets_prio_type_system },
+ [TCA_ETS_QUANTA_BAND] = { .type = NETLINK_TYPE_U32 },
+};
+
static const NLType rtnl_tca_option_data_fq_types[] = {
[TCA_FQ_PLIMIT] = { .type = NETLINK_TYPE_U32 },
[TCA_FQ_FLOW_PLIMIT] = { .type = NETLINK_TYPE_U32 },
@@ -833,6 +859,7 @@ static const char* const nl_union_tca_option_data_table[] = {
[NL_UNION_TCA_OPTION_DATA_CAKE] = "cake",
[NL_UNION_TCA_OPTION_DATA_CODEL] = "codel",
[NL_UNION_TCA_OPTION_DATA_DRR] = "drr",
+ [NL_UNION_TCA_OPTION_DATA_ETS] = "ets",
[NL_UNION_TCA_OPTION_DATA_FQ] = "fq",
[NL_UNION_TCA_OPTION_DATA_FQ_CODEL] = "fq_codel",
[NL_UNION_TCA_OPTION_DATA_GRED] = "gred",
@@ -853,6 +880,8 @@ static const NLTypeSystem rtnl_tca_option_data_type_systems[] = {
.types = rtnl_tca_option_data_codel_types },
[NL_UNION_TCA_OPTION_DATA_DRR] = { .count = ELEMENTSOF(rtnl_tca_option_data_drr_types),
.types = rtnl_tca_option_data_drr_types },
+ [NL_UNION_TCA_OPTION_DATA_ETS] = { .count = ELEMENTSOF(rtnl_tca_option_data_ets_types),
+ .types = rtnl_tca_option_data_ets_types },
[NL_UNION_TCA_OPTION_DATA_FQ] = { .count = ELEMENTSOF(rtnl_tca_option_data_fq_types),
.types = rtnl_tca_option_data_fq_types },
[NL_UNION_TCA_OPTION_DATA_FQ_CODEL] = { .count = ELEMENTSOF(rtnl_tca_option_data_fq_codel_types),
diff --git a/src/libsystemd/sd-netlink/netlink-types.h b/src/libsystemd/sd-netlink/netlink-types.h
index 1a0e1997cc..058747a2e9 100644
--- a/src/libsystemd/sd-netlink/netlink-types.h
+++ b/src/libsystemd/sd-netlink/netlink-types.h
@@ -99,6 +99,7 @@ typedef enum NLUnionTCAOptionData {
NL_UNION_TCA_OPTION_DATA_CAKE,
NL_UNION_TCA_OPTION_DATA_CODEL,
NL_UNION_TCA_OPTION_DATA_DRR,
+ NL_UNION_TCA_OPTION_DATA_ETS,
NL_UNION_TCA_OPTION_DATA_FQ,
NL_UNION_TCA_OPTION_DATA_FQ_CODEL,
NL_UNION_TCA_OPTION_DATA_GRED,
diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c
index 2fde4fbb64..ce6ae846c5 100644
--- a/src/libsystemd/sd-network/sd-network.c
+++ b/src/libsystemd/sd-network/sd-network.c
@@ -168,10 +168,6 @@ _public_ int sd_network_link_get_address_state(int ifindex, char **state) {
return network_link_get_string(ifindex, "ADDRESS_STATE", state);
}
-_public_ int sd_network_link_get_dhcp4_client_id_string(int ifindex, char **client_id) {
- return network_link_get_string(ifindex, "DHCP4_CLIENT_ID", client_id);
-}
-
_public_ int sd_network_link_get_dhcp6_client_iaid_string(int ifindex, char **iaid) {
return network_link_get_string(ifindex, "DHCP6_CLIENT_IAID", iaid);
}
@@ -236,14 +232,6 @@ _public_ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char
return network_link_get_strv(ifindex, "DNSSEC_NTA", nta);
}
-_public_ int sd_network_link_get_timezone(int ifindex, char **ret) {
- return network_link_get_string(ifindex, "TIMEZONE", ret);
-}
-
-_public_ int sd_network_link_get_dhcp4_address(int ifindex, char **ret) {
- return network_link_get_string(ifindex, "DHCP4_ADDRESS", ret);
-}
-
_public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
return network_link_get_strv(ifindex, "DNS", ret);
}
@@ -264,22 +252,6 @@ _public_ int sd_network_link_get_route_domains(int ifindex, char ***ret) {
return network_link_get_strv(ifindex, "ROUTE_DOMAINS", ret);
}
-_public_ int sd_network_link_get_sip_servers(int ifindex, char ***ret) {
- return network_link_get_strv(ifindex, "SIP", ret);
-}
-
-_public_ int sd_network_link_get_pop3_servers(int ifindex, char ***pop3) {
- return network_link_get_strv(ifindex, "POP3_SERVERS", pop3);
-}
-
-_public_ int sd_network_link_get_smtp_servers(int ifindex, char ***ret) {
- return network_link_get_strv(ifindex, "SMTP_SERVERS", ret);
-}
-
-_public_ int sd_network_link_get_lpr_servers(int ifindex, char ***ret) {
- return network_link_get_strv(ifindex, "LPR_SERVERS", ret);
-}
-
_public_ int sd_network_link_get_dns_default_route(int ifindex) {
char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1];
_cleanup_free_ char *s = NULL;
diff --git a/src/locale/localectl.c b/src/locale/localectl.c
index b7548a0f7f..96fc09a570 100644
--- a/src/locale/localectl.c
+++ b/src/locale/localectl.c
@@ -502,9 +502,7 @@ static int run(int argc, char *argv[]) {
int r;
setlocale(LC_ALL, "");
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/locale/localed.c b/src/locale/localed.c
index 8ffcf306b5..715ce5cac7 100644
--- a/src/locale/localed.c
+++ b/src/locale/localed.c
@@ -18,6 +18,7 @@
#include "bus-message.h"
#include "bus-polkit.h"
#include "def.h"
+#include "dlfcn-util.h"
#include "keymap-util.h"
#include "locale-util.h"
#include "macro.h"
@@ -530,7 +531,7 @@ static int verify_xkb_rmlvo(const char *model, const char *layout, const char *v
};
struct xkb_context *ctx = NULL;
struct xkb_keymap *km = NULL;
- void *dl;
+ _cleanup_(dlclosep) void *dl = NULL;
int r;
/* Compile keymap from RMLVO information to check out its validity */
@@ -582,7 +583,6 @@ finish:
if (symbol_xkb_context_unref && ctx)
symbol_xkb_context_unref(ctx);
- (void) dlclose(dl);
return r;
}
@@ -788,7 +788,10 @@ static int run(int argc, char *argv[]) {
return r;
umask(0022);
- mac_selinux_init();
+
+ r = mac_selinux_init();
+ if (r < 0)
+ return r;
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
diff --git a/src/locale/meson.build b/src/locale/meson.build
index e87a10ebeb..314b0a3d37 100644
--- a/src/locale/meson.build
+++ b/src/locale/meson.build
@@ -34,5 +34,5 @@ tests += [
'src/locale/keymap-util.c',
'src/locale/keymap-util.h'],
[libshared],
- [libdl]],
+ []],
]
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 7805863d8d..9216224bfc 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -1460,9 +1460,7 @@ static int run(int argc, char *argv[]) {
int r;
setlocale(LC_ALL, "");
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
/* The journal merging logic potentially needs a lot of fds. */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
diff --git a/src/login/logind-brightness.c b/src/login/logind-brightness.c
index 3f4b65e1fd..450ec32044 100644
--- a/src/login/logind-brightness.c
+++ b/src/login/logind-brightness.c
@@ -174,15 +174,11 @@ static int set_add_message(Set **set, sd_bus_message *message) {
if (r <= 0)
return r;
- r = set_ensure_allocated(set, &bus_message_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(*set, message);
- if (r < 0)
+ r = set_ensure_put(set, &bus_message_hash_ops, message);
+ if (r <= 0)
return r;
-
sd_bus_message_ref(message);
+
return 1;
}
diff --git a/src/login/logind.c b/src/login/logind.c
index dc746a2c9e..377fba25cf 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -1173,7 +1173,7 @@ static int run(int argc, char *argv[]) {
r = mac_selinux_init();
if (r < 0)
- return log_error_errno(r, "Could not initialize labelling: %m");
+ return r;
/* Always create the directories people can create inotify watches in. Note that some applications might check
* for the existence of /run/systemd/seats/ to determine whether logind is available, so please always make
diff --git a/src/login/user-runtime-dir.c b/src/login/user-runtime-dir.c
index fdf0124c41..38058d7b2a 100644
--- a/src/login/user-runtime-dir.c
+++ b/src/login/user-runtime-dir.c
@@ -192,11 +192,11 @@ static int run(int argc, char *argv[]) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"First argument must be either \"start\" or \"stop\".");
+ umask(0022);
+
r = mac_selinux_init();
if (r < 0)
- return log_error_errno(r, "Could not initialize labelling: %m\n");
-
- umask(0022);
+ return r;
if (streq(argv[1], "start"))
return do_mount(argv[2]);
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index d88b2651d2..d8f4526644 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -2882,9 +2882,7 @@ static int run(int argc, char *argv[]) {
int r;
setlocale(LC_ALL, "");
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
/* The journal merging logic potentially needs a lot of fds. */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
diff --git a/src/network/meson.build b/src/network/meson.build
index 9d5cdfa516..97a164091a 100644
--- a/src/network/meson.build
+++ b/src/network/meson.build
@@ -115,6 +115,8 @@ sources = files('''
tc/codel.h
tc/drr.c
tc/drr.h
+ tc/ets.c
+ tc/ets.h
tc/fifo.c
tc/fifo.h
tc/fq.c
diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c
index 713cdaa884..bff778179c 100644
--- a/src/network/netdev/wireguard.c
+++ b/src/network/netdev/wireguard.c
@@ -348,14 +348,7 @@ static int wireguard_resolve_handler(sd_resolve_query *q,
if (ret != 0) {
log_netdev_error(netdev, "Failed to resolve host '%s:%s': %s", peer->endpoint_host, peer->endpoint_port, gai_strerror(ret));
- r = set_ensure_allocated(&w->peers_with_failed_endpoint, NULL);
- if (r < 0) {
- log_oom();
- peer->section->invalid = true;
- goto resolve_next;
- }
-
- r = set_put(w->peers_with_failed_endpoint, peer);
+ r = set_ensure_put(&w->peers_with_failed_endpoint, NULL, peer);
if (r < 0) {
log_netdev_error(netdev, "Failed to save a peer, dropping the peer: %m");
peer->section->invalid = true;
@@ -580,7 +573,7 @@ int config_parse_wireguard_preshared_key(
void *data,
void *userdata) {
- _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL;
+ WireguardPeer *peer;
Wireguard *w;
int r;
@@ -592,12 +585,7 @@ int config_parse_wireguard_preshared_key(
if (r < 0)
return r;
- r = wireguard_decode_key_and_warn(rvalue, peer->preshared_key, unit, filename, line, lvalue);
- if (r < 0)
- return r;
-
- TAKE_PTR(peer);
- return 0;
+ return wireguard_decode_key_and_warn(rvalue, peer->preshared_key, unit, filename, line, lvalue);
}
int config_parse_wireguard_preshared_key_file(
@@ -766,10 +754,6 @@ int config_parse_wireguard_endpoint(
w = WIREGUARD(data);
assert(w);
- r = wireguard_peer_new_static(w, filename, section_line, &peer);
- if (r < 0)
- return r;
-
if (rvalue[0] == '[') {
begin = &rvalue[1];
end = strchr(rvalue, ']');
@@ -801,6 +785,10 @@ int config_parse_wireguard_endpoint(
++end;
}
+ r = wireguard_peer_new_static(w, filename, section_line, &peer);
+ if (r < 0)
+ return r;
+
r = free_and_strndup(&peer->endpoint_host, begin, len);
if (r < 0)
return log_oom();
@@ -809,15 +797,11 @@ int config_parse_wireguard_endpoint(
if (r < 0)
return log_oom();
- r = set_ensure_allocated(&w->peers_with_unresolved_endpoint, NULL);
+ r = set_ensure_put(&w->peers_with_unresolved_endpoint, NULL, peer);
if (r < 0)
return log_oom();
+ TAKE_PTR(peer); /* The peer may already have been in the hash map, that is fine too. */
- r = set_put(w->peers_with_unresolved_endpoint, peer);
- if (r < 0)
- return r;
-
- TAKE_PTR(peer);
return 0;
}
@@ -833,7 +817,7 @@ int config_parse_wireguard_keepalive(
void *data,
void *userdata) {
- _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL;
+ WireguardPeer *peer;
uint16_t keepalive = 0;
Wireguard *w;
int r;
@@ -854,15 +838,13 @@ int config_parse_wireguard_keepalive(
r = safe_atou16(rvalue, &keepalive);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "The persistent keepalive interval must be 0-65535. Ignore assignment: %s",
+ "Failed to parse \"%s\" as keepalive interval (range 0–65535), ignoring assignment: %m",
rvalue);
return 0;
}
}
peer->persistent_keepalive_interval = keepalive;
-
- TAKE_PTR(peer);
return 0;
}
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index f7c48f19b1..8b7cf292fa 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <arpa/inet.h>
#include <getopt.h>
#include <linux/if_addrlabel.h>
#include <net/if.h>
@@ -930,12 +931,13 @@ static int dump_gateways(
static int dump_addresses(
sd_netlink *rtnl,
+ sd_dhcp_lease *lease,
Table *table,
int ifindex) {
_cleanup_free_ struct local_address *local = NULL;
- _cleanup_free_ char *dhcp4_address = NULL;
_cleanup_strv_free_ char **buf = NULL;
+ struct in_addr dhcp4_address = {};
int r, n, i;
assert(rtnl);
@@ -945,7 +947,8 @@ static int dump_addresses(
if (n <= 0)
return n;
- (void) sd_network_link_get_dhcp4_address(ifindex, &dhcp4_address);
+ if (lease)
+ (void) sd_dhcp_lease_get_address(lease, &dhcp4_address);
for (i = 0; i < n; i++) {
_cleanup_free_ char *pretty = NULL;
@@ -955,13 +958,19 @@ static int dump_addresses(
if (r < 0)
return r;
- if (dhcp4_address && streq(pretty, dhcp4_address)) {
- _cleanup_free_ char *p = NULL;
+ if (local[i].family == AF_INET && in4_addr_equal(&local[i].address.in, &dhcp4_address)) {
+ struct in_addr server_address;
+ char *p, s[INET_ADDRSTRLEN];
- p = pretty;
- pretty = strjoin(pretty , " (DHCP4)");
- if (!pretty)
+ r = sd_dhcp_lease_get_server_identifier(lease, &server_address);
+ if (r >= 0 && inet_ntop(AF_INET, &server_address, s, sizeof(s)))
+ p = strjoin(pretty, " (DHCP4 via ", s, ")");
+ else
+ p = strjoin(pretty, " (DHCP4)");
+ if (!p)
return log_oom();
+
+ free_and_replace(pretty, p);
}
r = strv_extendf(&buf, "%s%s%s",
@@ -1378,14 +1387,13 @@ static int link_status_one(
sd_hwdb *hwdb,
const LinkInfo *info) {
- _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL,
- **pop3_server = NULL, **smtp_server = NULL, **lpr_server = NULL;
- _cleanup_free_ char *t = NULL, *network = NULL, *client_id = NULL, *iaid = NULL, *duid = NULL;
- const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL;
- _cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL;
- const char *on_color_operational, *off_color_operational,
- *on_color_setup, *off_color_setup;
+ _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL;
+ _cleanup_free_ char *t = NULL, *network = NULL, *iaid = NULL, *duid = NULL,
+ *setup_state = NULL, *operational_state = NULL, *lease_file = NULL;
+ const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL,
+ *on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup;
_cleanup_free_ int *carrier_bound_to = NULL, *carrier_bound_by = NULL;
+ _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
_cleanup_(table_unrefp) Table *table = NULL;
TableCell *cell;
int r;
@@ -1406,9 +1414,6 @@ static int link_status_one(
(void) sd_network_link_get_route_domains(info->ifindex, &route_domains);
(void) sd_network_link_get_ntp(info->ifindex, &ntp);
(void) sd_network_link_get_sip(info->ifindex, &sip);
- (void) sd_network_link_get_pop3_servers(info->ifindex, &pop3_server);
- (void) sd_network_link_get_smtp_servers(info->ifindex, &smtp_server);
- (void) sd_network_link_get_lpr_servers(info->ifindex, &lpr_server);
if (info->sd_device) {
(void) sd_device_get_property_value(info->sd_device, "ID_NET_LINK_FILE", &link);
@@ -1429,6 +1434,11 @@ static int link_status_one(
(void) sd_network_link_get_carrier_bound_to(info->ifindex, &carrier_bound_to);
(void) sd_network_link_get_carrier_bound_by(info->ifindex, &carrier_bound_by);
+ if (asprintf(&lease_file, "/run/systemd/netif/leases/%d", info->ifindex) < 0)
+ return log_oom();
+
+ (void) dhcp_lease_load(&lease, lease_file);
+
table = table_new("dot", "key", "value");
if (!table)
return log_oom();
@@ -2026,7 +2036,7 @@ static int link_status_one(
}
}
- r = dump_addresses(rtnl, table, info->ifindex);
+ r = dump_addresses(rtnl, lease, table, info->ifindex);
if (r < 0)
return r;
r = dump_gateways(rtnl, hwdb, table, info->ifindex);
@@ -2047,15 +2057,6 @@ static int link_status_one(
r = dump_list(table, "SIP:", sip);
if (r < 0)
return r;
- r = dump_list(table, "POP3 servers:", pop3_server);
- if (r < 0)
- return r;
- r = dump_list(table, "SMTP servers:", smtp_server);
- if (r < 0)
- return r;
- r = dump_list(table, "LPR servers:", lpr_server);
- if (r < 0)
- return r;
r = dump_ifindexes(table, "Carrier Bound To:", carrier_bound_to);
if (r < 0)
return r;
@@ -2063,24 +2064,35 @@ static int link_status_one(
if (r < 0)
return r;
- (void) sd_network_link_get_timezone(info->ifindex, &tz);
- if (tz) {
- r = table_add_many(table,
- TABLE_EMPTY,
- TABLE_STRING, "Time Zone:",
- TABLE_STRING, tz);
- if (r < 0)
- return table_log_add_error(r);
- }
+ if (lease) {
+ const void *client_id;
+ size_t client_id_len;
+ const char *tz;
- r = sd_network_link_get_dhcp4_client_id_string(info->ifindex, &client_id);
- if (r >= 0) {
- r = table_add_many(table,
- TABLE_EMPTY,
- TABLE_STRING, "DHCP4 Client ID:",
- TABLE_STRING, client_id);
- if (r < 0)
- return table_log_add_error(r);
+ r = sd_dhcp_lease_get_timezone(lease, &tz);
+ if (r >= 0) {
+ r = table_add_many(table,
+ TABLE_EMPTY,
+ TABLE_STRING, "Time Zone:",
+ TABLE_STRING, tz);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+
+ r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len);
+ if (r >= 0) {
+ _cleanup_free_ char *id = NULL;
+
+ r = sd_dhcp_client_id_to_string(client_id, client_id_len, &id);
+ if (r >= 0) {
+ r = table_add_many(table,
+ TABLE_EMPTY,
+ TABLE_STRING, "DHCP4 Client ID:",
+ TABLE_STRING, id);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+ }
}
r = sd_network_link_get_dhcp6_client_iaid_string(info->ifindex, &iaid);
@@ -2160,7 +2172,7 @@ static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) {
if (r < 0)
return table_log_add_error(r);
- r = dump_addresses(rtnl, table, 0);
+ r = dump_addresses(rtnl, NULL, table, 0);
if (r < 0)
return r;
r = dump_gateways(rtnl, hwdb, table, 0);
@@ -2806,9 +2818,7 @@ static void warn_networkd_missing(void) {
static int run(int argc, char* argv[]) {
int r;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 9b78530334..44e317e990 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -266,11 +266,7 @@ static int address_add_internal(Link *link, Set **addresses,
/* Consider address tentative until we get the real flags from the kernel */
address->flags = IFA_F_TENTATIVE;
- r = set_ensure_allocated(addresses, &address_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(*addresses, address);
+ r = set_ensure_put(addresses, &address_hash_ops, address);
if (r < 0)
return r;
if (r == 0)
@@ -280,9 +276,7 @@ static int address_add_internal(Link *link, Set **addresses,
if (ret)
*ret = address;
-
- address = NULL;
-
+ TAKE_PTR(address);
return 0;
}
@@ -302,11 +296,7 @@ int address_add(Link *link, int family, const union in_addr_union *in_addr, unsi
return r;
} else if (r == 0) {
/* Take over a foreign address */
- r = set_ensure_allocated(&link->addresses, &address_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(link->addresses, address);
+ r = set_ensure_put(&link->addresses, &address_hash_ops, address);
if (r < 0)
return r;
diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c
index 606ae9f3c2..5b1acde297 100644
--- a/src/network/networkd-dhcp-common.c
+++ b/src/network/networkd-dhcp-common.c
@@ -664,17 +664,8 @@ int config_parse_dhcp_request_options(
continue;
}
- if (ltype == AF_INET)
- r = set_ensure_allocated(&network->dhcp_request_options, NULL);
- else
- r = set_ensure_allocated(&network->dhcp6_request_options, NULL);
- if (r < 0)
- return log_oom();
-
- if (ltype == AF_INET)
- r = set_put(network->dhcp_request_options, UINT32_TO_PTR(i));
- else
- r = set_put(network->dhcp6_request_options, UINT32_TO_PTR(i));
+ r = set_ensure_put(ltype == AF_INET ? &network->dhcp_request_options : &network->dhcp6_request_options,
+ NULL, UINT32_TO_PTR(i));
if (r < 0)
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to store DHCP request option '%s', ignoring assignment: %m", n);
diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c
index 40705c3d81..6f25c9fc96 100644
--- a/src/network/networkd-dhcp-server.c
+++ b/src/network/networkd-dhcp-server.c
@@ -34,118 +34,95 @@ static Address* link_find_dhcp_server_address(Link *link) {
return NULL;
}
-static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
+static int link_push_uplink_to_dhcp_server(
+ Link *link,
+ sd_dhcp_lease_server_type what,
+ sd_dhcp_server *s) {
+
_cleanup_free_ struct in_addr *addresses = NULL;
size_t n_addresses = 0, n_allocated = 0;
+ bool use_dhcp_lease_data = true;
- for (unsigned i = 0; i < link->network->n_dns; i++) {
- struct in_addr ia;
+ assert(link);
- /* Only look for IPv4 addresses */
- if (link->network->dns[i].family != AF_INET)
- continue;
+ if (!link->network)
+ return 0;
+ assert(link->network);
- ia = link->network->dns[i].address.in;
+ log_link_debug(link, "Copying %s from link", dhcp_lease_server_type_to_string(what));
- /* Never propagate obviously borked data */
- if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia))
- continue;
+ switch (what) {
- if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
- return log_oom();
+ case SD_DHCP_LEASE_DNS:
+ /* For DNS we have a special case. We the data configured explicitly locally along with the
+ * data from the DHCP lease. */
- addresses[n_addresses++] = ia;
- }
+ for (unsigned i = 0; i < link->network->n_dns; i++) {
+ struct in_addr ia;
- if (link->network->dhcp_use_dns && link->dhcp_lease) {
- const struct in_addr *da;
+ /* Only look for IPv4 addresses */
+ if (link->network->dns[i].family != AF_INET)
+ continue;
- int n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
- if (n > 0) {
- if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
+ ia = link->network->dns[i].address.in;
+
+ /* Never propagate obviously borked data */
+ if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia))
+ continue;
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
return log_oom();
- for (int j = 0; j < n; j++)
- if (in4_addr_is_non_local(&da[j]))
- addresses[n_addresses++] = da[j];
+ addresses[n_addresses++] = ia;
}
- }
- if (n_addresses <= 0)
- return 0;
+ use_dhcp_lease_data = link->network->dhcp_use_dns;
+ break;
- return sd_dhcp_server_set_dns(s, addresses, n_addresses);
-}
+ case SD_DHCP_LEASE_NTP: {
+ char **i;
-static int link_push_uplink_to_dhcp_server(
- Link *link,
- sd_dhcp_lease_server_type what,
- sd_dhcp_server *s) {
-
- _cleanup_free_ struct in_addr *addresses = NULL;
- size_t n_addresses = 0, n_allocated = 0;
- bool lease_condition;
- char **servers;
+ /* For NTP things are similar, but for NTP hostnames can be configured too, which we cannot
+ * propagate via DHCP. Hence let's only propagate those which are IP addresses. */
- if (!link->network)
- return 0;
+ STRV_FOREACH(i, link->network->ntp) {
+ union in_addr_union ia;
- log_link_debug(link, "Copying %s from link", dhcp_lease_server_type_to_string(what));
+ if (in_addr_from_string(AF_INET, *i, &ia) < 0)
+ continue;
- switch (what) {
- case SD_DHCP_LEASE_DNS:
- /* DNS servers are stored as parsed data, so special handling is required.
- * TODO: check if DNS servers should be stored unparsed too. */
- return link_push_uplink_dns_to_dhcp_server(link, s);
+ /* Never propagate obviously borked data */
+ if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
+ continue;
- case SD_DHCP_LEASE_NTP:
- servers = link->network->ntp;
- lease_condition = link->network->dhcp_use_ntp;
- break;
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
+ return log_oom();
- case SD_DHCP_LEASE_POP3:
- servers = link->network->pop3;
- lease_condition = true;
- break;
+ addresses[n_addresses++] = ia.in;
+ }
- case SD_DHCP_LEASE_SMTP:
- servers = link->network->smtp;
- lease_condition = true;
+ use_dhcp_lease_data = link->network->dhcp_use_ntp;
break;
+ }
case SD_DHCP_LEASE_SIP:
- servers = link->network->sip;
- lease_condition = link->network->dhcp_use_sip;
+
+ /* For SIP we don't allow explicit, local configuration, but there's control whether to use the data */
+ use_dhcp_lease_data = link->network->dhcp_use_sip;
break;
+ case SD_DHCP_LEASE_POP3:
+ case SD_DHCP_LEASE_SMTP:
case SD_DHCP_LEASE_LPR:
- servers = link->network->lpr;
- lease_condition = true;
+ /* For the other server types we currently do not allow local configuration of server data,
+ * since there are typically no local consumers of the data. */
break;
default:
- assert_not_reached("Unknown DHCP lease info item");
- }
-
- char **a;
- STRV_FOREACH(a, servers) {
- union in_addr_union ia;
-
- /* Only look for IPv4 addresses */
- if (in_addr_from_string(AF_INET, *a, &ia) <= 0)
- continue;
-
- /* Never propagate obviously borked data */
- if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
- continue;
-
- if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
- return log_oom();
-
- addresses[n_addresses++] = ia.in;
+ assert_not_reached("Unexpected server type");
}
- if (lease_condition && link->dhcp_lease) {
+ if (use_dhcp_lease_data && link->dhcp_lease) {
const struct in_addr *da;
int n = sd_dhcp_lease_get_servers(link->dhcp_lease, what, &da);
@@ -153,9 +130,9 @@ static int link_push_uplink_to_dhcp_server(
if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
return log_oom();
- for (int i = 0; i < n; i++)
- if (in4_addr_is_non_local(&da[i]))
- addresses[n_addresses++] = da[i];
+ for (int j = 0; j < n; j++)
+ if (in4_addr_is_non_local(&da[j]))
+ addresses[n_addresses++] = da[j];
}
}
@@ -285,71 +262,43 @@ int dhcp4_server_configure(Link *link) {
return log_link_error_errno(link, r, "Failed to set default lease time for DHCPv4 server instance: %m");
}
- const struct {
- bool condition;
- const struct in_addr *servers;
- unsigned n_servers;
- } configs[] = {
- [SD_DHCP_LEASE_DNS] = {
- link->network->dhcp_server_emit_dns,
- link->network->dhcp_server_dns,
- link->network->n_dhcp_server_dns,
- },
- [SD_DHCP_LEASE_NTP] = {
- link->network->dhcp_server_emit_ntp,
- link->network->dhcp_server_ntp,
- link->network->n_dhcp_server_ntp,
- },
- [SD_DHCP_LEASE_SIP] = {
- link->network->dhcp_server_emit_sip,
- link->network->dhcp_server_sip,
- link->network->n_dhcp_server_sip,
- },
- [SD_DHCP_LEASE_POP3] = {
- true,
- link->network->dhcp_server_pop3,
- link->network->n_dhcp_server_pop3,
- },
- [SD_DHCP_LEASE_SMTP] = {
- true,
- link->network->dhcp_server_smtp,
- link->network->n_dhcp_server_smtp,
- },
- [SD_DHCP_LEASE_LPR] = {
- true,
- link->network->dhcp_server_lpr,
- link->network->n_dhcp_server_lpr,
- },
- };
- assert_cc(ELEMENTSOF(configs) == _SD_DHCP_LEASE_SERVER_TYPE_MAX);
-
- for (unsigned n = 0; n < ELEMENTSOF(configs); n++)
- if (configs[n].condition) {
- if (configs[n].n_servers > 0)
- r = sd_dhcp_server_set_servers(link->dhcp_server, n,
- configs[n].servers, configs[n].n_servers);
+ for (sd_dhcp_lease_server_type type = 0; type < _SD_DHCP_LEASE_SERVER_TYPE_MAX; type ++) {
+
+ if (!link->network->dhcp_server_emit[type].emit)
+ continue;
+
+ if (link->network->dhcp_server_emit[type].n_addresses > 0)
+ /* Explicitly specified servers to emit */
+ r = sd_dhcp_server_set_servers(
+ link->dhcp_server,
+ type,
+ link->network->dhcp_server_emit[type].addresses,
+ link->network->dhcp_server_emit[type].n_addresses);
+ else {
+ /* Emission is requested, but nothing explicitly configured. Let's find a suitable upling */
+ if (!acquired_uplink) {
+ uplink = manager_find_uplink(link->manager, link);
+ acquired_uplink = true;
+ }
+
+ if (uplink && uplink->network)
+ r = link_push_uplink_to_dhcp_server(uplink, type, link->dhcp_server);
+ else if (type == SD_DHCP_LEASE_DNS)
+ r = dhcp4_server_set_dns_from_resolve_conf(link);
else {
- if (!acquired_uplink) {
- uplink = manager_find_uplink(link->manager, link);
- acquired_uplink = true;
- }
-
- if (!uplink) {
- log_link_debug(link,
- "Not emitting %s on link, couldn't find suitable uplink.",
- dhcp_lease_server_type_to_string(n));
- r = 0;
- } else if (uplink->network)
- r = link_push_uplink_to_dhcp_server(uplink, n, link->dhcp_server);
- else if (n == SD_DHCP_LEASE_DNS)
- r = dhcp4_server_set_dns_from_resolve_conf(link);
+ log_link_debug(link,
+ "Not emitting %s on link, couldn't find suitable uplink.",
+ dhcp_lease_server_type_to_string(type));
+ continue;
}
- if (r < 0)
- log_link_warning_errno(link, r,
- "Failed to set %s for DHCP server, ignoring: %m",
- dhcp_lease_server_type_to_string(n));
}
+ if (r < 0)
+ log_link_warning_errno(link, r,
+ "Failed to set %s for DHCP server, ignoring: %m",
+ dhcp_lease_server_type_to_string(type));
+ }
+
r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set router emission for DHCP server: %m");
@@ -398,17 +347,21 @@ int dhcp4_server_configure(Link *link) {
return 0;
}
-static int config_parse_dhcp_lease_server_list(
+int config_parse_dhcp_server_emit(
const char *unit,
const char *filename,
unsigned line,
+ const char *section,
+ unsigned section_line,
const char *lvalue,
+ int ltype,
const char *rvalue,
- struct in_addr **addresses,
- unsigned *n_addresses) {
+ void *data,
+ void *userdata) {
+
+ NetworkDHCPServerEmitAddress *emit = data;
- assert(filename);
- assert(lvalue);
+ assert(emit);
assert(rvalue);
for (const char *p = rvalue;;) {
@@ -434,127 +387,11 @@ static int config_parse_dhcp_lease_server_list(
continue;
}
- struct in_addr *m = reallocarray(*addresses, *n_addresses + 1, sizeof(struct in_addr));
+ struct in_addr *m = reallocarray(emit->addresses, emit->n_addresses + 1, sizeof(struct in_addr));
if (!m)
return log_oom();
- m[(*n_addresses)++] = a.in;
- *addresses = m;
+ emit->addresses = m;
+ emit->addresses[emit->n_addresses++] = a.in;
}
}
-
-int config_parse_dhcp_server_dns(
- 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) {
-
- Network *n = data;
-
- return config_parse_dhcp_lease_server_list(unit, filename, line,
- lvalue, rvalue,
- &n->dhcp_server_dns, &n->n_dhcp_server_dns);
-}
-
-int config_parse_dhcp_server_ntp(
- 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) {
-
- Network *n = data;
-
- return config_parse_dhcp_lease_server_list(unit, filename, line,
- lvalue, rvalue,
- &n->dhcp_server_ntp, &n->n_dhcp_server_ntp);
-}
-
-int config_parse_dhcp_server_sip(
- 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) {
-
- Network *n = data;
-
- return config_parse_dhcp_lease_server_list(unit, filename, line,
- lvalue, rvalue,
- &n->dhcp_server_sip, &n->n_dhcp_server_sip);
-}
-
-int config_parse_dhcp_server_pop3_servers(
- 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) {
-
- Network *n = data;
-
- return config_parse_dhcp_lease_server_list(unit, filename, line,
- lvalue, rvalue,
- &n->dhcp_server_pop3, &n->n_dhcp_server_pop3);
-}
-
-int config_parse_dhcp_server_smtp_servers(
- 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) {
-
- Network *n = data;
-
- return config_parse_dhcp_lease_server_list(unit, filename, line,
- lvalue, rvalue,
- &n->dhcp_server_smtp, &n->n_dhcp_server_smtp);
-
-}
-
-int config_parse_dhcp_server_lpr_servers(
- 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) {
-
- Network *n = data;
-
- return config_parse_dhcp_lease_server_list(unit, filename, line,
- lvalue, rvalue,
- &n->dhcp_server_lpr, &n->n_dhcp_server_lpr);
-
-}
diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h
index 898e9acd52..2250a30af4 100644
--- a/src/network/networkd-dhcp-server.h
+++ b/src/network/networkd-dhcp-server.h
@@ -9,9 +9,4 @@ typedef struct Link Link;
int dhcp4_server_configure(Link *link);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_sip);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_pop3_servers);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_smtp_servers);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_lpr_servers);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_emit);
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 8e2c775fcf..6103792771 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -1564,7 +1564,6 @@ int config_parse_dhcp_black_listed_ip_address(
void *userdata) {
Network *network = data;
- const char *p;
int r;
assert(filename);
@@ -1577,7 +1576,7 @@ int config_parse_dhcp_black_listed_ip_address(
return 0;
}
- for (p = rvalue;;) {
+ for (const char *p = rvalue;;) {
_cleanup_free_ char *n = NULL;
union in_addr_union ip;
@@ -1598,11 +1597,7 @@ int config_parse_dhcp_black_listed_ip_address(
continue;
}
- r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL);
- if (r < 0)
- return log_oom();
-
- r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr));
+ r = set_ensure_put(&network->dhcp_black_listed_ip, NULL, UINT32_TO_PTR(ip.in.s_addr));
if (r < 0)
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n);
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index f0766f0af7..27b74407af 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -1065,7 +1065,7 @@ static int dhcp6_assign_delegated_prefix(Link *link,
address->in_addr.in6 = *prefix;
if (!in_addr_is_null(AF_INET6, &link->network->dhcp6_delegation_prefix_token))
- memcpy(&address->in_addr.in6.s6_addr + 8, &link->network->dhcp6_delegation_prefix_token.in6.s6_addr + 8, 8);
+ memcpy(address->in_addr.in6.s6_addr + 8, link->network->dhcp6_delegation_prefix_token.in6.s6_addr + 8, 8);
else {
r = generate_ipv6_eui_64_address(link, &address->in_addr.in6);
if (r < 0)
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index be5c58087e..06a467d15b 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2125,11 +2125,7 @@ static int link_append_to_master(Link *link, NetDev *netdev) {
if (r < 0)
return r;
- r = set_ensure_allocated(&master->slaves, NULL);
- if (r < 0)
- return r;
-
- r = set_put(master->slaves, link);
+ r = set_ensure_put(&master->slaves, NULL, link);
if (r <= 0)
return r;
@@ -3133,12 +3129,12 @@ static int link_configure_duid(Link *link) {
r = set_put(m->links_requesting_uuid, link);
if (r < 0)
return log_oom();
+ if (r > 0)
+ link_ref(link);
r = set_put(m->duids_requesting_uuid, duid);
if (r < 0)
return log_oom();
-
- link_ref(link);
}
return 0;
@@ -4196,32 +4192,11 @@ int link_save(Link *link) {
sd_dhcp6_lease_get_ntp_fqdn);
serialize_addresses(f, "SIP", NULL,
- link->network->sip,
+ NULL,
link->dhcp_lease,
link->network->dhcp_use_sip,
SD_DHCP_LEASE_SIP,
- false, NULL, NULL, NULL);
-
- serialize_addresses(f, "POP3", NULL,
- link->network->pop3,
- link->dhcp_lease,
- true,
- SD_DHCP_LEASE_POP3,
- false, NULL, NULL, NULL);
-
- serialize_addresses(f, "SMTP", NULL,
- link->network->smtp,
- link->dhcp_lease,
- true,
- SD_DHCP_LEASE_SMTP,
- false, NULL, NULL, NULL);
-
- serialize_addresses(f, "LPR", NULL,
- link->network->lpr,
- link->dhcp_lease,
- true,
- SD_DHCP_LEASE_LPR,
- false, NULL, NULL, NULL);
+ NULL, false, NULL, NULL);
/************************************************************/
@@ -4372,33 +4347,6 @@ int link_save(Link *link) {
print_link_hashmap(f, "CARRIER_BOUND_BY=", link->bound_by_links);
if (link->dhcp_lease) {
- struct in_addr address;
- const char *tz = NULL;
- size_t client_id_len;
- const void *client_id;
-
- assert(link->network);
-
- r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
- if (r >= 0)
- fprintf(f, "TIMEZONE=%s\n", tz);
-
- r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
- if (r >= 0) {
- fputs("DHCP4_ADDRESS=", f);
- serialize_in_addrs(f, &address, 1, NULL, NULL);
- fputc('\n', f);
- }
-
- r = sd_dhcp_lease_get_client_id(link->dhcp_lease, &client_id, &client_id_len);
- if (r >= 0) {
- _cleanup_free_ char *id = NULL;
-
- r = sd_dhcp_client_id_to_string(client_id, client_id_len, &id);
- if (r >= 0)
- fprintf(f, "DHCP4_CLIENT_ID=%s\n", id);
- }
-
r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
if (r < 0)
goto fail;
@@ -4461,16 +4409,10 @@ void link_dirty(Link *link) {
/* mark manager dirty as link is dirty */
manager_dirty(link->manager);
- r = set_ensure_allocated(&link->manager->dirty_links, NULL);
- if (r < 0)
- /* allocation errors are ignored */
- return;
-
- r = set_put(link->manager->dirty_links, link);
+ r = set_ensure_put(&link->manager->dirty_links, NULL, link);
if (r <= 0)
- /* don't take another ref if the link was already dirty */
+ /* Ignore allocation errors and don't take another ref if the link was already dirty */
return;
-
link_ref(link);
}
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index b1a8c432aa..2d36ed2463 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -159,7 +159,7 @@ typedef struct Link {
struct rtnl_link_stats64 stats_old, stats_new;
bool stats_updated;
- /* All kinds of DNS configuration */
+ /* All kinds of DNS configuration the user configured via D-Bus */
struct in_addr_data *dns;
unsigned n_dns;
OrderedSet *search_domains, *route_domains;
@@ -171,6 +171,7 @@ typedef struct Link {
DnsOverTlsMode dns_over_tls_mode;
Set *dnssec_negative_trust_anchors;
+ /* Similar, but NTP server configuration */
char **ntp;
} Link;
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index abfdf7ff74..08666fd92d 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -1499,8 +1499,7 @@ static int ordered_set_put_in4_addrv(OrderedSet *s,
}
static int manager_save(Manager *m) {
- _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *pop3 = NULL,
- *smtp = NULL, *lpr = NULL, *search_domains = NULL, *route_domains = NULL;
+ _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *search_domains = NULL, *route_domains = NULL;
const char *operstate_str, *carrier_state_str, *address_state_str;
LinkOperationalState operstate = LINK_OPERSTATE_OFF;
LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF;
@@ -1508,7 +1507,6 @@ static int manager_save(Manager *m) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_strv_free_ char **p = NULL;
_cleanup_fclose_ FILE *f = NULL;
- const struct in_addr *addresses;
Link *link;
Iterator i;
int r;
@@ -1529,18 +1527,6 @@ static int manager_save(Manager *m) {
if (!sip)
return -ENOMEM;
- pop3 = ordered_set_new(&string_hash_ops);
- if (!pop3)
- return -ENOMEM;
-
- smtp = ordered_set_new(&string_hash_ops);
- if (!smtp)
- return -ENOMEM;
-
- lpr = ordered_set_new(&string_hash_ops);
- if (!lpr)
- return -ENOMEM;
-
search_domains = ordered_set_new(&dns_name_hash_ops);
if (!search_domains)
return -ENOMEM;
@@ -1550,6 +1536,8 @@ static int manager_save(Manager *m) {
return -ENOMEM;
HASHMAP_FOREACH(link, m->links, i) {
+ const struct in_addr *addresses;
+
if (link->flags & IFF_LOOPBACK)
continue;
@@ -1616,30 +1604,6 @@ static int manager_save(Manager *m) {
return r;
}
- r = sd_dhcp_lease_get_pop3(link->dhcp_lease, &addresses);
- if (r > 0) {
- r = ordered_set_put_in4_addrv(pop3, addresses, r, in4_addr_is_non_local);
- if (r < 0)
- return r;
- } else if (r < 0 && r != -ENODATA)
- return r;
-
- r = sd_dhcp_lease_get_smtp(link->dhcp_lease, &addresses);
- if (r > 0) {
- r = ordered_set_put_in4_addrv(smtp, addresses, r, in4_addr_is_non_local);
- if (r < 0)
- return r;
- } else if (r < 0 && r != -ENODATA)
- return r;
-
- r = sd_dhcp_lease_get_lpr(link->dhcp_lease, &addresses);
- if (r > 0) {
- r = ordered_set_put_in4_addrv(lpr, addresses, r, in4_addr_is_non_local);
- if (r < 0)
- return r;
- } else if (r < 0 && r != -ENODATA)
- return r;
-
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
const char *domainname;
char **domains = NULL;
@@ -1691,9 +1655,6 @@ static int manager_save(Manager *m) {
ordered_set_print(f, "DNS=", dns);
ordered_set_print(f, "NTP=", ntp);
ordered_set_print(f, "SIP=", sip);
- ordered_set_print(f, "POP3_SERVERS=", pop3);
- ordered_set_print(f, "SMTP_SERVERS=", smtp);
- ordered_set_print(f, "LPR_SERVERS=", lpr);
ordered_set_print(f, "DOMAINS=", search_domains);
ordered_set_print(f, "ROUTE_DOMAINS=", route_domains);
@@ -2348,23 +2309,15 @@ int manager_request_product_uuid(Manager *m, Link *link) {
assert_se(duid = link_get_duid(link));
- r = set_ensure_allocated(&m->links_requesting_uuid, NULL);
+ r = set_ensure_put(&m->links_requesting_uuid, NULL, link);
if (r < 0)
return log_oom();
+ if (r > 0)
+ link_ref(link);
- r = set_ensure_allocated(&m->duids_requesting_uuid, NULL);
+ r = set_ensure_put(&m->duids_requesting_uuid, NULL, duid);
if (r < 0)
return log_oom();
-
- r = set_put(m->links_requesting_uuid, link);
- if (r < 0)
- return log_oom();
-
- r = set_put(m->duids_requesting_uuid, duid);
- if (r < 0)
- return log_oom();
-
- link_ref(link);
}
if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index 6de8428e1e..7889bfb191 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -77,7 +77,7 @@ static int make_stableprivate_address(Link *link, const struct in6_addr *prefix,
rid = htole64(siphash24_finalize(&state));
memcpy(addr->s6_addr, prefix->s6_addr, l);
- memcpy((uint8_t *) &addr->s6_addr + l, &rid, 16 - l);
+ memcpy(addr->s6_addr + l, &rid, 16 - l);
return 0;
}
@@ -299,7 +299,7 @@ static int ndisc_router_generate_addresses(Link *link, unsigned prefixlen, uint3
}
}
} else if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC) {
- memcpy(((uint8_t *)&new_address->in_addr.in6) + 8, ((uint8_t *) &j->prefix) + 8, 8);
+ memcpy(new_address->in_addr.in6.s6_addr + 8, j->prefix.s6_addr + 8, 8);
have_address = true;
}
@@ -591,10 +591,6 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
continue;
}
- r = set_ensure_allocated(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops);
- if (r < 0)
- return log_oom();
-
x = new(NDiscRDNSS, 1);
if (!x)
return log_oom();
@@ -604,13 +600,11 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
.valid_until = time_now + lifetime * USEC_PER_SEC,
};
- r = set_put(link->ndisc_rdnss, x);
+ r = set_ensure_consume(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops, TAKE_PTR(x));
if (r < 0)
return log_oom();
-
- TAKE_PTR(x);
-
assert(r > 0);
+
link_dirty(link);
}
@@ -686,22 +680,15 @@ static void ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
continue;
}
- r = set_ensure_allocated(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops);
- if (r < 0) {
- log_oom();
- return;
- }
-
s->valid_until = time_now + lifetime * USEC_PER_SEC;
- r = set_put(link->ndisc_dnssl, s);
+ r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s));
if (r < 0) {
log_oom();
return;
}
-
- s = NULL;
assert(r > 0);
+
link_dirty(link);
}
}
@@ -979,22 +966,13 @@ int config_parse_ndisc_black_listed_prefix(
if (set_contains(network->ndisc_black_listed_prefix, &ip.in6))
continue;
- r = set_ensure_allocated(&network->ndisc_black_listed_prefix, &in6_addr_hash_ops);
- if (r < 0)
- return log_oom();
-
a = newdup(struct in6_addr, &ip.in6, 1);
if (!a)
return log_oom();
- r = set_put(network->ndisc_black_listed_prefix, a);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to store NDISC black listed prefix '%s', ignoring assignment: %m", n);
- continue;
- }
-
- TAKE_PTR(a);
+ r = set_ensure_consume(&network->ndisc_black_listed_prefix, &in6_addr_hash_ops, TAKE_PTR(a));
+ if (r < 0)
+ return log_oom();
}
return 0;
diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c
index fd6219fcce..6d91f70511 100644
--- a/src/network/networkd-neighbor.c
+++ b/src/network/networkd-neighbor.c
@@ -300,11 +300,7 @@ static int neighbor_add_internal(Link *link, Set **neighbors, int family, const
.lladdr_size = lladdr_size,
};
- r = set_ensure_allocated(neighbors, &neighbor_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(*neighbors, neighbor);
+ r = set_ensure_put(neighbors, &neighbor_hash_ops, neighbor);
if (r < 0)
return r;
if (r == 0)
@@ -314,8 +310,7 @@ static int neighbor_add_internal(Link *link, Set **neighbors, int family, const
if (ret)
*ret = neighbor;
-
- neighbor = NULL;
+ TAKE_PTR(neighbor);
return 0;
}
@@ -332,11 +327,7 @@ int neighbor_add(Link *link, int family, const union in_addr_union *addr, const
return r;
} else if (r == 0) {
/* Neighbor is foreign, claim it as recognized */
- r = set_ensure_allocated(&link->neighbors, &neighbor_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(link->neighbors, neighbor);
+ r = set_ensure_put(&link->neighbors, &neighbor_hash_ops, neighbor);
if (r < 0)
return r;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 030ed6fba6..046eedc4bf 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -217,15 +217,18 @@ IPv6AcceptRA.RouteTable, config_parse_section_route_table,
IPv6AcceptRA.BlackList, config_parse_ndisc_black_listed_prefix, 0, 0
DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec)
DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec)
-DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns)
-DHCPServer.DNS, config_parse_dhcp_server_dns, 0, 0
-DHCPServer.EmitNTP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_ntp)
-DHCPServer.NTP, config_parse_dhcp_server_ntp, 0, 0
-DHCPServer.EmitSIP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_sip)
-DHCPServer.SIP, config_parse_dhcp_server_sip, 0, 0
-DHCPServer.POP3Servers, config_parse_dhcp_server_pop3_servers, 0, 0
-DHCPServer.SMTPServers, config_parse_dhcp_server_smtp_servers, 0, 0
-DHCPServer.LPRServers, config_parse_dhcp_server_lpr_servers, 0, 0
+DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_DNS].emit)
+DHCPServer.DNS, config_parse_dhcp_server_emit, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_DNS])
+DHCPServer.EmitNTP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_NTP].emit)
+DHCPServer.NTP, config_parse_dhcp_server_emit, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_NTP])
+DHCPServer.EmitSIP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_SIP].emit)
+DHCPServer.SIP, config_parse_dhcp_server_emit, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_SIP])
+DHCPServer.EmitPOP3, config_parse_bool, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_POP3].emit)
+DHCPServer.POP3, config_parse_dhcp_server_emit, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_POP3])
+DHCPServer.EmitSMTP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_SMTP].emit)
+DHCPServer.SMTP, config_parse_dhcp_server_emit, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_SMTP])
+DHCPServer.EmitLPR, config_parse_bool, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_LPR].emit)
+DHCPServer.LPR, config_parse_dhcp_server_emit, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_LPR])
DHCPServer.EmitRouter, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_router)
DHCPServer.EmitTimezone, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_timezone)
DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone)
@@ -306,6 +309,12 @@ DeficitRoundRobinScheduler.Handle, config_parse_qdisc_handle,
DeficitRoundRobinSchedulerClass.Parent, config_parse_tclass_parent, TCLASS_KIND_DRR, 0
DeficitRoundRobinSchedulerClass.ClassId, config_parse_tclass_classid, TCLASS_KIND_DRR, 0
DeficitRoundRobinSchedulerClass.Quantum, config_parse_drr_size, TCLASS_KIND_DRR, 0
+EnhancedTransmissionSelection.Parent, config_parse_qdisc_parent, QDISC_KIND_ETS, 0
+EnhancedTransmissionSelection.Handle, config_parse_qdisc_handle, QDISC_KIND_ETS, 0
+EnhancedTransmissionSelection.Bands, config_parse_ets_u8, QDISC_KIND_ETS, 0
+EnhancedTransmissionSelection.StrictBands, config_parse_ets_u8, QDISC_KIND_ETS, 0
+EnhancedTransmissionSelection.QuantumBytes, config_parse_ets_quanta, QDISC_KIND_ETS, 0
+EnhancedTransmissionSelection.PriorityMap, config_parse_ets_prio, QDISC_KIND_ETS, 0
PFIFO.Parent, config_parse_qdisc_parent, QDISC_KIND_PFIFO, 0
PFIFO.Handle, config_parse_qdisc_handle, QDISC_KIND_PFIFO, 0
PFIFO.PacketLimit, config_parse_pfifo_size, QDISC_KIND_PFIFO, 0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 51c57af563..8478fe8c9e 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -416,9 +416,10 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.dhcp6_pd_assign_prefix = true,
- .dhcp_server_emit_dns = true,
- .dhcp_server_emit_ntp = true,
- .dhcp_server_emit_sip = true,
+ .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
+ .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
+ .dhcp_server_emit[SD_DHCP_LEASE_SIP].emit = true,
+
.dhcp_server_emit_router = true,
.dhcp_server_emit_timezone = true,
@@ -511,6 +512,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
"ControlledDelay\0"
"DeficitRoundRobinScheduler\0"
"DeficitRoundRobinSchedulerClass\0"
+ "EnhancedTransmissionSelection\0"
"FairQueueing\0"
"FairQueueingControlledDelay\0"
"GenericRandomEarlyDetection\0"
@@ -673,8 +675,6 @@ static Network *network_free(Network *network) {
strv_free(network->ntp);
free(network->dns);
- strv_free(network->sip);
- strv_free(network->smtp);
ordered_set_free_free(network->search_domains);
ordered_set_free_free(network->route_domains);
strv_free(network->bind_carrier);
@@ -740,12 +740,9 @@ static Network *network_free(Network *network) {
free(network->name);
free(network->dhcp_server_timezone);
- free(network->dhcp_server_dns);
- free(network->dhcp_server_ntp);
- free(network->dhcp_server_sip);
- free(network->dhcp_server_pop3);
- free(network->dhcp_server_smtp);
- free(network->dhcp_server_lpr);
+
+ for (sd_dhcp_lease_server_type t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++)
+ free(network->dhcp_server_emit[t].addresses);
set_free_free(network->dnssec_negative_trust_anchors);
@@ -1272,15 +1269,9 @@ int config_parse_dnssec_negative_trust_anchors(
continue;
}
- r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
- if (r < 0)
- return log_oom();
-
- r = set_put(n->dnssec_negative_trust_anchors, w);
+ r = set_ensure_consume(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops, TAKE_PTR(w));
if (r < 0)
return log_oom();
- if (r > 0)
- w = NULL;
}
return 0;
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 00ecac6ca9..a2fcc5209b 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -54,6 +54,12 @@ typedef enum KeepConfiguration {
typedef struct Manager Manager;
+typedef struct NetworkDHCPServerEmitAddress {
+ bool emit;
+ struct in_addr *addresses;
+ size_t n_addresses;
+} NetworkDHCPServerEmitAddress;
+
struct Network {
Manager *manager;
@@ -149,28 +155,7 @@ struct Network {
/* DHCP Server Support */
bool dhcp_server;
-
- bool dhcp_server_emit_dns;
- struct in_addr *dhcp_server_dns;
- unsigned n_dhcp_server_dns;
-
- bool dhcp_server_emit_ntp;
- struct in_addr *dhcp_server_ntp;
- unsigned n_dhcp_server_ntp;
-
- bool dhcp_server_emit_sip;
- struct in_addr *dhcp_server_sip;
- unsigned n_dhcp_server_sip;
-
- struct in_addr *dhcp_server_pop3;
- unsigned n_dhcp_server_pop3;
-
- struct in_addr *dhcp_server_smtp;
- unsigned n_dhcp_server_smtp;
-
- struct in_addr *dhcp_server_lpr;
- unsigned n_dhcp_server_lpr;
-
+ NetworkDHCPServerEmitAddress dhcp_server_emit[_SD_DHCP_LEASE_SERVER_TYPE_MAX];
bool dhcp_server_emit_router;
bool dhcp_server_emit_timezone;
char *dhcp_server_timezone;
@@ -331,10 +316,6 @@ struct Network {
Set *dnssec_negative_trust_anchors;
char **ntp;
- char **sip;
- char **pop3;
- char **smtp;
- char **lpr;
char **bind_carrier;
};
diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c
index 45c13ca88f..5d91d791d1 100644
--- a/src/network/networkd-nexthop.c
+++ b/src/network/networkd-nexthop.c
@@ -209,11 +209,7 @@ static int nexthop_add_internal(Link *link, Set **nexthops, NextHop *in, NextHop
nexthop->family = in->family;
nexthop->gw = in->gw;
- r = set_ensure_allocated(nexthops, &nexthop_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(*nexthops, nexthop);
+ r = set_ensure_put(nexthops, &nexthop_hash_ops, nexthop);
if (r < 0)
return r;
if (r == 0)
@@ -245,11 +241,7 @@ int nexthop_add(Link *link, NextHop *in, NextHop **ret) {
return r;
} else if (r == 0) {
/* Take over a foreign nexthop */
- r = set_ensure_allocated(&link->nexthops, &nexthop_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(link->nexthops, nexthop);
+ r = set_ensure_put(&link->nexthops, &nexthop_hash_ops, nexthop);
if (r < 0)
return r;
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index de532eee7a..c93bf9feac 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -331,11 +331,7 @@ static int route_add_internal(Link *link, Set **routes, Route *in, Route **ret)
route->initrwnd = in->initrwnd;
route->lifetime = in->lifetime;
- r = set_ensure_allocated(routes, &route_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(*routes, route);
+ r = set_ensure_put(routes, &route_hash_ops, route);
if (r < 0)
return r;
if (r == 0)
@@ -368,11 +364,7 @@ int route_add(Link *link, Route *in, Route **ret) {
return r;
} else if (r == 0) {
/* Take over a foreign route */
- r = set_ensure_allocated(&link->routes, &route_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(link->routes, route);
+ r = set_ensure_put(&link->routes, &route_hash_ops, route);
if (r < 0)
return r;
diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c
index 641f884084..c4124c0906 100644
--- a/src/network/networkd-routing-policy-rule.c
+++ b/src/network/networkd-routing-policy-rule.c
@@ -263,11 +263,7 @@ int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule) {
if (set_contains(m->rules_foreign, rule)) {
set_remove(m->rules_foreign, rule);
- r = set_ensure_allocated(&m->rules, &routing_policy_rule_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(m->rules, rule);
+ r = set_ensure_put(&m->rules, &routing_policy_rule_hash_ops, rule);
if (r < 0)
return r;
if (r == 0)
@@ -295,11 +291,7 @@ static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPoli
if (r < 0)
return r;
- r = set_ensure_allocated(rules, &routing_policy_rule_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(*rules, rule);
+ r = set_ensure_put(rules, &routing_policy_rule_hash_ops, rule);
if (r < 0)
return r;
if (r == 0)
@@ -1328,10 +1320,6 @@ int routing_policy_load_rules(const char *state_file, Set **rules) {
if (!l)
return -ENOMEM;
- r = set_ensure_allocated(rules, &routing_policy_rule_hash_ops);
- if (r < 0)
- return r;
-
STRV_FOREACH(i, l) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
@@ -1461,7 +1449,7 @@ int routing_policy_load_rules(const char *state_file, Set **rules) {
}
}
- r = set_put(*rules, rule);
+ r = set_ensure_put(rules, &routing_policy_rule_hash_ops, rule);
if (r < 0) {
log_warning_errno(r, "Failed to add RPDB rule to saved DB, ignoring: %s", p);
continue;
diff --git a/src/network/tc/ets.c b/src/network/tc/ets.c
new file mode 100644
index 0000000000..c4fa5646dd
--- /dev/null
+++ b/src/network/tc/ets.c
@@ -0,0 +1,338 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <linux/pkt_sched.h>
+
+#include "alloc-util.h"
+#include "conf-parser.h"
+#include "ets.h"
+#include "memory-util.h"
+#include "netlink-util.h"
+#include "parse-util.h"
+#include "qdisc.h"
+#include "string-util.h"
+#include "tc-util.h"
+
+static int enhanced_transmission_selection_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
+ EnhancedTransmissionSelection *ets;
+ int r;
+
+ assert(link);
+ assert(qdisc);
+ assert(req);
+
+ ets = ETS(qdisc);
+
+ r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "ets");
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not open container TCA_OPTIONS: %m");
+
+ r = sd_netlink_message_append_u8(req, TCA_ETS_NBANDS, ets->n_bands);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append TCA_ETS_NBANDS attribute: %m");
+
+ if (ets->n_strict > 0) {
+ r = sd_netlink_message_append_u8(req, TCA_ETS_NSTRICT, ets->n_strict);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append TCA_ETS_NSTRICT attribute: %m");
+ }
+
+ if (ets->n_quanta > 0) {
+ r = sd_netlink_message_open_container(req, TCA_ETS_QUANTA);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not open container TCA_ETS_QUANTA: %m");
+
+ for (unsigned i = 0; i < ets->n_quanta; i++) {
+ r = sd_netlink_message_append_u32(req, TCA_ETS_QUANTA_BAND, ets->quanta[i]);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append TCA_ETS_QUANTA_BAND attribute: %m");
+ }
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not close container TCA_ETS_QUANTA: %m");
+ }
+
+ if (ets->n_prio > 0) {
+ r = sd_netlink_message_open_container(req, TCA_ETS_PRIOMAP);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not open container TCA_ETS_PRIOMAP: %m");
+
+ for (unsigned i = 0; i < ets->n_prio; i++) {
+ r = sd_netlink_message_append_u8(req, TCA_ETS_PRIOMAP_BAND, ets->prio[i]);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append TCA_ETS_PRIOMAP_BAND attribute: %m");
+ }
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not close container TCA_ETS_PRIOMAP: %m");
+ }
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not close container TCA_OPTIONS: %m");
+
+ return 0;
+}
+
+int config_parse_ets_u8(
+ 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) {
+
+ _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+ EnhancedTransmissionSelection *ets;
+ Network *network = data;
+ uint8_t v, *p;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = qdisc_new_static(QDISC_KIND_ETS, network, filename, section_line, &qdisc);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0)
+ return log_syntax(unit, LOG_ERR, filename, line, r,
+ "More than one kind of queueing discipline, ignoring assignment: %m");
+
+ ets = ETS(qdisc);
+ if (streq(lvalue, "Bands"))
+ p = &ets->n_bands;
+ else if (streq(lvalue, "StrictBands"))
+ p = &ets->n_strict;
+ else
+ assert_not_reached("Invalid lvalue.");
+
+ if (isempty(rvalue)) {
+ *p = 0;
+
+ qdisc = NULL;
+ return 0;
+ }
+
+ r = safe_atou8(rvalue, &v);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse '%s=', ignoring assignment: %s",
+ lvalue, rvalue);
+ return 0;
+ }
+ if (v > TCQ_ETS_MAX_BANDS) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Invalid '%s='. The value must be <= %d, ignoring assignment: %s",
+ lvalue, TCQ_ETS_MAX_BANDS, rvalue);
+ return 0;
+ }
+
+ *p = v;
+ qdisc = NULL;
+
+ return 0;
+}
+
+int config_parse_ets_quanta(
+ 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) {
+
+ _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+ EnhancedTransmissionSelection *ets;
+ Network *network = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = qdisc_new_static(QDISC_KIND_ETS, network, filename, section_line, &qdisc);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0)
+ return log_syntax(unit, LOG_ERR, filename, line, r,
+ "More than one kind of queueing discipline, ignoring assignment: %m");
+
+ ets = ETS(qdisc);
+
+ if (isempty(rvalue)) {
+ memzero(ets->quanta, sizeof(uint32_t) * TCQ_ETS_MAX_BANDS);
+ ets->n_quanta = 0;
+
+ qdisc = NULL;
+ return 0;
+ }
+
+ for (const char *p = rvalue;;) {
+ _cleanup_free_ char *word = NULL;
+ uint64_t v;
+
+ r = extract_first_word(&p, &word, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to extract next value, ignoring: %m");
+ continue;
+ }
+ if (r == 0)
+ break;
+
+ r = parse_size(word, 1024, &v);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse '%s=', ignoring assignment: %s",
+ lvalue, word);
+ continue;
+ }
+ if (v == 0 || v > UINT32_MAX) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Invalid '%s=', ignoring assignment: %s",
+ lvalue, word);
+ continue;
+ }
+ if (ets->n_quanta >= TCQ_ETS_MAX_BANDS) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Too many quanta in '%s=', ignoring assignment: %s",
+ lvalue, word);
+ continue;
+ }
+
+ ets->quanta[ets->n_quanta++] = v;
+ }
+
+ qdisc = NULL;
+
+ return 0;
+}
+
+int config_parse_ets_prio(
+ 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) {
+
+ _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+ EnhancedTransmissionSelection *ets;
+ Network *network = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = qdisc_new_static(QDISC_KIND_ETS, network, filename, section_line, &qdisc);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0)
+ return log_syntax(unit, LOG_ERR, filename, line, r,
+ "More than one kind of queueing discipline, ignoring assignment: %m");
+
+ ets = ETS(qdisc);
+
+ if (isempty(rvalue)) {
+ memzero(ets->prio, sizeof(uint8_t) * (TC_PRIO_MAX + 1));
+ ets->n_prio = 0;
+
+ qdisc = NULL;
+ return 0;
+ }
+
+ for (const char *p = rvalue;;) {
+ _cleanup_free_ char *word = NULL;
+ uint8_t v;
+
+ r = extract_first_word(&p, &word, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to extract next value, ignoring: %m");
+ continue;
+ }
+ if (r == 0)
+ break;
+
+ r = safe_atou8(word, &v);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse '%s=', ignoring assignment: %s",
+ lvalue, word);
+ continue;
+ }
+ if (ets->n_quanta > TC_PRIO_MAX) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Too many priomap in '%s=', ignoring assignment: %s",
+ lvalue, word);
+ continue;
+ }
+
+ ets->prio[ets->n_prio++] = v;
+ }
+
+ qdisc = NULL;
+
+ return 0;
+}
+
+static int enhanced_transmission_selection_verify(QDisc *qdisc) {
+ EnhancedTransmissionSelection *ets;
+
+ assert(qdisc);
+
+ ets = ETS(qdisc);
+
+ if (ets->n_bands == 0)
+ ets->n_bands = ets->n_strict + ets->n_quanta;
+
+ if (ets->n_bands == 0)
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: At least one of Band=, Strict=, or Quanta= must be specified. "
+ "Ignoring [EnhancedTransmissionSelection] section from line %u.",
+ qdisc->section->filename, qdisc->section->line);
+
+ if (ets->n_bands < ets->n_strict + ets->n_quanta)
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: Not enough total bands to cover all the strict bands and quanta. "
+ "Ignoring [EnhancedTransmissionSelection] section from line %u.",
+ qdisc->section->filename, qdisc->section->line);
+
+ for (unsigned i = 0; i < ets->n_prio; i++)
+ if (ets->prio[i] >= ets->n_bands)
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: PriorityMap= element is out of bands. "
+ "Ignoring [EnhancedTransmissionSelection] section from line %u.",
+ qdisc->section->filename, qdisc->section->line);
+
+ return 0;
+}
+
+const QDiscVTable ets_vtable = {
+ .object_size = sizeof(EnhancedTransmissionSelection),
+ .tca_kind = "ets",
+ .fill_message = enhanced_transmission_selection_fill_message,
+ .verify = enhanced_transmission_selection_verify,
+};
diff --git a/src/network/tc/ets.h b/src/network/tc/ets.h
new file mode 100644
index 0000000000..c35d5976d8
--- /dev/null
+++ b/src/network/tc/ets.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <linux/pkt_sched.h>
+
+#include "conf-parser.h"
+#include "qdisc.h"
+
+typedef struct EnhancedTransmissionSelection {
+ QDisc meta;
+
+ uint8_t n_bands;
+ uint8_t n_strict;
+ unsigned n_quanta;
+ uint32_t quanta[TCQ_ETS_MAX_BANDS];
+ unsigned n_prio;
+ uint8_t prio[TC_PRIO_MAX + 1];
+} EnhancedTransmissionSelection;
+
+DEFINE_QDISC_CAST(ETS, EnhancedTransmissionSelection);
+extern const QDiscVTable ets_vtable;
+
+CONFIG_PARSER_PROTOTYPE(config_parse_ets_u8);
+CONFIG_PARSER_PROTOTYPE(config_parse_ets_quanta);
+CONFIG_PARSER_PROTOTYPE(config_parse_ets_prio);
diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c
index 6ba4325c9c..91cdd8917f 100644
--- a/src/network/tc/qdisc.c
+++ b/src/network/tc/qdisc.c
@@ -20,6 +20,7 @@ const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX] = {
[QDISC_KIND_CAKE] = &cake_vtable,
[QDISC_KIND_CODEL] = &codel_vtable,
[QDISC_KIND_DRR] = &drr_vtable,
+ [QDISC_KIND_ETS] = &ets_vtable,
[QDISC_KIND_FQ] = &fq_vtable,
[QDISC_KIND_FQ_CODEL] = &fq_codel_vtable,
[QDISC_KIND_GRED] = &gred_vtable,
diff --git a/src/network/tc/qdisc.h b/src/network/tc/qdisc.h
index 802653efb0..0c9c0544b6 100644
--- a/src/network/tc/qdisc.h
+++ b/src/network/tc/qdisc.h
@@ -13,6 +13,7 @@ typedef enum QDiscKind {
QDISC_KIND_CAKE,
QDISC_KIND_CODEL,
QDISC_KIND_DRR,
+ QDISC_KIND_ETS,
QDISC_KIND_FQ,
QDISC_KIND_FQ_CODEL,
QDISC_KIND_GRED,
@@ -87,6 +88,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_qdisc_handle);
#include "cake.h"
#include "codel.h"
+#include "ets.h"
#include "fifo.h"
#include "fq-codel.h"
#include "fq.h"
diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c
index eb80c2960b..2fbaf65692 100644
--- a/src/nspawn/nspawn-mount.c
+++ b/src/nspawn/nspawn-mount.c
@@ -619,9 +619,9 @@ int mount_all(const char *dest,
#if HAVE_SELINUX
{ "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND,
- 0 }, /* Bind mount first */
+ MOUNT_MKDIR }, /* Bind mount first (mkdir/chown the mount point in case /sys/ is mounted as minimal skeleton tmpfs) */
{ NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT,
- 0 }, /* Then, make it r/o */
+ 0 }, /* Then, make it r/o (don't mkdir/chown the mount point here, the previous entry already did that) */
#endif
};
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index f3a3ee8a17..ae6828f2bf 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -5141,7 +5141,7 @@ static int run(int argc, char *argv[]) {
goto finish;
}
- r = verity_metadata_load(arg_image, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
+ r = verity_metadata_load(arg_image, NULL, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
arg_verity_data ? NULL : &arg_verity_data);
if (r < 0) {
log_error_errno(r, "Failed to read verity artefacts for %s: %m", arg_image);
diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c
index 6a2d9c885e..5dc5aacdff 100644
--- a/src/nss-systemd/nss-systemd.c
+++ b/src/nss-systemd/nss-systemd.c
@@ -8,6 +8,7 @@
#include "fd-util.h"
#include "group-record-nss.h"
#include "macro.h"
+#include "nss-systemd.h"
#include "nss-util.h"
#include "pthread-util.h"
#include "signal-util.h"
@@ -299,7 +300,7 @@ enum nss_status _nss_systemd_setpwent(int stayopen) {
PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
- if (userdb_nss_compat_is_enabled() <= 0)
+ if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
@@ -323,7 +324,7 @@ enum nss_status _nss_systemd_setgrent(int stayopen) {
PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
- if (userdb_nss_compat_is_enabled() <= 0)
+ if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
@@ -353,13 +354,7 @@ enum nss_status _nss_systemd_getpwent_r(
assert(result);
assert(errnop);
- r = userdb_nss_compat_is_enabled();
- if (r < 0) {
- UNPROTECT_ERRNO;
- *errnop = -r;
- return NSS_STATUS_UNAVAIL;
- }
- if (!r)
+ if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
@@ -406,14 +401,8 @@ enum nss_status _nss_systemd_getgrent_r(
assert(result);
assert(errnop);
- r = userdb_nss_compat_is_enabled();
- if (r < 0) {
- UNPROTECT_ERRNO;
- *errnop = -r;
- return NSS_STATUS_UNAVAIL;
- }
- if (!r)
- return NSS_STATUS_UNAVAIL;
+ if (_nss_systemd_is_blocked())
+ return NSS_STATUS_NOTFOUND;
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
@@ -459,7 +448,7 @@ enum nss_status _nss_systemd_getgrent_r(
}
if (getgrent_data.by_membership) {
- _cleanup_close_ int lock_fd = -1;
+ _cleanup_(_nss_systemd_unblockp) bool blocked = false;
for (;;) {
_cleanup_free_ char *user_name = NULL, *group_name = NULL;
@@ -479,13 +468,15 @@ enum nss_status _nss_systemd_getgrent_r(
continue;
/* We are about to recursively call into NSS, let's make sure we disable recursion into our own code. */
- if (lock_fd < 0) {
- lock_fd = userdb_nss_compat_disable();
- if (lock_fd < 0 && lock_fd != -EBUSY) {
+ if (!blocked) {
+ r = _nss_systemd_block(true);
+ if (r < 0) {
UNPROTECT_ERRNO;
- *errnop = -lock_fd;
+ *errnop = -r;
return NSS_STATUS_UNAVAIL;
}
+
+ blocked = true;
}
r = nss_group_record_by_name(group_name, false, &gr);
@@ -549,13 +540,7 @@ enum nss_status _nss_systemd_initgroups_dyn(
if (STR_IN_SET(user_name, root_passwd.pw_name, nobody_passwd.pw_name))
return NSS_STATUS_NOTFOUND;
- r = userdb_nss_compat_is_enabled();
- if (r < 0) {
- UNPROTECT_ERRNO;
- *errnop = -r;
- return NSS_STATUS_UNAVAIL;
- }
- if (!r)
+ if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
r = membershipdb_by_user(user_name, nss_glue_userdb_flags(), &iterator);
@@ -581,7 +566,7 @@ enum nss_status _nss_systemd_initgroups_dyn(
/* The group might be defined via traditional NSS only, hence let's do a full look-up without
* disabling NSS. This means we are operating recursively here. */
- r = groupdb_by_name(group_name, nss_glue_userdb_flags() & ~USERDB_AVOID_NSS, &g);
+ r = groupdb_by_name(group_name, (nss_glue_userdb_flags() & ~USERDB_AVOID_NSS) | USERDB_AVOID_SHADOW, &g);
if (r == -ESRCH)
continue;
if (r < 0) {
@@ -627,3 +612,29 @@ enum nss_status _nss_systemd_initgroups_dyn(
return any ? NSS_STATUS_SUCCESS : NSS_STATUS_NOTFOUND;
}
+
+static thread_local unsigned _blocked = 0;
+
+_public_ int _nss_systemd_block(bool b) {
+
+ /* This blocks recursively: it's blocked for as many times this function is called with `true` until
+ * it is called an equal time with `false`. */
+
+ if (b) {
+ if (_blocked >= UINT_MAX)
+ return -EOVERFLOW;
+
+ _blocked++;
+ } else {
+ if (_blocked <= 0)
+ return -EOVERFLOW;
+
+ _blocked--;
+ }
+
+ return b; /* Return what is passed in, i.e. the new state from the PoV of the caller */
+}
+
+_public_ bool _nss_systemd_is_blocked(void) {
+ return _blocked > 0;
+}
diff --git a/src/nss-systemd/nss-systemd.h b/src/nss-systemd/nss-systemd.h
new file mode 100644
index 0000000000..ffa75c12c4
--- /dev/null
+++ b/src/nss-systemd/nss-systemd.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+int _nss_systemd_block(bool b);
+bool _nss_systemd_is_blocked(void);
+
+/* For use with the _cleanup_() macro */
+static inline void _nss_systemd_unblockp(bool *b) {
+ if (*b)
+ assert_se(_nss_systemd_block(false) >= 0);
+}
diff --git a/src/nss-systemd/nss-systemd.sym b/src/nss-systemd/nss-systemd.sym
index 77e1fbe93f..f86d7643d1 100644
--- a/src/nss-systemd/nss-systemd.sym
+++ b/src/nss-systemd/nss-systemd.sym
@@ -20,5 +20,9 @@ global:
_nss_systemd_setgrent;
_nss_systemd_getgrent_r;
_nss_systemd_initgroups_dyn;
+
+ /* These two are not used by glibc, but can be used by apps to explicitly disable nss-systemd for the calling thread. */
+ _nss_systemd_block;
+ _nss_systemd_is_blocked;
local: *;
};
diff --git a/src/nss-systemd/userdb-glue.c b/src/nss-systemd/userdb-glue.c
index da1248a132..8e5b3eba6c 100644
--- a/src/nss-systemd/userdb-glue.c
+++ b/src/nss-systemd/userdb-glue.c
@@ -3,6 +3,7 @@
#include "env-util.h"
#include "fd-util.h"
#include "group-record-nss.h"
+#include "nss-systemd.h"
#include "strv.h"
#include "user-record.h"
#include "userdb-glue.h"
@@ -74,12 +75,7 @@ enum nss_status userdb_getpwnam(
assert(pwd);
assert(errnop);
- r = userdb_nss_compat_is_enabled();
- if (r < 0) {
- *errnop = -r;
- return NSS_STATUS_UNAVAIL;
- }
- if (!r)
+ if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
r = userdb_by_name(name, nss_glue_userdb_flags(), &hr);
@@ -112,12 +108,7 @@ enum nss_status userdb_getpwuid(
assert(pwd);
assert(errnop);
- r = userdb_nss_compat_is_enabled();
- if (r < 0) {
- *errnop = -r;
- return NSS_STATUS_UNAVAIL;
- }
- if (!r)
+ if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
r = userdb_by_uid(uid, nss_glue_userdb_flags(), &hr);
@@ -214,12 +205,7 @@ enum nss_status userdb_getgrnam(
assert(gr);
assert(errnop);
- r = userdb_nss_compat_is_enabled();
- if (r < 0) {
- *errnop = -r;
- return NSS_STATUS_UNAVAIL;
- }
- if (!r)
+ if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
r = groupdb_by_name(name, nss_glue_userdb_flags(), &g);
@@ -235,7 +221,7 @@ enum nss_status userdb_getgrnam(
}
if (!g) {
- _cleanup_close_ int lock_fd = -1;
+ _cleanup_(_nss_systemd_unblockp) bool blocked = false;
if (strv_isempty(members))
return NSS_STATUS_NOTFOUND;
@@ -245,11 +231,13 @@ enum nss_status userdb_getgrnam(
* acquire it, so that we can extend it (that's because glibc's group merging feature will
* merge groups only if both GID and name match and thus we need to have both first). It
* sucks behaving recursively likely this, but it's apparently what everybody does. We break
- * the recursion for ourselves via the userdb_nss_compat_disable() lock. */
+ * the recursion for ourselves via the _nss_systemd_block_nss() lock. */
+
+ r = _nss_systemd_block(true);
+ if (r < 0)
+ return r;
- lock_fd = userdb_nss_compat_disable();
- if (lock_fd < 0 && lock_fd != -EBUSY)
- return lock_fd;
+ blocked = true;
r = nss_group_record_by_name(name, false, &g);
if (r == -ESRCH)
@@ -285,12 +273,7 @@ enum nss_status userdb_getgrgid(
assert(gr);
assert(errnop);
- r = userdb_nss_compat_is_enabled();
- if (r < 0) {
- *errnop = -r;
- return NSS_STATUS_UNAVAIL;
- }
- if (!r)
+ if (_nss_systemd_is_blocked())
return NSS_STATUS_NOTFOUND;
r = groupdb_by_gid(gid, nss_glue_userdb_flags(), &g);
@@ -300,20 +283,21 @@ enum nss_status userdb_getgrgid(
}
if (!g) {
- _cleanup_close_ int lock_fd = -1;
+ _cleanup_(_nss_systemd_unblockp) bool blocked = false;
/* So, quite possibly we have to extend an existing group record with additional members. But
* to do this we need to know the group name first. The group didn't exist via non-NSS
* queries though, hence let's try to acquire it here recursively via NSS. */
- lock_fd = userdb_nss_compat_disable();
- if (lock_fd < 0 && lock_fd != -EBUSY)
- return lock_fd;
+ r = _nss_systemd_block(true);
+ if (r < 0)
+ return r;
+
+ blocked = true;
r = nss_group_record_by_gid(gid, false, &g);
if (r == -ESRCH)
return NSS_STATUS_NOTFOUND;
-
if (r < 0) {
*errnop = -r;
return NSS_STATUS_UNAVAIL;
diff --git a/src/partition/repart.c b/src/partition/repart.c
index 4c6e459529..d3706fe180 100644
--- a/src/partition/repart.c
+++ b/src/partition/repart.c
@@ -41,6 +41,7 @@
#include "pretty-print.h"
#include "proc-cmdline.h"
#include "sort-util.h"
+#include "specifier.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
@@ -48,6 +49,12 @@
#include "terminal-util.h"
#include "utf8.h"
+/* If not configured otherwise use a minimal partition size of 10M */
+#define DEFAULT_MIN_SIZE (10*1024*1024)
+
+/* Hard lower limit for new partition sizes */
+#define HARD_MIN_SIZE 4096
+
/* Note: When growing and placing new partitions we always align to 4K sector size. It's how newer hard disks
* are designed, and if everything is aligned to that performance is best. And for older hard disks with 512B
* sector size devices were generally assumed to have an even number of sectors, hence at the worst we'll
@@ -321,7 +328,9 @@ static uint64_t partition_min_size(const Partition *p) {
/* Calculate the disk space we really need at minimum for this partition. If the partition already
* exists the current size is what we really need. If it doesn't exist yet refuse to allocate less
- * than 4K. */
+ * than 4K.
+ *
+ * DEFAULT_MIN_SIZE is the default SizeMin= we configure if nothing else is specified. */
if (PARTITION_IS_FOREIGN(p)) {
/* Don't allow changing size of partitions not managed by us */
@@ -329,11 +338,8 @@ static uint64_t partition_min_size(const Partition *p) {
return p->current_size;
}
- sz = p->current_size != UINT64_MAX ? p->current_size : 4096;
- if (p->size_min != UINT64_MAX)
- return MAX(p->size_min, sz);
-
- return sz;
+ sz = p->current_size != UINT64_MAX ? p->current_size : HARD_MIN_SIZE;
+ return MAX(p->size_min == UINT64_MAX ? DEFAULT_MIN_SIZE : p->size_min, sz);
}
static uint64_t partition_max_size(const Partition *p) {
@@ -857,20 +863,42 @@ static int config_parse_label(
void *data,
void *userdata) {
+ static const Specifier specifier_table[] = {
+ { 'm', specifier_machine_id, NULL },
+ { 'b', specifier_boot_id, NULL },
+ { 'H', specifier_host_name, NULL },
+ { 'l', specifier_short_host_name, NULL },
+ { 'v', specifier_kernel_release, NULL },
+ { 'a', specifier_architecture, NULL },
+ { 'o', specifier_os_id, NULL },
+ { 'w', specifier_os_version_id, NULL },
+ { 'B', specifier_os_build_id, NULL },
+ { 'W', specifier_os_variant_id, NULL },
+ {}
+ };
+
_cleanup_free_ char16_t *recoded = NULL;
+ _cleanup_free_ char *resolved = NULL;
char **label = data;
int r;
assert(rvalue);
assert(label);
- if (!utf8_is_valid(rvalue)) {
+ r = specifier_printf(rvalue, specifier_table, NULL, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to expand specifiers in Label=, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (!utf8_is_valid(resolved)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Partition label not valid UTF-8, ignoring: %s", rvalue);
return 0;
}
- recoded = utf8_to_utf16(rvalue, strlen(rvalue));
+ recoded = utf8_to_utf16(resolved, strlen(resolved));
if (!recoded)
return log_oom();
@@ -880,10 +908,7 @@ static int config_parse_label(
return 0;
}
- r = free_and_strdup(label, rvalue);
- if (r < 0)
- return log_oom();
-
+ free_and_replace(*label, resolved);
return 0;
}
diff --git a/src/partition/test-repart.sh b/src/partition/test-repart.sh
index e1ff357929..897f11411a 100755
--- a/src/partition/test-repart.sh
+++ b/src/partition/test-repart.sh
@@ -33,6 +33,7 @@ ln -s root.conf $D/definitions/root2.conf
cat >$D/definitions/home.conf <<EOF
[Partition]
Type=home
+Label=home-%v
EOF
cat > $D/definitions/swap.conf <<EOF
@@ -46,6 +47,8 @@ $repart $D/zzz --dry-run=no --seed=$SEED --definitions=$D/definitions
sfdisk -d $D/zzz | grep -v -e 'sector-size' -e '^$' >$D/populated
+UNAME=`uname -r`
+
cmp $D/populated - <<EOF
label: gpt
label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
@@ -53,7 +56,7 @@ device: $D/zzz
unit: sectors
first-lba: 2048
last-lba: 2097118
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home"
+$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-$UNAME"
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
@@ -86,7 +89,7 @@ device: $D/zzz
unit: sectors
first-lba: 2048
last-lba: 2097118
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home"
+$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-$UNAME"
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
@@ -104,7 +107,7 @@ device: $D/zzz
unit: sectors
first-lba: 2048
last-lba: 4194270
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home"
+$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-$UNAME"
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
diff --git a/src/portable/portable.c b/src/portable/portable.c
index 7917ea3902..3dc6d9e422 100644
--- a/src/portable/portable.c
+++ b/src/portable/portable.c
@@ -1125,7 +1125,7 @@ int portable_detach(
sd_bus_error *error) {
_cleanup_(lookup_paths_free) LookupPaths paths = {};
- _cleanup_set_free_free_ Set *unit_files = NULL, *markers = NULL;
+ _cleanup_set_free_ Set *unit_files = NULL, *markers = NULL;
_cleanup_closedir_ DIR *d = NULL;
const char *where, *item;
Iterator iterator;
@@ -1149,10 +1149,6 @@ int portable_detach(
return log_debug_errno(errno, "Failed to open '%s' directory: %m", where);
}
- markers = set_new(&path_hash_ops);
- if (!markers)
- return -ENOMEM;
-
FOREACH_DIRENT(de, d, return log_debug_errno(errno, "Failed to enumerate '%s' directory: %m", where)) {
_cleanup_free_ char *marker = NULL;
UnitFileState state;
@@ -1193,15 +1189,9 @@ int portable_detach(
if (path_is_absolute(marker) &&
!image_in_search_path(IMAGE_PORTABLE, marker)) {
- r = set_ensure_allocated(&markers, &path_hash_ops);
+ r = set_ensure_consume(&markers, &path_hash_ops_free, TAKE_PTR(marker));
if (r < 0)
return r;
-
- r = set_put(markers, marker);
- if (r >= 0)
- marker = NULL;
- else if (r != -EEXIST)
- return r;
}
}
diff --git a/src/portable/portablectl.c b/src/portable/portablectl.c
index 1bde30e90f..01614b6684 100644
--- a/src/portable/portablectl.c
+++ b/src/portable/portablectl.c
@@ -1119,9 +1119,7 @@ static int run(int argc, char *argv[]) {
int r;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c
index 3cadac7639..a80b450bc0 100644
--- a/src/resolve/resolvectl.c
+++ b/src/resolve/resolvectl.c
@@ -3174,9 +3174,7 @@ static int run(int argc, char **argv) {
int r;
setlocale(LC_ALL, "");
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
if (streq(program_invocation_short_name, "resolvconf"))
r = resolvconf_parse_argv(argc, argv);
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
index d6eca6dfdd..906158c5ce 100644
--- a/src/resolve/resolved-dns-query.c
+++ b/src/resolve/resolved-dns-query.c
@@ -94,7 +94,7 @@ static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
}
static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResourceKey *key) {
- DnsTransaction *t;
+ _cleanup_(dns_transaction_gcp) DnsTransaction *t = NULL;
int r;
assert(c);
@@ -105,39 +105,26 @@ static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResource
r = dns_transaction_new(&t, c->scope, key);
if (r < 0)
return r;
- } else {
- if (set_contains(c->transactions, t))
- return 0;
- }
-
- r = set_ensure_allocated(&c->transactions, NULL);
- if (r < 0)
- goto gc;
-
- r = set_ensure_allocated(&t->notify_query_candidates, NULL);
- if (r < 0)
- goto gc;
+ } else if (set_contains(c->transactions, t))
+ return 0;
r = set_ensure_allocated(&t->notify_query_candidates_done, NULL);
if (r < 0)
- goto gc;
+ return r;
- r = set_put(t->notify_query_candidates, c);
+ r = set_ensure_put(&t->notify_query_candidates, NULL, c);
if (r < 0)
- goto gc;
+ return r;
- r = set_put(c->transactions, t);
+ r = set_ensure_put(&c->transactions, NULL, t);
if (r < 0) {
(void) set_remove(t->notify_query_candidates, c);
- goto gc;
+ return r;
}
t->clamp_ttl = c->query->clamp_ttl;
+ TAKE_PTR(t);
return 1;
-
-gc:
- dns_transaction_gc(t);
- return r;
}
static int dns_query_candidate_go(DnsQueryCandidate *c) {
@@ -513,7 +500,7 @@ static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
}
static int dns_query_add_candidate(DnsQuery *q, DnsScope *s) {
- DnsQueryCandidate *c;
+ _cleanup_(dns_query_candidate_freep) DnsQueryCandidate *c = NULL;
int r;
assert(q);
@@ -524,24 +511,21 @@ static int dns_query_add_candidate(DnsQuery *q, DnsScope *s) {
return r;
/* If this a single-label domain on DNS, we might append a suitable search domain first. */
- if ((q->flags & SD_RESOLVED_NO_SEARCH) == 0 &&
- dns_scope_name_needs_search_domain(s, dns_question_first_name(q->question_idna))) {
- /* OK, we need a search domain now. Let's find one for this scope */
+ if (!FLAGS_SET(q->flags, SD_RESOLVED_NO_SEARCH) &&
+ dns_scope_name_wants_search_domain(s, dns_question_first_name(q->question_idna))) {
+ /* OK, we want a search domain now. Let's find one for this scope */
r = dns_query_candidate_next_search_domain(c);
- if (r <= 0) /* if there's no search domain, then we won't add any transaction. */
- goto fail;
+ if (r < 0)
+ return r;
}
r = dns_query_candidate_setup_transactions(c);
if (r < 0)
- goto fail;
+ return r;
+ TAKE_PTR(c);
return 0;
-
-fail:
- dns_query_candidate_free(c);
- return r;
}
static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
diff --git a/src/resolve/resolved-dns-query.h b/src/resolve/resolved-dns-query.h
index fc7ccf553e..fe8a219557 100644
--- a/src/resolve/resolved-dns-query.h
+++ b/src/resolve/resolved-dns-query.h
@@ -102,6 +102,8 @@ enum {
};
DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c);
+DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryCandidate*, dns_query_candidate_free);
+
void dns_query_candidate_notify(DnsQueryCandidate *c);
int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question_utf8, DnsQuestion *question_idna, int family, uint64_t flags);
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index d06e428011..764ccee0e0 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -619,7 +619,7 @@ DnsScopeMatch dns_scope_good_domain(
manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via LLMNR */
return DNS_SCOPE_YES_BASE + 1; /* Return +1, as we consider ourselves authoritative
* for single-label names, i.e. one label. This is
- * particular relevant as it means a "." route on some
+ * particularly relevant as it means a "." route on some
* other scope won't pull all traffic away from
* us. (If people actually want to pull traffic away
* from us they should turn off LLMNR on the
@@ -651,20 +651,21 @@ bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key) {
if (s->protocol == DNS_PROTOCOL_DNS) {
- /* On classic DNS, looking up non-address RRs is always
- * fine. (Specifically, we want to permit looking up
- * DNSKEY and DS records on the root and top-level
- * domains.) */
+ /* On classic DNS, looking up non-address RRs is always fine. (Specifically, we want to
+ * permit looking up DNSKEY and DS records on the root and top-level domains.) */
if (!dns_resource_key_is_address(key))
return true;
- /* However, we refuse to look up A and AAAA RRs on the
- * root and single-label domains, under the assumption
- * that those should be resolved via LLMNR or search
- * path only, and should not be leaked onto the
- * internet. */
- return !(dns_name_is_single_label(dns_resource_key_name(key)) ||
- dns_name_is_root(dns_resource_key_name(key)));
+ /* Unless explicitly overridden, we refuse to look up A and AAAA RRs on the root and
+ * single-label domains, under the assumption that those should be resolved via LLMNR or
+ * search path only, and should not be leaked onto the internet. */
+ const char* name = dns_resource_key_name(key);
+
+ if (!s->manager->resolve_unicast_single_label &&
+ dns_name_is_single_label(name))
+ return false;
+
+ return !dns_name_is_root(name);
}
/* On mDNS and LLMNR, send A and AAAA queries only on the
@@ -1169,7 +1170,7 @@ DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s) {
return s->manager->search_domains;
}
-bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name) {
+bool dns_scope_name_wants_search_domain(DnsScope *s, const char *name) {
assert(s);
if (s->protocol != DNS_PROTOCOL_DNS)
@@ -1253,11 +1254,7 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) {
if (!scope->announced &&
dns_resource_key_is_dnssd_ptr(z->rr->key)) {
if (!set_contains(types, dns_resource_key_name(z->rr->key))) {
- r = set_ensure_allocated(&types, &dns_name_hash_ops);
- if (r < 0)
- return log_debug_errno(r, "Failed to allocate set: %m");
-
- r = set_put(types, dns_resource_key_name(z->rr->key));
+ r = set_ensure_put(&types, &dns_name_hash_ops, dns_resource_key_name(z->rr->key));
if (r < 0)
return log_debug_errno(r, "Failed to add item to set: %m");
}
diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h
index 974692be5b..b356b92120 100644
--- a/src/resolve/resolved-dns-scope.h
+++ b/src/resolve/resolved-dns-scope.h
@@ -99,7 +99,7 @@ void dns_scope_dump(DnsScope *s, FILE *f);
DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s);
-bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name);
+bool dns_scope_name_wants_search_domain(DnsScope *s, const char *name);
bool dns_scope_network_good(DnsScope *s);
diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c
index ce994a7ee0..03edbe26dc 100644
--- a/src/resolve/resolved-dns-stub.c
+++ b/src/resolve/resolved-dns-stub.c
@@ -278,7 +278,7 @@ static int dns_stub_stream_complete(DnsStream *s, int error) {
}
static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) {
- DnsQuery *q = NULL;
+ _cleanup_(dns_query_freep) DnsQuery *q = NULL;
int r;
assert(m);
@@ -289,52 +289,52 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) {
in_addr_is_localhost(p->family, &p->destination) <= 0) {
log_error("Got packet on unexpected IP range, refusing.");
dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false);
- goto fail;
+ return;
}
r = dns_packet_extract(p);
if (r < 0) {
log_debug_errno(r, "Failed to extract resources from incoming packet, ignoring packet: %m");
dns_stub_send_failure(m, s, p, DNS_RCODE_FORMERR, false);
- goto fail;
+ return;
}
if (!DNS_PACKET_VERSION_SUPPORTED(p)) {
log_debug("Got EDNS OPT field with unsupported version number.");
dns_stub_send_failure(m, s, p, DNS_RCODE_BADVERS, false);
- goto fail;
+ return;
}
if (dns_type_is_obsolete(p->question->keys[0]->type)) {
log_debug("Got message with obsolete key type, refusing.");
dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false);
- goto fail;
+ return;
}
if (dns_type_is_zone_transer(p->question->keys[0]->type)) {
log_debug("Got request for zone transfer, refusing.");
dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false);
- goto fail;
+ return;
}
if (!DNS_PACKET_RD(p)) {
/* If the "rd" bit is off (i.e. recursion was not requested), then refuse operation */
log_debug("Got request with recursion disabled, refusing.");
dns_stub_send_failure(m, s, p, DNS_RCODE_REFUSED, false);
- goto fail;
+ return;
}
if (DNS_PACKET_DO(p) && DNS_PACKET_CD(p)) {
log_debug("Got request with DNSSEC CD bit set, refusing.");
dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false);
- goto fail;
+ return;
}
r = dns_query_new(m, &q, p->question, p->question, 0, SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_SEARCH);
if (r < 0) {
log_error_errno(r, "Failed to generate query object: %m");
dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false);
- goto fail;
+ return;
}
/* Request that the TTL is corrected by the cached time for this lookup, so that we return vaguely useful TTLs */
@@ -348,30 +348,23 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) {
/* Remember which queries belong to this stream, so that we can cancel them when the stream
* is disconnected early */
- r = set_ensure_allocated(&s->queries, &trivial_hash_ops);
+ r = set_ensure_put(&s->queries, NULL, q);
if (r < 0) {
log_oom();
- goto fail;
- }
-
- if (set_put(s->queries, q) < 0) {
- log_oom();
- goto fail;
+ return;
}
+ assert(r > 0);
}
r = dns_query_go(q);
if (r < 0) {
log_error_errno(r, "Failed to start query: %m");
dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false);
- goto fail;
+ return;
}
log_debug("Processing query...");
- return;
-
-fail:
- dns_query_free(q);
+ TAKE_PTR(q);
}
static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 5898308d5f..cd5a0e3dd9 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -1501,11 +1501,7 @@ static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
add_known_answers = true;
if (t->key->type == DNS_TYPE_ANY) {
- r = set_ensure_allocated(&keys, &dns_resource_key_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(keys, t->key);
+ r = set_ensure_put(&keys, &dns_resource_key_hash_ops, t->key);
if (r < 0)
return r;
}
@@ -1571,11 +1567,7 @@ static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
add_known_answers = true;
if (other->key->type == DNS_TYPE_ANY) {
- r = set_ensure_allocated(&keys, &dns_resource_key_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(keys, other->key);
+ r = set_ensure_put(&keys, &dns_resource_key_hash_ops, other->key);
if (r < 0)
return r;
}
@@ -1800,7 +1792,7 @@ static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) {
}
static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResourceKey *key, DnsTransaction **ret) {
- DnsTransaction *aux;
+ _cleanup_(dns_transaction_gcp) DnsTransaction *aux = NULL;
int r;
assert(t);
@@ -1833,34 +1825,22 @@ static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResource
}
}
- r = set_ensure_allocated(&t->dnssec_transactions, NULL);
- if (r < 0)
- goto gc;
-
- r = set_ensure_allocated(&aux->notify_transactions, NULL);
- if (r < 0)
- goto gc;
-
r = set_ensure_allocated(&aux->notify_transactions_done, NULL);
if (r < 0)
- goto gc;
+ return r;
- r = set_put(t->dnssec_transactions, aux);
+ r = set_ensure_put(&t->dnssec_transactions, NULL, aux);
if (r < 0)
- goto gc;
+ return r;;
- r = set_put(aux->notify_transactions, t);
+ r = set_ensure_put(&aux->notify_transactions, NULL, t);
if (r < 0) {
(void) set_remove(t->dnssec_transactions, aux);
- goto gc;
+ return r;
}
- *ret = aux;
+ *ret = TAKE_PTR(aux);
return 1;
-
-gc:
- dns_transaction_gc(aux);
- return r;
}
static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) {
diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h
index b1d4348409..167541806a 100644
--- a/src/resolve/resolved-dns-transaction.h
+++ b/src/resolve/resolved-dns-transaction.h
@@ -138,6 +138,8 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key);
DnsTransaction* dns_transaction_free(DnsTransaction *t);
bool dns_transaction_gc(DnsTransaction *t);
+DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_gc);
+
int dns_transaction_go(DnsTransaction *t);
void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p);
diff --git a/src/resolve/resolved-dns-trust-anchor.c b/src/resolve/resolved-dns-trust-anchor.c
index 843f4c0f45..d68d0c3ba1 100644
--- a/src/resolve/resolved-dns-trust-anchor.c
+++ b/src/resolve/resolved-dns-trust-anchor.c
@@ -393,15 +393,9 @@ static int dns_trust_anchor_load_negative(DnsTrustAnchor *d, const char *path, u
return -EINVAL;
}
- r = set_ensure_allocated(&d->negative_by_name, &dns_name_hash_ops);
- if (r < 0)
- return log_oom();
-
- r = set_put(d->negative_by_name, domain);
+ r = set_ensure_consume(&d->negative_by_name, &dns_name_hash_ops, TAKE_PTR(domain));
if (r < 0)
return log_oom();
- if (r > 0)
- domain = NULL;
return 0;
}
@@ -592,11 +586,7 @@ static int dns_trust_anchor_revoked_put(DnsTrustAnchor *d, DnsResourceRecord *rr
assert(d);
- r = set_ensure_allocated(&d->revoked_by_rr, &dns_resource_record_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(d->revoked_by_rr, rr);
+ r = set_ensure_put(&d->revoked_by_rr, &dns_resource_record_hash_ops, rr);
if (r < 0)
return r;
if (r > 0)
diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c
index 0ef4c892f7..33879d6142 100644
--- a/src/resolve/resolved-dns-zone.c
+++ b/src/resolve/resolved-dns-zone.c
@@ -162,7 +162,7 @@ static int dns_zone_link_item(DnsZone *z, DnsZoneItem *i) {
}
static int dns_zone_item_probe_start(DnsZoneItem *i) {
- DnsTransaction *t;
+ _cleanup_(dns_transaction_gcp) DnsTransaction *t = NULL;
int r;
assert(i);
@@ -183,25 +183,20 @@ static int dns_zone_item_probe_start(DnsZoneItem *i) {
return r;
}
- r = set_ensure_allocated(&t->notify_zone_items, NULL);
- if (r < 0)
- goto gc;
-
r = set_ensure_allocated(&t->notify_zone_items_done, NULL);
if (r < 0)
- goto gc;
+ return r;
- r = set_put(t->notify_zone_items, i);
+ r = set_ensure_put(&t->notify_zone_items, NULL, i);
if (r < 0)
- goto gc;
+ return r;
- i->probe_transaction = t;
t->probing = true;
+ i->probe_transaction = TAKE_PTR(t);
- if (t->state == DNS_TRANSACTION_NULL) {
-
+ if (i->probe_transaction->state == DNS_TRANSACTION_NULL) {
i->block_ready++;
- r = dns_transaction_go(t);
+ r = dns_transaction_go(i->probe_transaction);
i->block_ready--;
if (r < 0) {
@@ -212,10 +207,6 @@ static int dns_zone_item_probe_start(DnsZoneItem *i) {
dns_zone_item_notify(i);
return 0;
-
-gc:
- dns_transaction_gc(t);
- return r;
}
int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) {
diff --git a/src/resolve/resolved-etc-hosts.c b/src/resolve/resolved-etc-hosts.c
index 2cb06c098d..6a7f749957 100644
--- a/src/resolve/resolved-etc-hosts.c
+++ b/src/resolve/resolved-etc-hosts.c
@@ -120,15 +120,10 @@ static int parse_line(EtcHosts *hosts, unsigned nr, const char *line) {
/* Optimize the case where we don't need to store any addresses, by storing
* only the name in a dedicated Set instead of the hashmap */
- r = set_ensure_allocated(&hosts->no_address, &dns_name_hash_ops);
- if (r < 0)
- return log_oom();
-
- r = set_put(hosts->no_address, name);
+ r = set_ensure_consume(&hosts->no_address, &dns_name_hash_ops, TAKE_PTR(name));
if (r < 0)
return r;
- TAKE_PTR(name);
continue;
}
diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf
index 4a451ccc4c..553da8d251 100644
--- a/src/resolve/resolved-gperf.gperf
+++ b/src/resolve/resolved-gperf.gperf
@@ -18,13 +18,14 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
-Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0
-Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0
-Resolve.Domains, config_parse_search_domains, 0, 0
-Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support)
-Resolve.MulticastDNS, config_parse_resolve_support, 0, offsetof(Manager, mdns_support)
-Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode)
-Resolve.DNSOverTLS, config_parse_dns_over_tls_mode, 0, offsetof(Manager, dns_over_tls_mode)
-Resolve.Cache, config_parse_dns_cache_mode, DNS_CACHE_MODE_YES, offsetof(Manager, enable_cache)
-Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0, offsetof(Manager, dns_stub_listener_mode)
-Resolve.ReadEtcHosts, config_parse_bool, 0, offsetof(Manager, read_etc_hosts)
+Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0
+Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0
+Resolve.Domains, config_parse_search_domains, 0, 0
+Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support)
+Resolve.MulticastDNS, config_parse_resolve_support, 0, offsetof(Manager, mdns_support)
+Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode)
+Resolve.DNSOverTLS, config_parse_dns_over_tls_mode, 0, offsetof(Manager, dns_over_tls_mode)
+Resolve.Cache, config_parse_dns_cache_mode, DNS_CACHE_MODE_YES, offsetof(Manager, enable_cache)
+Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0, offsetof(Manager, dns_stub_listener_mode)
+Resolve.ReadEtcHosts, config_parse_bool, 0, offsetof(Manager, read_etc_hosts)
+Resolve.ResolveUnicastSingleLabel, config_parse_bool, 0, offsetof(Manager, resolve_unicast_single_label)
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
index 6fa5e734bb..59944df746 100644
--- a/src/resolve/resolved-manager.h
+++ b/src/resolve/resolved-manager.h
@@ -70,9 +70,10 @@ struct Manager {
LIST_HEAD(DnsSearchDomain, search_domains);
unsigned n_search_domains;
- bool need_builtin_fallbacks:1;
+ bool need_builtin_fallbacks;
+ bool read_resolv_conf;
+ bool resolve_unicast_single_label;
- bool read_resolv_conf:1;
struct stat resolv_conf_stat;
DnsTrustAnchor trust_anchor;
diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c
index 50989a6b0a..566b950a63 100644
--- a/src/resolve/resolved.c
+++ b/src/resolve/resolved.c
@@ -40,7 +40,7 @@ static int run(int argc, char *argv[]) {
r = mac_selinux_init();
if (r < 0)
- return log_error_errno(r, "SELinux setup failed: %m");
+ return r;
/* Drop privileges, but only if we have been started as root. If we are not running as root we assume most
* privileges are already dropped and we can't create our directory. */
diff --git a/src/resolve/resolved.conf.in b/src/resolve/resolved.conf.in
index 85822e316c..082ad71626 100644
--- a/src/resolve/resolved.conf.in
+++ b/src/resolve/resolved.conf.in
@@ -22,3 +22,4 @@
#Cache=yes
#DNSStubListener=yes
#ReadEtcHosts=yes
+#ResolveUnicastSingleLabel=no
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index 4b1145a6ba..d93d5d6013 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -13,6 +13,7 @@
#include "escape.h"
#include "exec-util.h"
#include "exit-status.h"
+#include "fileio.h"
#include "hexdecoct.h"
#include "hostname-util.h"
#include "in-addr-util.h"
@@ -24,6 +25,7 @@
#include "nsflags.h"
#include "numa-util.h"
#include "parse-util.h"
+#include "path-util.h"
#include "process-util.h"
#include "rlimit-util.h"
#include "securebits-util.h"
@@ -494,18 +496,16 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
if (r < 0)
return bus_log_create_error(r);
return 1;
- } else if (isempty(eq) && STR_IN_SET(field, "DefaultMemoryLow",
- "DefaultMemoryMin",
- "MemoryLow",
- "MemoryMin")) {
- /* We can't use CGROUP_LIMIT_MIN nor CGROUP_LIMIT_MAX to convey the empty assignment
- * so marshall specially as a boolean. */
- r = sd_bus_message_append(m, "(sv)", field, "b", 0);
- if (r < 0)
- return bus_log_create_error(r);
- return 1;
} else if (isempty(eq)) {
- r = sd_bus_message_append(m, "(sv)", field, "t", CGROUP_LIMIT_MAX);
+ uint64_t empty_value = STR_IN_SET(field,
+ "DefaultMemoryLow",
+ "DefaultMemoryMin",
+ "MemoryLow",
+ "MemoryMin") ?
+ CGROUP_LIMIT_MIN :
+ CGROUP_LIMIT_MAX;
+
+ r = sd_bus_message_append(m, "(sv)", field, "t", empty_value);
if (r < 0)
return bus_log_create_error(r);
return 1;
@@ -849,6 +849,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
"ProtectHome",
"SELinuxContext",
"RootImage",
+ "RootVerity",
"RuntimeDirectoryPreserve",
"Personality",
"KeyringMode",
@@ -1415,6 +1416,24 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
return 1;
}
+ if (streq(field, "RootHash")) {
+ _cleanup_free_ void *roothash_decoded = NULL;
+ size_t roothash_decoded_size = 0;
+
+ /* We have the path to a roothash to load and decode, eg: RootHash=/foo/bar.roothash */
+ if (path_is_absolute(eq))
+ return bus_append_string(m, "RootHashPath", eq);
+
+ /* We have a roothash to decode, eg: RootHash=012345789abcdef */
+ r = unhexmem(eq, strlen(eq), &roothash_decoded, &roothash_decoded_size);
+ if (r < 0)
+ return log_error_errno(r, "Failed to decode RootHash= '%s': %m", eq);
+ if (roothash_decoded_size < sizeof(sd_id128_t))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "RootHash= '%s' is too short: %m", eq);
+
+ return bus_append_byte_array(m, field, roothash_decoded, roothash_decoded_size);
+ }
+
return 0;
}
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index a61f8e70da..f64e200731 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -613,13 +613,9 @@ int bus_message_print_all_properties(
return r;
if (found_properties) {
- r = set_ensure_allocated(found_properties, &string_hash_ops);
+ r = set_ensure_put(found_properties, &string_hash_ops, name);
if (r < 0)
return log_oom();
-
- r = set_put(*found_properties, name);
- if (r < 0 && r != -EEXIST)
- return log_oom();
}
name_with_equal = strjoin(name, "=");
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index 2c8a5d85bf..e576518c6b 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -1421,7 +1421,7 @@ int decrypted_image_relinquish(DecryptedImage *d) {
return 0;
}
-int verity_metadata_load(const char *image, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data) {
+int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data) {
_cleanup_free_ char *verity_filename = NULL;
_cleanup_free_ void *roothash_decoded = NULL;
size_t roothash_decoded_size = 0;
@@ -1465,24 +1465,31 @@ int verity_metadata_load(const char *image, void **ret_roothash, size_t *ret_roo
_cleanup_free_ char *text = NULL;
assert(ret_roothash_size);
- r = getxattr_malloc(image, "user.verity.roothash", &text, true);
- if (r < 0) {
- char *fn, *e, *n;
-
- if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT))
+ if (root_hash_path) {
+ /* We have the path to a roothash to load and decode, eg: RootHash=/foo/bar.roothash */
+ r = read_one_line_file(root_hash_path, &text);
+ if (r < 0)
return r;
+ } else {
+ r = getxattr_malloc(image, "user.verity.roothash", &text, true);
+ if (r < 0) {
+ char *fn, *e, *n;
+
+ if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT))
+ return r;
- fn = newa(char, strlen(image) + STRLEN(".roothash") + 1);
- n = stpcpy(fn, image);
- e = endswith(fn, ".raw");
- if (e)
- n = e;
+ fn = newa(char, strlen(image) + STRLEN(".roothash") + 1);
+ n = stpcpy(fn, image);
+ e = endswith(fn, ".raw");
+ if (e)
+ n = e;
- strcpy(n, ".roothash");
+ strcpy(n, ".roothash");
- r = read_one_line_file(fn, &text);
- if (r < 0 && r != -ENOENT)
- return r;
+ r = read_one_line_file(fn, &text);
+ if (r < 0 && r != -ENOENT)
+ return r;
+ }
}
if (text) {
diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h
index 92d223cfec..6a53b94948 100644
--- a/src/shared/dissect-image.h
+++ b/src/shared/dissect-image.h
@@ -100,6 +100,6 @@ int decrypted_image_relinquish(DecryptedImage *d);
const char* partition_designator_to_string(int i) _const_;
int partition_designator_from_string(const char *name) _pure_;
-int verity_metadata_load(const char *image, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data);
+int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data);
bool dissected_image_can_do_verity(const DissectedImage *image, unsigned partition_designator);
bool dissected_image_has_verity(const DissectedImage *image, unsigned partition_designator);
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index 6a3cfe770c..de05fb092c 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -1742,17 +1742,13 @@ int seccomp_restrict_archs(Set *archs) {
return 0;
}
-int parse_syscall_archs(char **l, Set **archs) {
- _cleanup_set_free_ Set *_archs = NULL;
+int parse_syscall_archs(char **l, Set **ret_archs) {
+ _cleanup_set_free_ Set *archs = NULL;
char **s;
int r;
assert(l);
- assert(archs);
-
- r = set_ensure_allocated(&_archs, NULL);
- if (r < 0)
- return r;
+ assert(ret_archs);
STRV_FOREACH(s, l) {
uint32_t a;
@@ -1761,13 +1757,12 @@ int parse_syscall_archs(char **l, Set **archs) {
if (r < 0)
return -EINVAL;
- r = set_put(_archs, UINT32_TO_PTR(a + 1));
+ r = set_ensure_put(&archs, NULL, UINT32_TO_PTR(a + 1));
if (r < 0)
return -ENOMEM;
}
- *archs = TAKE_PTR(_archs);
-
+ *ret_archs = TAKE_PTR(archs);
return 0;
}
diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h
index 0b48e74a87..9580f9268d 100644
--- a/src/shared/seccomp-util.h
+++ b/src/shared/seccomp-util.h
@@ -105,6 +105,6 @@ extern const uint32_t seccomp_local_archs[];
DEFINE_TRIVIAL_CLEANUP_FUNC(scmp_filter_ctx, seccomp_release);
-int parse_syscall_archs(char **l, Set **archs);
+int parse_syscall_archs(char **l, Set **ret_archs);
uint32_t scmp_act_kill_process(void);
diff --git a/src/shared/userdb.c b/src/shared/userdb.c
index c3a6e02e5a..6fedbd6ebe 100644
--- a/src/shared/userdb.c
+++ b/src/shared/userdb.c
@@ -3,6 +3,7 @@
#include <sys/auxv.h>
#include "dirent-util.h"
+#include "dlfcn-util.h"
#include "errno-util.h"
#include "fd-util.h"
#include "group-record-nss.h"
@@ -32,8 +33,8 @@ struct UserDBIterator {
bool nss_iterating:1;
bool synthesize_root:1;
bool synthesize_nobody:1;
+ bool nss_systemd_blocked:1;
int error;
- int nss_lock;
unsigned n_found;
sd_event *event;
UserRecord *found_user; /* when .what == LOOKUP_USER */
@@ -85,7 +86,9 @@ UserDBIterator* userdb_iterator_free(UserDBIterator *iterator) {
}
sd_event_unref(iterator->event);
- safe_close(iterator->nss_lock);
+
+ if (iterator->nss_systemd_blocked)
+ assert_se(userdb_block_nss_systemd(false) >= 0);
return mfree(iterator);
}
@@ -102,12 +105,27 @@ static UserDBIterator* userdb_iterator_new(LookupWhat what) {
*i = (UserDBIterator) {
.what = what,
- .nss_lock = -1,
};
return i;
}
+static int userdb_iterator_block_nss_systemd(UserDBIterator *iterator) {
+ int r;
+
+ assert(iterator);
+
+ if (iterator->nss_systemd_blocked)
+ return 0;
+
+ r = userdb_block_nss_systemd(true);
+ if (r < 0)
+ return r;
+
+ iterator->nss_systemd_blocked = true;
+ return 1;
+}
+
struct user_group_data {
JsonVariant *record;
bool incomplete;
@@ -359,15 +377,9 @@ static int userdb_connect(
if (r < 0)
return log_debug_errno(r, "Failed to invoke varlink method: %m");
- r = set_ensure_allocated(&iterator->links, &link_hash_ops);
- if (r < 0)
- return log_debug_errno(r, "Failed to allocate set: %m");
-
- r = set_put(iterator->links, vl);
+ r = set_ensure_consume(&iterator->links, &link_hash_ops, TAKE_PTR(vl));
if (r < 0)
return log_debug_errno(r, "Failed to add varlink connection to set: %m");
-
- TAKE_PTR(vl);
return r;
}
@@ -606,13 +618,11 @@ int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret) {
return r;
}
- if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && !(iterator && iterator->nss_covered)) {
- /* Make sure the NSS lookup doesn't recurse back to us. (EBUSY is fine here, it just means we
- * already took the lock from our thread, which is totally OK.) */
- r = userdb_nss_compat_disable();
- if (r >= 0 || r == -EBUSY) {
- iterator->nss_lock = r;
+ if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && !iterator->nss_covered) {
+ /* Make sure the NSS lookup doesn't recurse back to us. */
+ r = userdb_iterator_block_nss_systemd(iterator);
+ if (r >= 0) {
/* Client-side NSS fallback */
r = nss_user_record_by_name(name, !FLAGS_SET(flags, USERDB_AVOID_SHADOW), ret);
if (r >= 0)
@@ -655,11 +665,9 @@ int userdb_by_uid(uid_t uid, UserDBFlags flags, UserRecord **ret) {
return r;
}
- if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && !(iterator && iterator->nss_covered)) {
- r = userdb_nss_compat_disable();
- if (r >= 0 || r == -EBUSY) {
- iterator->nss_lock = r;
-
+ if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && !iterator->nss_covered) {
+ r = userdb_iterator_block_nss_systemd(iterator);
+ if (r >= 0) {
/* Client-side NSS fallback */
r = nss_user_record_by_uid(uid, !FLAGS_SET(flags, USERDB_AVOID_SHADOW), ret);
if (r >= 0)
@@ -693,9 +701,9 @@ int userdb_all(UserDBFlags flags, UserDBIterator **ret) {
r = userdb_start_query(iterator, "io.systemd.UserDatabase.GetUserRecord", true, NULL, flags);
if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && (r < 0 || !iterator->nss_covered)) {
- iterator->nss_lock = userdb_nss_compat_disable();
- if (iterator->nss_lock < 0 && iterator->nss_lock != -EBUSY)
- return iterator->nss_lock;
+ r = userdb_iterator_block_nss_systemd(iterator);
+ if (r < 0)
+ return r;
setpwent();
iterator->nss_iterating = true;
@@ -815,10 +823,8 @@ int groupdb_by_name(const char *name, UserDBFlags flags, GroupRecord **ret) {
}
if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && !(iterator && iterator->nss_covered)) {
- r = userdb_nss_compat_disable();
- if (r >= 0 || r == -EBUSY) {
- iterator->nss_lock = r;
-
+ r = userdb_iterator_block_nss_systemd(iterator);
+ if (r >= 0) {
r = nss_group_record_by_name(name, !FLAGS_SET(flags, USERDB_AVOID_SHADOW), ret);
if (r >= 0)
return r;
@@ -861,10 +867,8 @@ int groupdb_by_gid(gid_t gid, UserDBFlags flags, GroupRecord **ret) {
}
if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && !(iterator && iterator->nss_covered)) {
- r = userdb_nss_compat_disable();
- if (r >= 0 || r == -EBUSY) {
- iterator->nss_lock = r;
-
+ r = userdb_iterator_block_nss_systemd(iterator);
+ if (r >= 0) {
r = nss_group_record_by_gid(gid, !FLAGS_SET(flags, USERDB_AVOID_SHADOW), ret);
if (r >= 0)
return r;
@@ -897,9 +901,9 @@ int groupdb_all(UserDBFlags flags, UserDBIterator **ret) {
r = userdb_start_query(iterator, "io.systemd.UserDatabase.GetGroupRecord", true, NULL, flags);
if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && (r < 0 || !iterator->nss_covered)) {
- iterator->nss_lock = userdb_nss_compat_disable();
- if (iterator->nss_lock < 0 && iterator->nss_lock != -EBUSY)
- return iterator->nss_lock;
+ r = userdb_iterator_block_nss_systemd(iterator);
+ if (r < 0)
+ return r;
setgrent();
iterator->nss_iterating = true;
@@ -998,9 +1002,9 @@ int membershipdb_by_user(const char *name, UserDBFlags flags, UserDBIterator **r
if ((r >= 0 && iterator->nss_covered) || FLAGS_SET(flags, USERDB_AVOID_NSS))
goto finish;
- iterator->nss_lock = userdb_nss_compat_disable();
- if (iterator->nss_lock < 0 && iterator->nss_lock != -EBUSY)
- return iterator->nss_lock;
+ r = userdb_iterator_block_nss_systemd(iterator);
+ if (r < 0)
+ return r;
iterator->filter_user_name = strdup(name);
if (!iterator->filter_user_name)
@@ -1041,9 +1045,9 @@ int membershipdb_by_group(const char *name, UserDBFlags flags, UserDBIterator **
if ((r >= 0 && iterator->nss_covered) || FLAGS_SET(flags, USERDB_AVOID_NSS))
goto finish;
- iterator->nss_lock = userdb_nss_compat_disable();
- if (iterator->nss_lock < 0 && iterator->nss_lock != -EBUSY)
- return iterator->nss_lock;
+ r = userdb_iterator_block_nss_systemd(iterator);
+ if (r < 0)
+ return r;
/* We ignore all errors here, since the group might be defined by a userdb native service, and we queried them already above. */
(void) nss_group_record_by_name(name, false, &gr);
@@ -1082,9 +1086,9 @@ int membershipdb_all(UserDBFlags flags, UserDBIterator **ret) {
if ((r >= 0 && iterator->nss_covered) || FLAGS_SET(flags, USERDB_AVOID_NSS))
goto finish;
- iterator->nss_lock = userdb_nss_compat_disable();
- if (iterator->nss_lock < 0 && iterator->nss_lock != -EBUSY)
- return iterator->nss_lock;
+ r = userdb_iterator_block_nss_systemd(iterator);
+ if (r < 0)
+ return r;
setgrent();
iterator->nss_iterating = true;
@@ -1221,115 +1225,24 @@ int membershipdb_by_group_strv(const char *name, UserDBFlags flags, char ***ret)
return 0;
}
-static int userdb_thread_sockaddr(struct sockaddr_un *ret_sa, socklen_t *ret_salen) {
- static const uint8_t
- k1[16] = { 0x35, 0xc1, 0x1f, 0x41, 0x59, 0xc6, 0xa0, 0xf9, 0x33, 0x4b, 0x17, 0x3d, 0xb9, 0xf6, 0x14, 0xd9 },
- k2[16] = { 0x6a, 0x11, 0x4c, 0x37, 0xe5, 0xa3, 0x8c, 0xa6, 0x93, 0x55, 0x64, 0x8c, 0x93, 0xee, 0xa1, 0x7b };
-
- struct siphash sh;
- uint64_t x, y;
- pid_t tid;
- void *p;
-
- assert(ret_sa);
- assert(ret_salen);
-
- /* This calculates an AF_UNIX socket address in the abstract namespace whose existence works as an
- * indicator whether to emulate NSS records for complex user records that are also available via the
- * varlink protocol. The name of the socket is picked in a way so that:
- *
- * → it is per-thread (by hashing from the TID)
- *
- * → is not guessable for foreign processes (by hashing from the — hopefully secret — AT_RANDOM
- * value every process gets passed from the kernel
- *
- * By using a socket the NSS emulation can be nicely turned off for limited amounts of time only,
- * simply controlled by the lifetime of the fd itself. By using an AF_UNIX socket in the abstract
- * namespace the lock is automatically cleaned up when the process dies abnormally.
- *
- */
-
- p = ULONG_TO_PTR(getauxval(AT_RANDOM));
- if (!p)
- return -EIO;
-
- tid = gettid();
-
- siphash24_init(&sh, k1);
- siphash24_compress(p, 16, &sh);
- siphash24_compress(&tid, sizeof(tid), &sh);
- x = siphash24_finalize(&sh);
-
- siphash24_init(&sh, k2);
- siphash24_compress(p, 16, &sh);
- siphash24_compress(&tid, sizeof(tid), &sh);
- y = siphash24_finalize(&sh);
-
- *ret_sa = (struct sockaddr_un) {
- .sun_family = AF_UNIX,
- };
-
- sprintf(ret_sa->sun_path + 1, "userdb-%016" PRIx64 "%016" PRIx64, x, y);
- *ret_salen = offsetof(struct sockaddr_un, sun_path) + 1 + 7 + 32;
-
- return 0;
-}
-
-int userdb_nss_compat_is_enabled(void) {
- _cleanup_close_ int fd = -1;
- union sockaddr_union sa;
- socklen_t salen;
- int r;
-
- /* Tests whether the NSS compatibility logic is currently turned on for the invoking thread. Returns
- * true if NSS compatibility is turned on, i.e. whether NSS records shall be synthesized from complex
- * user records. */
-
- r = userdb_thread_sockaddr(&sa.un, &salen);
- if (r < 0)
- return r;
-
- fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
- if (fd < 0)
- return -errno;
+int userdb_block_nss_systemd(int b) {
+ _cleanup_(dlclosep) void *dl = NULL;
+ int (*call)(bool b);
- /* Try to connect(). This doesn't do anything really, except that it checks whether the socket
- * address is bound at all. */
- if (connect(fd, &sa.sa, salen) < 0) {
- if (errno == ECONNREFUSED) /* the socket is not bound, hence NSS emulation shall be done */
- return true;
+ /* Note that we might be called from libnss_systemd.so.2 itself, but that should be fine, really. */
- return -errno;
+ dl = dlopen(ROOTLIBDIR "libnss_systemd.so.2", RTLD_LAZY|RTLD_NODELETE);
+ if (!dl) {
+ /* If the file isn't installed, don't complain loudly */
+ log_debug("Failed to dlopen(libnss_systemd.so.2), ignoring: %s", dlerror());
+ return 0;
}
- return false;
-}
-
-int userdb_nss_compat_disable(void) {
- _cleanup_close_ int fd = -1;
- union sockaddr_union sa;
- socklen_t salen;
- int r;
-
- /* Turn off the NSS compatibility logic for the invoking thread. By default NSS records are
- * synthesized for all complex user records looked up via NSS. If this call is invoked this is
- * disabled for the invoking thread, but only for it. A caller that natively supports the varlink
- * user record protocol may use that to turn off the compatibility for NSS lookups. */
-
- r = userdb_thread_sockaddr(&sa.un, &salen);
- if (r < 0)
- return r;
-
- fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (fd < 0)
- return -errno;
-
- if (bind(fd, &sa.sa, salen) < 0) {
- if (errno == EADDRINUSE) /* lock already taken, convert this into a recognizable error */
- return -EBUSY;
-
- return -errno;
- }
+ call = (int (*)(bool b)) dlsym(dl, "_nss_systemd_block");
+ if (!call)
+ /* If the file is is installed but lacks the symbol we expect, things are weird, let's complain */
+ return log_debug_errno(SYNTHETIC_ERRNO(ELIBBAD),
+ "Unable to find symbol _nss_systemd_block in libnss_systemd.so.2: %s", dlerror());
- return TAKE_FD(fd);
+ return call(b);
}
diff --git a/src/shared/userdb.h b/src/shared/userdb.h
index 8af31aa86c..2464f54c3e 100644
--- a/src/shared/userdb.h
+++ b/src/shared/userdb.h
@@ -38,5 +38,4 @@ int membershipdb_all(UserDBFlags flags, UserDBIterator **ret);
int membershipdb_iterator_get(UserDBIterator *iterator, char **user, char **group);
int membershipdb_by_group_strv(const char *name, UserDBFlags flags, char ***ret);
-int userdb_nss_compat_is_enabled(void);
-int userdb_nss_compat_disable(void);
+int userdb_block_nss_systemd(int b);
diff --git a/src/shared/wifi-util.c b/src/shared/wifi-util.c
index 2717db6507..22bb3041fb 100644
--- a/src/shared/wifi-util.c
+++ b/src/shared/wifi-util.c
@@ -14,6 +14,9 @@ int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftyp
sd_genl_family family;
int r;
+ assert(genl);
+ assert(ifindex > 0);
+
r = sd_genl_message_new(genl, SD_GENL_NL80211, NL80211_CMD_GET_INTERFACE, &m);
if (r < 0)
return log_debug_errno(r, "Failed to create generic netlink message: %m");
@@ -23,10 +26,17 @@ int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftyp
return log_debug_errno(r, "Could not append NL80211_ATTR_IFINDEX attribute: %m");
r = sd_netlink_call(genl, m, 0, &reply);
+ if (r == -ENODEV) {
+ /* For obsolete WEXT driver. */
+ log_debug_errno(r, "Failed to request information about wifi interface %d. "
+ "The device doesn't seem to have nl80211 interface. Ignoring.",
+ ifindex);
+ goto nodata;
+ }
if (r < 0)
return log_debug_errno(r, "Failed to request information about wifi interface %d: %m", ifindex);
if (!reply)
- return 0;
+ goto nodata;
r = sd_netlink_message_get_errno(reply);
if (r < 0)
@@ -37,7 +47,7 @@ int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftyp
return log_debug_errno(r, "Failed to determine genl family: %m");
if (family != SD_GENL_NL80211) {
log_debug("Received message of unexpected genl family %u, ignoring.", family);
- return 0;
+ goto nodata;
}
if (iftype) {
@@ -51,11 +61,20 @@ int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftyp
if (ssid) {
r = sd_netlink_message_read_string_strdup(reply, NL80211_ATTR_SSID, ssid);
- if (r < 0 && r != -ENODATA)
+ if (r == -ENODATA)
+ goto nodata;
+ if (r < 0)
return log_debug_errno(r, "Failed to get NL80211_ATTR_SSID attribute: %m");
}
- return r == -ENODATA ? 0 : 1;
+ return 1;
+
+nodata:
+ if (iftype)
+ *iftype = 0;
+ if (ssid)
+ *ssid = NULL;
+ return 0;
}
int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
@@ -63,6 +82,10 @@ int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
sd_genl_family family;
int r;
+ assert(genl);
+ assert(ifindex > 0);
+ assert(bssid);
+
r = sd_genl_message_new(genl, SD_GENL_NL80211, NL80211_CMD_GET_STATION, &m);
if (r < 0)
return log_debug_errno(r, "Failed to create generic netlink message: %m");
@@ -79,7 +102,7 @@ int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
if (r < 0)
return log_debug_errno(r, "Failed to request information about wifi station: %m");
if (!reply)
- return 0;
+ goto nodata;
r = sd_netlink_message_get_errno(reply);
if (r < 0)
@@ -90,12 +113,18 @@ int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
return log_debug_errno(r, "Failed to determine genl family: %m");
if (family != SD_GENL_NL80211) {
log_debug("Received message of unexpected genl family %u, ignoring.", family);
- return 0;
+ goto nodata;
}
r = sd_netlink_message_read_ether_addr(reply, NL80211_ATTR_MAC, bssid);
- if (r < 0 && r != -ENODATA)
+ if (r == -ENODATA)
+ goto nodata;
+ if (r < 0)
return log_debug_errno(r, "Failed to get NL80211_ATTR_MAC attribute: %m");
- return r == -ENODATA ? 0 : 1;
+ return 1;
+
+nodata:
+ *bssid = (struct ether_addr) {};
+ return 0;
}
diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c
index 7b548c5076..b461aead60 100644
--- a/src/socket-proxy/socket-proxyd.c
+++ b/src/socket-proxy/socket-proxyd.c
@@ -480,25 +480,21 @@ static int add_connection_socket(Context *context, int fd) {
log_warning_errno(r, "Unable to disable idle timer, continuing: %m");
}
- r = set_ensure_allocated(&context->connections, NULL);
- if (r < 0) {
- log_oom();
- return 0;
- }
-
- c = new0(Connection, 1);
+ c = new(Connection, 1);
if (!c) {
log_oom();
return 0;
}
- c->context = context;
- c->server_fd = fd;
- c->client_fd = -1;
- c->server_to_client_buffer[0] = c->server_to_client_buffer[1] = -1;
- c->client_to_server_buffer[0] = c->client_to_server_buffer[1] = -1;
+ *c = (Connection) {
+ .context = context,
+ .server_fd = fd,
+ .client_fd = -1,
+ .server_to_client_buffer = {-1, -1},
+ .client_to_server_buffer = {-1, -1},
+ };
- r = set_put(context->connections, c);
+ r = set_ensure_put(&context->connections, NULL, c);
if (r < 0) {
free(c);
log_oom();
@@ -550,12 +546,6 @@ static int add_listen_socket(Context *context, int fd) {
assert(context);
assert(fd >= 0);
- r = set_ensure_allocated(&context->listen, NULL);
- if (r < 0) {
- log_oom();
- return r;
- }
-
r = sd_is_socket(fd, 0, SOCK_STREAM, 1);
if (r < 0)
return log_error_errno(r, "Failed to determine socket type: %m");
@@ -571,7 +561,7 @@ static int add_listen_socket(Context *context, int fd) {
if (r < 0)
return log_error_errno(r, "Failed to add event source: %m");
- r = set_put(context->listen, source);
+ r = set_ensure_put(&context->listen, NULL, source);
if (r < 0) {
log_error_errno(r, "Failed to add source to set: %m");
sd_event_source_unref(source);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index ad7400bacc..681992b7e5 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -9207,7 +9207,7 @@ static int run(int argc, char *argv[]) {
int r;
setlocale(LC_ALL, "");
- log_parse_environment();
+ log_parse_environment_cli();
log_open();
/* The journal merging logic potentially needs a lot of fds. */
diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h
index 2e15a6b181..b6a5e9db84 100644
--- a/src/systemd/sd-dhcp-server.h
+++ b/src/systemd/sd-dhcp-server.h
@@ -68,8 +68,8 @@ int sd_dhcp_server_set_lpr(sd_dhcp_server *server, const struct in_addr lpr[], s
int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], size_t n);
int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], size_t n);
int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], size_t n);
-int sd_dhcp_server_set_pop3(sd_dhcp_server *server, const struct in_addr pop3_server[], size_t n);
-int sd_dhcp_server_set_smtp(sd_dhcp_server *server, const struct in_addr smtp_server[], size_t n);
+int sd_dhcp_server_set_pop3(sd_dhcp_server *server, const struct in_addr pop3[], size_t n);
+int sd_dhcp_server_set_smtp(sd_dhcp_server *server, const struct in_addr smtp[], size_t n);
int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v);
int sd_dhcp_server_add_vendor_option(sd_dhcp_server *server, sd_dhcp_option *v);
diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h
index 7e42df17b9..42bcd74b74 100644
--- a/src/systemd/sd-network.h
+++ b/src/systemd/sd-network.h
@@ -110,10 +110,6 @@ int sd_network_link_get_network_file(int ifindex, char **filename);
* IP addresses */
int sd_network_link_get_dns(int ifindex, char ***ret);
-/* Get DHCP4 address for a given link. This is string representations of
- * IPv4 address */
-int sd_network_link_get_dhcp4_address(int ifindex, char **ret);
-
/* Get NTP entries for a given link. These are domain names or string
* representations of IP addresses */
int sd_network_link_get_ntp(int ifindex, char ***ret);
@@ -164,18 +160,6 @@ int sd_network_link_get_search_domains(int ifindex, char ***domains);
/* Get the route DNS domain names for a given link. */
int sd_network_link_get_route_domains(int ifindex, char ***domains);
-/* Get the sip servers for a given link. */
-int sd_network_link_get_sip_servers(int ifindex, char ***sip);
-
-/* Get the pop3 servers for a given link. */
-int sd_network_link_get_pop3_servers(int ifindex, char ***pop3);
-
-/* Get the SMTP servers for a given link. */
-int sd_network_link_get_smtp_servers(int ifindex, char ***smtp);
-
-/* Get the LPR servers for a given link. */
-int sd_network_link_get_lpr_servers(int ifindex, char ***lpr);
-
/* Get whether this link shall be used as 'default route' for DNS queries */
int sd_network_link_get_dns_default_route(int ifindex);
@@ -185,12 +169,6 @@ int sd_network_link_get_carrier_bound_to(int ifindex, int **ifindexes);
/* Get the CARRIERS that are bound to current link. */
int sd_network_link_get_carrier_bound_by(int ifindex, int **ifindexes);
-/* Get the timezone that was learnt on a specific link. */
-int sd_network_link_get_timezone(int ifindex, char **timezone);
-
-/* Get DHCPv4 client id for a given link. */
-int sd_network_link_get_dhcp4_client_id_string(int ifindex, char **client_id);
-
/* Get DHCPv6 client IAID for a given link. */
int sd_network_link_get_dhcp6_client_iaid_string(int ifindex, char **iaid);
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 6fbd5985d3..b5e7e08eee 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -1898,7 +1898,7 @@ static int run(int argc, char *argv[]) {
r = mac_selinux_init();
if (r < 0)
- return log_error_errno(r, "SELinux setup failed: %m");
+ return r;
/* If command line arguments are specified along with --replace, read all
* configuration files and insert the positional arguments at the specified
diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
index eb6b2d084e..a2c72d1009 100644
--- a/src/sysv-generator/sysv-generator.c
+++ b/src/sysv-generator/sysv-generator.c
@@ -817,7 +817,6 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic
Set *runlevel_services[ELEMENTSOF(rcnd_table)] = {};
_cleanup_strv_free_ char **sysvrcnd_path = NULL;
SysvStub *service;
- unsigned i;
Iterator j;
char **p;
int r;
@@ -828,9 +827,8 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic
if (r < 0)
return r;
- STRV_FOREACH(p, sysvrcnd_path) {
- for (i = 0; i < ELEMENTSOF(rcnd_table); i ++) {
-
+ STRV_FOREACH(p, sysvrcnd_path)
+ for (unsigned i = 0; i < ELEMENTSOF(rcnd_table); i ++) {
_cleanup_closedir_ DIR *d = NULL;
_cleanup_free_ char *path = NULL;
struct dirent *de;
@@ -885,22 +883,15 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic
service->sysv_start_priority = MAX(a*10 + b, service->sysv_start_priority);
- r = set_ensure_allocated(&runlevel_services[i], NULL);
- if (r < 0) {
- log_oom();
- goto finish;
- }
-
- r = set_put(runlevel_services[i], service);
+ r = set_ensure_put(&runlevel_services[i], NULL, service);
if (r < 0) {
log_oom();
goto finish;
}
}
}
- }
- for (i = 0; i < ELEMENTSOF(rcnd_table); i ++)
+ for (unsigned i = 0; i < ELEMENTSOF(rcnd_table); i++)
SET_FOREACH(service, runlevel_services[i], j) {
r = strv_extend(&service->before, rcnd_table[i].target);
if (r < 0) {
@@ -917,7 +908,7 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic
r = 0;
finish:
- for (i = 0; i < ELEMENTSOF(rcnd_table); i++)
+ for (unsigned i = 0; i < ELEMENTSOF(rcnd_table); i++)
set_free(runlevel_services[i]);
return r;
diff --git a/src/test/test-chase-symlinks.c b/src/test/test-chase-symlinks.c
index 0b7dd8764f..f7b3dd5e00 100644
--- a/src/test/test-chase-symlinks.c
+++ b/src/test/test-chase-symlinks.c
@@ -84,9 +84,7 @@ static int parse_argv(int argc, char *argv[]) {
static int run(int argc, char **argv) {
int r;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c
index f2bfc6c62b..d0b4ec2764 100644
--- a/src/test/test-namespace.c
+++ b/src/test/test-namespace.c
@@ -152,6 +152,10 @@ static void test_protect_kernel_logs(void) {
PROTECT_HOME_NO,
PROTECT_SYSTEM_NO,
0,
+ NULL,
+ 0,
+ NULL,
+ NULL,
0,
NULL);
assert_se(r == 0);
diff --git a/src/test/test-ns.c b/src/test/test-ns.c
index cf8b08ba9b..ba2c2ed53b 100644
--- a/src/test/test-ns.c
+++ b/src/test/test-ns.c
@@ -76,6 +76,10 @@ int main(int argc, char *argv[]) {
PROTECT_HOME_NO,
PROTECT_SYSTEM_NO,
0,
+ NULL,
+ 0,
+ NULL,
+ NULL,
0,
NULL);
if (r < 0) {
diff --git a/src/test/test-set.c b/src/test/test-set.c
index 9c93685dbc..d3e6de7978 100644
--- a/src/test/test-set.c
+++ b/src/test/test-set.c
@@ -107,6 +107,49 @@ static void test_set_put_strdupv(void) {
assert_se(set_size(m) == 3);
}
+static void test_set_ensure_allocated(void) {
+ _cleanup_set_free_ Set *m = NULL;
+
+ assert_se(set_ensure_allocated(&m, &string_hash_ops) == 1);
+ assert_se(set_ensure_allocated(&m, &string_hash_ops) == 0);
+ assert_se(set_ensure_allocated(&m, NULL) == 0);
+ assert_se(set_size(m) == 0);
+}
+
+static void test_set_ensure_put(void) {
+ _cleanup_set_free_ Set *m = NULL;
+
+ assert_se(set_ensure_put(&m, &string_hash_ops, "a") == 1);
+ assert_se(set_ensure_put(&m, &string_hash_ops, "a") == 0);
+ assert_se(set_ensure_put(&m, NULL, "a") == 0);
+ assert_se(set_ensure_put(&m, &string_hash_ops, "b") == 1);
+ assert_se(set_ensure_put(&m, &string_hash_ops, "b") == 0);
+ assert_se(set_ensure_put(&m, &string_hash_ops, "a") == 0);
+ assert_se(set_size(m) == 2);
+}
+
+static void test_set_ensure_consume(void) {
+ _cleanup_set_free_ Set *m = NULL;
+ char *s, *t;
+
+ assert_se(s = strdup("a"));
+ assert_se(set_ensure_consume(&m, &string_hash_ops_free, s) == 1);
+
+ assert_se(t = strdup("a"));
+ assert_se(set_ensure_consume(&m, &string_hash_ops_free, t) == 0);
+
+ assert_se(t = strdup("a"));
+ assert_se(set_ensure_consume(&m, &string_hash_ops_free, t) == 0);
+
+ assert_se(t = strdup("b"));
+ assert_se(set_ensure_consume(&m, &string_hash_ops_free, t) == 1);
+
+ assert_se(t = strdup("b"));
+ assert_se(set_ensure_consume(&m, &string_hash_ops_free, t) == 0);
+
+ assert_se(set_size(m) == 2);
+}
+
int main(int argc, const char *argv[]) {
test_set_steal_first();
test_set_free_with_destructor();
@@ -114,6 +157,9 @@ int main(int argc, const char *argv[]) {
test_set_put();
test_set_put_strdup();
test_set_put_strdupv();
+ test_set_ensure_allocated();
+ test_set_ensure_put();
+ test_set_ensure_consume();
return 0;
}
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index 3f34a91a7e..285eba802b 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -1052,9 +1052,7 @@ static int run(int argc, char *argv[]) {
int r;
setlocale(LC_ALL, "");
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index da59dd3314..afe593ff64 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -377,7 +377,10 @@ static int context_write_data_local_rtc(Context *c) {
}
}
- mac_selinux_init();
+ r = mac_selinux_init();
+ if (r < 0)
+ return r;
+
return write_string_file_atomic_label("/etc/adjtime", w);
}
diff --git a/src/tmpfiles/meson.build b/src/tmpfiles/meson.build
new file mode 100644
index 0000000000..2f8fb29bd9
--- /dev/null
+++ b/src/tmpfiles/meson.build
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+systemd_tmpfiles_sources = [
+ 'src/tmpfiles/tmpfiles.c',
+ 'src/tmpfiles/offline-passwd.c',
+ 'src/tmpfiles/offline-passwd.h',
+]
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index e827de1b06..7ad6f13b66 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -3196,11 +3196,7 @@ static int link_parent(ItemArray *a) {
if (!j)
j = ordered_hashmap_get(globs, prefix);
if (j) {
- r = set_ensure_allocated(&j->children, NULL);
- if (r < 0)
- return log_oom();
-
- r = set_put(j->children, a);
+ r = set_ensure_put(&j->children, NULL, a);
if (r < 0)
return log_oom();
@@ -3262,7 +3258,9 @@ static int run(int argc, char *argv[]) {
umask(0022);
- mac_selinux_init();
+ r = mac_selinux_init();
+ if (r < 0)
+ return r;
items = ordered_hashmap_new(&item_array_hash_ops);
globs = ordered_hashmap_new(&item_array_hash_ops);
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index e1c3e430ea..b468ce9c03 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -370,7 +370,7 @@ static ssize_t udev_event_subst_format(
}
case FORMAT_SUBST_PARENT:
r = sd_device_get_parent(dev, &parent);
- if (r == -ENODEV)
+ if (r == -ENOENT)
goto null_terminate;
if (r < 0)
return r;
@@ -437,9 +437,9 @@ null_terminate:
return 0;
}
-ssize_t udev_event_apply_format(UdevEvent *event,
- const char *src, char *dest, size_t size,
- bool replace_whitespace) {
+size_t udev_event_apply_format(UdevEvent *event,
+ const char *src, char *dest, size_t size,
+ bool replace_whitespace) {
const char *s = src;
int r;
@@ -455,9 +455,10 @@ ssize_t udev_event_apply_format(UdevEvent *event,
ssize_t subst_len;
r = get_subst_type(&s, false, &type, attr);
- if (r < 0)
- return log_device_warning_errno(event->dev, r, "Invalid format string, ignoring: %s", src);
- if (r == 0) {
+ if (r < 0) {
+ log_device_warning_errno(event->dev, r, "Invalid format string, ignoring: %s", src);
+ break;
+ } else if (r == 0) {
if (size < 2) /* need space for this char and the terminating NUL */
break;
*dest++ = *s++;
@@ -466,10 +467,12 @@ ssize_t udev_event_apply_format(UdevEvent *event,
}
subst_len = udev_event_subst_format(event, type, attr, dest, size);
- if (subst_len < 0)
- return log_device_warning_errno(event->dev, subst_len,
- "Failed to substitute variable '$%s' or apply format '%%%c', ignoring: %m",
- format_type_to_string(type), format_type_to_char(type));
+ if (subst_len < 0) {
+ log_device_warning_errno(event->dev, subst_len,
+ "Failed to substitute variable '$%s' or apply format '%%%c', ignoring: %m",
+ format_type_to_string(type), format_type_to_char(type));
+ break;
+ }
/* FORMAT_SUBST_RESULT handles spaces itself */
if (replace_whitespace && type != FORMAT_SUBST_RESULT)
diff --git a/src/udev/udev-event.h b/src/udev/udev-event.h
index a78cea440d..a0193ffef3 100644
--- a/src/udev/udev-event.h
+++ b/src/udev/udev-event.h
@@ -48,9 +48,9 @@ UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rt
UdevEvent *udev_event_free(UdevEvent *event);
DEFINE_TRIVIAL_CLEANUP_FUNC(UdevEvent*, udev_event_free);
-ssize_t udev_event_apply_format(UdevEvent *event,
- const char *src, char *dest, size_t size,
- bool replace_whitespace);
+size_t udev_event_apply_format(UdevEvent *event,
+ const char *src, char *dest, size_t size,
+ bool replace_whitespace);
int udev_check_format(const char *value, size_t *offset, const char **hint);
int udev_event_spawn(UdevEvent *event,
usec_t timeout_usec,
diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c
index 2ca98a729f..8cd8ed1a1e 100644
--- a/src/udev/udevadm-monitor.c
+++ b/src/udev/udevadm-monitor.c
@@ -169,24 +169,13 @@ static int parse_argv(int argc, char *argv[]) {
subsystem = devtype = NULL;
break;
}
- case 't': {
- _cleanup_free_ char *tag = NULL;
-
- r = set_ensure_allocated(&arg_tag_filter, &string_hash_ops);
+ case 't':
+ /* optarg is stored in argv[], so we don't need to copy it */
+ r = set_ensure_put(&arg_tag_filter, &string_hash_ops, optarg);
if (r < 0)
return r;
-
- tag = strdup(optarg);
- if (!tag)
- return -ENOMEM;
-
- r = set_put(arg_tag_filter, tag);
- if (r < 0)
- return r;
-
- tag = NULL;
break;
- }
+
case 'V':
return print_version();
case 'h':
@@ -260,7 +249,7 @@ int monitor_main(int argc, char *argv[], void *userdata) {
finalize:
hashmap_free_free_free(arg_subsystem_filter);
- set_free_free(arg_tag_filter);
+ set_free(arg_tag_filter);
return r;
}
diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
index 8b34809899..3f8bdc2812 100644
--- a/src/udev/udevadm-test.c
+++ b/src/udev/udevadm-test.c
@@ -151,7 +151,7 @@ int test_main(int argc, char *argv[], void *userdata) {
ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) {
char program[UTIL_PATH_SIZE];
- udev_event_apply_format(event, cmd, program, sizeof(program), false);
+ (void) udev_event_apply_format(event, cmd, program, sizeof(program), false);
printf("run: '%s'\n", program);
}
diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
index f1115bff7a..e476f88f00 100644
--- a/src/udev/udevadm.c
+++ b/src/udev/udevadm.c
@@ -124,7 +124,10 @@ static int run(int argc, char *argv[]) {
log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level());
- mac_selinux_init();
+ r = mac_selinux_init();
+ if (r < 0)
+ return r;
+
return udevadm_main(argc, argv);
}
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index d86c1484c3..8db19e4f89 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -1863,7 +1863,7 @@ int run_udevd(int argc, char *argv[]) {
r = mac_selinux_init();
if (r < 0)
- return log_error_errno(r, "Could not initialize labelling: %m");
+ return r;
r = mkdir_errno_wrapper("/run/udev", 0755);
if (r < 0 && r != -EEXIST)
diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c
index bbd14165d5..c001802dc9 100644
--- a/src/update-done/update-done.c
+++ b/src/update-done/update-done.c
@@ -49,10 +49,8 @@ int main(int argc, char *argv[]) {
}
r = mac_selinux_init();
- if (r < 0) {
- log_error_errno(r, "SELinux setup failed: %m");
+ if (r < 0)
return EXIT_FAILURE;
- }
r = apply_timestamp("/etc/.updated", &st.st_mtim);
q = apply_timestamp("/var/.updated", &st.st_mtim);
diff --git a/src/user-sessions/user-sessions.c b/src/user-sessions/user-sessions.c
index c241429517..cd92b696c0 100644
--- a/src/user-sessions/user-sessions.c
+++ b/src/user-sessions/user-sessions.c
@@ -25,7 +25,9 @@ static int run(int argc, char *argv[]) {
umask(0022);
- mac_selinux_init();
+ r = mac_selinux_init();
+ if (r < 0)
+ return r;
if (streq(argv[1], "start")) {
r = unlink_or_warn("/run/nologin");
diff --git a/src/userdb/userdbctl.c b/src/userdb/userdbctl.c
index 4b5eb34ca6..648eacd023 100644
--- a/src/userdb/userdbctl.c
+++ b/src/userdb/userdbctl.c
@@ -761,9 +761,7 @@ static int run(int argc, char *argv[]) {
int r;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup_cli();
r = parse_argv(argc, argv);
if (r <= 0)
diff --git a/src/userdb/userwork.c b/src/userdb/userwork.c
index 732063f6c7..d7202099be 100644
--- a/src/userdb/userwork.c
+++ b/src/userdb/userwork.c
@@ -660,7 +660,6 @@ static int process_connection(VarlinkServer *server, int fd) {
static int run(int argc, char *argv[]) {
usec_t start_time, listen_idle_usec, last_busy_usec = USEC_INFINITY;
_cleanup_(varlink_server_unrefp) VarlinkServer *server = NULL;
- _cleanup_close_ int lock = -1;
unsigned n_iterations = 0;
int m, listen_fd, r;
@@ -697,8 +696,8 @@ static int run(int argc, char *argv[]) {
return log_error_errno(r, "Failed to parse USERDB_FIXED_WORKER: %m");
listen_idle_usec = r ? USEC_INFINITY : LISTEN_IDLE_USEC;
- lock = userdb_nss_compat_disable();
- if (lock < 0)
+ r = userdb_block_nss_systemd(true);
+ if (r < 0)
return log_error_errno(r, "Failed to disable userdb NSS compatibility: %m");
start_time = now(CLOCK_MONOTONIC);
diff --git a/src/xdg-autostart-generator/xdg-autostart-service.c b/src/xdg-autostart-generator/xdg-autostart-service.c
index 6d10d7052b..0d33c70401 100644
--- a/src/xdg-autostart-generator/xdg-autostart-service.c
+++ b/src/xdg-autostart-generator/xdg-autostart-service.c
@@ -496,7 +496,7 @@ int xdg_autostart_service_generate_unit(
/* Nothing to do if type is not Application. */
if (!streq_ptr(service->type, "Application")) {
- log_info("Not generating service for XDG autostart %s, it is hidden.", service->name);
+ log_info("Not generating service for XDG autostart %s, only Type=Application is supported.", service->name);
return 0;
}
@@ -527,8 +527,9 @@ int xdg_autostart_service_generate_unit(
return 0;
}
- if (streq_ptr(service->gnome_autostart_phase, "EarlyInitialization")) {
- log_info("Not generating service for XDG autostart %s, EarlyInitialization needs to be handled separately.",
+ if (service->gnome_autostart_phase) {
+ /* There is no explicit value for the "Application" phase. */
+ log_info("Not generating service for XDG autostart %s, startup phases are not supported.",
service->name);
return 0;
}
@@ -563,10 +564,7 @@ int xdg_autostart_service_generate_unit(
fprintf(f, "Description=%s\n", t);
}
- /* Only start after the session is ready.
- * XXX: GNOME has an autostart order which we may want to support.
- * It is not clear how this can be implemented reliably, which
- * is why it is skipped for now. */
+ /* Only start after the session is ready. */
fprintf(f,
"After=graphical-session.target\n");
diff --git a/test/TEST-21-SYSUSERS/test.sh b/test/TEST-21-SYSUSERS/test.sh
index 527db85b07..2992beaa0b 100755
--- a/test/TEST-21-SYSUSERS/test.sh
+++ b/test/TEST-21-SYSUSERS/test.sh
@@ -115,9 +115,7 @@ test_run() {
echo "*** Running test $f"
prepare_testdir ${f%.input}
cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
- systemd-sysusers --root=$TESTDIR 2> /dev/null
- journalctl --sync
- journalctl -t systemd-sysusers -o cat | tail -n1 > $TESTDIR/tmp/err
+ systemd-sysusers --root=$TESTDIR 2>&1 | tail -n1 > $TESTDIR/tmp/err
if ! diff -u $TESTDIR/tmp/err ${f%.*}.expected-err; then
echo "**** Unexpected error output for $f"
cat $TESTDIR/tmp/err
diff --git a/test/TEST-52-HONORFIRSTSHUTDOWN/Makefile b/test/TEST-52-HONORFIRSTSHUTDOWN/Makefile
new file mode 100644
index 0000000000..a48af97793
--- /dev/null
+++ b/test/TEST-52-HONORFIRSTSHUTDOWN/Makefile
@@ -0,0 +1,16 @@
+BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
+
+all setup run clean clean-again:
+ @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
+
+# finish option is used to run checks that can only be run outside of
+# the test execution. Example case, honor first shutdown, proof is obtained
+# from the console output as the image shuts down. This does not show up in
+# the journal so the output from the do_test is captured in a file in /tmp.
+# Without the use of finish the test will still pass because if it fails
+# the test will loop and will be terminated via a command timeout.
+# This just provides concrete confirmation.
+finish:
+ @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./fini.sh --$@
+
+.PHONY: all setup run clean clean-again
diff --git a/test/TEST-52-HONORFIRSTSHUTDOWN/fini.sh b/test/TEST-52-HONORFIRSTSHUTDOWN/fini.sh
new file mode 100755
index 0000000000..993ada020e
--- /dev/null
+++ b/test/TEST-52-HONORFIRSTSHUTDOWN/fini.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+TEST_DESCRIPTION="test honor first shutdown"
+
+if grep -q "Shutdown is already active. Skipping emergency action request" /tmp/honorfirstshutdown.log; then
+ echo "$TEST_DESCRIPTION [pass]"
+ exit 0
+else
+ echo "$TEST_DESCRIPTION [fail]"
+ exit 1
+fi
diff --git a/test/TEST-52-HONORFIRSTSHUTDOWN/test.sh b/test/TEST-52-HONORFIRSTSHUTDOWN/test.sh
new file mode 100755
index 0000000000..a0848ef672
--- /dev/null
+++ b/test/TEST-52-HONORFIRSTSHUTDOWN/test.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+set -e
+. $TEST_BASE_DIR/test-functions
+TEST_REQUIRE_INSTALL_TESTS=0
+TEST_DESCRIPTION="testing honor first shutdown"
+#INTERACTIVE_DEBUG=1
+TEST_NO_QEMU=1
+
+#Using timeout because if the test fails it can loop.
+# The reason is because the poweroff executed by end.service
+# could turn into a reboot if the test fails.
+NSPAWN_TIMEOUT=20
+
+#Remove this file if it exists. this is used along with
+# the make target "finish". Since concrete confirmaion is
+# only found from the console during the poweroff.
+rm -f /tmp/honorfirstshutdown.log >/dev/null
+
+do_test "$@" 52 > /tmp/honorfirstshutdown.log
diff --git a/test/fuzz/fuzz-bus-message/zero-offset-to-null-pointer b/test/fuzz/fuzz-bus-message/zero-offset-to-null-pointer
new file mode 100644
index 0000000000..c1380441ed
--- /dev/null
+++ b/test/fuzz/fuzz-bus-message/zero-offset-to-null-pointer
Binary files differ
diff --git a/test/fuzz/fuzz-netdev-parser/wireguard-duplicated-endpoint b/test/fuzz/fuzz-netdev-parser/wireguard-duplicated-endpoint
new file mode 100644
index 0000000000..adff4c186b
--- /dev/null
+++ b/test/fuzz/fuzz-netdev-parser/wireguard-duplicated-endpoint
@@ -0,0 +1,6 @@
+[NetDev]
+Name=w
+Kind=wireguard
+[WireGuardPeer]
+Endpoint=:0
+Endpoint=:8 \ No newline at end of file
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index 40b936e9dc..562d244ba7 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -289,9 +289,12 @@ EmitDNS=
NTP=
EmitSIP=
SIP=
-POP3Servers=
-SMTPServers=
-LPRServers=
+EmitPOP3=
+POP3=
+EmitSMTP=
+SMTP=
+EmitLPR=
+LPR=
EmitRouter=
MaxLeaseTimeSec=
DefaultLeaseTimeSec=
@@ -434,6 +437,13 @@ Handle=
Parent=
ClassId=
Quantum=
+[EnhancedTransmissionSelection]
+Parent=
+Handle=
+Bands=
+StrictBands=
+QuantumBytes=
+PriorityMap=
[HeavyHitterFilter]
Parent=
Handle=
diff --git a/test/fuzz/fuzz-network-parser/dns-trust-anchor-duplicate.network b/test/fuzz/fuzz-network-parser/dns-trust-anchor-duplicate.network
new file mode 100644
index 0000000000..ed7bdabfd1
--- /dev/null
+++ b/test/fuzz/fuzz-network-parser/dns-trust-anchor-duplicate.network
@@ -0,0 +1,2 @@
+[Network]
+DNSSECNegativeTrustAnchors=i i \ No newline at end of file
diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service
index 7435d7abec..492d2a033b 100644
--- a/test/fuzz/fuzz-unit-file/directives.service
+++ b/test/fuzz/fuzz-unit-file/directives.service
@@ -196,6 +196,8 @@ ReusePort=
RootDirectory=
RootDirectoryStartOnly=
RootImage=
+RootHash=
+RootVerity=
RuntimeMaxSec=
SELinuxContextFromNet=
SecureBits=
diff --git a/test/meson.build b/test/meson.build
index 404b923467..8bda38a2e2 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -28,6 +28,8 @@ install_subdir('testsuite-28.units',
install_dir : testdata_dir)
install_subdir('testsuite-30.units',
install_dir : testdata_dir)
+install_subdir('testsuite-52.units',
+ install_dir : testdata_dir)
testsuite08_dir = testdata_dir + '/testsuite-08.units'
install_data('testsuite-08.units/-.mount',
diff --git a/test/test-functions b/test/test-functions
index df87261ea2..f7f604aec3 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -935,7 +935,7 @@ install_config_files() {
inst /etc/login.defs
inst /etc/group
inst /etc/shells
- inst /etc/nsswitch.conf
+ inst_any /etc/nsswitch.conf /usr/etc/nsswitch.conf
inst /etc/pam.conf || :
inst /etc/os-release
inst /etc/localtime
diff --git a/test/test-network/conf/25-qdisc-ets.network b/test/test-network/conf/25-qdisc-ets.network
new file mode 100644
index 0000000000..a8c6b68235
--- /dev/null
+++ b/test/test-network/conf/25-qdisc-ets.network
@@ -0,0 +1,20 @@
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.3/16
+
+[EnhancedTransmissionSelection]
+Parent=root
+Handle=3a
+Bands=10
+StrictBands=3
+QuantumBytes=2 4 6
+QuantumBytes=
+QuantumBytes=1 2 3
+QuantumBytes=4 5
+PriorityMap=8 7 6 5
+PriorityMap=
+PriorityMap=3 4 5
+PriorityMap=6 7
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index c783ada33a..c48163b055 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -194,6 +194,18 @@ def expectedFailureIfHHFIsNotAvailable():
return f
+def expectedFailureIfETSIsNotAvailable():
+ def f(func):
+ call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
+ rc = call('tc qdisc add dev dummy98 parent root ets bands 10', stderr=subprocess.DEVNULL)
+ call('ip link del dummy98', stderr=subprocess.DEVNULL)
+ if rc == 0:
+ return func
+ else:
+ return unittest.expectedFailure(func)
+
+ return f
+
def setUpModule():
global running_units
@@ -1673,6 +1685,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
'25-qdisc-cake.network',
'25-qdisc-clsact-and-htb.network',
'25-qdisc-drr.network',
+ '25-qdisc-ets.network',
'25-qdisc-hhf.network',
'25-qdisc-ingress-netem-compat.network',
'25-qdisc-pie.network',
@@ -2482,6 +2495,19 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'qdisc hhf 3a: root')
self.assertRegex(output, 'limit 1022p')
+ @expectedFailureIfETSIsNotAvailable()
+ def test_qdisc_ets(self):
+ copy_unit_to_networkd_unit_path('25-qdisc-ets.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
+
+ output = check_output('tc qdisc show dev dummy98')
+ print(output)
+ self.assertRegex(output, 'qdisc ets 3a: root')
+ self.assertRegex(output, 'bands 10 strict 3')
+ self.assertRegex(output, 'quanta 1 2 3 4 5')
+ self.assertRegex(output, 'priomap 3 4 5 6 7')
+
class NetworkdStateFileTests(unittest.TestCase, Utilities):
links = [
'dummy98',
diff --git a/test/testsuite-52.units/testsuite-52.service b/test/testsuite-52.units/testsuite-52.service
new file mode 100755
index 0000000000..93f847f044
--- /dev/null
+++ b/test/testsuite-52.units/testsuite-52.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=Testsuite service
+
+[Service]
+ExecStart=/usr/lib/systemd/tests/testdata/%N.units/%N.sh
+Type=oneshot
diff --git a/test/testsuite-52.units/testsuite-52.sh b/test/testsuite-52.units/testsuite-52.sh
new file mode 100755
index 0000000000..9cccf1b6c1
--- /dev/null
+++ b/test/testsuite-52.units/testsuite-52.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+set -ex
+set -o pipefail
+
+if ! test -x /usr/lib/systemd/tests/testdata/units/test-honor-first-shutdown.sh ; then
+ echo "honor-first-shutdown script not found - FAIL" > /testok
+ exit 0
+fi
+
+systemd-analyze log-level debug
+systemd-analyze log-target console
+
+systemctl enable test-honor-first-shutdown.service
+systemctl start test-honor-first-shutdown.service
+
+echo OK > /testok
+
+exit 0
diff --git a/test/units/test-honor-first-shutdown.service b/test/units/test-honor-first-shutdown.service
new file mode 100644
index 0000000000..374f1e6b5f
--- /dev/null
+++ b/test/units/test-honor-first-shutdown.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Honor First Shutdown feature
+After=multi-user.target
+
+[Service]
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
+ExecStop=sh -c 'kill -SIGKILL $MAINPID'
+FailureAction=reboot
+
+[Install]
+WantedBy=multi-user.target \ No newline at end of file
diff --git a/test/units/test-honor-first-shutdown.sh b/test/units/test-honor-first-shutdown.sh
new file mode 100755
index 0000000000..17c1ec9686
--- /dev/null
+++ b/test/units/test-honor-first-shutdown.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+echo "Honor first shutdown test script"
+sleep infinity;
diff --git a/tools/make-autosuspend-rules.py b/tools/make-autosuspend-rules.py
index 25b261ea0d..e13ca33f6f 100755
--- a/tools/make-autosuspend-rules.py
+++ b/tools/make-autosuspend-rules.py
@@ -1,14 +1,24 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1+
-# Generate autosuspend rules for devices that have been whitelisted (IE tested)
-# by the Chromium OS team. Please keep this script in sync with:
+# Generate autosuspend rules for devices that have been tested to work properly
+# with autosuspend by the Chromium OS team. Based on
# https://chromium.googlesource.com/chromiumos/platform2/+/master/power_manager/udev/gen_autosuspend_rules.py
-import sys
import chromiumos.gen_autosuspend_rules
-if __name__ == '__main__':
- if len(sys.argv) > 1:
- sys.stdout = open(sys.argv[1], 'w')
- chromiumos.gen_autosuspend_rules.main()
+print('# pci:v<00VENDOR>d<00DEVICE> (8 uppercase hexadecimal digits twice)')
+for entry in chromiumos.gen_autosuspend_rules.PCI_IDS:
+ vendor, device = entry.split(':')
+ vendor = int(vendor, 16)
+ device = int(device, 16)
+ print('pci:v{:08X}d{:08X}*'.format(vendor, device))
+
+print('# usb:v<VEND>p<PROD> (4 uppercase hexadecimal digits twice')
+for entry in chromiumos.gen_autosuspend_rules.USB_IDS:
+ vendor, product = entry.split(':')
+ vendor = int(vendor, 16)
+ product = int(product, 16)
+ print('usb:v{:04X}p{:04X}*'.format(vendor, product))
+
+print(' ID_AUTOSUSPEND=1')
diff --git a/travis-ci/managers/debian.sh b/travis-ci/managers/debian.sh
index 60f6237606..a2a987d8fd 100755
--- a/travis-ci/managers/debian.sh
+++ b/travis-ci/managers/debian.sh
@@ -9,23 +9,25 @@
# export CONT_NAME="my-fancy-container"
# travis-ci/managers/debian.sh SETUP RUN CLEANUP
-PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
+PHASES=(${@:-SETUP RUN RUN_ASAN_UBSAN CLEANUP})
DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}"
-CONT_NAME="${CONT_NAME:-debian-$DEBIAN_RELEASE-$RANDOM}"
+CONT_NAME="${CONT_NAME:-systemd-debian-$DEBIAN_RELEASE}"
DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
DOCKER_RUN="${DOCKER_RUN:-docker run}"
REPO_ROOT="${REPO_ROOT:-$PWD}"
-ADDITIONAL_DEPS=(python3-libevdev
- python3-pyparsing
- clang
- perl
- libpwquality-dev
- fdisk
- libfdisk-dev
- libp11-kit-dev
- libssl-dev
- libzstd-dev
- zstd)
+ADDITIONAL_DEPS=(
+ clang
+ fdisk
+ libfdisk-dev
+ libp11-kit-dev
+ libpwquality-dev
+ libssl-dev
+ libzstd-dev
+ perl
+ python3-libevdev
+ python3-pyparsing
+ zstd
+)
function info() {
echo -e "\033[33;1m$1\033[0m"
@@ -54,7 +56,7 @@ for phase in "${PHASES[@]}"; do
$DOCKER_EXEC apt-get -y build-dep systemd
$DOCKER_EXEC apt-get -y install "${ADDITIONAL_DEPS[@]}"
;;
- RUN|RUN_CLANG)
+ RUN|RUN_GCC|RUN_CLANG)
if [[ "$phase" = "RUN_CLANG" ]]; then
ENV_VARS="-e CC=clang -e CXX=clang++"
fi
@@ -62,8 +64,8 @@ for phase in "${PHASES[@]}"; do
$DOCKER_EXEC ninja -v -C build
docker exec -e "TRAVIS=$TRAVIS" -it $CONT_NAME ninja -C build test
;;
- RUN_ASAN|RUN_CLANG_ASAN)
- if [[ "$phase" = "RUN_CLANG_ASAN" ]]; then
+ RUN_ASAN_UBSAN|RUN_GCC_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN)
+ if [[ "$phase" = "RUN_CLANG_ASAN_UBSAN" ]]; then
ENV_VARS="-e CC=clang -e CXX=clang++"
# Build fuzzer regression tests only with clang (for now),
# see: https://github.com/systemd/systemd/pull/15886#issuecomment-632689604
diff --git a/travis-ci/managers/fedora.sh b/travis-ci/managers/fedora.sh
index b3c85ebd09..cc665021d4 100755
--- a/travis-ci/managers/fedora.sh
+++ b/travis-ci/managers/fedora.sh
@@ -9,38 +9,32 @@
# export CONT_NAME="my-fancy-container"
# travis-ci/managers/fedora.sh SETUP RUN CLEANUP
-PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
+PHASES=(${@:-SETUP RUN RUN_ASAN_UBSAN CLEANUP})
FEDORA_RELEASE="${FEDORA_RELEASE:-rawhide}"
-CONT_NAME="${CONT_NAME:-fedora-$FEDORA_RELEASE-$RANDOM}"
+CONT_NAME="${CONT_NAME:-systemd-fedora-$FEDORA_RELEASE}"
DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
DOCKER_RUN="${DOCKER_RUN:-docker run}"
REPO_ROOT="${REPO_ROOT:-$PWD}"
-ADDITIONAL_DEPS=(dnf-plugins-core
- jq iputils
- hostname libasan
- python3-pyparsing
- python3-evdev
- libubsan
- clang
- llvm
- perl
- libfdisk-devel
- libpwquality-devel
- openssl-devel
- p11-kit-devel)
+ADDITIONAL_DEPS=(
+ clang
+ dnf-plugins-core
+ hostname libasan
+ jq iputils
+ libfdisk-devel
+ libpwquality-devel
+ libubsan
+ llvm
+ openssl-devel
+ p11-kit-devel
+ perl
+ python3-evdev
+ python3-pyparsing
+)
info() {
echo -e "\033[33;1m$1\033[0m"
}
-error() {
- echo >&2 -e "\033[31;1m$1\033[0m"
-}
-
-success() {
- echo >&2 -e "\033[32;1m$1\033[0m"
-}
-
# Simple wrapper which retries given command up to five times
_retry() {
local EC=1
@@ -94,8 +88,8 @@ for phase in "${PHASES[@]}"; do
$DOCKER_EXEC ninja -v -C build
$DOCKER_EXEC ninja -C build test
;;
- RUN_ASAN|RUN_CLANG_ASAN)
- if [[ "$phase" = "RUN_CLANG_ASAN" ]]; then
+ RUN_ASAN|RUN_GCC_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN)
+ if [[ "$phase" = "RUN_CLANG_ASAN_UBSAN" ]]; then
ENV_VARS="-e CC=clang -e CXX=clang++"
MESON_ARGS="-Db_lundef=false" # See https://github.com/mesonbuild/meson/issues/764
fi
@@ -110,46 +104,6 @@ for phase in "${PHASES[@]}"; do
-t $CONT_NAME \
meson test --timeout-multiplier=3 -C ./build/ --print-errorlogs
;;
- RUN_BUILD_CHECK_GCC|RUN_BUILD_CHECK_CLANG)
- ARGS=(
- "--optimization=0"
- "--optimization=2"
- "--optimization=3"
- "--optimization=s"
- "-Db_lto=true"
- "-Db_ndebug=true"
- )
-
- if [[ "$phase" = "RUN_BUILD_CHECK_CLANG" ]]; then
- ENV_VARS="-e CC=clang -e CXX=clang++"
- $DOCKER_EXEC clang --version
- else
- $DOCKER_EXEC gcc --version
- fi
-
- for args in "${ARGS[@]}"; do
- SECONDS=0
- info "Checking build with $args"
- # Redirect meson/ninja logs into separate files, otherwise we
- # would trip over Travis' log size limit
- if ! docker exec $ENV_VARS -it $CONT_NAME meson --werror $args build &> meson.log; then
- cat meson.log
- error "meson failed with $args"
- exit 1
- fi
-
- if ! $DOCKER_EXEC ninja -v -C build &> ninja.log; then
- cat ninja.log
- error "ninja failed with $args"
- exit 1
- fi
-
- $DOCKER_EXEC rm -fr build
- rm -f meson.log ninja.log
- success "Build with $args passed in $SECONDS seconds"
- done
-
- ;;
CLEANUP)
info "Cleanup phase"
docker stop $CONT_NAME