diff --git a/SOURCES/0801-sd-bus-bump-message-queue-size-again.patch b/SOURCES/0801-sd-bus-bump-message-queue-size-again.patch new file mode 100644 index 00000000..1ca9e2e0 --- /dev/null +++ b/SOURCES/0801-sd-bus-bump-message-queue-size-again.patch @@ -0,0 +1,28 @@ +From 4ebd0ef2af8b302bafa76383a5c182a5a749654a Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Fri, 8 Nov 2019 12:46:23 +0100 +Subject: [PATCH] sd-bus: bump message queue size again + +Simliarly to issue #4068, the current limit turns out to be too small for a +big storage setup that uses many small disks. Let's bump it further. + +Resolves: #1770158 +--- + src/libsystemd/sd-bus/bus-internal.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h +index 33a5569146..87c6d8cb76 100644 +--- a/src/libsystemd/sd-bus/bus-internal.h ++++ b/src/libsystemd/sd-bus/bus-internal.h +@@ -326,8 +326,8 @@ struct sd_bus { + + #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) + +-#define BUS_WQUEUE_MAX (192*1024) +-#define BUS_RQUEUE_MAX (192*1024) ++#define BUS_WQUEUE_MAX (384*1024) ++#define BUS_RQUEUE_MAX (384*1024) + + #define BUS_MESSAGE_SIZE_MAX (128*1024*1024) + #define BUS_AUTH_SIZE_MAX (64*1024) diff --git a/SOURCES/0802-unit-fix-potential-use-of-cgroup_path-after-free-whe.patch b/SOURCES/0802-unit-fix-potential-use-of-cgroup_path-after-free-whe.patch new file mode 100644 index 00000000..30485e58 --- /dev/null +++ b/SOURCES/0802-unit-fix-potential-use-of-cgroup_path-after-free-whe.patch @@ -0,0 +1,39 @@ +From 8a2dc9e983d6fb67955ae68da0a4af4248ecaf2d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Sat, 23 Nov 2019 13:37:02 +0100 +Subject: [PATCH] unit: fix potential use of cgroup_path after free() when + freeing unit + +Resolves: #1760149 +--- + src/core/cgroup.c | 3 +-- + src/core/unit.c | 2 +- + 2 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 0ce265dbf4..9af8126957 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -874,8 +874,7 @@ void unit_destroy_cgroup_if_empty(Unit *u) { + + hashmap_remove(u->manager->cgroup_unit, u->cgroup_path); + +- free(u->cgroup_path); +- u->cgroup_path = NULL; ++ u->cgroup_path = mfree(u->cgroup_path); + u->cgroup_realized = false; + u->cgroup_realized_mask = 0; + } +diff --git a/src/core/unit.c b/src/core/unit.c +index 294c9eb70f..0dc66203a4 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -515,7 +515,7 @@ void unit_free(Unit *u) { + + if (u->cgroup_path) { + hashmap_remove(u->manager->cgroup_unit, u->cgroup_path); +- free(u->cgroup_path); ++ u->cgroup_path = mfree(u->cgroup_path); + } + + set_remove(u->manager->failed_units, u); diff --git a/SOURCES/0803-add-test-for-ExecStopPost.patch b/SOURCES/0803-add-test-for-ExecStopPost.patch new file mode 100644 index 00000000..a5c8ea2d --- /dev/null +++ b/SOURCES/0803-add-test-for-ExecStopPost.patch @@ -0,0 +1,261 @@ +From 94da4f86eab658c14feac290663634ca29348a60 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Thu, 3 Oct 2019 19:05:06 +0200 +Subject: [PATCH] add test for ExecStopPost + +This is a follow-up to #4843. + +(cherry picked from commit 02baf239d87295362740d961765091b778795573) + +Related: #1733998 +--- + test/TEST-42-EXECSTOPPOST/Makefile | 10 +++ + test/TEST-42-EXECSTOPPOST/test.sh | 95 ++++++++++++++++++++ + test/TEST-42-EXECSTOPPOST/testsuite.sh | 119 +++++++++++++++++++++++++ + 3 files changed, 224 insertions(+) + create mode 100644 test/TEST-42-EXECSTOPPOST/Makefile + create mode 100755 test/TEST-42-EXECSTOPPOST/test.sh + create mode 100755 test/TEST-42-EXECSTOPPOST/testsuite.sh + +diff --git a/test/TEST-42-EXECSTOPPOST/Makefile b/test/TEST-42-EXECSTOPPOST/Makefile +new file mode 100644 +index 0000000000..5e89a29eff +--- /dev/null ++++ b/test/TEST-42-EXECSTOPPOST/Makefile +@@ -0,0 +1,10 @@ ++all: ++ @make -s --no-print-directory -C ../.. all ++ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --all ++setup: ++ @make --no-print-directory -C ../.. all ++ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --setup ++clean: ++ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --clean ++run: ++ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --run +diff --git a/test/TEST-42-EXECSTOPPOST/test.sh b/test/TEST-42-EXECSTOPPOST/test.sh +new file mode 100755 +index 0000000000..0958e01d68 +--- /dev/null ++++ b/test/TEST-42-EXECSTOPPOST/test.sh +@@ -0,0 +1,95 @@ ++#!/bin/bash ++TEST_DESCRIPTION="test that ExecStopPost= is always run" ++ ++. $TEST_BASE_DIR/test-functions ++ ++check_result_qemu() { ++ ret=1 ++ mkdir -p $TESTDIR/root ++ mount ${LOOPDEV}p1 $TESTDIR/root ++ [[ -e $TESTDIR/root/testok ]] && ret=0 ++ [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR ++ [[ -f $TESTDIR/root/var/log/journal ]] && cp -a $TESTDIR/root/var/log/journal $TESTDIR ++ umount $TESTDIR/root ++ [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed ++ ls -l $TESTDIR/journal/*/*.journal ++ test -s $TESTDIR/failed && ret=$(($ret+1)) ++ return $ret ++} ++ ++test_run() { ++ if run_qemu; then ++ check_result_qemu || return 1 ++ else ++ dwarn "can't run QEMU, skipping" ++ fi ++ if check_nspawn; then ++ run_nspawn ++ check_result_nspawn || return 1 ++ else ++ dwarn "can't run systemd-nspawn, skipping" ++ fi ++ return 0 ++} ++ ++test_setup() { ++ create_empty_image ++ mkdir -p $TESTDIR/root ++ mount ${LOOPDEV}p1 $TESTDIR/root ++ ++ ( ++ LOG_LEVEL=5 ++ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) ++ ++ setup_basic_environment ++ dracut_install false true env touch ++ ++ # mask some services that we do not want to run in these tests ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service ++ ++ # setup policy for Type=dbus test ++ mkdir -p $initdir/etc/dbus-1/system.d ++ cat > $initdir/etc/dbus-1/system.d/systemd.test.ExecStopPost.conf < ++ ++ ++ ++ ++ ++ ++EOF ++ ++ # setup the testsuite service ++ cat >$initdir/etc/systemd/system/testsuite.service </dev/null ++ [[ $LOOPDEV ]] && losetup -d $LOOPDEV ++ return 0 ++} ++ ++do_test "$@" +diff --git a/test/TEST-42-EXECSTOPPOST/testsuite.sh b/test/TEST-42-EXECSTOPPOST/testsuite.sh +new file mode 100755 +index 0000000000..a7e663adb3 +--- /dev/null ++++ b/test/TEST-42-EXECSTOPPOST/testsuite.sh +@@ -0,0 +1,119 @@ ++#!/bin/bash ++set -ex ++ ++systemd-analyze set-log-level debug ++ ++# Emulates systemd-run to overcome its limitations on RHEL-7, like nonexistent ++# support for --wait and only a handful of supported properties. ++systemd-run-wait() { ++ local unit="$1" ++ local unitfile=/etc/systemd/system/$unit ++ ++ shift ++ ++ cat > $unitfile <> $unitfile ;; ++ esac ++ done ++ shift $((OPTIND - 1)) ++ echo "ExecStart=/usr/bin/env $@" >> $unitfile ++ systemctl daemon-reload ++ ++ systemctl start $unit ++ while systemctl is-active -q $unit ; do ++ sleep 1 ++ done ++ ! systemctl is-failed -q $unit ++} ++ ++systemd-run-wait simple1.service -p Type=simple -p ExecStopPost='/bin/touch /run/simple1' true ++test -f /run/simple1 ++ ++! systemd-run-wait simple2.service -p Type=simple -p ExecStopPost='/bin/touch /run/simple2' false ++test -f /run/simple2 ++ ++cat > /tmp/forking1.sh < /tmp/forking2.sh < /tmp/notify1.sh < /testok ++ ++exit 0 diff --git a/SOURCES/0804-core-when-restarting-services-don-t-close-fds.patch b/SOURCES/0804-core-when-restarting-services-don-t-close-fds.patch new file mode 100644 index 00000000..308802c6 --- /dev/null +++ b/SOURCES/0804-core-when-restarting-services-don-t-close-fds.patch @@ -0,0 +1,112 @@ +From 70215e23a5c77445ed1b62186c069a173c632618 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sat, 22 Oct 2016 22:16:02 -0400 +Subject: [PATCH] core: when restarting services, don't close fds + +We would close all the stored fds in service_release_resources(), which of +course broke the whole concept of storing fds over service restart. + +Fixes #4408. + +(cherry picked from commit f0bfbfac43b7faa68ef1bb2ad659c191b9ec85d2) +(cherry picked from commit 4c271437cd695c31e76adb191013009689a7797c) +Resolves: #1757704 +--- + src/core/service.c | 22 +++++++++++++++------- + src/core/unit.c | 6 ++++-- + src/core/unit.h | 2 +- + 3 files changed, 20 insertions(+), 10 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index e538280bad..3c2f69a003 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -258,7 +258,17 @@ static void service_fd_store_unlink(ServiceFDStore *fs) { + free(fs); + } + +-static void service_release_resources(Unit *u) { ++static void service_release_fd_store(Service *s) { ++ assert(s); ++ ++ log_unit_debug(UNIT(s)->id, "Releasing all stored fds"); ++ while (s->fd_store) ++ service_fd_store_unlink(s->fd_store); ++ ++ assert(s->n_fd_store == 0); ++} ++ ++static void service_release_resources(Unit *u, bool inactive) { + Service *s = SERVICE(u); + + assert(s); +@@ -266,12 +276,10 @@ static void service_release_resources(Unit *u) { + if (!s->fd_store) + return; + +- log_debug("Releasing all resources for %s", u->id); +- +- while (s->fd_store) +- service_fd_store_unlink(s->fd_store); ++ log_unit_debug(u->id, "Releasing resources."); + +- assert(s->n_fd_store == 0); ++ if (inactive) ++ service_release_fd_store(s); + } + + static void service_done(Unit *u) { +@@ -319,7 +327,7 @@ static void service_done(Unit *u) { + + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + +- service_release_resources(u); ++ service_release_resources(u, true); + } + + static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) { +diff --git a/src/core/unit.c b/src/core/unit.c +index 0dc66203a4..22e31a76b3 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -285,6 +285,7 @@ int unit_set_description(Unit *u, const char *description) { + + bool unit_may_gc(Unit *u) { + UnitActiveState state; ++ bool inactive; + assert(u); + + /* Checks whether the unit is ready to be unloaded for garbage collection. +@@ -302,16 +303,17 @@ bool unit_may_gc(Unit *u) { + return false; + + state = unit_active_state(u); ++ inactive = state == UNIT_INACTIVE; + + /* If the unit is inactive and failed and no job is queued for + * it, then release its runtime resources */ + if (UNIT_IS_INACTIVE_OR_FAILED(state) && + UNIT_VTABLE(u)->release_resources) +- UNIT_VTABLE(u)->release_resources(u); ++ UNIT_VTABLE(u)->release_resources(u, inactive); + + /* But we keep the unit object around for longer when it is + * referenced or configured to not be gc'ed */ +- if (state != UNIT_INACTIVE) ++ if (!inactive) + return false; + + if (UNIT_VTABLE(u)->no_gc) +diff --git a/src/core/unit.h b/src/core/unit.h +index 719fc95260..232be8164f 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -360,7 +360,7 @@ struct UnitVTable { + + /* When the unit is not running and no job for it queued we + * shall release its runtime resources */ +- void (*release_resources)(Unit *u); ++ void (*release_resources)(Unit *u, bool inactive); + + /* Return true when this unit is suitable for snapshotting */ + bool (*check_snapshot)(Unit *u); diff --git a/SOURCES/0805-unit-rework-a-bit-how-we-keep-the-service-fdstore-fr.patch b/SOURCES/0805-unit-rework-a-bit-how-we-keep-the-service-fdstore-fr.patch new file mode 100644 index 00000000..427521f3 --- /dev/null +++ b/SOURCES/0805-unit-rework-a-bit-how-we-keep-the-service-fdstore-fr.patch @@ -0,0 +1,170 @@ +From 29254c6a73ede5af4df1c364c958a978f5a7af8a Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 13 Nov 2017 15:08:49 +0100 +Subject: [PATCH] unit: rework a bit how we keep the service fdstore from being + destroyed during service restart + +When preparing for a restart we quickly go through the DEAD/INACTIVE +service state before entering AUTO_RESTART. When doing this, we need to +make sure we don't destroy the FD store. Previously this was done by +checking the failure state of the unit, and keeping the FD store around +when the unit failed, under the assumption that the restart logic will +then get into action. + +This is not entirely correct howver, as there might be failure states +that will no result in restarts. + +With this commit we slightly alter the logic: a ref counter for the fd +store is added, that is increased right before we handle the restart +logic, and decreased again right-after. + +This should ensure that the fdstore lives exactly as long as it needs. + +Follow-up for f0bfbfac43b7faa68ef1bb2ad659c191b9ec85d2. + +(cherry picked from commit 7eb2a8a1259043e107ebec94e30ed160a93f40a7) +(cherry picked from commit e2636bde0f07319d0d35262dac6ff2638ba4e598) +Resolves: #1757704 +--- + src/core/service.c | 23 ++++++++++++++++++----- + src/core/service.h | 1 + + src/core/unit.c | 12 ++++-------- + src/core/unit.h | 5 ++--- + 4 files changed, 25 insertions(+), 16 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index 3c2f69a003..e32cdf4594 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -261,6 +261,9 @@ static void service_fd_store_unlink(ServiceFDStore *fs) { + static void service_release_fd_store(Service *s) { + assert(s); + ++ if (s->n_keep_fd_store > 0) ++ return; ++ + log_unit_debug(UNIT(s)->id, "Releasing all stored fds"); + while (s->fd_store) + service_fd_store_unlink(s->fd_store); +@@ -268,7 +271,7 @@ static void service_release_fd_store(Service *s) { + assert(s->n_fd_store == 0); + } + +-static void service_release_resources(Unit *u, bool inactive) { ++static void service_release_resources(Unit *u) { + Service *s = SERVICE(u); + + assert(s); +@@ -278,8 +281,7 @@ static void service_release_resources(Unit *u, bool inactive) { + + log_unit_debug(u->id, "Releasing resources."); + +- if (inactive) +- service_release_fd_store(s); ++ service_release_fd_store(s); + } + + static void service_done(Unit *u) { +@@ -327,7 +329,7 @@ static void service_done(Unit *u) { + + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + +- service_release_resources(u, true); ++ service_release_resources(u); + } + + static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) { +@@ -1330,6 +1332,10 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) + if (f != SERVICE_SUCCESS) + s->result = f; + ++ /* Make sure service_release_resources() doesn't destroy our FD store, while we are changing through ++ * SERVICE_FAILED/SERVICE_DEAD before entering into SERVICE_AUTO_RESTART. */ ++ s->n_keep_fd_store++; ++ + service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD); + + if (s->result != SERVICE_SUCCESS) { +@@ -1351,12 +1357,19 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) + (!IN_SET(s->main_exec_status.code, CLD_KILLED, CLD_DUMPED) || !set_contains(s->restart_prevent_status.signal, INT_TO_PTR(s->main_exec_status.status)))) { + + r = service_arm_timer(s, s->restart_usec); +- if (r < 0) ++ if (r < 0) { ++ s->n_keep_fd_store--; + goto fail; ++ } + + service_set_state(s, SERVICE_AUTO_RESTART); + } + ++ /* The new state is in effect, let's decrease the fd store ref counter again. Let's also readd us to the GC ++ * queue, so that the fd store is possibly gc'ed again */ ++ s->n_keep_fd_store--; ++ unit_add_to_gc_queue(UNIT(s)); ++ + s->forbid_restart = false; + + /* We want fresh tmpdirs in case service is started again immediately */ +diff --git a/src/core/service.h b/src/core/service.h +index 82938a1fc4..e5753f1f4c 100644 +--- a/src/core/service.h ++++ b/src/core/service.h +@@ -215,6 +215,7 @@ struct Service { + ServiceFDStore *fd_store; + unsigned n_fd_store; + unsigned n_fd_store_max; ++ unsigned n_keep_fd_store; + }; + + extern const UnitVTable service_vtable; +diff --git a/src/core/unit.c b/src/core/unit.c +index 22e31a76b3..eff9fdbe70 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -285,7 +285,6 @@ int unit_set_description(Unit *u, const char *description) { + + bool unit_may_gc(Unit *u) { + UnitActiveState state; +- bool inactive; + assert(u); + + /* Checks whether the unit is ready to be unloaded for garbage collection. +@@ -303,17 +302,14 @@ bool unit_may_gc(Unit *u) { + return false; + + state = unit_active_state(u); +- inactive = state == UNIT_INACTIVE; + +- /* If the unit is inactive and failed and no job is queued for +- * it, then release its runtime resources */ ++ /* If the unit is inactive and failed and no job is queued for it, then release its runtime resources */ + if (UNIT_IS_INACTIVE_OR_FAILED(state) && + UNIT_VTABLE(u)->release_resources) +- UNIT_VTABLE(u)->release_resources(u, inactive); ++ UNIT_VTABLE(u)->release_resources(u); + +- /* But we keep the unit object around for longer when it is +- * referenced or configured to not be gc'ed */ +- if (!inactive) ++ /* But we keep the unit object around for longer when it is referenced or configured to not be gc'ed */ ++ if (state != UNIT_INACTIVE) + return false; + + if (UNIT_VTABLE(u)->no_gc) +diff --git a/src/core/unit.h b/src/core/unit.h +index 232be8164f..3b0fd8d9df 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -358,9 +358,8 @@ struct UnitVTable { + * even though nothing references it and it isn't active in any way. */ + bool (*may_gc)(Unit *u); + +- /* When the unit is not running and no job for it queued we +- * shall release its runtime resources */ +- void (*release_resources)(Unit *u, bool inactive); ++ /* When the unit is not running and no job for it queued we shall release its runtime resources */ ++ void (*release_resources)(Unit *u); + + /* Return true when this unit is suitable for snapshotting */ + bool (*check_snapshot)(Unit *u); diff --git a/SOURCES/0806-tests-add-basic-journal-test.patch b/SOURCES/0806-tests-add-basic-journal-test.patch new file mode 100644 index 00000000..7f70faaa --- /dev/null +++ b/SOURCES/0806-tests-add-basic-journal-test.patch @@ -0,0 +1,145 @@ +From 5042511b6d12e30fc66e5a404153aac6c63af7d9 Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Tue, 17 Nov 2015 11:21:23 +0000 +Subject: [PATCH] tests: add basic journal test + +(cherry picked from commit 1c36b4a73b876258fbe01fbe9bc9b750b7dcc9ce) +(cherry picked from commit e974b9915ccc7bf56d23fd6fc67631990d893c89) +Resolves: #1757704 +--- + test/TEST-04-JOURNAL/Makefile | 1 + + test/TEST-04-JOURNAL/test-journal.sh | 18 +++++++ + test/TEST-04-JOURNAL/test.sh | 76 ++++++++++++++++++++++++++++ + test/test-functions | 2 +- + 4 files changed, 96 insertions(+), 1 deletion(-) + create mode 120000 test/TEST-04-JOURNAL/Makefile + create mode 100755 test/TEST-04-JOURNAL/test-journal.sh + create mode 100755 test/TEST-04-JOURNAL/test.sh + +diff --git a/test/TEST-04-JOURNAL/Makefile b/test/TEST-04-JOURNAL/Makefile +new file mode 120000 +index 0000000000..e9f93b1104 +--- /dev/null ++++ b/test/TEST-04-JOURNAL/Makefile +@@ -0,0 +1 @@ ++../TEST-01-BASIC/Makefile +\ No newline at end of file +diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh +new file mode 100755 +index 0000000000..c75f396ceb +--- /dev/null ++++ b/test/TEST-04-JOURNAL/test-journal.sh +@@ -0,0 +1,18 @@ ++#!/bin/bash ++ ++set -x ++set -e ++set -o pipefail ++ ++# Test stdout stream ++ ++# Skip empty lines ++ID=$(journalctl --new-id128 | sed -n 2p) ++>/expected ++printf $'\n\n\n' | systemd-cat -t "$ID" --level-prefix false ++journalctl --flush ++journalctl -b -o cat -t "$ID" >/output ++cmp /expected /output ++ ++touch /testok ++exit 0 +diff --git a/test/TEST-04-JOURNAL/test.sh b/test/TEST-04-JOURNAL/test.sh +new file mode 100755 +index 0000000000..e37cb7d412 +--- /dev/null ++++ b/test/TEST-04-JOURNAL/test.sh +@@ -0,0 +1,76 @@ ++#!/bin/bash ++# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- ++# ex: ts=8 sw=4 sts=4 et filetype=sh ++TEST_DESCRIPTION="Journal-related tests" ++ ++. $TEST_BASE_DIR/test-functions ++ ++check_result_qemu() { ++ ret=1 ++ mkdir -p $TESTDIR/root ++ mount ${LOOPDEV}p1 $TESTDIR/root ++ [[ -e $TESTDIR/root/testok ]] && ret=0 ++ [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR ++ cp -a $TESTDIR/root/var/log/journal $TESTDIR ++ umount $TESTDIR/root ++ [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed ++ ls -l $TESTDIR/journal/*/*.journal ++ test -s $TESTDIR/failed && ret=$(($ret+1)) ++ return $ret ++} ++ ++test_run() { ++ if run_qemu; then ++ check_result_qemu || return 1 ++ else ++ dwarn "can't run QEMU, skipping" ++ fi ++ if check_nspawn; then ++ run_nspawn ++ check_result_nspawn || return 1 ++ else ++ dwarn "can't run systemd-nspawn, skipping" ++ fi ++ return 0 ++} ++ ++test_setup() { ++ create_empty_image ++ mkdir -p $TESTDIR/root ++ mount ${LOOPDEV}p1 $TESTDIR/root ++ ++ # Create what will eventually be our root filesystem onto an overlay ++ ( ++ LOG_LEVEL=5 ++ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) ++ ++ setup_basic_environment ++ ++ # setup the testsuite service ++ cat >$initdir/etc/systemd/system/testsuite.service </dev/null ++ [[ $LOOPDEV ]] && losetup -d $LOOPDEV ++ return 0 ++} ++ ++do_test "$@" +diff --git a/test/test-functions b/test/test-functions +index e50ce556fd..d5e9650903 100644 +--- a/test/test-functions ++++ b/test/test-functions +@@ -12,7 +12,7 @@ if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then + ROOTLIBDIR=/usr/lib/systemd + fi + +-BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe chmod chown ln" ++BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe chmod chown ln sed cmp tee" + DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname" + + function find_qemu_bin() { diff --git a/SOURCES/0807-tests-add-regression-test-for-systemctl-restart-syst.patch b/SOURCES/0807-tests-add-regression-test-for-systemctl-restart-syst.patch new file mode 100644 index 00000000..9f91eaee --- /dev/null +++ b/SOURCES/0807-tests-add-regression-test-for-systemctl-restart-syst.patch @@ -0,0 +1,54 @@ +From ae68ff48fffe8df34c2065ad221b7d2377523edc Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Wed, 30 Dec 2015 03:33:43 +0000 +Subject: [PATCH] tests: add regression test for `systemctl restart + systemd-journald` + +See https://github.com/systemd/systemd/issues/2236 + +(cherry picked from commit 3889613ec6bc54b9e02955f62b9d5c5b571c3d4b) +(cherry picked from commit 4dc893c03fe9c56a3d3070fb8583f5584014aa49) +Resolves: #1757704 +--- + test/TEST-04-JOURNAL/test-journal.sh | 8 ++++++++ + test/TEST-04-JOURNAL/test.sh | 9 +++++++++ + 2 files changed, 17 insertions(+) + +diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh +index c75f396ceb..701b0cf724 100755 +--- a/test/TEST-04-JOURNAL/test-journal.sh ++++ b/test/TEST-04-JOURNAL/test-journal.sh +@@ -14,5 +14,13 @@ journalctl --flush + journalctl -b -o cat -t "$ID" >/output + cmp /expected /output + ++# Don't lose streams on restart ++systemctl start forever-print-hola ++sleep 3 ++systemctl restart systemd-journald ++sleep 3 ++systemctl stop forever-print-hola ++[[ ! -f "/i-lose-my-logs" ]] ++ + touch /testok + exit 0 +diff --git a/test/TEST-04-JOURNAL/test.sh b/test/TEST-04-JOURNAL/test.sh +index e37cb7d412..6aea67ba4e 100755 +--- a/test/TEST-04-JOURNAL/test.sh ++++ b/test/TEST-04-JOURNAL/test.sh +@@ -55,6 +55,15 @@ After=multi-user.target + [Service] + ExecStart=/test-journal.sh + Type=oneshot ++EOF ++ ++ cat >$initdir/etc/systemd/system/forever-print-hola.service < +Date: Thu, 20 Oct 2016 13:18:12 +0000 +Subject: [PATCH] tests: add test that journald keeps fds over termination by + signal + +This test fails before previous commit, and passes with it. + +(cherry picked from commit bff653e3970bb79832568ae86b095ee530b62302) +(cherry picked from commit ee8f69ae5ddac6f05c56ea7dbcb76fbbb2e355ee) +Resolves: #1757704 +--- + test/TEST-04-JOURNAL/test-journal.sh | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh +index 701b0cf724..d0b05c46d6 100755 +--- a/test/TEST-04-JOURNAL/test-journal.sh ++++ b/test/TEST-04-JOURNAL/test-journal.sh +@@ -22,5 +22,13 @@ sleep 3 + systemctl stop forever-print-hola + [[ ! -f "/i-lose-my-logs" ]] + ++# https://github.com/systemd/systemd/issues/4408 ++rm -f /i-lose-my-logs ++systemctl start forever-print-hola ++sleep 3 ++systemctl kill --signal=SIGKILL systemd-journald ++sleep 3 ++[[ ! -f "/i-lose-my-logs" ]] ++ + touch /testok + exit 0 diff --git a/SOURCES/0809-nss-util-silence-warning-about-deprecated-RES_USE_IN.patch b/SOURCES/0809-nss-util-silence-warning-about-deprecated-RES_USE_IN.patch new file mode 100644 index 00000000..4e835656 --- /dev/null +++ b/SOURCES/0809-nss-util-silence-warning-about-deprecated-RES_USE_IN.patch @@ -0,0 +1,51 @@ +From 351e67e1a7259ac31ec3a7c2d5e850e60f622a5a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 31 Jan 2017 19:55:33 -0500 +Subject: [PATCH] nss-util: silence warning about deprecated RES_USE_INET6 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +src/nss-resolve/nss-resolve.c: In function ‘_nss_resolve_gethostbyname_r’: +src/nss-resolve/nss-resolve.c:680:13: warning: RES_USE_INET6 is deprecated + NSS_GETHOSTBYNAME_FALLBACKS(resolve); + ^~~~~~~~~~~~~~~~~~~~~~~~~ + +In glibc bz #19582, RES_USE_INET6 was deprecated. This might make sense for +clients, but they didn't take into account nss module implementations which +*must* continue to support the option. glibc internally defines +DEPRECATED_RES_USE_INET6 which can be used without emitting a warning, but +it's not exported publicly. Let's do the same, and just copy the definition +to our header. + +(cherry picked from commit 6154d33de3f15bbd5d5df718103af9c37ba0a768) + +Resolves: #1799002 +--- + src/shared/nss-util.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/shared/nss-util.h b/src/shared/nss-util.h +index 230a986040..01524289c5 100644 +--- a/src/shared/nss-util.h ++++ b/src/shared/nss-util.h +@@ -25,6 +25,10 @@ + #include + #include + ++#ifndef DEPRECATED_RES_USE_INET6 ++# define DEPRECATED_RES_USE_INET6 0x00002000 ++#endif ++ + #define NSS_GETHOSTBYNAME_PROTOTYPES(module) \ + enum nss_status _nss_##module##_gethostbyname4_r( \ + const char *name, \ +@@ -90,7 +94,7 @@ enum nss_status _nss_##module##_gethostbyname_r( \ + int *errnop, int *h_errnop) { \ + enum nss_status ret = NSS_STATUS_NOTFOUND; \ + \ +- if (_res.options & RES_USE_INET6) \ ++ if (_res.options & DEPRECATED_RES_USE_INET6) \ + ret = _nss_##module##_gethostbyname3_r( \ + name, \ + AF_INET6, \ diff --git a/SOURCES/0810-journal-do-not-trigger-assertion-when-journal_file_c.patch b/SOURCES/0810-journal-do-not-trigger-assertion-when-journal_file_c.patch new file mode 100644 index 00000000..dd2c171f --- /dev/null +++ b/SOURCES/0810-journal-do-not-trigger-assertion-when-journal_file_c.patch @@ -0,0 +1,49 @@ +From 248925c68092bab7ce0231449176db153f55d818 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Tue, 7 Jan 2020 11:22:26 +0100 +Subject: [PATCH] journal: do not trigger assertion when journal_file_close() + get NULL + +We generally expect destructors to not complain if a NULL argument is passed. + +Closes #12400. + +(cherry picked from commit c377a6f3ad3d9bed4ce7e873e8e9ec6b1650c57d) +Resolves: #1786046 +--- + src/journal/journal-file.c | 3 ++- + src/journal/journald-server.c | 7 ++----- + 2 files changed, 4 insertions(+), 6 deletions(-) + +diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c +index 586f620e21..cf8dad3fcd 100644 +--- a/src/journal/journal-file.c ++++ b/src/journal/journal-file.c +@@ -129,7 +129,8 @@ int journal_file_set_offline(JournalFile *f) { + } + + void journal_file_close(JournalFile *f) { +- assert(f); ++ if (!f) ++ return; + + #ifdef HAVE_GCRYPT + /* Write the final tag */ +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index aaabb2f7ab..ffe2daa7be 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -1933,11 +1933,8 @@ void server_done(Server *s) { + while (s->stdout_streams) + stdout_stream_free(s->stdout_streams); + +- if (s->system_journal) +- journal_file_close(s->system_journal); +- +- if (s->runtime_journal) +- journal_file_close(s->runtime_journal); ++ (void) journal_file_close(s->system_journal); ++ (void) journal_file_close(s->runtime_journal); + + while ((f = ordered_hashmap_steal_first(s->user_journals))) + journal_file_close(f); diff --git a/SOURCES/0811-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch b/SOURCES/0811-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch new file mode 100644 index 00000000..8e8d0b16 --- /dev/null +++ b/SOURCES/0811-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch @@ -0,0 +1,53 @@ +From f5e4e0c8139bc0fe001846fabe83c3220fe4bea7 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 28 Nov 2018 12:41:44 +0100 +Subject: [PATCH] mount: don't propagate errors from mount_setup_unit() further + up + +If we can't process a specific line in /proc/self/mountinfo we should +log about it (which we do), but this should not affect other lines, nor +further processing of mount units. Let's keep these failures local. + +Fixes: #10874 +(cherry picked from commit ba0d56f55f2073164799be714b5bd1aad94d059a) +Resolves: #1804757 +--- + src/core/mount.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/src/core/mount.c b/src/core/mount.c +index 3167bd6bb1..126038c27f 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1571,7 +1571,7 @@ fail: + static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { + _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL; +- int r = 0; ++ int r; + + assert(m); + +@@ -1587,7 +1587,6 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { + if (r < 0) + return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); + +- r = 0; + for (;;) { + const char *device, *path, *options, *fstype; + _cleanup_free_ const char *d = NULL, *p = NULL; +@@ -1615,12 +1614,10 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { + + (void) device_found_node(m, d, true, DEVICE_FOUND_MOUNT, set_flags); + +- k = mount_setup_unit(m, d, p, options, fstype, set_flags); +- if (r == 0 && k < 0) +- r = k; ++ (void) mount_setup_unit(m, d, p, options, fstype, set_flags); + } + +- return r; ++ return 0; + } + + static void mount_shutdown(Manager *m) { diff --git a/SOURCES/0812-mount-when-allocating-a-Mount-object-based-on-proc-s.patch b/SOURCES/0812-mount-when-allocating-a-Mount-object-based-on-proc-s.patch new file mode 100644 index 00000000..1da5ebf2 --- /dev/null +++ b/SOURCES/0812-mount-when-allocating-a-Mount-object-based-on-proc-s.patch @@ -0,0 +1,35 @@ +From 774f040ecc62e9c559269bb13afb1c4d04e1b6ab Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 28 Nov 2018 14:51:04 +0100 +Subject: [PATCH] mount: when allocating a Mount object based on + /proc/self/mountinfo mark it so + +Let's set 'from_proc_self_mountinfo' right away, since we know its from +there. This is important so that when the load queue is dispatched (and +thus mount_load() called) this +fact is already known. + +(cherry picked from commit 6d7e89b07065b8c49af47aaf1ccc336d017fc3a2) +Related: #1804757 +--- + src/core/mount.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/core/mount.c b/src/core/mount.c +index 126038c27f..34c4b548ad 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1480,6 +1480,13 @@ static int mount_setup_unit( + } + } + ++ /* This unit was generated because /proc/self/mountinfo reported it. Remember this, so that by the time we load ++ * the unit file for it (and thus add in extra deps right after) we know what source to attributes the deps ++ * to.*/ ++ MOUNT(u)->from_proc_self_mountinfo = true; ++ ++ /* We have only allocated the stub now, let's enqueue this unit for loading now, so that everything else is ++ * loaded in now. */ + unit_add_to_load_queue(u); + changed = true; + } else { diff --git a/SOURCES/0813-fix-the-fix-for-1691511.patch b/SOURCES/0813-fix-the-fix-for-1691511.patch new file mode 100644 index 00000000..5be3f01b --- /dev/null +++ b/SOURCES/0813-fix-the-fix-for-1691511.patch @@ -0,0 +1,51 @@ +From 591bcfa98983c97df4dbb9d15bc272c3fc093863 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Mon, 16 Mar 2020 09:37:22 +0100 +Subject: [PATCH] fix the fix for #1691511 + +The fix for #1691511 should have been used only for existing mounts +(mount_setup_existing_unit() in current master). + +Related: #1804757 +--- + src/core/mount.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/core/mount.c b/src/core/mount.c +index 34c4b548ad..56fda1b73f 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1416,6 +1416,7 @@ static int mount_setup_unit( + bool load_extras = false; + MountParameters *p; + bool delete, changed = false; ++ bool just_mounted; + Unit *u; + int r; + +@@ -1489,6 +1490,7 @@ static int mount_setup_unit( + * loaded in now. */ + unit_add_to_load_queue(u); + changed = true; ++ just_mounted = true; + } else { + delete = false; + +@@ -1518,6 +1520,8 @@ static int mount_setup_unit( + load_extras = true; + changed = true; + } ++ ++ just_mounted = !MOUNT(u)->from_proc_self_mountinfo || MOUNT(u)->just_mounted; + } + + w = strdup(what); +@@ -1537,7 +1541,7 @@ static int mount_setup_unit( + + if (set_flags) { + MOUNT(u)->is_mounted = true; +- MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo || MOUNT(u)->just_mounted; ++ MOUNT(u)->just_mounted = just_mounted; + MOUNT(u)->just_changed = changed; + } + diff --git a/SOURCES/0814-v3-Properly-parsing-SCSI-Hyperv-devices-8509.patch b/SOURCES/0814-v3-Properly-parsing-SCSI-Hyperv-devices-8509.patch new file mode 100644 index 00000000..539fb21d --- /dev/null +++ b/SOURCES/0814-v3-Properly-parsing-SCSI-Hyperv-devices-8509.patch @@ -0,0 +1,68 @@ +From f99cc28e392874b317b4ff2054bbd6970f71ecdd Mon Sep 17 00:00:00 2001 +From: Long Li +Date: Wed, 21 Mar 2018 03:51:28 -0700 +Subject: [PATCH] v3: Properly parsing SCSI Hyperv devices (#8509) + +Since 2016, Hyperv devices moved to using standard way to expose UUID to sysfs. Fix the parsing function to work with the newer format. + +Change log: +v2: changed code to work with both old and new path format +v3: changed guid_str_len type to size_t, fixed length in char guid[] in handle_scsi_hyperv() + +(cherry picked from commit cf3fabacaa141a1224a2ad239806a1fa28b51687) + +Resolves: #1809053 +--- + src/udev/udev-builtin-path_id.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c +index d113ff21b0..b0bcd80571 100644 +--- a/src/udev/udev-builtin-path_id.c ++++ b/src/udev/udev-builtin-path_id.c +@@ -424,14 +424,16 @@ out: + return hostdev; + } + +-static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char **path) { ++static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char **path, size_t guid_str_len) { + struct udev_device *hostdev; + struct udev_device *vmbusdev; + const char *guid_str; +- char *lun = NULL; +- char guid[38]; ++ _cleanup_free_ char *lun = NULL; ++ char guid[39]; + size_t i, k; + ++ assert(guid_str_len < sizeof(guid)); ++ + hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host"); + if (!hostdev) + return NULL; +@@ -444,10 +446,10 @@ static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char * + if (!guid_str) + return NULL; + +- if (strlen(guid_str) < 37 || guid_str[0] != '{' || guid_str[36] != '}') ++ if (strlen(guid_str) < guid_str_len || guid_str[0] != '{' || guid_str[guid_str_len-1] != '}') + return NULL; + +- for (i = 1, k = 0; i < 36; i++) { ++ for (i = 1, k = 0; i < guid_str_len-1; i++) { + if (guid_str[i] == '-') + continue; + guid[k++] = guid_str[i]; +@@ -545,7 +547,11 @@ static struct udev_device *handle_scsi(struct udev_device *parent, bool enable_n + } + + if (strstr(name, "/vmbus_") != NULL) { +- parent = handle_scsi_hyperv(parent, path); ++ parent = handle_scsi_hyperv(parent, path, 37); ++ goto out; ++ } ++ else if (strstr(name, "/VMBUS")) { ++ parent = handle_scsi_hyperv(parent, path, 38); + goto out; + } + diff --git a/SOURCES/0815-Consider-smb3-as-remote-filesystem.patch b/SOURCES/0815-Consider-smb3-as-remote-filesystem.patch new file mode 100644 index 00000000..28110bd7 --- /dev/null +++ b/SOURCES/0815-Consider-smb3-as-remote-filesystem.patch @@ -0,0 +1,29 @@ +From a1e395b76292480649c1d94893af93c1262b2f5f Mon Sep 17 00:00:00 2001 +From: Kenneth D'souza +Date: Mon, 30 Sep 2019 16:01:21 +0530 +Subject: [PATCH] Consider smb3 as remote filesystem + +Currently systemd will treat smb3 as local filesystem and cause +can't boot failures. Add smb3 to the list of remote filesystems +to fix this issue. + +Signed-off-by: Kenneth D'souza +(cherry picked from commit ff7d6a740b0c6fa3be63d3908a0858730a0837c5) + +Resolves: #1811700 +--- + src/shared/util.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/shared/util.c b/src/shared/util.c +index ce6678eb38..3fb4492a81 100644 +--- a/src/shared/util.c ++++ b/src/shared/util.c +@@ -1937,6 +1937,7 @@ bool fstype_is_network(const char *fstype) { + static const char table[] = + "afs\0" + "cifs\0" ++ "smb3\0" + "smbfs\0" + "sshfs\0" + "ncpfs\0" diff --git a/SOURCES/0816-mount-don-t-add-Requires-for-tmp.mount.patch b/SOURCES/0816-mount-don-t-add-Requires-for-tmp.mount.patch new file mode 100644 index 00000000..b537d084 --- /dev/null +++ b/SOURCES/0816-mount-don-t-add-Requires-for-tmp.mount.patch @@ -0,0 +1,26 @@ +From 070dfe9be5cf873e2a815232900da9651dfe4544 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Tue, 17 Mar 2020 10:49:44 +0100 +Subject: [PATCH] mount: don't add Requires for tmp.mount + +This is a follow-up to #1372249. + +rhel-only +Resolves: #1813270 +--- + src/core/mount.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/mount.c b/src/core/mount.c +index 56fda1b73f..72e981676d 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -300,7 +300,7 @@ static int mount_add_mount_links(Mount *m) { + if (r < 0) + return r; + +- if (UNIT(m)->fragment_path) { ++ if (UNIT(m)->fragment_path && !streq(UNIT(m)->id, "tmp.mount")) { + /* If we have fragment configuration, then make this dependency required */ + r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true); + if (r < 0) diff --git a/SOURCES/0817-sd-bus-when-attached-to-an-sd-event-loop-disconnect-.patch b/SOURCES/0817-sd-bus-when-attached-to-an-sd-event-loop-disconnect-.patch new file mode 100644 index 00000000..9f66ab5d --- /dev/null +++ b/SOURCES/0817-sd-bus-when-attached-to-an-sd-event-loop-disconnect-.patch @@ -0,0 +1,106 @@ +From 24622692a67b59e943afc1d309da696e48bf6a54 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 15 Dec 2017 22:24:16 +0100 +Subject: [PATCH] sd-bus: when attached to an sd-event loop, disconnect on + processing errors + +If we can't process the bus for some reason we shouldn't just disable +the event source, but log something and give up on the connection. Hence +do that, and disconnect. + +(cherry-picked from commit 5ae37ad833583e6c1c7765767b7f8360afca3b07) + +Resolves: #1769928 +--- + src/libsystemd/sd-bus/sd-bus.c | 45 +++++++++++++++++++++------------- + 1 file changed, 28 insertions(+), 17 deletions(-) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 44ed2c7497..2c8cc66367 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -3037,8 +3037,10 @@ static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userd + assert(bus); + + r = sd_bus_process(bus, NULL); +- if (r < 0) +- return r; ++ if (r < 0) { ++ log_debug_errno(r, "Processing of bus failed, closing down: %m"); ++ bus_enter_closing(bus); ++ } + + return 1; + } +@@ -3050,8 +3052,10 @@ static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) { + assert(bus); + + r = sd_bus_process(bus, NULL); +- if (r < 0) +- return r; ++ if (r < 0) { ++ log_debug_errno(r, "Processing of bus failed, closing down: %m"); ++ bus_enter_closing(bus); ++ } + + return 1; + } +@@ -3065,38 +3069,45 @@ static int prepare_callback(sd_event_source *s, void *userdata) { + assert(bus); + + e = sd_bus_get_events(bus); +- if (e < 0) +- return e; ++ if (e < 0) { ++ r = e; ++ goto fail; ++ } + + if (bus->output_fd != bus->input_fd) { + + r = sd_event_source_set_io_events(bus->input_io_event_source, e & POLLIN); + if (r < 0) +- return r; ++ goto fail; + + r = sd_event_source_set_io_events(bus->output_io_event_source, e & POLLOUT); +- if (r < 0) +- return r; +- } else { ++ } else + r = sd_event_source_set_io_events(bus->input_io_event_source, e); +- if (r < 0) +- return r; +- } ++ if (r < 0) ++ goto fail; + + r = sd_bus_get_timeout(bus, &until); + if (r < 0) +- return r; ++ goto fail; + if (r > 0) { + int j; + + j = sd_event_source_set_time(bus->time_event_source, until); +- if (j < 0) +- return j; ++ if (j < 0) { ++ r = j; ++ goto fail; ++ } + } + + r = sd_event_source_set_enabled(bus->time_event_source, r > 0); + if (r < 0) +- return r; ++ goto fail; ++ ++ return 1; ++ ++fail: ++ log_debug_errno(r, "Preparing of bus events failed, closing down: %m"); ++ bus_enter_closing(bus); + + return 1; + } diff --git a/SOURCES/0818-sd-journal-close-journal-files-that-were-deleted-by-.patch b/SOURCES/0818-sd-journal-close-journal-files-that-were-deleted-by-.patch new file mode 100644 index 00000000..a319b461 --- /dev/null +++ b/SOURCES/0818-sd-journal-close-journal-files-that-were-deleted-by-.patch @@ -0,0 +1,75 @@ +From 8a98e68dc1fdf10881fffc40604dfd28a49fdc27 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Tue, 4 Feb 2020 14:23:14 +0100 +Subject: [PATCH] sd-journal: close journal files that were deleted by journald + before we've setup inotify watch + +(cherry-picked from commit 28ca867abdb20d0e4ac1901e2ed669cdb41ea3f6) + +Fixes #14695 + +Related: #1812889 +--- + src/journal/journal-file.c | 2 +- + src/journal/journal-file.h | 1 + + src/journal/sd-journal.c | 15 +++++++++++++++ + 3 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c +index cf8dad3fcd..86a7e2642a 100644 +--- a/src/journal/journal-file.c ++++ b/src/journal/journal-file.c +@@ -337,7 +337,7 @@ static int journal_file_verify_header(JournalFile *f) { + return 0; + } + +-static int journal_file_fstat(JournalFile *f) { ++int journal_file_fstat(JournalFile *f) { + assert(f); + assert(f->fd >= 0); + +diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h +index 37749c4459..ee9772b9bb 100644 +--- a/src/journal/journal-file.h ++++ b/src/journal/journal-file.h +@@ -139,6 +139,7 @@ int journal_file_open( + + int journal_file_set_offline(JournalFile *f); + void journal_file_close(JournalFile *j); ++int journal_file_fstat(JournalFile *j); + + int journal_file_open_reliably( + const char *fname, +diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c +index 004fe646d4..09466df810 100644 +--- a/src/journal/sd-journal.c ++++ b/src/journal/sd-journal.c +@@ -2386,6 +2386,8 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { + assert_return(!journal_pid_changed(j), -ECHILD); + + if (j->inotify_fd < 0) { ++ Iterator i; ++ JournalFile *f; + + /* This is the first invocation, hence create the + * inotify watch */ +@@ -2393,6 +2395,19 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { + if (r < 0) + return r; + ++ /* Server might have done some vacuuming while we weren't watching. ++ Get rid of the deleted files now so they don't stay around indefinitely. */ ++ ORDERED_HASHMAP_FOREACH(f, j->files, i) { ++ r = journal_file_fstat(f); ++ if (r < 0) { ++ log_error("Failed to fstat() journal file '%s' : %m", f->path); ++ continue; ++ } ++ ++ if (f->last_stat.st_nlink <= 0) ++ remove_file_real(j, f); ++ } ++ + /* The journal might have changed since the context + * object was created and we weren't watching before, + * hence don't wait for anything, and return diff --git a/SOURCES/0819-sd-journal-remove-the-dead-code-and-actually-fix-146.patch b/SOURCES/0819-sd-journal-remove-the-dead-code-and-actually-fix-146.patch new file mode 100644 index 00000000..962770b9 --- /dev/null +++ b/SOURCES/0819-sd-journal-remove-the-dead-code-and-actually-fix-146.patch @@ -0,0 +1,42 @@ +From 7fe6194a2a7872532f121e6159d4fa60d1c85c50 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Fri, 27 Mar 2020 17:01:59 +0100 +Subject: [PATCH] sd-journal: remove the dead code and actually fix #14695 + +journal_file_fstat() returns an error if we call it on already unlinked +journal file and hence we never reach remove_file_real() which is the +entire point. + +I must have made some mistake while testing the fix that got me thinking +the issue is gone while opposite was true. + +Fixes #14695 + +(cherry-picked from commit 8581b9f9732d4c158bb5f773230a65ce77f2c292) + +Resolves: #1812889 +--- + src/journal/sd-journal.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c +index 09466df810..1f03c8e8ba 100644 +--- a/src/journal/sd-journal.c ++++ b/src/journal/sd-journal.c +@@ -2399,13 +2399,12 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { + Get rid of the deleted files now so they don't stay around indefinitely. */ + ORDERED_HASHMAP_FOREACH(f, j->files, i) { + r = journal_file_fstat(f); +- if (r < 0) { ++ if (r == -EIDRM) ++ remove_file_real(j, f); ++ else if (r < 0) { + log_error("Failed to fstat() journal file '%s' : %m", f->path); + continue; + } +- +- if (f->last_stat.st_nlink <= 0) +- remove_file_real(j, f); + } + + /* The journal might have changed since the context diff --git a/SOURCES/0820-swap-adjust-swap.c-in-a-similar-way-to-what-we-just-.patch b/SOURCES/0820-swap-adjust-swap.c-in-a-similar-way-to-what-we-just-.patch new file mode 100644 index 00000000..4c1c0758 --- /dev/null +++ b/SOURCES/0820-swap-adjust-swap.c-in-a-similar-way-to-what-we-just-.patch @@ -0,0 +1,259 @@ +From b77d7c2a22c679cb9445f34c59462804051bd12f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 25 Sep 2017 19:53:19 +0200 +Subject: [PATCH] swap: adjust swap.c in a similar way to what we just did to + mount.c + +Also drop the redundant states and make all similar changes too. +Thankfully the swap.c state engine is much simpler than mount.c's, hence +this should be easier to digest. + +(cherry picked from commit 50864457e1bc5f7a4ab2fd02e1565bc5d135d2f3) + +Related: #1749621 +--- + src/core/swap.c | 96 +++++++++++++++++++++++-------------------------- + src/core/swap.h | 2 -- + 2 files changed, 44 insertions(+), 54 deletions(-) + +diff --git a/src/core/swap.c b/src/core/swap.c +index 4a5e882332..c9cce3d945 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -49,8 +49,6 @@ static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = { + [SWAP_ACTIVATING_DONE] = UNIT_ACTIVE, + [SWAP_ACTIVE] = UNIT_ACTIVE, + [SWAP_DEACTIVATING] = UNIT_DEACTIVATING, +- [SWAP_ACTIVATING_SIGTERM] = UNIT_DEACTIVATING, +- [SWAP_ACTIVATING_SIGKILL] = UNIT_DEACTIVATING, + [SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING, + [SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING, + [SWAP_FAILED] = UNIT_FAILED +@@ -490,8 +488,6 @@ static void swap_set_state(Swap *s, SwapState state) { + s->state = state; + + if (state != SWAP_ACTIVATING && +- state != SWAP_ACTIVATING_SIGTERM && +- state != SWAP_ACTIVATING_SIGKILL && + state != SWAP_ACTIVATING_DONE && + state != SWAP_DEACTIVATING && + state != SWAP_DEACTIVATING_SIGTERM && +@@ -538,8 +534,6 @@ static int swap_coldplug(Unit *u, Hashmap *deferred_work) { + return 0; + + if (new_state == SWAP_ACTIVATING || +- new_state == SWAP_ACTIVATING_SIGTERM || +- new_state == SWAP_ACTIVATING_SIGKILL || + new_state == SWAP_ACTIVATING_DONE || + new_state == SWAP_DEACTIVATING || + new_state == SWAP_DEACTIVATING_SIGTERM || +@@ -682,6 +676,15 @@ static void swap_enter_active(Swap *s, SwapResult f) { + swap_set_state(s, SWAP_ACTIVE); + } + ++static void swap_enter_dead_or_active(Swap *s, SwapResult f) { ++ assert(s); ++ ++ if (s->from_proc_swaps) ++ swap_enter_active(s, f); ++ else ++ swap_enter_dead(s, f); ++} ++ + static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) { + int r; + +@@ -693,8 +696,7 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) { + r = unit_kill_context( + UNIT(s), + &s->kill_context, +- (state != SWAP_ACTIVATING_SIGTERM && state != SWAP_DEACTIVATING_SIGTERM) ? +- KILL_KILL : KILL_TERMINATE, ++ state != SWAP_DEACTIVATING_SIGTERM ? KILL_KILL : KILL_TERMINATE, + -1, + s->control_pid, + false); +@@ -707,18 +709,16 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) { + goto fail; + + swap_set_state(s, state); +- } else if (state == SWAP_ACTIVATING_SIGTERM) +- swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_SUCCESS); +- else if (state == SWAP_DEACTIVATING_SIGTERM) ++ } else if (state == SWAP_DEACTIVATING_SIGTERM && s->kill_context.send_sigkill) + swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS); + else +- swap_enter_dead(s, SWAP_SUCCESS); ++ swap_enter_dead_or_active(s, SWAP_SUCCESS); + + return; + + fail: + log_unit_warning_errno(UNIT(s)->id, r, "%s failed to kill processes: %m", UNIT(s)->id); +- swap_enter_dead(s, SWAP_FAILURE_RESOURCES); ++ swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES); + } + + static void swap_enter_activating(Swap *s) { +@@ -781,7 +781,7 @@ static void swap_enter_activating(Swap *s) { + + fail: + log_unit_warning_errno(UNIT(s)->id, r, "%s failed to run 'swapon' task: %m", UNIT(s)->id); +- swap_enter_dead(s, SWAP_FAILURE_RESOURCES); ++ swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES); + } + + static void swap_enter_deactivating(Swap *s) { +@@ -811,7 +811,7 @@ static void swap_enter_deactivating(Swap *s) { + + fail: + log_unit_warning_errno(UNIT(s)->id, r, "%s failed to run 'swapoff' task: %m", UNIT(s)->id); +- swap_enter_active(s, SWAP_FAILURE_RESOURCES); ++ swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES); + } + + static int swap_start(Unit *u) { +@@ -824,11 +824,10 @@ static int swap_start(Unit *u) { + + if (s->state == SWAP_DEACTIVATING || + s->state == SWAP_DEACTIVATING_SIGTERM || +- s->state == SWAP_DEACTIVATING_SIGKILL || +- s->state == SWAP_ACTIVATING_SIGTERM || +- s->state == SWAP_ACTIVATING_SIGKILL) ++ s->state == SWAP_DEACTIVATING_SIGKILL) + return -EAGAIN; + ++ /* Already on it! */ + if (s->state == SWAP_ACTIVATING) + return 0; + +@@ -854,22 +853,30 @@ static int swap_stop(Unit *u) { + + assert(s); + +- if (s->state == SWAP_DEACTIVATING || +- s->state == SWAP_DEACTIVATING_SIGTERM || +- s->state == SWAP_DEACTIVATING_SIGKILL || +- s->state == SWAP_ACTIVATING_SIGTERM || +- s->state == SWAP_ACTIVATING_SIGKILL) ++ switch (s->state) { ++ ++ case SWAP_DEACTIVATING: ++ case SWAP_DEACTIVATING_SIGTERM: ++ case SWAP_DEACTIVATING_SIGKILL: ++ /* Already on it */ ++ return 0; ++ ++ case SWAP_ACTIVATING: ++ case SWAP_ACTIVATING_DONE: ++ /* There's a control process pending, directly enter kill mode */ ++ swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_SUCCESS); + return 0; + +- assert(s->state == SWAP_ACTIVATING || +- s->state == SWAP_ACTIVATING_DONE || +- s->state == SWAP_ACTIVE); ++ case SWAP_ACTIVE: ++ if (detect_container(NULL) > 0) ++ return -EPERM; + +- if (detect_container(NULL) > 0) +- return -EPERM; ++ swap_enter_deactivating(s); ++ return 1; + +- swap_enter_deactivating(s); +- return 1; ++ default: ++ assert_not_reached("Unexpected state."); ++ } + } + + static int swap_serialize(Unit *u, FILE *f, FDSet *fds) { +@@ -1002,10 +1009,8 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) { + + case SWAP_ACTIVATING: + case SWAP_ACTIVATING_DONE: +- case SWAP_ACTIVATING_SIGTERM: +- case SWAP_ACTIVATING_SIGKILL: + +- if (f == SWAP_SUCCESS) ++ if (f == SWAP_SUCCESS || s->from_proc_swaps) + swap_enter_active(s, f); + else + swap_enter_dead(s, f); +@@ -1015,7 +1020,7 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) { + case SWAP_DEACTIVATING_SIGKILL: + case SWAP_DEACTIVATING_SIGTERM: + +- swap_enter_dead(s, f); ++ swap_enter_dead_or_active(s, f); + break; + + default: +@@ -1037,7 +1042,7 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd + case SWAP_ACTIVATING: + case SWAP_ACTIVATING_DONE: + log_unit_warning(UNIT(s)->id, "%s activation timed out. Stopping.", UNIT(s)->id); +- swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT); ++ swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT); + break; + + case SWAP_DEACTIVATING: +@@ -1045,30 +1050,19 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd + swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT); + break; + +- case SWAP_ACTIVATING_SIGTERM: +- if (s->kill_context.send_sigkill) { +- log_unit_warning(UNIT(s)->id, "%s activation timed out. Killing.", UNIT(s)->id); +- swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT); +- } else { +- log_unit_warning(UNIT(s)->id, "%s activation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id); +- swap_enter_dead(s, SWAP_FAILURE_TIMEOUT); +- } +- break; +- + case SWAP_DEACTIVATING_SIGTERM: + if (s->kill_context.send_sigkill) { +- log_unit_warning(UNIT(s)->id, "%s deactivation timed out. Killing.", UNIT(s)->id); ++ log_unit_warning(UNIT(s)->id, "Swap process timed out. Killing."); + swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT); + } else { +- log_unit_warning(UNIT(s)->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id); +- swap_enter_dead(s, SWAP_FAILURE_TIMEOUT); ++ log_unit_warning(UNIT(s)->id, "Swap process timed out. Skipping SIGKILL. Ignoring."); ++ swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT); + } + break; + +- case SWAP_ACTIVATING_SIGKILL: + case SWAP_DEACTIVATING_SIGKILL: + log_unit_warning(UNIT(s)->id, "%s swap process still around after SIGKILL. Ignoring.", UNIT(s)->id); +- swap_enter_dead(s, SWAP_FAILURE_TIMEOUT); ++ swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT); + break; + + default: +@@ -1428,8 +1422,6 @@ static const char* const swap_state_table[_SWAP_STATE_MAX] = { + [SWAP_ACTIVATING_DONE] = "activating-done", + [SWAP_ACTIVE] = "active", + [SWAP_DEACTIVATING] = "deactivating", +- [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm", +- [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill", + [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm", + [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill", + [SWAP_FAILED] = "failed" +diff --git a/src/core/swap.h b/src/core/swap.h +index 914a2dbccd..f46873b5e1 100644 +--- a/src/core/swap.h ++++ b/src/core/swap.h +@@ -34,8 +34,6 @@ typedef enum SwapState { + SWAP_ACTIVATING_DONE, /* /sbin/swapon is running, and the swap is done. */ + SWAP_ACTIVE, + SWAP_DEACTIVATING, +- SWAP_ACTIVATING_SIGTERM, +- SWAP_ACTIVATING_SIGKILL, + SWAP_DEACTIVATING_SIGTERM, + SWAP_DEACTIVATING_SIGKILL, + SWAP_FAILED, diff --git a/SOURCES/0821-swap-finish-the-secondary-swap-units-jobs-if-deactiv.patch b/SOURCES/0821-swap-finish-the-secondary-swap-units-jobs-if-deactiv.patch new file mode 100644 index 00000000..a84e747a --- /dev/null +++ b/SOURCES/0821-swap-finish-the-secondary-swap-units-jobs-if-deactiv.patch @@ -0,0 +1,79 @@ +From e2cf8d5fcec71c1c4ca7223c51552847eb2a456e Mon Sep 17 00:00:00 2001 +From: HATAYAMA Daisuke +Date: Wed, 24 Jul 2019 23:54:48 -0400 +Subject: [PATCH] swap: finish the secondary swap units' jobs if deactivation + of the primary swap unit fails + +Currently, if deactivation of the primary swap unit fails: + + # LANG=C systemctl --no-pager stop dev-mapper-fedora\\x2dswap.swap + Job for dev-mapper-fedora\x2dswap.swap failed. + See "systemctl status "dev-mapper-fedora\\x2dswap.swap"" and "journalctl -xe" for details. + +then there are still the running stop jobs for all the secondary swap units +that follow the primary one: + + # systemctl list-jobs + JOB UNIT TYPE STATE + 3233 dev-disk-by\x2duuid-2dc8b9b1\x2da0a5\x2d44d8\x2d89c4\x2d6cdd26cd5ce0.swap stop running + 3232 dev-dm\x2d1.swap stop running + 3231 dev-disk-by\x2did-dm\x2duuid\x2dLVM\x2dyuXWpCCIurGzz2nkGCVnUFSi7GH6E3ZcQjkKLnF0Fil0RJmhoLN8fcOnDybWCMTj.swap stop running + 3230 dev-disk-by\x2did-dm\x2dname\x2dfedora\x2dswap.swap stop running + 3234 dev-fedora-swap.swap stop running + + 5 jobs listed. + +This remains endlessly because their JobTimeoutUSec is infinity: + + # LANG=C systemctl show -p JobTimeoutUSec dev-fedora-swap.swap + JobTimeoutUSec=infinity + +If this issue happens during system shutdown, the system shutdown appears to +get hang and the system will be forcibly shutdown or rebooted 30 minutes later +by the following configuration: + + # grep -E "^JobTimeout" /usr/lib/systemd/system/reboot.target + JobTimeoutSec=30min + JobTimeoutAction=reboot-force + +The scenario in the real world seems that there is some service unit with +KillMode=none, processes whose memory is being swapped out are not killed +during stop operation in the service unit and then swapoff command fails. + +On the other hand, it works well in successful case of swapoff command because +the secondary jobs monitor /proc/swaps file and can detect deletion of the +corresponding swap file. + +This commit fixes the issue by finishing the secondary swap units' jobs if +deactivation of the primary swap unit fails. + +Fixes: #11577 +(cherry picked from commit 9c1f969d40f84d5cc98d810bab8b24148b2d8928) + +Resolves: #1749621 +--- + src/core/swap.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/core/swap.c b/src/core/swap.c +index c9cce3d945..ff27936142 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -679,9 +679,15 @@ static void swap_enter_active(Swap *s, SwapResult f) { + static void swap_enter_dead_or_active(Swap *s, SwapResult f) { + assert(s); + +- if (s->from_proc_swaps) ++ if (s->from_proc_swaps) { ++ Swap *other; ++ + swap_enter_active(s, f); +- else ++ ++ LIST_FOREACH_OTHERS(same_devnode, other, s) ++ if (UNIT(other)->job) ++ swap_enter_dead_or_active(other, f); ++ } else + swap_enter_dead(s, f); + } + diff --git a/SOURCES/0822-core-add-a-new-unit-file-setting-CollectMode-for-twe.patch b/SOURCES/0822-core-add-a-new-unit-file-setting-CollectMode-for-twe.patch new file mode 100644 index 00000000..54e9aed7 --- /dev/null +++ b/SOURCES/0822-core-add-a-new-unit-file-setting-CollectMode-for-twe.patch @@ -0,0 +1,317 @@ +From 909d27fffffb28f4da7752be25e5c47990eba641 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 13 Nov 2017 17:14:07 +0100 +Subject: [PATCH] core: add a new unit file setting CollectMode= for tweaking + the GC logic + +Right now, the option only takes one of two possible values "inactive" +or "inactive-or-failed", the former being the default, and exposing same +behaviour as the status quo ante. If set to "inactive-or-failed" units +may be collected by the GC logic when in the "failed" state too. + +This logic should be a nicer alternative to using the "-" modifier for +ExecStart= and friends, as the exit data is collected and logged about +and only removed when the GC comes along. This should be useful in +particular for per-connection socket-activated services, as well as +"systemd-run" command lines that shall leave no artifacts in the +system. + +I was thinking about whether to expose this as a boolean, but opted for +an enum instead, as I have the suspicion other tweaks like this might be +a added later on, in which case we extend this setting instead of having +to add yet another one. + +Also, let's add some documentation for the GC logic. + +(cherry-picked from commit 5afe510c89f26b0e721b276a0e78af914b47f0b0) + +Resolves: #1817576 +--- + man/systemd.unit.xml | 56 +++++++++++++++++++++++++++ + src/core/dbus-unit.c | 20 ++++++++++ + src/core/load-fragment-gperf.gperf.m4 | 1 + + src/core/load-fragment.c | 2 + + src/core/load-fragment.h | 1 + + src/core/unit.c | 36 ++++++++++++++--- + src/core/unit.h | 13 +++++++ + 7 files changed, 124 insertions(+), 5 deletions(-) + +diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml +index 414749bae9..0c06add166 100644 +--- a/man/systemd.unit.xml ++++ b/man/systemd.unit.xml +@@ -303,6 +303,45 @@ + + + ++ ++ Unit Garbage Collection ++ ++ The system and service manager loads a unit's configuration automatically when a unit is referenced for the ++ first time. It will automatically unload the unit configuration and state again when the unit is not needed anymore ++ ("garbage collection"). A unit may be referenced through a number of different mechanisms: ++ ++ ++ Another loaded unit references it with a dependency such as After=, ++ Wants=, … ++ ++ The unit is currently starting, running, reloading or stopping. ++ ++ The unit is currently in the failed state. (But see below.) ++ ++ A job for the unit is pending. ++ ++ The unit is pinned by an active IPC client program. ++ ++ The unit is a special "perpetual" unit that is always active and loaded. Examples for perpetual ++ units are the root mount unit -.mount or the scope unit init.scope that ++ the service manager itself lives in. ++ ++ The unit has running processes associated with it. ++ ++ ++ The garbage collection logic may be altered with the CollectMode= option, which allows ++ configuration whether automatic unloading of units that are in failed state is permissible, ++ see below. ++ ++ Note that when a unit's configuration and state is unloaded, all execution results, such as exit codes, exit ++ signals, resource consumption and other statistics are lost, except for what is stored in the log subsystem. ++ ++ Use systemctl daemon-reload or an equivalent command to reload unit configuration while ++ the unit is already loaded. In this case all configuration settings are flushed out and replaced with the new ++ configuration (which however might not be in effect immediately), however all runtime state is ++ saved/restored. ++ ++ + + [Unit] Section Options + +@@ -666,6 +705,23 @@ + ones. + + ++ ++ CollectMode= ++ ++ Tweaks the "garbage collection" algorithm for this unit. Takes one of ++ or . If set to the unit will be unloaded if it is ++ in the inactive state and is not referenced by clients, jobs or other units — however it ++ is not unloaded if it is in the failed state. In mode, failed ++ units are not unloaded until the user invoked systemctl reset-failed on them to reset the ++ failed state, or an equivalent command. This behaviour is altered if this option is set to ++ : in this case the unit is unloaded even if the unit is in a ++ failed state, and thus an explicitly resetting of the failed state is ++ not necessary. Note that if this mode is used unit results (such as exit codes, exit signals, consumed ++ resources, …) are flushed out immediately after the unit completed, except for what is stored in the logging ++ subsystem. Defaults to . ++ ++ ++ + + JobTimeoutSec= + JobTimeoutAction= +diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c +index 77073308c8..ea6ac6767f 100644 +--- a/src/core/dbus-unit.c ++++ b/src/core/dbus-unit.c +@@ -34,6 +34,7 @@ + static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState); + static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode); + static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction); ++static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode); + + static int property_get_names( + sd_bus *bus, +@@ -605,6 +606,7 @@ const sd_bus_vtable bus_unit_vtable[] = { + SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0), + SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST), ++ SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0), + + SD_BUS_METHOD("Start", "s", "o", method_start, 0), + SD_BUS_METHOD("Stop", "s", "o", method_stop, 0), +@@ -937,6 +939,24 @@ static int bus_unit_set_transient_property( + + return 1; + ++ } else if (streq(name, "CollectMode")) { ++ const char *s; ++ CollectMode m; ++ ++ r = sd_bus_message_read(message, "s", &s); ++ if (r < 0) ++ return r; ++ ++ m = collect_mode_from_string(s); ++ if (m < 0) ++ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown garbage collection mode: %s", s); ++ ++ if (mode != UNIT_CHECK) { ++ u->collect_mode = m; ++ unit_write_drop_in_format(u, mode, name, "[Unit]\nCollectMode=%s", collect_mode_to_string(m)); ++ } ++ ++ return 1; + } else if (streq(name, "Slice") && unit_get_cgroup_context(u)) { + const char *s; + +diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 +index 664bba0ef6..3a8ee96fa3 100644 +--- a/src/core/load-fragment-gperf.gperf.m4 ++++ b/src/core/load-fragment-gperf.gperf.m4 +@@ -200,6 +200,7 @@ Unit.AssertCapability, config_parse_unit_condition_string, CONDITION_C + Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts) + Unit.AssertACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, asserts) + Unit.AssertNull, config_parse_unit_condition_null, 0, offsetof(Unit, asserts) ++Unit.CollectMode, config_parse_collect_mode, 0, offsetof(Unit, collect_mode) + m4_dnl + Service.PIDFile, config_parse_unit_path_printf, 0, offsetof(Service, pid_file) + Service.ExecStartPre, config_parse_exec, SERVICE_EXEC_START_PRE, offsetof(Service, exec_command) +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 1721fea8f3..8d73d5df41 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -98,6 +98,8 @@ int config_parse_warn_compat( + return 0; + } + ++DEFINE_CONFIG_PARSE_ENUM(config_parse_collect_mode, collect_mode, CollectMode, "Failed to parse garbage collection mode"); ++ + int config_parse_unit_deps(const char *unit, + const char *filename, + unsigned line, +diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h +index 4bd286c11b..7b1193ddb2 100644 +--- a/src/core/load-fragment.h ++++ b/src/core/load-fragment.h +@@ -110,6 +110,7 @@ int config_parse_cpu_quota(const char *unit, const char *filename, unsigned line + int config_parse_protect_home(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); + int config_parse_protect_system(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); + int config_parse_bus_name(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); ++int config_parse_collect_mode(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); + + /* gperf prototypes */ + const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length); +diff --git a/src/core/unit.c b/src/core/unit.c +index eff9fdbe70..502830d2cb 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -67,7 +67,7 @@ const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = { + [UNIT_TIMER] = &timer_vtable, + [UNIT_PATH] = &path_vtable, + [UNIT_SLICE] = &slice_vtable, +- [UNIT_SCOPE] = &scope_vtable ++ [UNIT_SCOPE] = &scope_vtable, + }; + + static int maybe_warn_about_dependency(const char *id, const char *other, UnitDependency dependency); +@@ -285,6 +285,7 @@ int unit_set_description(Unit *u, const char *description) { + + bool unit_may_gc(Unit *u) { + UnitActiveState state; ++ + assert(u); + + /* Checks whether the unit is ready to be unloaded for garbage collection. +@@ -308,16 +309,31 @@ bool unit_may_gc(Unit *u) { + UNIT_VTABLE(u)->release_resources) + UNIT_VTABLE(u)->release_resources(u); + +- /* But we keep the unit object around for longer when it is referenced or configured to not be gc'ed */ +- if (state != UNIT_INACTIVE) +- return false; +- + if (UNIT_VTABLE(u)->no_gc) + return false; + + if (u->no_gc) + return false; + ++ /* But we keep the unit object around for longer when it is referenced or configured to not be gc'ed */ ++ switch (u->collect_mode) { ++ ++ case COLLECT_INACTIVE: ++ if (state != UNIT_INACTIVE) ++ return false; ++ ++ break; ++ ++ case COLLECT_INACTIVE_OR_FAILED: ++ if (!IN_SET(state, UNIT_INACTIVE, UNIT_FAILED)) ++ return false; ++ ++ break; ++ ++ default: ++ assert_not_reached("Unknown garbage collection mode"); ++ } ++ + if (UNIT_VTABLE(u)->may_gc && !UNIT_VTABLE(u)->may_gc(u)) + return false; + +@@ -896,6 +912,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { + "%s\tMay GC: %s\n" + "%s\tNeed Daemon Reload: %s\n" + "%s\tTransient: %s\n" ++ "%s\tGarbage Collection Mode: %s\n" + "%s\tSlice: %s\n" + "%s\tCGroup: %s\n" + "%s\tCGroup realized: %s\n" +@@ -913,6 +930,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { + prefix, yes_no(unit_may_gc(u)), + prefix, yes_no(unit_need_daemon_reload(u)), + prefix, yes_no(u->transient), ++ prefix, collect_mode_to_string(u->collect_mode), + prefix, strna(unit_slice_name(u)), + prefix, strna(u->cgroup_path), + prefix, yes_no(u->cgroup_realized), +@@ -3732,3 +3750,11 @@ static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = { + }; + + DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState); ++ ++static const char* const collect_mode_table[_COLLECT_MODE_MAX] = { ++ [COLLECT_INACTIVE] = "inactive", ++ [COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed", ++}; ++ ++DEFINE_STRING_TABLE_LOOKUP(collect_mode, CollectMode); ++ +diff --git a/src/core/unit.h b/src/core/unit.h +index 3b0fd8d9df..8cc7a9e0b2 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -60,6 +60,13 @@ typedef enum KillOperation { + KILL_ABORT, + } KillOperation; + ++typedef enum CollectMode { ++ COLLECT_INACTIVE, ++ COLLECT_INACTIVE_OR_FAILED, ++ _COLLECT_MODE_MAX, ++ _COLLECT_MODE_INVALID = -1, ++} CollectMode; ++ + static inline bool UNIT_IS_ACTIVE_OR_RELOADING(UnitActiveState t) { + return t == UNIT_ACTIVE || t == UNIT_RELOADING; + } +@@ -198,6 +205,9 @@ struct Unit { + /* How to start OnFailure units */ + JobMode on_failure_job_mode; + ++ /* Tweaking the GC logic */ ++ CollectMode collect_mode; ++ + /* Garbage collect us we nobody wants or requires us anymore */ + bool stop_when_unneeded; + +@@ -630,6 +640,9 @@ pid_t unit_main_pid(Unit *u); + const char *unit_active_state_to_string(UnitActiveState i) _const_; + UnitActiveState unit_active_state_from_string(const char *s) _pure_; + ++const char* collect_mode_to_string(CollectMode m) _const_; ++CollectMode collect_mode_from_string(const char *s) _pure_; ++ + bool unit_needs_console(Unit *u); + + /* Macros which append UNIT= or USER_UNIT= to the message */ diff --git a/SOURCES/0823-run-add-G-as-shortcut-for-property-CollectMode-inact.patch b/SOURCES/0823-run-add-G-as-shortcut-for-property-CollectMode-inact.patch new file mode 100644 index 00000000..00c6d87a --- /dev/null +++ b/SOURCES/0823-run-add-G-as-shortcut-for-property-CollectMode-inact.patch @@ -0,0 +1,108 @@ +From c2975479c63cafea5a5f0254f4525136244f3301 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 13 Nov 2017 17:17:53 +0100 +Subject: [PATCH] run: add "-G" as shortcut for + "--property=CollectMode=inactive-or-failed" + +This option is likely to be very useful for systemd-run invocations, +hence let's add a shortcut for it. + +With this new concepts it's now very easy to put together systemd-run +invocations that leave zero artifacts in the system, including when they +fail. + +(cherry-picked from commit fe9d0be90ba142bf06d43a831d8be53283415caa) + +Related: #1817576 +--- + man/systemd-run.xml | 15 +++++++++++++++ + src/run/run.c | 15 ++++++++++++++- + 2 files changed, 29 insertions(+), 1 deletion(-) + +diff --git a/man/systemd-run.xml b/man/systemd-run.xml +index f46fc3abf4..97cf2879eb 100644 +--- a/man/systemd-run.xml ++++ b/man/systemd-run.xml +@@ -294,6 +294,21 @@ + set-property command. + + ++ ++ ++ ++ ++ Unload the transient unit after it completed, even if it failed. Normally, without this option, ++ all units that ran and failed are kept in memory until the user explicitly resets their failure state with ++ systemctl reset-failed or an equivalent command. On the other hand, units that ran ++ successfully are unloaded immediately. If this option is turned on the "garbage collection" of units is more ++ aggressive, and unloads units regardless if they exited successfully or failed. This option is a shortcut for ++ --property=CollectMode=inactive-or-failed, see the explanation for ++ CollectMode= in ++ systemd.unit5 for further ++ information. ++ ++ + + + +diff --git a/src/run/run.c b/src/run/run.c +index bbb542b65b..df97641f87 100644 +--- a/src/run/run.c ++++ b/src/run/run.c +@@ -60,6 +60,7 @@ static usec_t arg_on_unit_inactive = 0; + static char *arg_on_calendar = NULL; + static char **arg_timer_property = NULL; + static bool arg_quiet = false; ++static bool arg_aggressive_gc = false; + + static void help(void) { + printf("%s [OPTIONS...] {COMMAND} [ARGS...]\n\n" +@@ -84,6 +85,7 @@ static void help(void) { + " --setenv=NAME=VALUE Set environment\n" + " -t --pty Run service on pseudo tty\n" + " -q --quiet Suppress information messages during runtime\n\n" ++ " -G --collect Unload unit after it ran, even when failed\n\n" + "Timer options:\n\n" + " --on-active=SECONDS Run after SECONDS delay\n" + " --on-boot=SECONDS Run SECONDS after machine was booted up\n" +@@ -153,6 +155,7 @@ static int parse_argv(int argc, char *argv[]) { + { "on-unit-inactive", required_argument, NULL, ARG_ON_UNIT_INACTIVE }, + { "on-calendar", required_argument, NULL, ARG_ON_CALENDAR }, + { "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY }, ++ { "collect", no_argument, NULL, 'G' }, + {}, + }; + +@@ -162,7 +165,7 @@ static int parse_argv(int argc, char *argv[]) { + assert(argc >= 0); + assert(argv); + +- while ((c = getopt_long(argc, argv, "+hrH:M:p:tq", options, NULL)) >= 0) ++ while ((c = getopt_long(argc, argv, "+hrH:M:p:tqG", options, NULL)) >= 0) + + switch (c) { + +@@ -329,6 +332,10 @@ static int parse_argv(int argc, char *argv[]) { + + break; + ++ case 'G': ++ arg_aggressive_gc = true; ++ break; ++ + case '?': + return -EINVAL; + +@@ -382,6 +389,12 @@ static int transient_unit_set_properties(sd_bus_message *m, char **properties) { + if (r < 0) + return r; + ++ if (arg_aggressive_gc) { ++ r = sd_bus_message_append(m, "(sv)", "CollectMode", "s", "inactive-or-failed"); ++ if (r < 0) ++ return r; ++ } ++ + STRV_FOREACH(i, properties) { + r = sd_bus_message_open_container(m, 'r', "sv"); + if (r < 0) diff --git a/SOURCES/0824-core-clarify-that-the-CollectMode-bus-property-is-co.patch b/SOURCES/0824-core-clarify-that-the-CollectMode-bus-property-is-co.patch new file mode 100644 index 00000000..4d8a904e --- /dev/null +++ b/SOURCES/0824-core-clarify-that-the-CollectMode-bus-property-is-co.patch @@ -0,0 +1,27 @@ +From b12e40d3e16b998542faef3fe916d5605b3fe0cb Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 29 Nov 2018 16:40:13 +0100 +Subject: [PATCH] core: clarify that the CollectMode bus property is constant + +it's configured from unit files only, and hence is constant. + +(cherry-picked from commit 641e0d7a1bf4e24f5bf5f99a2d74a97635335c8e) + +Related: #1817576 +--- + src/core/dbus-unit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c +index ea6ac6767f..8febdfd021 100644 +--- a/src/core/dbus-unit.c ++++ b/src/core/dbus-unit.c +@@ -606,7 +606,7 @@ const sd_bus_vtable bus_unit_vtable[] = { + SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0), + SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST), +- SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0), ++ SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), SD_BUS_VTABLE_PROPERTY_CONST), + + SD_BUS_METHOD("Start", "s", "o", method_start, 0), + SD_BUS_METHOD("Stop", "s", "o", method_stop, 0), diff --git a/SOURCES/0825-udev-rules-make-tape-changers-also-apprear-in-dev-ta.patch b/SOURCES/0825-udev-rules-make-tape-changers-also-apprear-in-dev-ta.patch new file mode 100644 index 00000000..f084f81f --- /dev/null +++ b/SOURCES/0825-udev-rules-make-tape-changers-also-apprear-in-dev-ta.patch @@ -0,0 +1,57 @@ +From 1b723aea42e29becd0be2fdef990401803dbfba6 Mon Sep 17 00:00:00 2001 +From: Joerg Steffens +Date: Tue, 21 Nov 2017 12:21:49 +0100 +Subject: [PATCH] udev-rules: make tape-changers also apprear in + /dev/tape/by-path/ + +It is important to be able to access tape changer ("Medium Changers") by +persistant name. +While tape devices can be accessed via /dev/tape/by-id/ and +/dev/tape/by-path/, tape-changers could only be accessed by +/dev/tape/by-id/. +However, in some cases, especially when accessing Amazon Webservice +Storage Gateway VTLs (or accessing iSCSI VTLs in general?) this does not +work, as all tape devices and the tape changer have the same ENV{ID_SERIAL}. +The results is, that only the last device is available in +/dev/tape/by-id/, as the former devices have been overwritten. + +As this behavior is hard to change without breaking consistentcy, +this additional device in /dev/tape/by-path/ can be used to access the medium changes. +The tape devices can also be accessed by this path. + +The content of the directory will now look like: + + # SCSI tape device, rewind (unchanged) + /dev/tape/by-path/$env{ID_PATH} -> ../../st* + + # SCSI tape device, no-rewind (unchanged) + /dev/tape/by-path/$env{ID_PATH}-nst -> ../../nst* + + # SCSI tape changer device (newly added) + /dev/tape/by-path/$env{ID_PATH}-changer -> ../../sg* + +Tape devices and tape changer have different ID_PATHs. +SCSI tape changer get the suffix "-changer" +to make them better distinguishable from tape devices. + +(cherry-picked from commmit 7f8ddf96a25162f06bd94a684cf700c128d18142) + +Resolves: #1814028 +--- + rules/60-persistent-storage-tape.rules | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/rules/60-persistent-storage-tape.rules b/rules/60-persistent-storage-tape.rules +index f2eabd92a8..99898c147b 100644 +--- a/rules/60-persistent-storage-tape.rules ++++ b/rules/60-persistent-storage-tape.rules +@@ -8,6 +8,9 @@ ACTION=="remove", GOTO="persistent_storage_tape_end" + SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{program}="scsi_id --sg-version=3 --export --whitelisted -d $devnode", \ + SYMLINK+="tape/by-id/scsi-$env{ID_SERIAL}" + ++SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{builtin}="path_id", \ ++ SYMLINK+="tape/by-path/$env{ID_PATH}-changer" ++ + SUBSYSTEM!="scsi_tape", GOTO="persistent_storage_tape_end" + + KERNEL=="st*[0-9]|nst*[0-9]", ATTRS{ieee1394_id}=="?*", ENV{ID_SERIAL}="$attr{ieee1394_id}", ENV{ID_BUS}="ieee1394" diff --git a/SOURCES/0826-logind-check-PolicyKit-before-allowing-VT-switch.patch b/SOURCES/0826-logind-check-PolicyKit-before-allowing-VT-switch.patch new file mode 100644 index 00000000..12225077 --- /dev/null +++ b/SOURCES/0826-logind-check-PolicyKit-before-allowing-VT-switch.patch @@ -0,0 +1,209 @@ +From fb419649754767124f30dba36f8fdbd114b0e9d7 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 22 Jan 2020 12:04:38 +0100 +Subject: [PATCH] logind: check PolicyKit before allowing VT switch + +Let's lock this down a bit. Effectively nothing much changes, since the +default PK policy will allow users on the VT to change VT. Only users +with no local VT session won't be able to switch VTs. + +(cherry picked from commit 4acf0cfd2f92edb94ad48d04f1ce6c9ab4e19d55) + +Resolves: #1797672 +--- + src/login/logind-dbus.c | 18 ++++++-- + src/login/logind-seat-dbus.c | 50 +++++++++++++++++++++- + src/login/logind-session-dbus.c | 16 ++++++- + src/login/logind-session.h | 2 + + src/login/org.freedesktop.login1.policy.in | 10 +++++ + 5 files changed, 89 insertions(+), 7 deletions(-) + +diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c +index 63b9a0df36..019aa193f5 100644 +--- a/src/login/logind-dbus.c ++++ b/src/login/logind-dbus.c +@@ -854,11 +854,9 @@ static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *u + if (r < 0) + return r; + +- r = session_activate(session); +- if (r < 0) +- return r; ++ /* PolicyKit is done by bus_session_method_activate() */ + +- return sd_bus_reply_method_return(message, NULL); ++ return bus_session_method_activate(bus, message, session, error); + } + + static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { +@@ -890,6 +888,18 @@ static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, + if (session->seat != seat) + return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name); + ++ r = bus_verify_polkit_async( ++ message, ++ CAP_SYS_ADMIN, ++ "org.freedesktop.login1.chvt", ++ false, ++ &m->polkit_registry, ++ error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Will call us back */ ++ + r = session_activate(session); + if (r < 0) + return r; +diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c +index 50b0b8842f..f49e416fce 100644 +--- a/src/login/logind-seat-dbus.c ++++ b/src/login/logind-seat-dbus.c +@@ -229,6 +229,18 @@ static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *u + if (session->seat != s) + return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id); + ++ r = bus_verify_polkit_async( ++ message, ++ CAP_SYS_ADMIN, ++ "org.freedesktop.login1.chvt", ++ false, ++ &s->manager->polkit_registry, ++ error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Will call us back */ ++ + r = session_activate(session); + if (r < 0) + return r; +@@ -250,7 +262,19 @@ static int method_switch_to(sd_bus *bus, sd_bus_message *message, void *userdata + return r; + + if (to <= 0) +- return -EINVAL; ++ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid virtual terminal"); ++ ++ r = bus_verify_polkit_async( ++ message, ++ CAP_SYS_ADMIN, ++ "org.freedesktop.login1.chvt", ++ false, ++ &s->manager->polkit_registry, ++ error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Will call us back */ + + r = seat_switch_to(s, to); + if (r < 0) +@@ -267,6 +291,18 @@ static int method_switch_to_next(sd_bus *bus, sd_bus_message *message, void *use + assert(message); + assert(s); + ++ r = bus_verify_polkit_async( ++ message, ++ CAP_SYS_ADMIN, ++ "org.freedesktop.login1.chvt", ++ false, ++ &s->manager->polkit_registry, ++ error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Will call us back */ ++ + r = seat_switch_to_next(s); + if (r < 0) + return r; +@@ -282,6 +318,18 @@ static int method_switch_to_previous(sd_bus *bus, sd_bus_message *message, void + assert(message); + assert(s); + ++ r = bus_verify_polkit_async( ++ message, ++ CAP_SYS_ADMIN, ++ "org.freedesktop.login1.chvt", ++ false, ++ &s->manager->polkit_registry, ++ error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Will call us back */ ++ + r = seat_switch_to_previous(s); + if (r < 0) + return r; +diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c +index 75b7186e8f..0ec4196257 100644 +--- a/src/login/logind-session-dbus.c ++++ b/src/login/logind-session-dbus.c +@@ -213,7 +213,7 @@ static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata + return sd_bus_reply_method_return(message, NULL); + } + +-static int method_activate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { ++int bus_session_method_activate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { + Session *s = userdata; + int r; + +@@ -221,6 +221,18 @@ static int method_activate(sd_bus *bus, sd_bus_message *message, void *userdata, + assert(message); + assert(s); + ++ r = bus_verify_polkit_async( ++ message, ++ CAP_SYS_ADMIN, ++ "org.freedesktop.login1.chvt", ++ false, ++ &s->manager->polkit_registry, ++ error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Will call us back */ ++ + r = session_activate(s); + if (r < 0) + return r; +@@ -506,7 +518,7 @@ const sd_bus_vtable session_vtable[] = { + SD_BUS_PROPERTY("LockedHint", "b", property_get_locked_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + + SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), +- SD_BUS_METHOD("Activate", NULL, NULL, method_activate, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("Activate", NULL, NULL, bus_session_method_activate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Lock", NULL, NULL, method_lock, 0), + SD_BUS_METHOD("Unlock", NULL, NULL, method_lock, 0), + SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED), +diff --git a/src/login/logind-session.h b/src/login/logind-session.h +index d662082d85..b498f49592 100644 +--- a/src/login/logind-session.h ++++ b/src/login/logind-session.h +@@ -184,3 +184,5 @@ void session_leave_vt(Session *s); + bool session_is_controller(Session *s, const char *sender); + int session_set_controller(Session *s, const char *sender, bool force); + void session_drop_controller(Session *s); ++ ++int bus_session_method_activate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error); +diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in +index 49094eeddb..fa51ed8d74 100644 +--- a/src/login/org.freedesktop.login1.policy.in ++++ b/src/login/org.freedesktop.login1.policy.in +@@ -270,4 +270,14 @@ + org.freedesktop.login1.hibernate + + ++ ++ Change Session ++ Authentication is required for changing the virtual terminal. ++ ++ auth_admin_keep ++ auth_admin_keep ++ yes ++ ++ ++ + diff --git a/SOURCES/0827-timer-don-t-use-persietent-file-timestamps-from-the-.patch b/SOURCES/0827-timer-don-t-use-persietent-file-timestamps-from-the-.patch new file mode 100644 index 00000000..50ced8ad --- /dev/null +++ b/SOURCES/0827-timer-don-t-use-persietent-file-timestamps-from-the-.patch @@ -0,0 +1,50 @@ +From 016f8f9305a5584d718579f90ee537398dfed33b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 14 Sep 2017 18:26:10 +0200 +Subject: [PATCH] timer: don't use persietent file timestamps from the future + (#6823) + +Also, use the mtime rather than the atime of the timestamp file. While +the atime is not completely wrong, the mtime appears more appropriate +as that's what we actually explicitly change, and is not effected by +mere reading. + +Fixes: #6821 +(cherry picked from commit 77542a7905520f1d637912bf47bddb4855506e41) + +Resolves: #1769923 +--- + src/core/timer.c | 20 +++++++++++++++++--- + 1 file changed, 17 insertions(+), 3 deletions(-) + +diff --git a/src/core/timer.c b/src/core/timer.c +index 1d4868643a..fb192d558a 100644 +--- a/src/core/timer.c ++++ b/src/core/timer.c +@@ -595,9 +595,23 @@ static int timer_start(Unit *u) { + if (t->stamp_path) { + struct stat st; + +- if (stat(t->stamp_path, &st) >= 0) +- t->last_trigger.realtime = timespec_load(&st.st_atim); +- else if (errno == ENOENT) ++ if (stat(t->stamp_path, &st) >= 0) { ++ usec_t ft; ++ ++ /* Load the file timestamp, but only if it is actually in the past. If it is in the future, ++ * something is wrong with the system clock. */ ++ ++ ft = timespec_load(&st.st_mtim); ++ if (ft < now(CLOCK_REALTIME)) ++ t->last_trigger.realtime = ft; ++ else { ++ char z[FORMAT_TIMESTAMP_MAX]; ++ ++ log_unit_warning(u->id, "%s not using persistent file timestamp %s as it is in the future.", ++ u->id, format_timestamp(z, sizeof(z), ft)); ++ } ++ ++ } else if (errno == ENOENT) + /* The timer has never run before, + * make sure a stamp file exists. + */ diff --git a/SOURCES/0828-core-transition-to-FINAL_SIGTERM-state-after-ExecSto.patch b/SOURCES/0828-core-transition-to-FINAL_SIGTERM-state-after-ExecSto.patch new file mode 100644 index 00000000..9b34f910 --- /dev/null +++ b/SOURCES/0828-core-transition-to-FINAL_SIGTERM-state-after-ExecSto.patch @@ -0,0 +1,193 @@ +From b1135a4f292a4bc193bcef768898d06f8b732215 Mon Sep 17 00:00:00 2001 +From: Anita Zhang +Date: Sat, 25 Jan 2020 16:46:16 +0100 +Subject: [PATCH] core: transition to FINAL_SIGTERM state after ExecStopPost= + +Fixes #14566 + +(cherry picked from commit c1566ef0d22ed786b9ecf4c476e53b8a91e67578) + +Resolves: #1766477 +--- + src/core/service.c | 10 +++ + test/TEST-47-ISSUE-14566/Makefile | 1 + + test/TEST-47-ISSUE-14566/repro.sh | 5 ++ + test/TEST-47-ISSUE-14566/test.sh | 91 +++++++++++++++++++++++++++ + test/TEST-47-ISSUE-14566/testsuite.sh | 21 +++++++ + 5 files changed, 128 insertions(+) + create mode 120000 test/TEST-47-ISSUE-14566/Makefile + create mode 100755 test/TEST-47-ISSUE-14566/repro.sh + create mode 100755 test/TEST-47-ISSUE-14566/test.sh + create mode 100755 test/TEST-47-ISSUE-14566/testsuite.sh + +diff --git a/src/core/service.c b/src/core/service.c +index e32cdf4594..7f0e6df412 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -2751,6 +2751,12 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + break; + + case SERVICE_STOP_POST: ++ ++ if (control_pid_good(s) <= 0) ++ service_enter_signal(s, SERVICE_FINAL_SIGTERM, f); ++ ++ break; ++ + case SERVICE_FINAL_SIGTERM: + case SERVICE_FINAL_SIGKILL: + +@@ -2894,6 +2900,10 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + break; + + case SERVICE_STOP_POST: ++ if (main_pid_good(s) <= 0) ++ service_enter_signal(s, SERVICE_FINAL_SIGTERM, f); ++ break; ++ + case SERVICE_FINAL_SIGTERM: + case SERVICE_FINAL_SIGKILL: + if (main_pid_good(s) <= 0) +diff --git a/test/TEST-47-ISSUE-14566/Makefile b/test/TEST-47-ISSUE-14566/Makefile +new file mode 120000 +index 0000000000..e9f93b1104 +--- /dev/null ++++ b/test/TEST-47-ISSUE-14566/Makefile +@@ -0,0 +1 @@ ++../TEST-01-BASIC/Makefile +\ No newline at end of file +diff --git a/test/TEST-47-ISSUE-14566/repro.sh b/test/TEST-47-ISSUE-14566/repro.sh +new file mode 100755 +index 0000000000..5217602257 +--- /dev/null ++++ b/test/TEST-47-ISSUE-14566/repro.sh +@@ -0,0 +1,5 @@ ++#!/bin/bash ++ ++sleep infinity & ++echo $! > /leakedtestpid ++wait $! +diff --git a/test/TEST-47-ISSUE-14566/test.sh b/test/TEST-47-ISSUE-14566/test.sh +new file mode 100755 +index 0000000000..35d72d17ee +--- /dev/null ++++ b/test/TEST-47-ISSUE-14566/test.sh +@@ -0,0 +1,91 @@ ++#!/bin/bash ++TEST_DESCRIPTION="Test that KillMode=mixed does not leave left over proccesses with ExecStopPost=" ++. $TEST_BASE_DIR/test-functions ++ ++check_result_qemu() { ++ ret=1 ++ mkdir -p $TESTDIR/root ++ mount ${LOOPDEV}p1 $TESTDIR/root ++ [[ -e $TESTDIR/root/testok ]] && ret=0 ++ [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR ++ [[ -f $TESTDIR/root/var/log/journal ]] && cp -a $TESTDIR/root/var/log/journal $TESTDIR ++ umount $TESTDIR/root ++ [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed ++ ls -l $TESTDIR/journal/*/*.journal ++ test -s $TESTDIR/failed && ret=$(($ret+1)) ++ return $ret ++} ++ ++test_run() { ++ if run_qemu; then ++ check_result_qemu || return 1 ++ else ++ dwarn "can't run QEMU, skipping" ++ fi ++ if check_nspawn; then ++ run_nspawn ++ check_result_nspawn || return 1 ++ else ++ dwarn "can't run systemd-nspawn, skipping" ++ fi ++ return 0 ++} ++ ++test_setup() { ++ create_empty_image ++ mkdir -p $TESTDIR/root ++ mount ${LOOPDEV}p1 $TESTDIR/root ++ ++ ( ++ LOG_LEVEL=5 ++ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) ++ ++ setup_basic_environment ++ ++ # mask some services that we do not want to run in these tests ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service ++ ++ # setup the testsuite service ++ cat >$initdir/etc/systemd/system/testsuite.service < $initdir/etc/systemd/system/issue_14566_test.service << EOF ++[Unit] ++Description=Issue 14566 Repro ++ ++[Service] ++ExecStart=/repro.sh ++ExecStopPost=/bin/true ++KillMode=mixed ++EOF ++ ++ cp testsuite.sh $initdir/ ++ cp repro.sh $initdir/ ++ ++ setup_testsuite ++ ) ++ setup_nspawn_root ++ ++ ddebug "umount $TESTDIR/root" ++ umount $TESTDIR/root ++} ++ ++test_cleanup() { ++ umount $TESTDIR/root 2>/dev/null ++ [[ $LOOPDEV ]] && losetup -d $LOOPDEV ++ return 0 ++} ++ ++do_test "$@" +diff --git a/test/TEST-47-ISSUE-14566/testsuite.sh b/test/TEST-47-ISSUE-14566/testsuite.sh +new file mode 100755 +index 0000000000..6363266713 +--- /dev/null ++++ b/test/TEST-47-ISSUE-14566/testsuite.sh +@@ -0,0 +1,21 @@ ++#!/bin/bash ++set -ex ++ ++systemd-analyze set-log-level debug ++ ++systemctl start issue_14566_test ++systemctl status issue_14566_test ++ ++leaked_pid=$(cat /leakedtestpid) ++ ++systemctl stop issue_14566_test ++ ++# Leaked PID will still be around if we're buggy. ++# I personally prefer to see 42. ++ps -p "$leaked_pid" && exit 42 ++ ++systemd-analyze log-level info ++ ++echo OK > /testok ++ ++exit 0 diff --git a/SOURCES/0829-bus_open-leak-sd_event_source-when-udevadm-trigger.patch b/SOURCES/0829-bus_open-leak-sd_event_source-when-udevadm-trigger.patch new file mode 100644 index 00000000..7be3f375 --- /dev/null +++ b/SOURCES/0829-bus_open-leak-sd_event_source-when-udevadm-trigger.patch @@ -0,0 +1,30 @@ +From b88483b804e92a59800e8785c87d17a7213aafc4 Mon Sep 17 00:00:00 2001 +From: ven <2988994+hexiaowen@users.noreply.github.com> +Date: Wed, 22 May 2019 14:24:28 +0800 +Subject: [PATCH] =?UTF-8?q?bus=5Fopen=20leak=20sd=5Fevent=5Fsource=20when?= + =?UTF-8?q?=20udevadm=20trigger=E3=80=82?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On my host, when executing the udevadm trigger, I only receive the change event, which causes memleak + +(cherry picked from commit b2774a3ae692113e1f47a336a6c09bac9cfb49ad) + +Resolves: #1798503 +--- + src/login/logind-button.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/login/logind-button.c b/src/login/logind-button.c +index d7211e66ce..9145176e58 100644 +--- a/src/login/logind-button.c ++++ b/src/login/logind-button.c +@@ -259,6 +259,7 @@ int button_open(Button *b) { + goto fail; + } + ++ b->io_event_source = sd_event_source_unref(b->io_event_source); + r = sd_event_add_io(b->manager->event, &b->io_event_source, b->fd, EPOLLIN, button_dispatch, b); + if (r < 0) { + log_error_errno(r, "Failed to add button event: %m"); diff --git a/SOURCES/0830-journal-remote-split-mode-host-remove-port-from-jour.patch b/SOURCES/0830-journal-remote-split-mode-host-remove-port-from-jour.patch new file mode 100644 index 00000000..ae4bece8 --- /dev/null +++ b/SOURCES/0830-journal-remote-split-mode-host-remove-port-from-jour.patch @@ -0,0 +1,117 @@ +From 21b3ef4130291a1e3c184bb47c80cb962b32b782 Mon Sep 17 00:00:00 2001 +From: Klearchos Chaloulos +Date: Tue, 1 Dec 2015 19:29:59 +0200 +Subject: [PATCH] journal-remote: split-mode=host, remove port from journal + filename + +When constructing the journal filename to store logs from a remote host, remove the port of the tcp connection, as the port will change with every reboot/connection loss between sender/reveiver machines. Having the port in the filename will cause a new journal file to be created for every reboot or connection loss. +For the implementation, a new argument "bool include_port" is added to the getpeername_pretty() function. This is passed to the sockaddr_pretty() function. The value of the include_port argument is set to true in all calls of getpeername_pretty(), except for 2 calls in journal-remote.c, where it is set to false. + +(cherry picked from commit 366b7db4b65b994cd33cf4fd3c1be429be561307) + +Resolves: #1244691 +--- + src/activate/activate.c | 2 +- + src/core/service.c | 2 +- + src/journal-remote/journal-remote.c | 4 ++-- + src/shared/socket-util.c | 4 ++-- + src/shared/socket-util.h | 2 +- + src/socket-proxy/socket-proxyd.c | 2 +- + 6 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/src/activate/activate.c b/src/activate/activate.c +index 2689934c40..a456af1573 100644 +--- a/src/activate/activate.c ++++ b/src/activate/activate.c +@@ -241,7 +241,7 @@ static int do_accept(const char* name, char **argv, char **envp, int fd) { + } + + getsockname_pretty(fd2, &local); +- getpeername_pretty(fd2, &peer); ++ getpeername_pretty(fd2, true, &peer); + log_info("Connection from %s to %s", strna(peer), strna(local)); + + return launch1(name, argv, envp, fd2); +diff --git a/src/core/service.c b/src/core/service.c +index 7f0e6df412..dd0ae7cb88 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -3309,7 +3309,7 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context + if (s->state != SERVICE_DEAD) + return -EAGAIN; + +- if (getpeername_pretty(fd, &peer) >= 0) { ++ if (getpeername_pretty(fd, true, &peer) >= 0) { + + if (UNIT(s)->description) { + _cleanup_free_ char *a; +diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c +index 431e28329b..166bdad541 100644 +--- a/src/journal-remote/journal-remote.c ++++ b/src/journal-remote/journal-remote.c +@@ -620,7 +620,7 @@ static int request_handler( + if (r < 0) + return code; + } else { +- r = getnameinfo_pretty(fd, &hostname); ++ r = getpeername_pretty(fd, false, &hostname); + if (r < 0) { + return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, + "Cannot check remote hostname"); +@@ -880,7 +880,7 @@ static int remoteserver_init(RemoteServer *s, + } else if (sd_is_socket(fd, AF_UNSPEC, 0, false)) { + char *hostname; + +- r = getnameinfo_pretty(fd, &hostname); ++ r = getpeername_pretty(fd, false, &hostname); + if (r < 0) + return log_error_errno(r, "Failed to retrieve remote name: %m"); + +diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c +index b14e368176..d492ae4222 100644 +--- a/src/shared/socket-util.c ++++ b/src/shared/socket-util.c +@@ -612,7 +612,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ + return 0; + } + +-int getpeername_pretty(int fd, char **ret) { ++int getpeername_pretty(int fd, bool include_port, char **ret) { + union sockaddr_union sa; + socklen_t salen = sizeof(sa); + int r; +@@ -642,7 +642,7 @@ int getpeername_pretty(int fd, char **ret) { + /* For remote sockets we translate IPv6 addresses back to IPv4 + * if applicable, since that's nicer. */ + +- return sockaddr_pretty(&sa.sa, salen, true, true, ret); ++ return sockaddr_pretty(&sa.sa, salen, true, include_port, ret); + } + + int getsockname_pretty(int fd, char **ret) { +diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h +index 9200ce8822..403c9bc098 100644 +--- a/src/shared/socket-util.h ++++ b/src/shared/socket-util.h +@@ -102,7 +102,7 @@ bool socket_ipv6_is_supported(void); + int sockaddr_port(const struct sockaddr *_sa) _pure_; + + int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret); +-int getpeername_pretty(int fd, char **ret); ++int getpeername_pretty(int fd, bool include_port, char **ret); + int getsockname_pretty(int fd, char **ret); + + int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret); +diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c +index a3c3c87f11..b0a062b716 100644 +--- a/src/socket-proxy/socket-proxyd.c ++++ b/src/socket-proxy/socket-proxyd.c +@@ -504,7 +504,7 @@ static int accept_cb(sd_event_source *s, int fd, uint32_t revents, void *userdat + if (errno != -EAGAIN) + log_warning_errno(errno, "Failed to accept() socket: %m"); + } else { +- getpeername_pretty(nfd, &peer); ++ getpeername_pretty(nfd, true, &peer); + log_debug("New connection from %s", strna(peer)); + + r = add_connection_socket(context, nfd); diff --git a/SOURCES/0831-core-downgrade-log-message-about-inability-to-propag.patch b/SOURCES/0831-core-downgrade-log-message-about-inability-to-propag.patch new file mode 100644 index 00000000..2d5b971e --- /dev/null +++ b/SOURCES/0831-core-downgrade-log-message-about-inability-to-propag.patch @@ -0,0 +1,45 @@ +From d081baa951ee0d1c918170c7c666208fe04944e2 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 8 Sep 2017 17:24:57 +0200 +Subject: [PATCH] core: downgrade log message about inability to propagate + cgroup release message + +If dbus is already down during shutdown, we can't propagate the cgroup +release message anymore, but that's expected and nothing to warn about. +Hence let's downgrade the message from LOG_WARN to LOG_DEBUG. + +Fixes: #6777 +(cherry picked from commit d5f1532657da107f1c8be8a97c15d964cd96665c) + +Resolves: #1679934 +--- + src/core/dbus.c | 2 +- + src/core/manager.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/core/dbus.c b/src/core/dbus.c +index d551eab016..9d19138ab3 100644 +--- a/src/core/dbus.c ++++ b/src/core/dbus.c +@@ -93,7 +93,7 @@ int bus_forward_agent_released(Manager *m, const char *path) { + "Released", + "s", path); + if (r < 0) +- return log_warning_errno(r, "Failed to propagate agent release message: %m"); ++ return log_debug_errno(r, "Failed to propagate agent release message: %m"); + + return 1; + } +diff --git a/src/core/manager.c b/src/core/manager.c +index 4c87ad8a2f..7bbe912dc9 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -1666,7 +1666,7 @@ static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, ui + buf[n] = 0; + + manager_notify_cgroup_empty(m, buf); +- bus_forward_agent_released(m, buf); ++ (void) bus_forward_agent_released(m, buf); + + return 0; + } diff --git a/SOURCES/0832-units-move-Before-deps-for-quota-services-to-remote-.patch b/SOURCES/0832-units-move-Before-deps-for-quota-services-to-remote-.patch new file mode 100644 index 00000000..9319612d --- /dev/null +++ b/SOURCES/0832-units-move-Before-deps-for-quota-services-to-remote-.patch @@ -0,0 +1,48 @@ +From 0693f51f979f260426cddc1f270e28e3cb2b46fa Mon Sep 17 00:00:00 2001 +From: tblume +Date: Thu, 30 Mar 2017 11:21:18 +0200 +Subject: [PATCH] units: move Before deps for quota services to + remote-fs.target (#5627) + +Creating quota on an iscsi device is causing dependency loops at next reboot. +Reason is that systemd-quotacheck and quotaon.service are ordered before +local-fs.target and quota enabled mounts have a before dependency to them. +This cannot work for _netdev mounts, because network activation is ordered +after local-fs.target. +Moving the Before dependency for systemd-quotacheck and quotaon.service +to remote-fs.target fixes this. + +(cherry picked from commit 4e6f13af93a551933a75331b1f67123b3d09f6ef) + +Resolves: #1693374 +--- + units/quotaon.service.in | 2 +- + units/systemd-quotacheck.service.in | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/units/quotaon.service.in b/units/quotaon.service.in +index 49a50a7feb..57667e110d 100644 +--- a/units/quotaon.service.in ++++ b/units/quotaon.service.in +@@ -10,7 +10,7 @@ Description=Enable File System Quotas + Documentation=man:quotaon(8) + DefaultDependencies=no + After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-quotacheck.service +-Before=local-fs.target shutdown.target ++Before=remote-fs.target shutdown.target + ConditionPathExists=@QUOTAON@ + + [Service] +diff --git a/units/systemd-quotacheck.service.in b/units/systemd-quotacheck.service.in +index f726ea1bcd..41c9bea6d2 100644 +--- a/units/systemd-quotacheck.service.in ++++ b/units/systemd-quotacheck.service.in +@@ -10,7 +10,7 @@ Description=File System Quota Check + Documentation=man:systemd-quotacheck.service(8) + DefaultDependencies=no + After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-remount-fs.service +-Before=local-fs.target shutdown.target ++Before=remote-fs.target shutdown.target + ConditionPathExists=@QUOTACHECK@ + + [Service] diff --git a/SOURCES/0833-set-kptr_restrict-1.patch b/SOURCES/0833-set-kptr_restrict-1.patch new file mode 100644 index 00000000..7031b903 --- /dev/null +++ b/SOURCES/0833-set-kptr_restrict-1.patch @@ -0,0 +1,24 @@ +From 7e8934693393c45ba76155088b01ad1ace9daeac Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Tue, 3 Dec 2019 13:57:38 +0100 +Subject: [PATCH] set kptr_restrict=1 + +Resolves: #1689344 +--- + sysctl.d/50-default.conf | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sysctl.d/50-default.conf b/sysctl.d/50-default.conf +index 44c48236cc..b1806502e8 100644 +--- a/sysctl.d/50-default.conf ++++ b/sysctl.d/50-default.conf +@@ -20,6 +20,9 @@ kernel.sysrq = 16 + # Append the PID to the core filename + kernel.core_uses_pid = 1 + ++# https://bugzilla.redhat.com/show_bug.cgi?id=1689344 ++kernel.kptr_restrict = 1 ++ + # Source route verification + net.ipv4.conf.default.rp_filter = 1 + net.ipv4.conf.all.rp_filter = 1 diff --git a/SOURCES/0834-journal-break-recursion.patch b/SOURCES/0834-journal-break-recursion.patch new file mode 100644 index 00000000..d93950b9 --- /dev/null +++ b/SOURCES/0834-journal-break-recursion.patch @@ -0,0 +1,82 @@ +From 19bb218559b8dca65bbb68ad7a4ff0bc9cbfe8fb Mon Sep 17 00:00:00 2001 +From: Stepan Broz +Date: Wed, 11 Mar 2020 14:45:26 +0100 +Subject: [PATCH] journal: break recursion + +available_space(s, true) tries to log the current status, which does, in +turn, lead to another call to available_space(s, true) and so on and so +on... The call sequence is: + +available_space() + server_driver_message() + dispatch_message_real() + write_to_journal() + find_journal() + system_journal_open() + available_space() + +RHEL-only + +Resolves: #1778744 +--- + src/journal/journald-server.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index ffe2daa7be..11348af490 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -311,7 +311,7 @@ static bool flushed_flag_is_set(void) { + return access("/run/systemd/journal/flushed", F_OK) >= 0; + } + +-static int system_journal_open(Server *s, bool flush_requested) { ++static int system_journal_open(Server *s, bool flush_requested, bool verbose) { + int r; + char *fn; + sd_id128_t machine; +@@ -344,7 +344,7 @@ static int system_journal_open(Server *s, bool flush_requested) { + + if (r >= 0) { + server_fix_perms(s, s->system_journal, 0); +- available_space(s, true); ++ available_space(s, verbose); + } else { + if (r != -ENOENT && r != -EROFS) + log_warning_errno(r, "Failed to open system journal: %m"); +@@ -406,7 +406,7 @@ static int system_journal_open(Server *s, bool flush_requested) { + + if (s->runtime_journal) { + server_fix_perms(s, s->runtime_journal, 0); +- available_space(s, true); ++ available_space(s, verbose); + } + } + +@@ -430,7 +430,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) { + * else that's left the journals as NULL). + * + * Fixes https://github.com/systemd/systemd/issues/3968 */ +- (void) system_journal_open(s, false); ++ (void) system_journal_open(s, false, false); + + /* We split up user logs only on /var, not on /run. If the + * runtime file is open, we write to it exclusively, in order +@@ -1132,7 +1132,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) { + if (require_flag_file && !flushed_flag_is_set()) + return 0; + +- system_journal_open(s, true); ++ system_journal_open(s, true, true); + + if (!s->system_journal) + return 0; +@@ -1903,7 +1903,7 @@ int server_init(Server *s) { + + (void) server_connect_notify(s); + +- r = system_journal_open(s, false); ++ r = system_journal_open(s, false, true); + if (r < 0) + return r; + diff --git a/SOURCES/0835-core-enforce-a-ratelimiter-when-stopping-units-due-t.patch b/SOURCES/0835-core-enforce-a-ratelimiter-when-stopping-units-due-t.patch new file mode 100644 index 00000000..0a249891 --- /dev/null +++ b/SOURCES/0835-core-enforce-a-ratelimiter-when-stopping-units-due-t.patch @@ -0,0 +1,59 @@ +From d27610cfef24a985116ed88f29a462f627745b19 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 19 May 2015 16:00:24 +0200 +Subject: [PATCH] core: enforce a ratelimiter when stopping units due to + StopWhenUnneeded=1 + +Otherwise we might end up in an endless stop loop. + +http://lists.freedesktop.org/archives/systemd-devel/2015-April/030224.html +(cherry picked from commit bea355dac94e82697aa98e25d80ee4248263bf92) + +Related: #1775291 +--- + src/core/unit.c | 10 ++++++++++ + src/core/unit.h | 3 +++ + 2 files changed, 13 insertions(+) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 502830d2cb..750b8b9a5c 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -97,6 +97,8 @@ Unit *unit_new(Manager *m, size_t size) { + u->on_failure_job_mode = JOB_REPLACE; + u->sigchldgen = 0; + ++ RATELIMIT_INIT(u->check_unneeded_ratelimit, 10 * USEC_PER_SEC, 16); ++ + return u; + } + +@@ -1612,6 +1614,14 @@ static void unit_check_unneeded(Unit *u) { + if (unit_active_or_pending(other)) + return; + ++ /* If stopping a unit fails continously we might enter a stop ++ * loop here, hence stop acting on the service being ++ * unnecessary after a while. */ ++ if (!ratelimit_test(&u->check_unneeded_ratelimit)) { ++ log_unit_warning(u->id, "Unit not needed anymore, but not stopping since we tried this too often recently."); ++ return; ++ } ++ + log_unit_info(u->id, "Unit %s is not needed anymore. Stopping.", u->id); + + /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ +diff --git a/src/core/unit.h b/src/core/unit.h +index 8cc7a9e0b2..e930d8ba5f 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -192,6 +192,9 @@ struct Unit { + /* Error code when we didn't manage to load the unit (negative) */ + int load_error; + ++ /* Make sure we never enter endless loops with the check unneeded logic */ ++ RateLimit check_unneeded_ratelimit; ++ + /* Cached unit file state and preset */ + UnitFileState unit_file_state; + int unit_file_preset; diff --git a/SOURCES/0836-core-rework-StopWhenUnneeded-logic.patch b/SOURCES/0836-core-rework-StopWhenUnneeded-logic.patch new file mode 100644 index 00000000..7d8f6615 --- /dev/null +++ b/SOURCES/0836-core-rework-StopWhenUnneeded-logic.patch @@ -0,0 +1,342 @@ +From ba36c6a8c8d134aa7196750af4a6651d5810f6d3 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Aug 2018 16:26:27 +0200 +Subject: [PATCH] core: rework StopWhenUnneeded= logic + +Previously, we'd act immediately on StopWhenUnneeded= when a unit state +changes. With this rework we'll maintain a queue instead: whenever +there's the chance that StopWhenUneeded= might have an effect we enqueue +the unit, and process it later when we have nothing better to do. + +This should make the implementation a bit more reliable, as the unit notify event +cannot immediately enqueue tons of side-effect jobs that might +contradict each other, but we do so only in a strictly ordered fashion, +from the main event loop. + +This slightly changes the check when to consider a unit "unneeded". +Previously, we'd assume that a unit in "deactivating" state could also +be cleaned up. With this new logic we'll only consider units unneeded +that are fully up and have no job queued. This means that whenever +there's something pending for a unit we won't clean it up. + +(cherry picked from commit a3c1168ac293f16d9343d248795bb4c246aaff4a) + +Resolves: #1775291 +--- + src/core/manager.c | 43 +++++++++++++++ + src/core/manager.h | 3 ++ + src/core/unit.c | 132 ++++++++++++++++++++++++--------------------- + src/core/unit.h | 7 +++ + 4 files changed, 124 insertions(+), 61 deletions(-) + +diff --git a/src/core/manager.c b/src/core/manager.c +index 7bbe912dc9..db562b18a5 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -961,6 +961,45 @@ static unsigned manager_dispatch_gc_queue(Manager *m) { + return n; + } + ++static unsigned manager_dispatch_stop_when_unneeded_queue(Manager *m) { ++ unsigned n = 0; ++ Unit *u; ++ int r; ++ ++ assert(m); ++ ++ while ((u = m->stop_when_unneeded_queue)) { ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; ++ assert(m->stop_when_unneeded_queue); ++ ++ assert(u->in_stop_when_unneeded_queue); ++ LIST_REMOVE(stop_when_unneeded_queue, m->stop_when_unneeded_queue, u); ++ u->in_stop_when_unneeded_queue = false; ++ ++ n++; ++ ++ if (!unit_is_unneeded(u)) ++ continue; ++ ++ log_unit_debug(u->id, "Unit is not needed anymore."); ++ ++ /* If stopping a unit fails continuously we might enter a stop loop here, hence stop acting on the ++ * service being unnecessary after a while. */ ++ ++ if (!ratelimit_test(&u->check_unneeded_ratelimit)) { ++ log_unit_warning(u->id, "Unit not needed anymore, but not stopping since we tried this too often recently."); ++ continue; ++ } ++ ++ /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ ++ r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, &error, NULL); ++ if (r < 0) ++ log_unit_warning_errno(u->id, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r)); ++ } ++ ++ return n; ++} ++ + static void manager_clear_jobs_and_units(Manager *m) { + Unit *u; + +@@ -977,6 +1016,7 @@ static void manager_clear_jobs_and_units(Manager *m) { + assert(!m->dbus_job_queue); + assert(!m->cleanup_queue); + assert(!m->gc_queue); ++ assert(!m->stop_when_unneeded_queue); + + assert(hashmap_isempty(m->jobs)); + assert(hashmap_isempty(m->units)); +@@ -2259,6 +2299,9 @@ int manager_loop(Manager *m) { + if (manager_dispatch_cgroup_queue(m) > 0) + continue; + ++ if (manager_dispatch_stop_when_unneeded_queue(m) > 0) ++ continue; ++ + if (manager_dispatch_dbus_queue(m) > 0) + continue; + +diff --git a/src/core/manager.h b/src/core/manager.h +index cfc564dfb6..f9280956e9 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -117,6 +117,9 @@ struct Manager { + /* Target units whose default target dependencies haven't been set yet */ + LIST_HEAD(Unit, target_deps_queue); + ++ /* Units that might be subject to StopWhenUnneeded= clean-up */ ++ LIST_HEAD(Unit, stop_when_unneeded_queue); ++ + sd_event *event; + + /* We use two hash tables here, since the same PID might be +diff --git a/src/core/unit.c b/src/core/unit.c +index 750b8b9a5c..2b058dd3e8 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -396,6 +396,22 @@ void unit_add_to_dbus_queue(Unit *u) { + u->in_dbus_queue = true; + } + ++void unit_add_to_stop_when_unneeded_queue(Unit *u) { ++ assert(u); ++ ++ if (u->in_stop_when_unneeded_queue) ++ return; ++ ++ if (!u->stop_when_unneeded) ++ return; ++ ++ if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) ++ return; ++ ++ LIST_PREPEND(stop_when_unneeded_queue, u->manager->stop_when_unneeded_queue, u); ++ u->in_stop_when_unneeded_queue = true; ++} ++ + static void bidi_set_free(Unit *u, Set *s) { + Iterator i; + Unit *other; +@@ -560,6 +576,9 @@ void unit_free(Unit *u) { + u->manager->n_in_gc_queue--; + } + ++ if (u->in_stop_when_unneeded_queue) ++ LIST_REMOVE(stop_when_unneeded_queue, u->manager->stop_when_unneeded_queue, u); ++ + if (u->on_console) + manager_unref_console(u->manager); + +@@ -1583,49 +1602,68 @@ bool unit_can_reload(Unit *u) { + return UNIT_VTABLE(u)->can_reload(u); + } + +-static void unit_check_unneeded(Unit *u) { +- Iterator i; +- Unit *other; ++bool unit_is_unneeded(Unit *u) { ++ static const UnitDependency deps[] = { ++ UNIT_REQUIRED_BY, ++ UNIT_REQUIRED_BY_OVERRIDABLE, ++ UNIT_WANTED_BY, ++ UNIT_BOUND_BY, ++ }; ++ size_t j; + + assert(u); + +- /* If this service shall be shut down when unneeded then do +- * so. */ +- + if (!u->stop_when_unneeded) +- return; ++ return false; + +- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) +- return; ++ /* Don't clean up while the unit is transitioning or is even inactive. */ ++ if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) ++ return false; ++ if (u->job) ++ return false; + +- SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i) +- if (unit_active_or_pending(other)) +- return; ++ for (j = 0; j < ELEMENTSOF(deps); j++) { ++ Unit *other; ++ Iterator i; + +- SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i) +- if (unit_active_or_pending(other)) +- return; ++ /* If a dependending unit has a job queued, or is active (or in transitioning), or is marked for ++ * restart, then don't clean this one up. */ + +- SET_FOREACH(other, u->dependencies[UNIT_WANTED_BY], i) +- if (unit_active_or_pending(other)) +- return; ++ SET_FOREACH(other, u->dependencies[deps[j]], i) { ++ if (u->job) ++ return false; + +- SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i) +- if (unit_active_or_pending(other)) +- return; +- +- /* If stopping a unit fails continously we might enter a stop +- * loop here, hence stop acting on the service being +- * unnecessary after a while. */ +- if (!ratelimit_test(&u->check_unneeded_ratelimit)) { +- log_unit_warning(u->id, "Unit not needed anymore, but not stopping since we tried this too often recently."); +- return; ++ if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) ++ return false; ++ } + } + +- log_unit_info(u->id, "Unit %s is not needed anymore. Stopping.", u->id); ++ return true; ++} + +- /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ +- manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL); ++static void check_unneeded_dependencies(Unit *u) { ++ ++ static const UnitDependency deps[] = { ++ UNIT_REQUIRES, ++ UNIT_REQUIRES_OVERRIDABLE, ++ UNIT_REQUISITE, ++ UNIT_REQUISITE_OVERRIDABLE, ++ UNIT_WANTS, ++ UNIT_BINDS_TO, ++ }; ++ size_t j; ++ ++ assert(u); ++ ++ /* Add all units this unit depends on to the queue that processes StopWhenUnneeded= behaviour. */ ++ ++ for (j = 0; j < ELEMENTSOF(deps); j++) { ++ Unit *other; ++ Iterator i; ++ ++ SET_FOREACH(other, u->dependencies[deps[j]], i) ++ unit_add_to_stop_when_unneeded_queue(other); ++ } + } + + static void unit_check_binds_to(Unit *u) { +@@ -1711,34 +1749,6 @@ static void retroactively_stop_dependencies(Unit *u) { + manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL); + } + +-static void check_unneeded_dependencies(Unit *u) { +- Iterator i; +- Unit *other; +- +- assert(u); +- assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u))); +- +- /* Garbage collect services that might not be needed anymore, if enabled */ +- SET_FOREACH(other, u->dependencies[UNIT_REQUIRES], i) +- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) +- unit_check_unneeded(other); +- SET_FOREACH(other, u->dependencies[UNIT_REQUIRES_OVERRIDABLE], i) +- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) +- unit_check_unneeded(other); +- SET_FOREACH(other, u->dependencies[UNIT_WANTS], i) +- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) +- unit_check_unneeded(other); +- SET_FOREACH(other, u->dependencies[UNIT_REQUISITE], i) +- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) +- unit_check_unneeded(other); +- SET_FOREACH(other, u->dependencies[UNIT_REQUISITE_OVERRIDABLE], i) +- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) +- unit_check_unneeded(other); +- SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i) +- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) +- unit_check_unneeded(other); +-} +- + void unit_start_on_failure(Unit *u) { + Unit *other; + Iterator i; +@@ -1916,7 +1926,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su + } + + /* stop unneeded units regardless if going down was expected or not */ +- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(ns)) ++ if (UNIT_IS_INACTIVE_OR_FAILED(ns)) + check_unneeded_dependencies(u); + + if (ns != os && ns == UNIT_FAILED) { +@@ -1977,7 +1987,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su + if (u->manager->n_reloading <= 0) { + /* Maybe we finished startup and are now ready for + * being stopped because unneeded? */ +- unit_check_unneeded(u); ++ unit_add_to_stop_when_unneeded_queue(u); + + /* Maybe we finished startup, but something we needed + * has vanished? Let's die then. (This happens when +diff --git a/src/core/unit.h b/src/core/unit.h +index e930d8ba5f..f426f3df21 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -172,6 +172,9 @@ struct Unit { + /* Target dependencies queue */ + LIST_FIELDS(Unit, target_deps_queue); + ++ /* Queue of units with StopWhenUnneeded set that shell be checked for clean-up. */ ++ LIST_FIELDS(Unit, stop_when_unneeded_queue); ++ + /* PIDs we keep an eye on. Note that a unit might have many + * more, but these are the ones we care enough about to + * process SIGCHLD for */ +@@ -245,6 +248,7 @@ struct Unit { + bool in_gc_queue:1; + bool in_cgroup_queue:1; + bool in_target_deps_queue:1; ++ bool in_stop_when_unneeded_queue:1; + + bool sent_dbus_new_signal:1; + +@@ -518,6 +522,7 @@ void unit_add_to_dbus_queue(Unit *u); + void unit_add_to_cleanup_queue(Unit *u); + void unit_add_to_gc_queue(Unit *u); + void unit_add_to_target_deps_queue(Unit *u); ++void unit_add_to_stop_when_unneeded_queue(Unit *u); + + int unit_merge(Unit *u, Unit *other); + int unit_merge_by_name(Unit *u, const char *other); +@@ -637,6 +642,8 @@ int unit_make_transient(Unit *u); + + int unit_require_mounts_for(Unit *u, const char *path); + ++bool unit_is_unneeded(Unit *u); ++ + pid_t unit_control_pid(Unit *u); + pid_t unit_main_pid(Unit *u); + diff --git a/SOURCES/0837-core-coldplug-possible-nop_job.patch b/SOURCES/0837-core-coldplug-possible-nop_job.patch new file mode 100644 index 00000000..b2170d14 --- /dev/null +++ b/SOURCES/0837-core-coldplug-possible-nop_job.patch @@ -0,0 +1,52 @@ +From 8ee652948b0255005e4c9d278ac06b30711d9dbd Mon Sep 17 00:00:00 2001 +From: chenglin130 +Date: Sat, 9 Nov 2019 23:04:04 +0800 +Subject: [PATCH] core: coldplug possible nop_job + +When a unit in a state INACTIVE or DEACTIVATING, JobType JOB_TRY_RESTART or +JOB_TRY_RELOAD will be collapsed to JOB_NOP. And use u->nop_job instead +of u->job. + +If a JOB_NOP job is going on with a waiting state, a parallel daemon-reload +just install it during deserialization. Without a coldplug, the job will +not be in m->run_queue, which results in a hung try-restart or +try-reload process. + +Reproduce: +1. run systemctl try-restart test.servcie (inactive) repeatly in a terminal. +2. run systemctl daemon-reload repeatly in other terminals. + +After successful reproduce, systemctl list-jobs will list the hang job. + +Upsteam: +https://github.com/systemd/systemd/pull/13124 + +Resolves: #1829754 +--- + src/core/unit.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 2b058dd3e8..d953780a52 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -2918,6 +2918,7 @@ static int unit_add_deserialized_job_coldplug(Unit *u) { + + int unit_coldplug(Unit *u, Hashmap *deferred_work) { + int r; ++ Job *uj; + + assert(u); + +@@ -2925,8 +2926,9 @@ int unit_coldplug(Unit *u, Hashmap *deferred_work) { + if ((r = UNIT_VTABLE(u)->coldplug(u, deferred_work)) < 0) + return r; + +- if (u->job) { +- r = job_coldplug(u->job); ++ uj = u->job ?: u->nop_job; ++ if (uj) { ++ r = job_coldplug(uj); + if (r < 0) + return r; + } else if (u->deserialized_job >= 0) diff --git a/SOURCES/0838-core-make-sure-to-restore-the-control-command-id-too.patch b/SOURCES/0838-core-make-sure-to-restore-the-control-command-id-too.patch new file mode 100644 index 00000000..3e937ac3 --- /dev/null +++ b/SOURCES/0838-core-make-sure-to-restore-the-control-command-id-too.patch @@ -0,0 +1,30 @@ +From df8adf9c8a8258ae041db28f4bf411da6156170a Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 22 Apr 2020 20:34:02 +0200 +Subject: [PATCH] core: make sure to restore the control command id, too + +Fixes: #15356 +(cherry picked from commit e9da62b18af647bfa73807e1c7fc3bfa4bb4b2ac) + +Resolves: #1828953 +--- + src/core/service.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index dd0ae7cb88..4c73b6ef96 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -2263,9 +2263,10 @@ static int service_deserialize_exec_command(Unit *u, const char *key, const char + break; + } + +- if (command && control) ++ if (command && control) { + s->control_command = command; +- else if (command) ++ s->control_command_id = id; ++ } else if (command) + s->main_command = command; + else + log_unit_warning(u->id, "Current command vanished from the unit file, execution of the command list won't be resumed."); diff --git a/SOURCES/0839-avoid-double-free.patch b/SOURCES/0839-avoid-double-free.patch new file mode 100644 index 00000000..e2017ab5 --- /dev/null +++ b/SOURCES/0839-avoid-double-free.patch @@ -0,0 +1,26 @@ +From 20fb5227cd981c5eb188a6ad738672486e40a50e Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Mon, 11 May 2020 13:34:24 +0200 +Subject: [PATCH] avoid double free + +This was a mis-merge in the fix for #1809053 (commit +f99cc28e392874b317b4ff2054bbd6970f71ecdd). + +Resolves: #1832816 +--- + src/udev/udev-builtin-path_id.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c +index b0bcd80571..1db403b39c 100644 +--- a/src/udev/udev-builtin-path_id.c ++++ b/src/udev/udev-builtin-path_id.c +@@ -428,7 +428,7 @@ static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char * + struct udev_device *hostdev; + struct udev_device *vmbusdev; + const char *guid_str; +- _cleanup_free_ char *lun = NULL; ++ char *lun = NULL; + char guid[39]; + size_t i, k; + diff --git a/SOURCES/org.freedesktop.login1.policy b/SOURCES/org.freedesktop.login1.policy index 0a192737..129bc788 100644 --- a/SOURCES/org.freedesktop.login1.policy +++ b/SOURCES/org.freedesktop.login1.policy @@ -740,4 +740,14 @@ org.freedesktop.login1.hibernate - \ No newline at end of file + + Change Session + Authentication is required for changing the virtual terminal. + + auth_admin_keep + auth_admin_keep + yes + + + + diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index 4d0b7246..9801dffa 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -840,25 +840,45 @@ Patch0797: 0797-service-go-through-stop_post-on-failure-4770.patch Patch0798: 0798-Call-getgroups-to-know-size-of-supplementary-groups-.patch Patch0799: 0799-udev-introduce-CONST-key-name.patch Patch0800: 0800-path-stop-watching-path-specs-once-we-triggered-the-.patch -Patch0801: 0801-unit-fix-potential-use-of-cgroup_path-after-free-whe.patch -Patch0802: 0802-core-when-restarting-services-don-t-close-fds.patch -Patch0803: 0803-unit-rework-a-bit-how-we-keep-the-service-fdstore-fr.patch -Patch0804: 0804-tests-add-basic-journal-test.patch -Patch0805: 0805-tests-add-regression-test-for-systemctl-restart-syst.patch -Patch0806: 0806-tests-add-test-that-journald-keeps-fds-over-terminat.patch -Patch0807: 0807-journal-do-not-trigger-assertion-when-journal_file_c.patch -Patch0808: 0808-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch -Patch0809: 0809-mount-when-allocating-a-Mount-object-based-on-proc-s.patch -Patch0810: 0810-core-enforce-a-ratelimiter-when-stopping-units-due-t.patch -Patch0811: 0811-core-rework-StopWhenUnneeded-logic.patch -Patch0812: 0812-fix-the-fix-for-1691511.patch -Patch0813: 0813-sd-bus-when-attached-to-an-sd-event-loop-disconnect-.patch -Patch0814: 0814-sd-journal-close-journal-files-that-were-deleted-by-.patch -Patch0815: 0815-sd-journal-remove-the-dead-code-and-actually-fix-146.patch -Patch0816: 0816-swap-adjust-swap.c-in-a-similar-way-to-what-we-just-.patch -Patch0817: 0817-swap-finish-the-secondary-swap-units-jobs-if-deactiv.patch -Patch0818: 0818-udev-rules-make-tape-changers-also-apprear-in-dev-ta.patch -Patch0819: 0819-core-make-sure-to-restore-the-control-command-id-too.patch +Patch0801: 0801-sd-bus-bump-message-queue-size-again.patch +Patch0802: 0802-unit-fix-potential-use-of-cgroup_path-after-free-whe.patch +Patch0803: 0803-add-test-for-ExecStopPost.patch +Patch0804: 0804-core-when-restarting-services-don-t-close-fds.patch +Patch0805: 0805-unit-rework-a-bit-how-we-keep-the-service-fdstore-fr.patch +Patch0806: 0806-tests-add-basic-journal-test.patch +Patch0807: 0807-tests-add-regression-test-for-systemctl-restart-syst.patch +Patch0808: 0808-tests-add-test-that-journald-keeps-fds-over-terminat.patch +Patch0809: 0809-nss-util-silence-warning-about-deprecated-RES_USE_IN.patch +Patch0810: 0810-journal-do-not-trigger-assertion-when-journal_file_c.patch +Patch0811: 0811-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch +Patch0812: 0812-mount-when-allocating-a-Mount-object-based-on-proc-s.patch +Patch0813: 0813-fix-the-fix-for-1691511.patch +Patch0814: 0814-v3-Properly-parsing-SCSI-Hyperv-devices-8509.patch +Patch0815: 0815-Consider-smb3-as-remote-filesystem.patch +Patch0816: 0816-mount-don-t-add-Requires-for-tmp.mount.patch +Patch0817: 0817-sd-bus-when-attached-to-an-sd-event-loop-disconnect-.patch +Patch0818: 0818-sd-journal-close-journal-files-that-were-deleted-by-.patch +Patch0819: 0819-sd-journal-remove-the-dead-code-and-actually-fix-146.patch +Patch0820: 0820-swap-adjust-swap.c-in-a-similar-way-to-what-we-just-.patch +Patch0821: 0821-swap-finish-the-secondary-swap-units-jobs-if-deactiv.patch +Patch0822: 0822-core-add-a-new-unit-file-setting-CollectMode-for-twe.patch +Patch0823: 0823-run-add-G-as-shortcut-for-property-CollectMode-inact.patch +Patch0824: 0824-core-clarify-that-the-CollectMode-bus-property-is-co.patch +Patch0825: 0825-udev-rules-make-tape-changers-also-apprear-in-dev-ta.patch +Patch0826: 0826-logind-check-PolicyKit-before-allowing-VT-switch.patch +Patch0827: 0827-timer-don-t-use-persietent-file-timestamps-from-the-.patch +Patch0828: 0828-core-transition-to-FINAL_SIGTERM-state-after-ExecSto.patch +Patch0829: 0829-bus_open-leak-sd_event_source-when-udevadm-trigger.patch +Patch0830: 0830-journal-remote-split-mode-host-remove-port-from-jour.patch +Patch0831: 0831-core-downgrade-log-message-about-inability-to-propag.patch +Patch0832: 0832-units-move-Before-deps-for-quota-services-to-remote-.patch +Patch0833: 0833-set-kptr_restrict-1.patch +Patch0834: 0834-journal-break-recursion.patch +Patch0835: 0835-core-enforce-a-ratelimiter-when-stopping-units-due-t.patch +Patch0836: 0836-core-rework-StopWhenUnneeded-logic.patch +Patch0837: 0837-core-coldplug-possible-nop_job.patch +Patch0838: 0838-core-make-sure-to-restore-the-control-command-id-too.patch +Patch0839: 0839-avoid-double-free.patch Patch9999: 9999-Update-kernel-install-script-by-backporting-fedora-p.patch %global num_patches %{lua: c=0; for i,p in ipairs(patches) do c=c+1; end; print(c);} @@ -1837,10 +1857,46 @@ fi %{_mandir}/man8/systemd-resolved.* %changelog -* Mon May 25 2020 systemd maintenance team - 219-73.8 -- core: make sure to restore the control command id, too (#1837973) +* Tue May 12 2020 systemd maintenance team - 219-78 +- avoid double free (#1832816) + +* Thu Apr 30 2020 systemd maintenance team - 219-77 +- core: coldplug possible nop_job (#1829754) +- core: make sure to restore the control command id, too (#1828953) + +* Wed Apr 29 2020 systemd maintenance team - 219-76 +- core: enforce a ratelimiter when stopping units due to StopWhenUnneeded=1 (#1775291) +- core: rework StopWhenUnneeded= logic (#1775291) -* Mon May 18 2020 systemd maintenance team - 219-73.7 +* Wed Apr 29 2020 systemd maintenance team - 219-75 +- journal: break recursion (#1778744) + +* Tue Apr 28 2020 systemd maintenance team - 219-74 +- sd-bus: bump message queue size again (#1770158) +- unit: fix potential use of cgroup_path after free() when freeing unit (#1760149) +- add test for ExecStopPost (#1733998) +- core: when restarting services, don't close fds (#1757704) +- unit: rework a bit how we keep the service fdstore from being destroyed during service restart (#1757704) +- tests: add basic journal test (#1757704) +- tests: add regression test for `systemctl restart systemd-journald` (#1757704) +- tests: add test that journald keeps fds over termination by signal (#1757704) +- nss-util: silence warning about deprecated RES_USE_INET6 (#1799002) +- journal: do not trigger assertion when journal_file_close() get NULL (#1786046) +- mount: don't propagate errors from mount_setup_unit() further up (#1804757) +- mount: when allocating a Mount object based on /proc/self/mountinfo mark it so (#1804757) +- fix the fix for #1691511 (#1804757) +- v3: Properly parsing SCSI Hyperv devices (#8509) (#1809053) +- Consider smb3 as remote filesystem (#1811700) +- mount: don't add Requires for tmp.mount (#1813270) +- sd-bus: when attached to an sd-event loop, disconnect on processing errors (#1769928) +- sd-journal: close journal files that were deleted by journald before we've setup inotify watch (#1812889) +- sd-journal: remove the dead code and actually fix #14695 (#1812889) +- swap: adjust swap.c in a similar way to what we just did to mount.c (#1749621) +- swap: finish the secondary swap units' jobs if deactivation of the primary swap unit fails (#1749621) +- core: add a new unit file setting CollectMode= for tweaking the GC logic (#1817576) +- run: add "-G" as shortcut for "--property=CollectMode=inactive-or-failed" (#1817576) +- core: clarify that the CollectMode bus property is constant (#1817576) +- core: make sure to restore the control command id, too (#1837973) - udev-rules: make tape-changers also apprear in /dev/tape/by-path/ (#1814028) * Mon Apr 06 2020 systemd maintenance team - 219-73.6