From 7cd04ce014732a5c50389dc0c6d9804a9e2c0e5c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 22 Sep 2017 12:37:12 +0200 Subject: core: inject route list to delete for nm_platform_ip_route_sync() Whenever we call a platform operation that reads or writes the netlink socket, there is the possibility that the cache gets updated, as we receive netlink events. It is thus racy, if nm_platform_ip_route_sync() *first* adds routes, and then obtains a list of routes to delete. The correct approach is to determine which routes to delete first (and keep it in a list @routes_prune), and pass that list down to nm_platform_ip_route_sync(). Arguably, this doesn't yet solve every race. For example, NMDevice calls update_ext_ip_config() during ip4_config_merge_and_apply(). That is good, as it resyncs with platform. However, before calling nm_ip4_config_commit() it calls other platform operations, like _commit_mtu(). So, the race is still there. --- src/nm-ip6-config.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/nm-ip6-config.c') diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index fce5fa8e90..1c0094d94c 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -608,6 +608,7 @@ nm_ip6_config_commit (const NMIP6Config *self, { gs_unref_ptrarray GPtrArray *addresses = NULL; gs_unref_ptrarray GPtrArray *routes = NULL; + gs_unref_ptrarray GPtrArray *routes_prune = NULL; int ifindex; gboolean success = TRUE; @@ -618,16 +619,21 @@ nm_ip6_config_commit (const NMIP6Config *self, addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip6_config_lookup_addresses (self), NULL, NULL); + routes = nm_dedup_multi_objs_to_ptr_array_head (nm_ip6_config_lookup_routes (self), NULL, NULL); + + routes_prune = nm_platform_ip_route_get_prune_list (platform, + AF_INET6, + ifindex); + nm_platform_ip6_address_sync (platform, ifindex, addresses, TRUE); if (!nm_platform_ip_route_sync (platform, AF_INET6, ifindex, routes, - nm_platform_lookup_predicate_routes_main, - NULL, + routes_prune, out_temporary_not_available)) success = FALSE; -- cgit v1.2.1