import systemd-239-58.el8_6.3

This commit is contained in:
CentOS Sources 2022-08-02 03:02:52 -04:00 committed by Stepan Oksanichenko
parent ff9b3458f8
commit 4b5a13cea2
15 changed files with 976 additions and 1 deletions

View File

@ -0,0 +1,51 @@
From 96bc9caf3216b391a1da88b92ca507fa617177f7 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 23 Apr 2020 08:49:10 +0200
Subject: [PATCH] acpi-fpdt: mark structures as packed
Let's make sure the alignment doesn't matter.
(cherry picked from commit 49490c1d353bc920cbf73f4c71e9c35d2e3eb8b1)
Related: #2084052
---
src/shared/acpi-fpdt.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c
index d565ebd43e..38c464c912 100644
--- a/src/shared/acpi-fpdt.c
+++ b/src/shared/acpi-fpdt.c
@@ -23,7 +23,7 @@ struct acpi_table_header {
uint32_t oem_revision;
char asl_compiler_id[4];
uint32_t asl_compiler_revision;
-};
+} _packed_;
enum {
ACPI_FPDT_TYPE_BOOT = 0,
@@ -36,12 +36,12 @@ struct acpi_fpdt_header {
uint8_t revision;
uint8_t reserved[4];
uint64_t ptr;
-};
+} _packed_;
struct acpi_fpdt_boot_header {
char signature[4];
uint32_t length;
-};
+} _packed_;
enum {
ACPI_FPDT_S3PERF_RESUME_REC = 0,
@@ -59,7 +59,7 @@ struct acpi_fpdt_boot {
uint64_t startup_start;
uint64_t exit_services_entry;
uint64_t exit_services_exit;
-};
+} _packed;
int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit) {
_cleanup_free_ char *buf = NULL;

View File

@ -0,0 +1,46 @@
From 9e3aefa21a631e7f47a8121097384a8b08ae8502 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Fri, 6 May 2022 14:01:22 +0900
Subject: [PATCH] core/slice: make slice_freezer_action() return 0 if freezing
state is unchanged
Fixes #23278.
(cherry picked from commit d171e72e7afa11b238ba20758384d223b0c76e39)
Related: #2084052
---
src/core/slice.c | 6 +-----
src/core/unit.c | 2 ++
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/core/slice.c b/src/core/slice.c
index c10e830917..34f3c84bf9 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -395,11 +395,7 @@ static int slice_freezer_action(Unit *s, FreezerAction action) {
return r;
}
- r = unit_cgroup_freezer_action(s, action);
- if (r < 0)
- return r;
-
- return 1;
+ return unit_cgroup_freezer_action(s, action);
}
static int slice_freeze(Unit *s) {
diff --git a/src/core/unit.c b/src/core/unit.c
index e2c61ce866..bd79578255 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -5622,6 +5622,8 @@ static int unit_freezer_action(Unit *u, FreezerAction action) {
if (r <= 0)
return r;
+ assert(IN_SET(u->freezer_state, FREEZER_FREEZING, FREEZER_THAWING));
+
return 1;
}

View File

@ -0,0 +1,29 @@
From 330e0ea2859db6107fae65bce982c0f2e2ababf5 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 9 May 2022 00:56:05 +0900
Subject: [PATCH] core/unit: fix use-after-free
Fixes #23312.
(cherry picked from commit 734582830b58e000a26e18807ea277c18778573c)
Related: #2084052
---
src/core/unit.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index bd79578255..68affa2c0e 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -580,8 +580,8 @@ void unit_free(Unit *u) {
unit_dequeue_rewatch_pids(u);
- sd_bus_slot_unref(u->match_bus_slot);
- sd_bus_track_unref(u->bus_track);
+ u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
+ u->bus_track = sd_bus_track_unref(u->bus_track);
u->deserialized_refs = strv_free(u->deserialized_refs);
u->pending_freezer_message = sd_bus_message_unref(u->pending_freezer_message);

View File

@ -0,0 +1,58 @@
From d3d0969d7c366d6bb2f66501e61cbcd11a60face Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 17 Apr 2022 07:05:07 +0900
Subject: [PATCH] sd-bus: fix reference counter to be incremented
Fixes #23097.
(cherry picked from commit b21f237d996c8c18991a68e1204f060d07dc4745)
[msekleta: This commit also contains the hunk from c2d7dd35d2
(in sd_bus_track_remove_name). I've decided to not backport that commit
fully because of conflicts and because its was made largely irrelevant
by 7f40cb7c86]
Related: #2084052
---
src/libsystemd/sd-bus/bus-track.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
index 16bf615f50..b1ec5ecbbb 100644
--- a/src/libsystemd/sd-bus/bus-track.c
+++ b/src/libsystemd/sd-bus/bus-track.c
@@ -208,12 +208,12 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
i = hashmap_get(track->names, name);
if (i) {
if (track->recursive) {
- unsigned k = track->n_ref + 1;
+ unsigned k = i->n_ref + 1;
- if (k < track->n_ref) /* Check for overflow */
+ if (k < i->n_ref) /* Check for overflow */
return -EOVERFLOW;
- track->n_ref = k;
+ i->n_ref = k;
}
bus_track_remove_from_queue(track);
@@ -281,14 +281,13 @@ _public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) {
i = hashmap_get(track->names, name);
if (!i)
return -EUNATCH;
- if (i->n_ref <= 0)
- return -EUNATCH;
-
- i->n_ref--;
- if (i->n_ref <= 0)
+ assert(i->n_ref >=1);
+ if (i->n_ref <= 1)
return bus_track_remove_name_fully(track, name);
+ i->n_ref--;
+
return 1;
}

View File

@ -0,0 +1,32 @@
From 6f8278097070d77e39d15e5f5d11e1c8b83871c2 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 17 Apr 2022 07:25:09 +0900
Subject: [PATCH] sd-bus: do not read unused value
(cherry picked from commit 6a7ca27740be4229b4c9f540cd610b205ca5752c)
Related: #2084052
---
src/libsystemd/sd-bus/bus-track.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
index b1ec5ecbbb..b9965d9d64 100644
--- a/src/libsystemd/sd-bus/bus-track.c
+++ b/src/libsystemd/sd-bus/bus-track.c
@@ -182,13 +182,13 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
sd_bus_track *track = userdata;
- const char *name, *old, *new;
+ const char *name;
int r;
assert(message);
assert(track);
- r = sd_bus_message_read(message, "sss", &name, &old, &new);
+ r = sd_bus_message_read(message, "sss", &name, NULL, NULL);
if (r < 0)
return 0;

View File

@ -0,0 +1,35 @@
From 3005733945670cc4a77920bb55e5cdda331cff4d Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 17 Apr 2022 07:29:24 +0900
Subject: [PATCH] sd-bus: do not return negative errno when unknown name is
specified
When 'recursive' is false, then sd_bus_track_remove_name() does not
return negative errno when unknown name is specified. Let's follow the
same pattern for the case that 'recursive' is true.
(cherry picked from commit 55bfacc6c33eaf3475762e71172b2ef504be5af8)
Related: #2084052
---
src/libsystemd/sd-bus/bus-track.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
index b9965d9d64..8893f190a1 100644
--- a/src/libsystemd/sd-bus/bus-track.c
+++ b/src/libsystemd/sd-bus/bus-track.c
@@ -275,12 +275,9 @@ _public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) {
if (!track) /* Treat a NULL track object as an empty track object */
return 0;
- if (!track->recursive)
- return bus_track_remove_name_fully(track, name);
-
i = hashmap_get(track->names, name);
if (!i)
- return -EUNATCH;
+ return 0;
assert(i->n_ref >=1);
if (i->n_ref <= 1)

View File

@ -0,0 +1,48 @@
From 78b5b6dbd0bb4e5644e798748d186cca88fc523d Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 20 Apr 2022 22:30:22 +0200
Subject: [PATCH] sd-bus: switch to a manual overflow check in
sd_bus_track_add_name()
This is generally used in a directly client controllable way, hence we
should handle ref count overflow gracefully, instead of hitting an
assert().
As discussed:
https://github.com/systemd/systemd/pull/23099#discussion_r854341850
(cherry picked from commit 7f40cb7c86b0fff3a82096a9499570bad9c19fd2)
[msekleta: We've never switched to using track_item_ref/unref introduced
in c2d7dd35d2 hence we still had potential undefined behavior related to
overflow check and this commit fixes that.]
Related: #2084052
---
src/libsystemd/sd-bus/bus-track.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
index 8893f190a1..b818e93bec 100644
--- a/src/libsystemd/sd-bus/bus-track.c
+++ b/src/libsystemd/sd-bus/bus-track.c
@@ -208,12 +208,16 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
i = hashmap_get(track->names, name);
if (i) {
if (track->recursive) {
- unsigned k = i->n_ref + 1;
+ assert(i->n_ref > 0);
- if (k < i->n_ref) /* Check for overflow */
+ /* Manual oveflow check (instead of a DEFINE_TRIVIAL_REF_FUNC() helper or so), so
+ * that we can return a proper error, given this is almost always called in a
+ * directly client controllable way, and thus better should never hit an assertion
+ * here. */
+ if (i->n_ref >= UINT_MAX)
return -EOVERFLOW;
- i->n_ref = k;
+ i->n_ref++;
}
bus_track_remove_from_queue(track);

View File

@ -0,0 +1,62 @@
From 3dc25568b15bff0c79ae6e136a73ffd18a69f525 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com>
Date: Fri, 2 Oct 2020 17:30:35 +0200
Subject: [PATCH] unit: don't emit PropertiesChanged signal if adding a
dependency to a unit is a no-op
(cherry picked from commit 5177cb0a9add4ae568cff6e6f7c2b3c77760c343)
Resolves: #2091590
---
src/core/unit.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index 68affa2c0e..e3e534ea2e 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2818,6 +2818,9 @@ int unit_add_dependency(
};
Unit *original_u = u, *original_other = other;
int r;
+ /* Helper to know whether sending a notification is necessary or not:
+ * if the dependency is already there, no need to notify! */
+ bool noop = true;
assert(u);
assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX);
@@ -2842,24 +2845,33 @@ int unit_add_dependency(
r = unit_add_dependency_hashmap(u->dependencies + d, other, mask, 0);
if (r < 0)
return r;
+ else if (r > 0)
+ noop = false;
if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID && inverse_table[d] != d) {
r = unit_add_dependency_hashmap(other->dependencies + inverse_table[d], u, 0, mask);
if (r < 0)
return r;
+ else if (r > 0)
+ noop = false;
}
if (add_reference) {
r = unit_add_dependency_hashmap(u->dependencies + UNIT_REFERENCES, other, mask, 0);
if (r < 0)
return r;
+ else if (r > 0)
+ noop = false;
r = unit_add_dependency_hashmap(other->dependencies + UNIT_REFERENCED_BY, u, 0, mask);
if (r < 0)
return r;
+ else if (r > 0)
+ noop = false;
}
- unit_add_to_dbus_queue(u);
+ if (!noop)
+ unit_add_to_dbus_queue(u);
return 0;
}

View File

@ -0,0 +1,122 @@
From 336ec08378b901b0372b726ace8b354ef22dd13d Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 11 Sep 2020 19:49:33 +0200
Subject: [PATCH] core: propagate triggered unit in more load states
In 4c2ef3276735ad9f7fccf33f5bdcbe7d8751e7ec we enabled propagating
triggered unit state to the triggering unit for service units in more
load states, so that we don't accidentally stop tracking state
correctly.
Do the same for our other triggering unit states: automounts, paths, and
timers.
Also, make this an assertion rather than a simple test. After all it
should never happen that we get called for half-loaded units or units of
the wrong type. The load routines should already have made this
impossible.
(cherry picked from commit 0377cd2936ae5cac0c9d76a4b58889f121c097c4)
Related: #2086553
---
src/core/automount.c | 4 ++--
src/core/path.c | 7 +++----
src/core/socket.c | 4 ++--
src/core/timer.c | 4 ++--
src/core/transaction.c | 2 +-
src/core/unit.h | 4 ++++
6 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/src/core/automount.c b/src/core/automount.c
index f212620c8f..c1c513d4a5 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -492,8 +492,8 @@ static void automount_trigger_notify(Unit *u, Unit *other) {
assert(other);
/* Filter out invocations with bogus state */
- if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT)
- return;
+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
+ assert(other->type == UNIT_MOUNT);
/* Don't propagate state changes from the mount if we are already down */
if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING))
diff --git a/src/core/path.c b/src/core/path.c
index 58f490589d..a7c2e0b7c1 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -696,11 +696,10 @@ static void path_trigger_notify(Unit *u, Unit *other) {
assert(u);
assert(other);
- /* Invoked whenever the unit we trigger changes state or gains
- * or loses a job */
+ /* Invoked whenever the unit we trigger changes state or gains or loses a job */
- if (other->load_state != UNIT_LOADED)
- return;
+ /* Filter out invocations with bogus state */
+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
if (p->state == PATH_RUNNING &&
UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
diff --git a/src/core/socket.c b/src/core/socket.c
index 3589300e68..74c1cc70cb 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -3190,8 +3190,8 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
assert(other);
/* Filter out invocations with bogus state */
- if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
- return;
+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
+ assert(other->type == UNIT_SERVICE);
/* Don't propagate state changes from the service if we are already down */
if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING))
diff --git a/src/core/timer.c b/src/core/timer.c
index 684180bf99..990f05fee4 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -745,8 +745,8 @@ static void timer_trigger_notify(Unit *u, Unit *other) {
assert(u);
assert(other);
- if (other->load_state != UNIT_LOADED)
- return;
+ /* Filter out invocations with bogus state */
+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
/* Reenable all timers that depend on unit state */
LIST_FOREACH(value, v, t->values)
diff --git a/src/core/transaction.c b/src/core/transaction.c
index ee5b39fef4..8196aba927 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -915,7 +915,7 @@ int transaction_add_job_and_dependencies(
/* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set
* temporarily. */
- if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_MASKED))
+ if (!UNIT_IS_LOAD_COMPLETE(unit->load_state))
return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
if (type != JOB_STOP) {
diff --git a/src/core/unit.h b/src/core/unit.h
index 0cd259411f..b8b914711f 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -47,6 +47,10 @@ static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) {
return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED);
}
+static inline bool UNIT_IS_LOAD_COMPLETE(UnitLoadState t) {
+ return t >= 0 && t < _UNIT_LOAD_STATE_MAX && t != UNIT_STUB && t != UNIT_MERGED;
+}
+
/* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We
* use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be
* created as a result of multiple "reasons", hence the bitmask. */

