sys-apps/systemd: Backport fix for networkd unmanaged issue to v256

This is upstream issue https://github.com/systemd/systemd/issues/36997 which we
are hitting on Auzre, most likely since the networking rules shipped by
azure-vm-utils are taking priority over Flatcar's own rule to keep enslaved
NICs unmanaged. The azure-vm-utils configs use the ID_NET_MANAGED_BY property
in addition to a custom property set on interfaces to keep them unmanaged. It
isn't yet clear if only ID_NET_MANAGED_BY is affected or if it's the only thing
that was fixed.

Meanwhile we need to backport the bugfix. Patch 0011 is the actual fix and 0010
is included because it makes the backport easier. The bugfix will be in v258
and has been backported to v257.7 upstream.

Signed-off-by: Jeremi Piotrowski <jpiotrowski@microsoft.com>
This commit is contained in:
Jeremi Piotrowski 2025-07-31 14:59:50 +02:00
parent a9221a4e57
commit d8161761b0
3 changed files with 267 additions and 0 deletions

View File

@ -0,0 +1,119 @@
From 7136aa7db4423432392a0fe6055c48a922a4aad4 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 10 Sep 2024 00:12:41 +0900
Subject: [PATCH] network/netdev: also check ifindex, iftype, and kind when
assigning NetDev to Link
Even when a NetDev object with the same name found, its iftype or kind
may be different. For safety, let's also check them.
(cherry picked from commit 1788c3462853e8bb955ff656007e20f402dd9af2)
Signed-off-by: Jeremi Piotrowski <jpiotrowski@microsoft.com>
---
src/network/netdev/netdev.c | 37 +++++++++++++++++++++++++++++++++++++
src/network/netdev/netdev.h | 1 +
src/network/networkd-link.c | 10 ++--------
3 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c
index 2b411425ba..9a528137ea 100644
--- a/src/network/netdev/netdev.c
+++ b/src/network/netdev/netdev.c
@@ -265,6 +265,43 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) {
return 0;
}
+void link_assign_netdev(Link *link) {
+ _unused_ _cleanup_(netdev_unrefp) NetDev *old = NULL;
+ NetDev *netdev;
+
+ assert(link);
+ assert(link->manager);
+ assert(link->ifname);
+
+ old = TAKE_PTR(link->netdev);
+
+ if (netdev_get(link->manager, link->ifname, &netdev) < 0)
+ return;
+
+ if (netdev->ifindex != link->ifindex)
+ return;
+
+ if (NETDEV_VTABLE(netdev)->iftype != link->iftype)
+ return;
+
+ if (!NETDEV_VTABLE(netdev)->skip_netdev_kind_check) {
+ const char *kind;
+
+ if (netdev->kind == NETDEV_KIND_TAP)
+ kind = "tun"; /* the kernel does not distinguish between tun and tap */
+ else
+ kind = netdev_kind_to_string(netdev->kind);
+
+ if (!streq_ptr(kind, link->kind))
+ return;
+ }
+
+ link->netdev = netdev_ref(netdev);
+
+ if (netdev != old)
+ log_link_debug(link, "Found matching .netdev file: %s", netdev->filename);
+}
+
void netdev_enter_failed(NetDev *netdev) {
netdev->state = NETDEV_STATE_FAILED;
}
diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h
index cb8cc8c6a9..1a03a9b592 100644
--- a/src/network/netdev/netdev.h
+++ b/src/network/netdev/netdev.h
@@ -206,6 +206,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref);
bool netdev_is_managed(NetDev *netdev);
int netdev_get(Manager *manager, const char *name, NetDev **ret);
+void link_assign_netdev(Link *link);
int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink);
int netdev_generate_hw_addr(NetDev *netdev, Link *link, const char *name,
const struct hw_addr_data *hw_addr, struct hw_addr_data *ret);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 8f21504d92..c3a5dc1f0d 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1317,7 +1317,6 @@ static int link_get_network(Link *link, Network **ret) {
int link_reconfigure_impl(Link *link, bool force) {
Network *network = NULL;
- NetDev *netdev = NULL;
int r;
assert(link);
@@ -1326,13 +1325,11 @@ int link_reconfigure_impl(Link *link, bool force) {
if (link->manager->state != MANAGER_RUNNING)
return 0;
+ link_assign_netdev(link);
+
if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER))
return 0;
- r = netdev_get(link->manager, link->ifname, &netdev);
- if (r < 0 && r != -ENOENT)
- return r;
-
r = link_get_network(link, &network);
if (r < 0 && r != -ENOENT)
return r;
@@ -1397,9 +1394,6 @@ int link_reconfigure_impl(Link *link, bool force) {
link_free_engines(link);
link->network = network_unref(link->network);
- netdev_unref(link->netdev);
- link->netdev = netdev_ref(netdev);
-
if (!network) {
link_set_state(link, LINK_STATE_UNMANAGED);
return 0;
--
2.39.5

View File

@ -0,0 +1,146 @@
From 916523aabc7fcb3b5b9362100a5e3417aae00cb2 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 11 Jun 2025 18:05:46 +0900
Subject: [PATCH] network: also check ID_NET_MANAGED_BY property on
reconfigure
Previously, the property was checked only when an uevent is received,
so even if an interface has ID_NET_MANAGED_BY property, the interface
will be configured by networkd when reconfiguration is triggered e.g.
when interface state is changed.
Follow-up for ba87a61d05d637be9f0b21707f7fe3b0a74c5a05.
Fixes #36997.
(cherry picked from commit 78f8d5ed71ecc16ad36d1c215d2d57433d127679)
Signed-off-by: Jeremi Piotrowski <jpiotrowski@microsoft.com>
---
src/network/networkd-link.c | 44 ++++++++++++++-----
.../test-network/conf/11-dummy-unmanaged.link | 8 ++++
test/test-network/systemd-networkd-tests.py | 11 +++++
3 files changed, 53 insertions(+), 10 deletions(-)
create mode 100644 test/test-network/conf/11-dummy-unmanaged.link
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index c3a5dc1f0d..3ed1584807 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1315,6 +1315,32 @@ static int link_get_network(Link *link, Network **ret) {
return -ENOENT;
}
+static int link_managed_by_us(Link *link) {
+ int r;
+
+ assert(link);
+
+ if (!link->dev)
+ return true;
+
+ const char *s;
+ r = sd_device_get_property_value(link->dev, "ID_NET_MANAGED_BY", &s);
+ if (r == -ENOENT)
+ return true;
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to get ID_NET_MANAGED_BY udev property: %m");
+
+ if (streq(s, "io.systemd.Network"))
+ return true;
+
+ if (link->state == LINK_STATE_UNMANAGED)
+ return false; /* Already in unmanaged state */
+
+ log_link_debug(link, "Interface is requested to be managed by '%s', unmanaging the interface.", s);
+ link_set_state(link, LINK_STATE_UNMANAGED);
+ return false;
+}
+
int link_reconfigure_impl(Link *link, bool force) {
Network *network = NULL;
int r;
@@ -1330,6 +1356,10 @@ int link_reconfigure_impl(Link *link, bool force) {
if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER))
return 0;
+ r = link_managed_by_us(link);
+ if (r <= 0)
+ return r;
+
r = link_get_network(link, &network);
if (r < 0 && r != -ENOENT)
return r;
@@ -1584,6 +1614,10 @@ static int link_initialized(Link *link, sd_device *device) {
* or sysattrs) may be outdated. */
device_unref_and_replace(link->dev, device);
+ r = link_managed_by_us(link);
+ if (r <= 0)
+ return r;
+
if (link->dhcp_client) {
r = sd_dhcp_client_attach_device(link->dhcp_client, link->dev);
if (r < 0)
@@ -1651,7 +1685,6 @@ static int link_check_initialized(Link *link) {
int manager_udev_process_link(Manager *m, sd_device *device, sd_device_action_t action) {
int r, ifindex;
- const char *s;
Link *link;
assert(m);
@@ -1686,15 +1719,6 @@ int manager_udev_process_link(Manager *m, sd_device *device, sd_device_action_t
return 0;
}
- r = sd_device_get_property_value(device, "ID_NET_MANAGED_BY", &s);
- if (r < 0 && r != -ENOENT)
- log_device_debug_errno(device, r, "Failed to get ID_NET_MANAGED_BY udev property, ignoring: %m");
- if (r >= 0 && !streq(s, "io.systemd.Network")) {
- log_device_debug(device, "Interface is requested to be managed by '%s', not managing the interface.", s);
- link_set_state(link, LINK_STATE_UNMANAGED);
- return 0;
- }
-
r = link_initialized(link, device);
if (r < 0)
link_enter_failed(link);
diff --git a/test/test-network/conf/11-dummy-unmanaged.link b/test/test-network/conf/11-dummy-unmanaged.link
new file mode 100644
index 0000000000..99c07a72ce
--- /dev/null
+++ b/test/test-network/conf/11-dummy-unmanaged.link
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: MIT-0
+[Match]
+Kind=dummy
+OriginalName=test1
+
+[Link]
+NamePolicy=keep
+Property=ID_NET_MANAGED_BY=hoge
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index d8acf538f0..391d219de8 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -2735,6 +2735,17 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
def tearDown(self):
tear_down_common()
+ def test_ID_NET_MANAGED_BY(self):
+ copy_network_unit('11-dummy.netdev', '11-dummy-unmanaged.link', '11-dummy.network')
+ start_networkd()
+ self.wait_online('test1:off', setup_state='unmanaged')
+
+ check_output('ip link set dev test1 up')
+ self.wait_online('test1:degraded', setup_state='unmanaged')
+
+ check_output('ip link set dev test1 down')
+ self.wait_online('test1:off', setup_state='unmanaged')
+
def verify_address_static(
self,
label1: str,
--
2.39.5

View File

@ -266,6 +266,8 @@ src_prepare() {
"${FILESDIR}/0006-Revert-getty-Pass-tty-to-use-by-agetty-via-stdin.patch" "${FILESDIR}/0006-Revert-getty-Pass-tty-to-use-by-agetty-via-stdin.patch"
"${FILESDIR}/0007-units-Keep-using-old-journal-file-format.patch" "${FILESDIR}/0007-units-Keep-using-old-journal-file-format.patch"
"${FILESDIR}/0009-initrd-parse-etc.service.patch" "${FILESDIR}/0009-initrd-parse-etc.service.patch"
"${FILESDIR}/0010-network-netdev-also-check-ifindex-iftype-and-kind-wh.patch"
"${FILESDIR}/0011-network-also-check-ID_NET_MANAGED_BY-property-on-rec.patch"
) )
if ! use vanilla; then if ! use vanilla; then