manager: fix race condition while enumerating devices at startup

While enumerating devices at startup, we take a snapshot of existing
links from platform and we start creating device instances for
them. It's possible that in the meantime, while processing netlink
events in platform_link_added(), a link gets renamed. If that happens,
then we have two different views of the same ifindex: the cached link
from `links` and the link in platform.

This can cause issues: in platform_link_added() we create the device
with the cached name; then in NMDevice's constructor(), we look up
from platform the ifindex for the given name. Because of the rename,
this lookup can match a newly created, different link.

The end result is that the ifindex from the initial snapshot doesn't
get a NMDevice and is not handled by NetworkManager.

Fix this problem by fetching the latest version of the link from
platform to make sure we have a consistent view of the state.

https://issues.redhat.com/browse/RHEL-25808
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1897
This commit is contained in:
Beniamino Galvani
2024-03-21 09:45:15 +01:00
parent 666dd2840a
commit de130df3e2

View File

@@ -4438,10 +4438,25 @@ platform_query_devices(NMManager *self)
links = nm_platform_link_get_all(priv->platform);
if (!links)
return;
for (i = 0; i < links->len; i++) {
const NMPlatformLink *link = NMP_OBJECT_CAST_LINK(links->pdata[i]);
const NMPlatformLink *elem = NMP_OBJECT_CAST_LINK(links->pdata[i]);
const NMPlatformLink *link;
const NMConfigDeviceStateData *dev_state;
/*
* @links is an immutable snapshot of the platform links captured before
* the loop was started. It's possible that in the meantime, while
* processing netlink events in platform_link_added(), a link was
* renamed. If that happens, we have 2 different views of the same
* ifindex: the one from @links and the one from platform. This can
* cause race conditions; make sure to use the latest known version of
* the link.
*/
link = nm_platform_link_get(priv->platform, elem->ifindex);
if (!link)
continue;
dev_state = nm_config_device_state_get(priv->config, link->ifindex);
platform_link_added(self,
link->ifindex,