View File

@ -0,0 +1,68 @@
From 2ce14fcc879b0a24d29dc5f5d36db80c5c1f2653 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 11 Sep 2020 19:57:09 +0200
Subject: [PATCH] core: propagate unit start limit hit state to triggering path
unit
We already do this for socket and automount units, do it for path units
too: if the triggered service keeps hitting the start limit, then fail
the triggering unit too, so that we don#t busy loop forever.
(Note that this leaves only timer units out in the cold for this kind of
protection, but it shouldn't matter there, as they are naturally
protected against busy loops: they are scheduled by time anyway).
Fixes: #16669
(cherry picked from commit 47ab8f73e3468b6e5a48218eacdb830e978d2cfd)
Related: #2086553
---
src/core/path.c | 15 +++++++++++++++
src/core/path.h | 1 +
2 files changed, 16 insertions(+)
diff --git a/src/core/path.c b/src/core/path.c
index a7c2e0b7c1..c2facf0b16 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -701,6 +701,20 @@ static void path_trigger_notify(Unit *u, Unit *other) {
/* Filter out invocations with bogus state */
assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
+ /* Don't propagate state changes from the triggered unit if we are already down */
+ if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING))
+ return;
+
+ /* Propagate start limit hit state */
+ if (other->start_limit_hit) {
+ path_enter_dead(p, PATH_FAILURE_UNIT_START_LIMIT_HIT);
+ return;
+ }
+
+ /* Don't propagate anything if there's still a job queued */
+ if (other->job)
+ return;
+
if (p->state == PATH_RUNNING &&
UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
log_unit_debug(UNIT(p), "Got notified about unit deactivation.");
@@ -752,6 +766,7 @@ static const char* const path_result_table[_PATH_RESULT_MAX] = {
[PATH_SUCCESS] = "success",
[PATH_FAILURE_RESOURCES] = "resources",
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
+ [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
};
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
diff --git a/src/core/path.h b/src/core/path.h
index 4d4b6236c2..8a69f06c13 100644
--- a/src/core/path.h
+++ b/src/core/path.h
@@ -45,6 +45,7 @@ typedef enum PathResult {
PATH_SUCCESS,
PATH_FAILURE_RESOURCES,
PATH_FAILURE_START_LIMIT_HIT,
+ PATH_FAILURE_UNIT_START_LIMIT_HIT,
_PATH_RESULT_MAX,
_PATH_RESULT_INVALID = -1
} PathResult;

View File

@ -0,0 +1,31 @@
From 182d91dbf7f5242dfd390f5145ce342927c3bd50 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Sat, 30 Oct 2021 22:12:06 +0100
Subject: [PATCH] core: Move 'r' variable declaration to start of unit_start()
(cherry picked from commit 5f37c1a955e399756c4137d22f7f0f45a619f425)
Related: #2086553
---
src/core/unit.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index e3e534ea2e..4fd9af87b7 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1725,12 +1725,13 @@ static bool unit_verify_deps(Unit *u) {
int unit_start(Unit *u) {
UnitActiveState state;
Unit *following;
+ int r;
assert(u);
/* Check our ability to start early so that failure conditions don't cause us to enter a busy loop. */
if (UNIT_VTABLE(u)->can_start) {
- int r = UNIT_VTABLE(u)->can_start(u);
+ r = UNIT_VTABLE(u)->can_start(u);
if (r < 0)
return r;
}

View File

@ -0,0 +1,49 @@
From aaeac7a33c8cc23cb890d2ad33b0b1542d5a9176 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Tue, 19 Oct 2021 10:45:48 +0100
Subject: [PATCH] core: Delay start rate limit check when starting a unit
Doing start rate limit checks before doing condition checks made
condition check failures count towards the start rate limit which
broke existing assumptions (see #21025). Run the rate limit checks
after the condition checks again to restore the previous behaviour.
(cherry picked from commit ce2146f5256659c7fb53a7d5b9dc551252e27e7e)
Related: #2086553
---
src/core/unit.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index 4fd9af87b7..b825e2418c 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1729,13 +1729,6 @@ int unit_start(Unit *u) {
assert(u);
- /* Check our ability to start early so that failure conditions don't cause us to enter a busy loop. */
- if (UNIT_VTABLE(u)->can_start) {
- r = UNIT_VTABLE(u)->can_start(u);
- if (r < 0)
- return r;
- }
-
/* If this is already started, then this will succeed. Note that this will even succeed if this unit
* is not startable by the user. This is relied on to detect when we need to wait for units and when
* waiting is finished. */
@@ -1790,6 +1783,13 @@ int unit_start(Unit *u) {
return unit_start(following);
}
+ /* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
+ if (UNIT_VTABLE(u)->can_start) {
+ r = UNIT_VTABLE(u)->can_start(u);
+ if (r < 0)
+ return r;
+ }
+
/* If it is stopped, but we cannot start it, then fail */
if (!UNIT_VTABLE(u)->start)
return -EBADR;

View File

@ -0,0 +1,258 @@
From 42b7498556a3078906834772fec78e2e7303011e Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Mon, 18 Oct 2021 14:17:02 +0200
Subject: [PATCH] core: Propagate condition failed state to triggering units.
Alternative to https://github.com/systemd/systemd/pull/20531.
Whenever a service triggered by another unit fails condition checks,
stop the triggering unit to prevent systemd busy looping trying to
start the triggered unit.
(cherry picked from commit 12ab94a1e4961a39c32efb60b71866ab588d3ea2)
Resolves: #2086553
---
src/core/automount.c | 14 ++++++++++----
src/core/automount.h | 1 +
src/core/path.c | 16 +++++++++++-----
src/core/path.h | 1 +
src/core/socket.c | 28 +++++++++++++++++++---------
src/core/socket.h | 1 +
src/core/timer.c | 12 +++++++++---
src/core/timer.h | 1 +
src/core/unit.c | 10 ++++++++++
src/core/unit.h | 2 ++
10 files changed, 65 insertions(+), 21 deletions(-)
diff --git a/src/core/automount.c b/src/core/automount.c
index c1c513d4a5..bac3b2fab7 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -776,6 +776,11 @@ static void automount_enter_running(Automount *a) {
goto fail;
}
+ if (unit_has_failed_condition_or_assert(trigger)) {
+ automount_enter_dead(a, AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED);
+ return;
+ }
+
r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
if (r < 0) {
log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
@@ -1087,10 +1092,11 @@ static int automount_can_start(Unit *u) {
}
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
- [AUTOMOUNT_SUCCESS] = "success",
- [AUTOMOUNT_FAILURE_RESOURCES] = "resources",
- [AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
- [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
+ [AUTOMOUNT_SUCCESS] = "success",
+ [AUTOMOUNT_FAILURE_RESOURCES] = "resources",
+ [AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
+ [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
+ [AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED] = "mount-condition-failed",
};
DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
diff --git a/src/core/automount.h b/src/core/automount.h
index 21dd1c0774..a7417d195c 100644
--- a/src/core/automount.h
+++ b/src/core/automount.h
@@ -10,6 +10,7 @@ typedef enum AutomountResult {
AUTOMOUNT_FAILURE_RESOURCES,
AUTOMOUNT_FAILURE_START_LIMIT_HIT,
AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT,
+ AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED,
_AUTOMOUNT_RESULT_MAX,
_AUTOMOUNT_RESULT_INVALID = -1
} AutomountResult;
diff --git a/src/core/path.c b/src/core/path.c
index c2facf0b16..bf7e1bf3c2 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -453,7 +453,7 @@ static void path_enter_dead(Path *p, PathResult f) {
else
unit_log_failure(UNIT(p), path_result_to_string(p->result));
- path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD);
+ path_set_state(p, p->result == PATH_SUCCESS ? PATH_DEAD : PATH_FAILED);
}
static void path_enter_running(Path *p) {
@@ -711,6 +711,11 @@ static void path_trigger_notify(Unit *u, Unit *other) {
return;
}
+ if (unit_has_failed_condition_or_assert(other)) {
+ path_enter_dead(p, PATH_FAILURE_UNIT_CONDITION_FAILED);
+ return;
+ }
+
/* Don't propagate anything if there's still a job queued */
if (other->job)
return;
@@ -763,10 +768,11 @@ static const char* const path_type_table[_PATH_TYPE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(path_type, PathType);
static const char* const path_result_table[_PATH_RESULT_MAX] = {
- [PATH_SUCCESS] = "success",
- [PATH_FAILURE_RESOURCES] = "resources",
- [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
- [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
+ [PATH_SUCCESS] = "success",
+ [PATH_FAILURE_RESOURCES] = "resources",
+ [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
+ [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
+ [PATH_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed",
};
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
diff --git a/src/core/path.h b/src/core/path.h
index 8a69f06c13..0ad6bd12c6 100644
--- a/src/core/path.h
+++ b/src/core/path.h
@@ -46,6 +46,7 @@ typedef enum PathResult {
PATH_FAILURE_RESOURCES,
PATH_FAILURE_START_LIMIT_HIT,
PATH_FAILURE_UNIT_START_LIMIT_HIT,
+ PATH_FAILURE_UNIT_CONDITION_FAILED,
_PATH_RESULT_MAX,
_PATH_RESULT_INVALID = -1
} PathResult;
diff --git a/src/core/socket.c b/src/core/socket.c
index 74c1cc70cb..6f9a0f7575 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -2272,6 +2272,15 @@ static void socket_enter_running(Socket *s, int cfd) {
goto refuse;
}
+ if (UNIT_ISSET(s->service) && cfd < 0) {
+ Unit *service = UNIT_DEREF(s->service);
+
+ if (unit_has_failed_condition_or_assert(service)) {
+ socket_enter_dead(s, SOCKET_FAILURE_SERVICE_CONDITION_FAILED);
+ return;
+ }
+ }
+
if (cfd < 0) {
bool pending = false;
Unit *other;
@@ -3287,15 +3296,16 @@ static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand);
static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
- [SOCKET_SUCCESS] = "success",
- [SOCKET_FAILURE_RESOURCES] = "resources",
- [SOCKET_FAILURE_TIMEOUT] = "timeout",
- [SOCKET_FAILURE_EXIT_CODE] = "exit-code",
- [SOCKET_FAILURE_SIGNAL] = "signal",
- [SOCKET_FAILURE_CORE_DUMP] = "core-dump",
- [SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
- [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
- [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit"
+ [SOCKET_SUCCESS] = "success",
+ [SOCKET_FAILURE_RESOURCES] = "resources",
+ [SOCKET_FAILURE_TIMEOUT] = "timeout",
+ [SOCKET_FAILURE_EXIT_CODE] = "exit-code",
+ [SOCKET_FAILURE_SIGNAL] = "signal",
+ [SOCKET_FAILURE_CORE_DUMP] = "core-dump",
+ [SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
+ [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
+ [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit",
+ [SOCKET_FAILURE_SERVICE_CONDITION_FAILED] = "service-condition-failed",
};
DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
diff --git a/src/core/socket.h b/src/core/socket.h
index 2409dbf2a0..b171b94316 100644
--- a/src/core/socket.h
+++ b/src/core/socket.h
@@ -39,6 +39,7 @@ typedef enum SocketResult {
SOCKET_FAILURE_START_LIMIT_HIT,
SOCKET_FAILURE_TRIGGER_LIMIT_HIT,
SOCKET_FAILURE_SERVICE_START_LIMIT_HIT,
+ SOCKET_FAILURE_SERVICE_CONDITION_FAILED,
_SOCKET_RESULT_MAX,
_SOCKET_RESULT_INVALID = -1
} SocketResult;
diff --git a/src/core/timer.c b/src/core/timer.c
index 990f05fee4..3c8d89771d 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -567,6 +567,11 @@ static void timer_enter_running(Timer *t) {
return;
}
+ if (unit_has_failed_condition_or_assert(trigger)) {
+ timer_enter_dead(t, TIMER_FAILURE_UNIT_CONDITION_FAILED);
+ return;
+ }
+
r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
if (r < 0)
goto fail;
@@ -850,9 +855,10 @@ static const char* const timer_base_table[_TIMER_BASE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
- [TIMER_SUCCESS] = "success",
- [TIMER_FAILURE_RESOURCES] = "resources",
- [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
+ [TIMER_SUCCESS] = "success",
+ [TIMER_FAILURE_RESOURCES] = "resources",
+ [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
+ [TIMER_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed",
};
DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
diff --git a/src/core/timer.h b/src/core/timer.h
index 833aadb0b8..d23e19d622 100644
--- a/src/core/timer.h
+++ b/src/core/timer.h
@@ -32,6 +32,7 @@ typedef enum TimerResult {
TIMER_SUCCESS,
TIMER_FAILURE_RESOURCES,
TIMER_FAILURE_START_LIMIT_HIT,
+ TIMER_FAILURE_UNIT_CONDITION_FAILED,
_TIMER_RESULT_MAX,
_TIMER_RESULT_INVALID = -1
} TimerResult;
diff --git a/src/core/unit.c b/src/core/unit.c
index b825e2418c..c00d30e837 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -5657,6 +5657,16 @@ int unit_thaw_vtable_common(Unit *u) {
return unit_cgroup_freezer_action(u, FREEZER_THAW);
}
+bool unit_has_failed_condition_or_assert(Unit *u) {
+ if (dual_timestamp_is_set(&u->condition_timestamp) && !u->condition_result)
+ return true;
+
+ if (dual_timestamp_is_set(&u->assert_timestamp) && !u->assert_result)
+ return true;
+
+ return false;
+}
+
static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
[COLLECT_INACTIVE] = "inactive",
[COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
diff --git a/src/core/unit.h b/src/core/unit.h
index b8b914711f..a924bd2e83 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -847,6 +847,8 @@ void unit_thawed(Unit *u);
int unit_freeze_vtable_common(Unit *u);
int unit_thaw_vtable_common(Unit *u);
+bool unit_has_failed_condition_or_assert(Unit *u);
+
/* Macros which append UNIT= or USER_UNIT= to the message */
#define log_unit_full(unit, level, error, ...) \

View File

@ -0,0 +1,52 @@
From 38e66bd347619efaa42118ebec55b43a87fe02c6 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Mon, 30 May 2022 11:55:41 +0200
Subject: [PATCH] unit: check for mount rate limiting before checking active
state
Having this check as part of mount_can_start() is too late because
UNIT(u)->can_start() virtual method is called after checking the active
state of unit in unit_start().
We need to hold off running mount start jobs when /p/s/mountinfo monitor
is rate limited even when given mount unit is already active.
Fixes #20329
(cherry picked from commit b161bc394b2cc8b271dda9208e310cc2af0cc29d)
Resolves: #2097336
---
src/core/mount.c | 3 ---
src/core/unit.c | 4 ++++
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/core/mount.c b/src/core/mount.c
index 9547cb9b29..d37b5731f8 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1999,9 +1999,6 @@ static int mount_can_start(Unit *u) {
assert(m);
- if (sd_event_source_is_ratelimited(u->manager->mount_event_source))
- return -EAGAIN;
-
r = unit_test_start_limit(u);
if (r < 0) {
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
diff --git a/src/core/unit.c b/src/core/unit.c
index c00d30e837..0810bf5a58 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1729,6 +1729,10 @@ int unit_start(Unit *u) {
assert(u);
+ /* Let's hold off running start jobs for mount units when /proc/self/mountinfo monitor is rate limited. */
+ if (u->type == UNIT_MOUNT && sd_event_source_is_ratelimited(u->manager->mount_event_source))
+ return -EAGAIN;
+
/* If this is already started, then this will succeed. Note that this will even succeed if this unit
* is not startable by the user. This is relied on to detect when we need to wait for units and when
* waiting is finished. */

View File

@ -13,7 +13,7 @@
Name: systemd
Url: http://www.freedesktop.org/wiki/Software/systemd
Version: 239
Release: 58%{?dist}
Release: 58%{?dist}.3
# For a breakdown of the licensing, see README
License: LGPLv2+ and MIT and GPLv2+
Summary: System and Service Manager
@ -793,6 +793,20 @@ Patch0740: 0740-sysctl-fix-segfault.patch
Patch0741: 0741-ci-drop-CentOS-8-CI.patch
Patch0742: 0742-test-adapt-to-the-new-capsh-format.patch
Patch0743: 0743-test-ignore-IAB-capabilities-in-test-execute.patch
Patch0744: 0744-acpi-fpdt-mark-structures-as-packed.patch
Patch0745: 0745-core-slice-make-slice_freezer_action-return-0-if-fre.patch
Patch0746: 0746-core-unit-fix-use-after-free.patch
Patch0747: 0747-sd-bus-fix-reference-counter-to-be-incremented.patch
Patch0748: 0748-sd-bus-do-not-read-unused-value.patch
Patch0749: 0749-sd-bus-do-not-return-negative-errno-when-unknown-nam.patch
Patch0750: 0750-sd-bus-switch-to-a-manual-overflow-check-in-sd_bus_t.patch
Patch0751: 0751-unit-don-t-emit-PropertiesChanged-signal-if-adding-a.patch
Patch0752: 0752-core-propagate-triggered-unit-in-more-load-states.patch
Patch0753: 0753-core-propagate-unit-start-limit-hit-state-to-trigger.patch
Patch0754: 0754-core-Move-r-variable-declaration-to-start-of-unit_st.patch
Patch0755: 0755-core-Delay-start-rate-limit-check-when-starting-a-un.patch
Patch0756: 0756-core-Propagate-condition-failed-state-to-triggering-.patch
Patch0757: 0757-unit-check-for-mount-rate-limiting-before-checking-a.patch
%ifarch %{ix86} x86_64 aarch64
@ -1423,6 +1437,26 @@ fi
%files tests -f .file-list-tests
%changelog
* Thu Jun 23 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-58.3
- unit: check for mount rate limiting before checking active state (#2097336)
* Thu Jun 09 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-58.2
- unit: don't emit PropertiesChanged signal if adding a dependency to a unit is a no-op (#2091590)
- core: propagate triggered unit in more load states (#2086553)
- core: propagate unit start limit hit state to triggering path unit (#2086553)
- core: Move 'r' variable declaration to start of unit_start() (#2086553)
- core: Delay start rate limit check when starting a unit (#2086553)
- core: Propagate condition failed state to triggering units. (#2086553)
* Wed May 11 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-58.1
- acpi-fpdt: mark structures as packed (#2084052)
- core/slice: make slice_freezer_action() return 0 if freezing state is unchanged (#2084052)
- core/unit: fix use-after-free (#2084052)
- sd-bus: fix reference counter to be incremented (#2084052)
- sd-bus: do not read unused value (#2084052)
- sd-bus: do not return negative errno when unknown name is specified (#2084052)
- sd-bus: switch to a manual overflow check in sd_bus_track_add_name() (#2084052)
* Tue Feb 08 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-58
- ci: drop CentOS 8 CI (#2017033)
- test: adapt to the new capsh format (#2017033)