From d137eaea0c8b60930b2f75a46fe5e8a6581a40e4 Mon Sep 17 00:00:00 2001 From: Radek Vykydal Date: Dec 11 2020 10:35:17 +0000 Subject: network: fix double-free using libnm function filter_connections() Based-on-patch-by: Thomas Haller The libnm functions nm_{device,access_pointer}_filter_connections() return ownership of a newly create GPtrArray, which also owns the content by having the g_ptr_array_set_free_func() function set to g_object_unref(). Consequently, this functions should be annotate with "(transfer container)" or "(transfer full)", but various bindings treat that differently. To make pygobject happy, it would require "(transfer container)", but that breaks vala (and vice versa). This leads to a double-free and a crash in anaconda. This is not really fixable in libnm. But the workaround is simple. Let's just not use these functions. See-also: https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/commit/b012877445bddd772eec79e3ce38f93cc40de720 See-also: https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/305 Resolves: rhbaz#1873561 --- diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py index 3db13cb..39ffca5 100644 --- a/pyanaconda/ui/gui/spokes/network.py +++ b/pyanaconda/ui/gui/spokes/network.py @@ -485,7 +485,7 @@ class NetworkControlBox(GObject.GObject): def _get_the_only_wireless_connection(self, device): con_uuid = con_ssid = "" if device: - cons = device.filter_connections(self.client.get_connections()) + cons = _safe_device_filter_connections(device, self.client.get_connections()) if len(cons) == 1: connection = cons[0] con_uuid = connection.get_setting_connection().get_uuid() @@ -1184,7 +1184,7 @@ class ConfigureWirelessNetworksDialog(GUIObject): log.warnig("device for interface %s not found", device) return - cons = device.filter_connections(self._nm_client.get_connections()) + cons = _safe_device_filter_connections(device, self._nm_client.get_connections()) # Update model self._store.clear() @@ -1383,7 +1383,8 @@ class SelectWirelessNetworksDialog(GUIObject): if not ap: return - cons = ap.filter_connections(device.filter_connections(self._nm_client.get_connections())) + cons = _safe_device_filter_connections(device, self._nm_client.get_connections()) + cons = _safe_ap_filter_connections(ap, cons) if cons: con = cons[0] self._nm_client.activate_connection_async(con, device, ap.get_path(), None) @@ -1685,3 +1686,13 @@ class NetworkStandaloneSpoke(StandaloneSpoke): def _update_hostname(self): self.network_control_box.current_hostname = self._network_module.GetCurrentHostname() + + +def _safe_device_filter_connections(device, connections): + # Do not use device.filter_connections, rhbz#1873561 + return [c for c in connections if device.connection_valid(c)] + + +def _safe_ap_filter_connections(ap, connections): + # Do not use ap.filter_connections, rhbz#1873561 + return [c for c in connections if ap.connection_valid(c)]