summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2024-11-02 20:56:32 +0100
committerYu Watanabe <watanabe.yu+github@gmail.com>2024-11-03 01:14:36 +0100
commitef45f5c8d0bfbeda2a57b28bba9831f044b23b21 (patch)
treeab2302c6d81661019eca6a712dd1ad74f5dd9e00 /src/network
parentmkosi: Add extra tools tree packages required to run integration tests (diff)
downloadsystemd-ef45f5c8d0bfbeda2a57b28bba9831f044b23b21.tar.xz
systemd-ef45f5c8d0bfbeda2a57b28bba9831f044b23b21.zip
network: refuse further requests when manager is in MANAGER_STOPPED
In that case, requests will never be processed anyway. But further more, we cannot call link_ref() at that stage. Otherwise, we trigger assertion.
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkd-netlabel.c3
-rw-r--r--src/network/networkd-queue.c15
-rw-r--r--src/network/networkd-route.c3
-rw-r--r--src/network/networkd-state-file.c5
4 files changed, 26 insertions, 0 deletions
diff --git a/src/network/networkd-netlabel.c b/src/network/networkd-netlabel.c
index 94bf8f5d26..f153a929e3 100644
--- a/src/network/networkd-netlabel.c
+++ b/src/network/networkd-netlabel.c
@@ -38,6 +38,9 @@ static int netlabel_command(uint16_t command, const char *label, const Address *
assert(address->link->manager->genl);
assert(IN_SET(address->family, AF_INET, AF_INET6));
+ if (address->link->manager->state == MANAGER_STOPPED)
+ return 0; /* We cannot call link_ref() below. */
+
r = sd_genl_message_new(address->link->manager->genl, NETLBL_NLTYPE_UNLABELED_NAME, command, &m);
if (r < 0)
return r;
diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c
index e898ea6e85..f5ad748397 100644
--- a/src/network/networkd-queue.c
+++ b/src/network/networkd-queue.c
@@ -142,6 +142,15 @@ static int request_new(
assert(manager);
assert(process);
+ /* Note, requests will be processed only when the manager is in MANAGER_RUNNING. If a new operation
+ * is requested when the manager is in MANAGER_TERMINATING or MANAGER_RESTARTING, the request will be
+ * successfully queued but will never be processed. Then, here why we refuse new requests when the
+ * manager is in MANAGER_STOPPED? This is because we cannot call link_ref() in that case, as this may
+ * be called during link_free(), that means the reference counter of the link is already 0 and
+ * calling link_ref() below triggers assertion. */
+ if (manager->state == MANAGER_STOPPED)
+ return -EBUSY;
+
req = new(Request, 1);
if (!req)
return -ENOMEM;
@@ -426,6 +435,12 @@ int remove_request_add(
assert(netlink);
assert(message);
+ /* Unlike request_new(), remove requests will be also processed when the manager is in
+ * MANAGER_TERMINATING or MANAGER_RESTARTING. When the manager is in MANAGER_STOPPED, we cannot
+ * queue new remove requests anymore with the same reason explained in request_new(). */
+ if (manager->state == MANAGER_STOPPED)
+ return 0;
+
req = new(RemoveRequest, 1);
if (!req)
return -ENOMEM;
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index 3be737ae49..6aa4d0547b 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -574,6 +574,9 @@ int route_remove(Route *route, Manager *manager) {
assert(route);
assert(manager);
+ if (manager->state == MANAGER_STOPPED)
+ return 0; /* The remove request will not be queued anyway. Suppress logging below. */
+
/* If the route is remembered, then use the remembered object. */
(void) route_get(manager, route, &route);
diff --git a/src/network/networkd-state-file.c b/src/network/networkd-state-file.c
index 337eaa5447..0c9e530128 100644
--- a/src/network/networkd-state-file.c
+++ b/src/network/networkd-state-file.c
@@ -948,6 +948,11 @@ void link_dirty(Link *link) {
assert(link);
assert(link->manager);
+ /* When the manager is in MANAGER_STOPPED, it is not necessary to update state files anymore, as they
+ * will be removed soon anyway. Moreover, we cannot call link_ref() in that case. */
+ if (link->manager->state == MANAGER_STOPPED)
+ return;
+
/* The serialized state in /run is no longer up-to-date. */
/* Also mark manager dirty as link is dirty */