diff --git a/SOURCES/0023-udev-initialized-race-rh1388286.patch b/SOURCES/0023-udev-initialized-race-rh1388286.patch new file mode 100644 index 0000000..323d720 --- /dev/null +++ b/SOURCES/0023-udev-initialized-race-rh1388286.patch @@ -0,0 +1,2972 @@ +From 443691e1017a66509dffdc81cff15d86d5e4d0b4 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Thu, 6 Oct 2016 21:28:40 +0200 +Subject: [PATCH 01/15] logging: remove LOGD_HW alias for LOGD_PLATFORM + +Since commit 1495853e01299d1eb33d4eb10b91e37dcf855cc8, LOGD_HW is renamed to +LOGD_PLATFORM. Remove the internal usage of the deprecated name. + +Backport this patch to nm-1-4 because it avoids follow-up conflicts with +future backports. Also, it is a really trivial change, meaning, we only +replace the obsolte LOGD_HW name. + +(cherry picked from commit 64951f07fb39e1c88448ba2ad72a5e710712c89d) + +Conflicts: + src/devices/nm-device.c + src/devices/wwan/nm-modem.c + +(cherry picked from commit a67eb9d8d00b9c69f52879e5edf087932bf4d07d) +--- + src/devices/adsl/nm-atm-manager.c | 14 +++++++------- + src/devices/nm-device-bond.c | 2 +- + src/devices/nm-device-ethernet.c | 14 +++++++------- + src/devices/nm-device-factory.c | 18 +++++++++--------- + src/devices/nm-device-ip-tunnel.c | 8 ++++---- + src/devices/nm-device-macvlan.c | 2 +- + src/devices/nm-device-tun.c | 2 +- + src/devices/nm-device-veth.c | 2 +- + src/devices/nm-device-vxlan.c | 2 +- + src/devices/nm-device.c | 30 +++++++++++++++--------------- + src/devices/wifi/nm-device-wifi.c | 2 +- + src/devices/wifi/nm-wifi-factory.c | 2 +- + src/devices/wwan/nm-modem.c | 4 ++-- + src/nm-logging.h | 1 - + src/nm-manager.c | 6 +++--- + src/nm-rfkill-manager.c | 2 +- + src/platform/wifi/wifi-utils-nl80211.c | 16 ++++++++-------- + src/platform/wifi/wifi-utils-wext.c | 32 ++++++++++++++++---------------- + 18 files changed, 79 insertions(+), 80 deletions(-) + +diff --git a/src/devices/adsl/nm-atm-manager.c b/src/devices/adsl/nm-atm-manager.c +index 6708575..40c782f 100644 +--- a/src/devices/adsl/nm-atm-manager.c ++++ b/src/devices/adsl/nm-atm-manager.c +@@ -68,7 +68,7 @@ dev_get_attrs (GUdevDevice *udev_device, + + path = g_udev_device_get_sysfs_path (udev_device); + if (!path) { +- nm_log_warn (LOGD_HW, "couldn't determine device path; ignoring..."); ++ nm_log_warn (LOGD_PLATFORM, "couldn't determine device path; ignoring..."); + return FALSE; + } + +@@ -110,11 +110,11 @@ adsl_add (NMAtmManager *self, GUdevDevice *udev_device) + + ifname = g_udev_device_get_name (udev_device); + if (!ifname) { +- nm_log_warn (LOGD_HW, "failed to get device's interface name"); ++ nm_log_warn (LOGD_PLATFORM, "failed to get device's interface name"); + return; + } + +- nm_log_dbg (LOGD_HW, "(%s): found ATM device", ifname); ++ nm_log_dbg (LOGD_PLATFORM, "(%s): found ATM device", ifname); + + atm_index_path = g_strdup_printf ("/sys/class/atm/%s/atmindex", + NM_ASSERT_VALID_PATH_COMPONENT (ifname)); +@@ -123,12 +123,12 @@ adsl_add (NMAtmManager *self, GUdevDevice *udev_device) + 10, 0, G_MAXINT, + -1); + if (atm_index < 0) { +- nm_log_warn (LOGD_HW, "(%s): failed to get ATM index", ifname); ++ nm_log_warn (LOGD_PLATFORM, "(%s): failed to get ATM index", ifname); + return; + } + + if (!dev_get_attrs (udev_device, &sysfs_path, &driver)) { +- nm_log_warn (LOGD_HW, "(%s): failed to get ATM attributes", ifname); ++ nm_log_warn (LOGD_PLATFORM, "(%s): failed to get ATM attributes", ifname); + return; + } + +@@ -153,7 +153,7 @@ adsl_remove (NMAtmManager *self, GUdevDevice *udev_device) + const char *iface = g_udev_device_get_name (udev_device); + GSList *iter; + +- nm_log_dbg (LOGD_HW, "(%s): removing ATM device", iface); ++ nm_log_dbg (LOGD_PLATFORM, "(%s): removing ATM device", iface); + + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *device = iter->data; +@@ -210,7 +210,7 @@ handle_uevent (GUdevClient *client, + + ifindex = g_udev_device_get_property (device, "IFINDEX"); + seqnum = g_udev_device_get_seqnum (device); +- nm_log_dbg (LOGD_HW, "UDEV event: action '%s' subsys '%s' device '%s' (%s); seqnum=%" G_GUINT64_FORMAT, ++ nm_log_dbg (LOGD_PLATFORM, "UDEV event: action '%s' subsys '%s' device '%s' (%s); seqnum=%" G_GUINT64_FORMAT, + action, subsys, g_udev_device_get_name (device), ifindex ? ifindex : "unknown", seqnum); + + if (!strcmp (action, "add")) +diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c +index 3f17849..75b2e31 100644 +--- a/src/devices/nm-device-bond.c ++++ b/src/devices/nm-device-bond.c +@@ -129,7 +129,7 @@ set_bond_attr (NMDevice *device, NMBondMode mode, const char *attr, const char * + + ret = nm_platform_sysctl_master_set_option (NM_PLATFORM_GET, ifindex, attr, value); + if (!ret) +- _LOGW (LOGD_HW, "failed to set bonding attribute '%s' to '%s'", attr, value); ++ _LOGW (LOGD_PLATFORM, "failed to set bonding attribute '%s' to '%s'", attr, value); + return ret; + } + +diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c +index b213a0c..2f0b68a 100644 +--- a/src/devices/nm-device-ethernet.c ++++ b/src/devices/nm-device-ethernet.c +@@ -188,7 +188,7 @@ _update_s390_subchannels (NMDeviceEthernet *self) + parent_path = g_udev_device_get_sysfs_path (parent); + dir = g_dir_open (parent_path, 0, &error); + if (!dir) { +- _LOGW (LOGD_DEVICE | LOGD_HW, "update-s390: failed to open directory '%s': %s", ++ _LOGW (LOGD_DEVICE | LOGD_PLATFORM, "update-s390: failed to open directory '%s': %s", + parent_path, error->message); + g_clear_error (&error); + return; +@@ -218,11 +218,11 @@ _update_s390_subchannels (NMDeviceEthernet *self) + g_hash_table_insert (priv->s390_options, g_strdup (item), value); + value = NULL; + } else +- _LOGW (LOGD_DEVICE | LOGD_HW, "update-s390: error reading %s", path); ++ _LOGW (LOGD_DEVICE | LOGD_PLATFORM, "update-s390: error reading %s", path); + } + + if (error) { +- _LOGW (LOGD_DEVICE | LOGD_HW, "update-s390: failed reading sysfs for %s (%s)", item, error->message); ++ _LOGW (LOGD_DEVICE | LOGD_PLATFORM, "update-s390: failed reading sysfs for %s (%s)", item, error->message); + g_clear_error (&error); + } + } +@@ -247,7 +247,7 @@ _update_s390_subchannels (NMDeviceEthernet *self) + priv->subchannels_dbus[2] = g_strdup (priv->subchan3); + priv->subchannels_dbus[3] = NULL; + +- _LOGI (LOGD_DEVICE | LOGD_HW, "update-s390: found s390 '%s' subchannels [%s]", ++ _LOGI (LOGD_DEVICE | LOGD_PLATFORM, "update-s390: found s390 '%s' subchannels [%s]", + nm_device_get_driver ((NMDevice *) self) ?: "(unknown driver)", + priv->subchannels); + +@@ -311,7 +311,7 @@ get_generic_capabilities (NMDevice *device) + if (nm_platform_link_supports_carrier_detect (NM_PLATFORM_GET, nm_device_get_ifindex (device))) + return NM_DEVICE_CAP_CARRIER_DETECT; + else { +- _LOGI (LOGD_HW, "driver '%s' does not support carrier detection.", ++ _LOGI (LOGD_PLATFORM, "driver '%s' does not support carrier detection.", + nm_device_get_driver (device)); + return NM_DEVICE_CAP_NONE; + } +@@ -1324,7 +1324,7 @@ deactivate (NMDevice *device) + s_dcb = (NMSettingDcb *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_DCB); + if (s_dcb) { + if (!nm_dcb_cleanup (nm_device_get_iface (device), &error)) { +- _LOGW (LOGD_DEVICE | LOGD_HW, "failed to disable DCB/FCoE: %s", ++ _LOGW (LOGD_DEVICE | LOGD_PLATFORM, "failed to disable DCB/FCoE: %s", + error->message); + g_clear_error (&error); + } +@@ -1529,7 +1529,7 @@ get_link_speed (NMDevice *device) + priv->speed = speed; + _notify (self, PROP_SPEED); + +- _LOGD (LOGD_HW | LOGD_ETHER, "speed is now %d Mb/s", speed); ++ _LOGD (LOGD_PLATFORM | LOGD_ETHER, "speed is now %d Mb/s", speed); + } + + static void +diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c +index 7873756..a72c0bb 100644 +--- a/src/devices/nm-device-factory.c ++++ b/src/devices/nm-device-factory.c +@@ -369,7 +369,7 @@ read_device_factory_paths (void) + + dir = g_dir_open (NMPLUGINDIR, 0, &error); + if (!dir) { +- nm_log_warn (LOGD_HW, "device plugin: failed to open directory %s: %s", ++ nm_log_warn (LOGD_PLATFORM, "device plugin: failed to open directory %s: %s", + NMPLUGINDIR, + error->message); + g_clear_error (&error); +@@ -391,17 +391,17 @@ read_device_factory_paths (void) + + if (stat (data.path, &data.st) != 0) { + errsv = errno; +- nm_log_warn (LOGD_HW, "device plugin: skip invalid file %s (error during stat: %s)", data.path, strerror (errsv)); ++ nm_log_warn (LOGD_PLATFORM, "device plugin: skip invalid file %s (error during stat: %s)", data.path, strerror (errsv)); + goto NEXT; + } + if (!S_ISREG (data.st.st_mode)) + goto NEXT; + if (data.st.st_uid != 0) { +- nm_log_warn (LOGD_HW, "device plugin: skip invalid file %s (file must be owned by root)", data.path); ++ nm_log_warn (LOGD_PLATFORM, "device plugin: skip invalid file %s (file must be owned by root)", data.path); + goto NEXT; + } + if (data.st.st_mode & (S_IWGRP | S_IWOTH | S_ISUID)) { +- nm_log_warn (LOGD_HW, "device plugin: skip invalid file %s (invalid file permissions)", data.path); ++ nm_log_warn (LOGD_PLATFORM, "device plugin: skip invalid file %s (invalid file permissions)", data.path); + goto NEXT; + } + +@@ -443,7 +443,7 @@ _add_factory (NMDeviceFactory *factory, + if (check_duplicates) { + found = find_factory (link_types, setting_types); + if (found) { +- nm_log_warn (LOGD_HW, "Loading device plugin failed: multiple plugins " ++ nm_log_warn (LOGD_PLATFORM, "Loading device plugin failed: multiple plugins " + "for same type (using '%s' instead of '%s')", + (char *) g_object_get_data (G_OBJECT (found), PLUGIN_PATH_TAG), + path); +@@ -459,7 +459,7 @@ _add_factory (NMDeviceFactory *factory, + + callback (factory, user_data); + +- nm_log_info (LOGD_HW, "Loaded device plugin: %s (%s)", G_OBJECT_TYPE_NAME (factory), path); ++ nm_log_info (LOGD_PLATFORM, "Loaded device plugin: %s (%s)", G_OBJECT_TYPE_NAME (factory), path); + return TRUE; + } + +@@ -502,12 +502,12 @@ nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc call + plugin = g_module_open (*path, G_MODULE_BIND_LOCAL); + + if (!plugin) { +- nm_log_warn (LOGD_HW, "(%s): failed to load plugin: %s", item, g_module_error ()); ++ nm_log_warn (LOGD_PLATFORM, "(%s): failed to load plugin: %s", item, g_module_error ()); + continue; + } + + if (!g_module_symbol (plugin, "nm_device_factory_create", (gpointer) &create_func)) { +- nm_log_warn (LOGD_HW, "(%s): failed to find device factory creator: %s", item, g_module_error ()); ++ nm_log_warn (LOGD_PLATFORM, "(%s): failed to find device factory creator: %s", item, g_module_error ()); + g_module_close (plugin); + continue; + } +@@ -518,7 +518,7 @@ nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc call + + factory = create_func (&error); + if (!factory) { +- nm_log_warn (LOGD_HW, "(%s): failed to initialize device factory: %s", ++ nm_log_warn (LOGD_PLATFORM, "(%s): failed to initialize device factory: %s", + item, NM_G_ERROR_MSG (error)); + g_clear_error (&error); + continue; +diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c +index 785010e..72a1389 100644 +--- a/src/devices/nm-device-ip-tunnel.c ++++ b/src/devices/nm-device-ip-tunnel.c +@@ -160,7 +160,7 @@ clear: + + lnk = nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, ifindex, NULL); + if (!lnk) { +- _LOGW (LOGD_HW, "could not read %s properties", "gre"); ++ _LOGW (LOGD_PLATFORM, "could not read %s properties", "gre"); + goto clear; + } + +@@ -205,7 +205,7 @@ clear: + + lnk = nm_platform_link_get_lnk_sit (NM_PLATFORM_GET, ifindex, NULL); + if (!lnk) { +- _LOGW (LOGD_HW, "could not read %s properties", "sit"); ++ _LOGW (LOGD_PLATFORM, "could not read %s properties", "sit"); + goto clear; + } + +@@ -220,7 +220,7 @@ clear: + + lnk = nm_platform_link_get_lnk_ipip (NM_PLATFORM_GET, ifindex, NULL); + if (!lnk) { +- _LOGW (LOGD_HW, "could not read %s properties", "ipip"); ++ _LOGW (LOGD_PLATFORM, "could not read %s properties", "ipip"); + goto clear; + } + +@@ -236,7 +236,7 @@ clear: + + lnk = nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, ifindex, NULL); + if (!lnk) { +- _LOGW (LOGD_HW, "could not read %s properties", "ip6tnl"); ++ _LOGW (LOGD_PLATFORM, "could not read %s properties", "ip6tnl"); + goto clear; + } + +diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c +index 2bfc65c..0a43646 100644 +--- a/src/devices/nm-device-macvlan.c ++++ b/src/devices/nm-device-macvlan.c +@@ -180,7 +180,7 @@ update_properties (NMDevice *device) + props = nm_platform_link_get_lnk_macvlan (NM_PLATFORM_GET, nm_device_get_ifindex (device), &plink); + + if (!props) { +- _LOGW (LOGD_HW, "could not get %s properties", priv->props.tap ? "macvtap" : "macvlan"); ++ _LOGW (LOGD_PLATFORM, "could not get %s properties", priv->props.tap ? "macvtap" : "macvlan"); + return; + } + +diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c +index 1f42d06..f818cd7 100644 +--- a/src/devices/nm-device-tun.c ++++ b/src/devices/nm-device-tun.c +@@ -171,7 +171,7 @@ update_connection (NMDevice *device, NMConnection *connection) + } + + if (!nm_platform_link_tun_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (device), &props)) { +- _LOGW (LOGD_HW, "failed to get TUN interface info while updating connection."); ++ _LOGW (LOGD_PLATFORM, "failed to get TUN interface info while updating connection."); + return; + } + +diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c +index 5692331..c16df6d 100644 +--- a/src/devices/nm-device-veth.c ++++ b/src/devices/nm-device-veth.c +@@ -91,7 +91,7 @@ get_peer (NMDeviceVeth *self) + return priv->peer; + + if (!nm_platform_link_veth_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (device), &peer_ifindex)) { +- _LOGW (LOGD_HW, "could not read veth properties"); ++ _LOGW (LOGD_PLATFORM, "could not read veth properties"); + return NULL; + } + +diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c +index 674c2a7..2453543 100644 +--- a/src/devices/nm-device-vxlan.c ++++ b/src/devices/nm-device-vxlan.c +@@ -84,7 +84,7 @@ update_properties (NMDevice *device) + + props = nm_platform_link_get_lnk_vxlan (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL); + if (!props) { +- _LOGW (LOGD_HW, "could not get vxlan properties"); ++ _LOGW (LOGD_PLATFORM, "could not get vxlan properties"); + return; + } + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index aabbd53..96d6a7c 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -757,7 +757,7 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface) + nm_platform_link_set_up (NM_PLATFORM_GET, priv->ip_ifindex, NULL); + } else { + /* Device IP interface must always be a kernel network interface */ +- _LOGW (LOGD_HW, "failed to look up interface index"); ++ _LOGW (LOGD_PLATFORM, "failed to look up interface index"); + } + } + +@@ -900,7 +900,7 @@ get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *out_iid) + priv->dev_id, + out_iid); + if (!success) { +- _LOGW (LOGD_HW, "failed to generate interface identifier " ++ _LOGW (LOGD_PLATFORM, "failed to generate interface identifier " + "for link type %u hwaddr_len %u", pllink->type, (unsigned) pllink->addr.len); + } + return success; +@@ -2299,7 +2299,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) + + if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { + check_carrier (self); +- _LOGD (LOGD_HW, ++ _LOGD (LOGD_PLATFORM, + "carrier is %s%s", + priv->carrier ? "ON" : "OFF", + priv->ignore_carrier ? " (but ignored)" : ""); +@@ -9033,7 +9033,7 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + +- _LOGD (LOGD_HW, "bringing up device"); ++ _LOGD (LOGD_PLATFORM, "bringing up device"); + + if (NM_DEVICE_GET_CLASS (self)->bring_up) { + if (!NM_DEVICE_GET_CLASS (self)->bring_up (self, no_firmware)) +@@ -9059,9 +9059,9 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) + + if (!device_is_up) { + if (block) +- _LOGW (LOGD_HW, "device not up after timeout!"); ++ _LOGW (LOGD_PLATFORM, "device not up after timeout!"); + else +- _LOGD (LOGD_HW, "device not up immediately"); ++ _LOGD (LOGD_PLATFORM, "device not up immediately"); + return FALSE; + } + +@@ -9125,7 +9125,7 @@ nm_device_take_down (NMDevice *self, gboolean block) + + g_return_if_fail (NM_IS_DEVICE (self)); + +- _LOGD (LOGD_HW, "taking down device"); ++ _LOGD (LOGD_PLATFORM, "taking down device"); + + if (NM_DEVICE_GET_CLASS (self)->take_down) { + if (!NM_DEVICE_GET_CLASS (self)->take_down (self)) +@@ -9147,9 +9147,9 @@ nm_device_take_down (NMDevice *self, gboolean block) + + if (device_is_up) { + if (block) +- _LOGW (LOGD_HW, "device not down after timeout!"); ++ _LOGW (LOGD_PLATFORM, "device not down after timeout!"); + else +- _LOGD (LOGD_HW, "device not down immediately"); ++ _LOGD (LOGD_PLATFORM, "device not down immediately"); + } + } + +@@ -9162,7 +9162,7 @@ take_down (NMDevice *self) + return nm_platform_link_set_down (NM_PLATFORM_GET, ifindex); + + /* devices without ifindex are always up. */ +- _LOGD (LOGD_HW, "cannot take down device without ifindex"); ++ _LOGD (LOGD_PLATFORM, "cannot take down device without ifindex"); + return FALSE; + } + +@@ -11150,7 +11150,7 @@ _set_state_full (NMDevice *self, + if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) { + if (old_state == NM_DEVICE_STATE_UNMANAGED || priv->firmware_missing) { + if (!nm_device_bring_up (self, TRUE, &no_firmware) && no_firmware) +- _LOGW (LOGD_HW, "firmware may be missing."); ++ _LOGW (LOGD_PLATFORM, "firmware may be missing."); + nm_device_set_firmware_missing (self, no_firmware ? TRUE : FALSE); + } + +@@ -11533,7 +11533,7 @@ nm_device_update_hw_address (NMDevice *self) + g_free (priv->hw_addr); + priv->hw_addr = nm_utils_hwaddr_ntoa (hwaddr, hwaddrlen); + +- _LOGD (LOGD_HW | LOGD_DEVICE, "hw-addr: hardware address now %s", priv->hw_addr); ++ _LOGD (LOGD_PLATFORM | LOGD_DEVICE, "hw-addr: hardware address now %s", priv->hw_addr); + _notify (self, PROP_HW_ADDRESS); + + if ( !priv->hw_addr_initial +@@ -11550,11 +11550,11 @@ nm_device_update_hw_address (NMDevice *self) + } else { + /* Invalid or no hardware address */ + if (priv->hw_addr_len != 0) { +- _LOGD (LOGD_HW | LOGD_DEVICE, ++ _LOGD (LOGD_PLATFORM | LOGD_DEVICE, + "hw-addr: failed reading current MAC address (stay with %s)", + priv->hw_addr); + } else { +- _LOGD (LOGD_HW | LOGD_DEVICE, ++ _LOGD (LOGD_PLATFORM | LOGD_DEVICE, + "hw-addr: failed reading current MAC address"); + } + } +@@ -11614,7 +11614,7 @@ nm_device_update_permanent_hw_address (NMDevice *self) + * + * In some cases it might be necessary to know whether this is a "real" or + * a temporary address (fake). */ +- _LOGD (LOGD_HW | LOGD_ETHER, "hw-addr: %s (use current: %s)", ++ _LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use current: %s)", + success_read + ? "read HW addr length of permanent MAC address differs" + : "unable to read permanent MAC address", +diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c +index f97e668..f467c81 100644 +--- a/src/devices/wifi/nm-device-wifi.c ++++ b/src/devices/wifi/nm-device-wifi.c +@@ -203,7 +203,7 @@ constructed (GObject *object) + G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructed (object); + + if (priv->capabilities & NM_WIFI_DEVICE_CAP_AP) +- _LOGI (LOGD_HW | LOGD_WIFI, "driver supports Access Point (AP) mode"); ++ _LOGI (LOGD_PLATFORM | LOGD_WIFI, "driver supports Access Point (AP) mode"); + + /* Connect to the supplicant manager */ + priv->sup_mgr = g_object_ref (nm_supplicant_manager_get ()); +diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c +index 2d5f8fa..cf8cf03 100644 +--- a/src/devices/wifi/nm-wifi-factory.c ++++ b/src/devices/wifi/nm-wifi-factory.c +@@ -76,7 +76,7 @@ create_device (NMDeviceFactory *factory, + if (!nm_platform_wifi_get_capabilities (NM_PLATFORM_GET, + plink->ifindex, + &capabilities)) { +- nm_log_warn (LOGD_HW | LOGD_WIFI, "(%s) failed to initialize Wi-Fi driver for ifindex %d", iface, plink->ifindex); ++ nm_log_warn (LOGD_PLATFORM | LOGD_WIFI, "(%s) failed to initialize Wi-Fi driver for ifindex %d", iface, plink->ifindex); + return NULL; + } + +diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c +index 2e3d63b..df6f7cf 100644 +--- a/src/devices/wwan/nm-modem.c ++++ b/src/devices/wwan/nm-modem.c +@@ -1327,12 +1327,12 @@ constructor (GType type, + priv = NM_MODEM_GET_PRIVATE (object); + + if (!priv->data_port && !priv->control_port) { +- nm_log_err (LOGD_HW, "neither modem command nor data interface provided"); ++ nm_log_err (LOGD_PLATFORM, "neither modem command nor data interface provided"); + goto err; + } + + if (!priv->path) { +- nm_log_err (LOGD_HW, "D-Bus path not provided"); ++ nm_log_err (LOGD_PLATFORM, "D-Bus path not provided"); + goto err; + } + +diff --git a/src/nm-logging.h b/src/nm-logging.h +index 9e2b010..72eb3db 100644 +--- a/src/nm-logging.h ++++ b/src/nm-logging.h +@@ -78,7 +78,6 @@ typedef enum { /*< skip >*/ + /* aliases: */ + LOGD_DHCP = LOGD_DHCP4 | LOGD_DHCP6, + LOGD_IP = LOGD_IP4 | LOGD_IP6, +- LOGD_HW = LOGD_PLATFORM, + } NMLogDomain; + + /* Log levels */ +diff --git a/src/nm-manager.c b/src/nm-manager.c +index 9ad6517..932dafd 100644 +--- a/src/nm-manager.c ++++ b/src/nm-manager.c +@@ -2125,10 +2125,10 @@ platform_link_added (NMManager *self, + device = nm_device_factory_create_device (factory, plink->name, plink, NULL, &ignore, &error); + if (!device) { + if (!ignore) { +- _LOGW (LOGD_HW, "%s: factory failed to create device: %s", ++ _LOGW (LOGD_PLATFORM, "%s: factory failed to create device: %s", + plink->name, error->message); + } else { +- _LOGD (LOGD_HW, "%s: factory failed to create device: %s", ++ _LOGD (LOGD_PLATFORM, "%s: factory failed to create device: %s", + plink->name, error->message); + } + return; +@@ -2142,7 +2142,7 @@ platform_link_added (NMManager *self, + case NM_LINK_TYPE_OLPC_MESH: + case NM_LINK_TYPE_TEAM: + case NM_LINK_TYPE_WIFI: +- _LOGI (LOGD_HW, "(%s): '%s' plugin not available; creating generic device", ++ _LOGI (LOGD_PLATFORM, "(%s): '%s' plugin not available; creating generic device", + plink->name, nm_link_type_to_string (plink->type)); + nm_plugin_missing = TRUE; + /* fall through */ +diff --git a/src/nm-rfkill-manager.c b/src/nm-rfkill-manager.c +index 453a3b9..e4e738c 100644 +--- a/src/nm-rfkill-manager.c ++++ b/src/nm-rfkill-manager.c +@@ -347,7 +347,7 @@ handle_uevent (GUdevClient *client, + subsys = g_udev_device_get_subsystem (device); + g_return_if_fail (!g_strcmp0 (subsys, "rfkill")); + +- nm_log_dbg (LOGD_HW, "udev rfkill event: action '%s' device '%s'", ++ nm_log_dbg (LOGD_PLATFORM, "udev rfkill event: action '%s' device '%s'", + action, g_udev_device_get_name (device)); + + if (!strcmp (action, "add")) +diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c +index 79f217a..2e222eb 100644 +--- a/src/platform/wifi/wifi-utils-nl80211.c ++++ b/src/platform/wifi/wifi-utils-nl80211.c +@@ -1003,7 +1003,7 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg) + case WLAN_CIPHER_SUITE_SMS4: + break; + default: +- nm_log_dbg (LOGD_HW | LOGD_WIFI, "Don't know the meaning of NL80211_ATTR_CIPHER_SUITE %#8.8x.", ciphers[i]); ++ nm_log_dbg (LOGD_PLATFORM | LOGD_WIFI, "Don't know the meaning of NL80211_ATTR_CIPHER_SUITE %#8.8x.", ciphers[i]); + break; + } + } +@@ -1071,42 +1071,42 @@ wifi_nl80211_init (const char *iface, int ifindex) + + if (nl80211_send_and_recv (nl80211, msg, nl80211_wiphy_info_handler, + &device_info) < 0) { +- nm_log_dbg (LOGD_HW | LOGD_WIFI, ++ nm_log_dbg (LOGD_PLATFORM | LOGD_WIFI, + "(%s): NL80211_CMD_GET_WIPHY request failed", + nl80211->parent.iface); + goto error; + } + + if (!device_info.success) { +- nm_log_dbg (LOGD_HW | LOGD_WIFI, ++ nm_log_dbg (LOGD_PLATFORM | LOGD_WIFI, + "(%s): NL80211_CMD_GET_WIPHY request indicated failure", + nl80211->parent.iface); + goto error; + } + + if (!device_info.supported) { +- nm_log_dbg (LOGD_HW | LOGD_WIFI, ++ nm_log_dbg (LOGD_PLATFORM | LOGD_WIFI, + "(%s): driver does not fully support nl80211, falling back to WEXT", + nl80211->parent.iface); + goto error; + } + + if (!device_info.can_scan_ssid) { +- nm_log_err (LOGD_HW | LOGD_WIFI, ++ nm_log_err (LOGD_PLATFORM | LOGD_WIFI, + "(%s): driver does not support SSID scans", + nl80211->parent.iface); + goto error; + } + + if (device_info.num_freqs == 0 || device_info.freqs == NULL) { +- nm_log_err (LOGD_HW | LOGD_WIFI, ++ nm_log_err (LOGD_PLATFORM | LOGD_WIFI, + "(%s): driver reports no supported frequencies", + nl80211->parent.iface); + goto error; + } + + if (device_info.caps == 0) { +- nm_log_err (LOGD_HW | LOGD_WIFI, ++ nm_log_err (LOGD_PLATFORM | LOGD_WIFI, + "(%s): driver doesn't report support of any encryption", + nl80211->parent.iface); + goto error; +@@ -1120,7 +1120,7 @@ wifi_nl80211_init (const char *iface, int ifindex) + if (device_info.can_wowlan) + nl80211->parent.get_wowlan = wifi_nl80211_get_wowlan; + +- nm_log_info (LOGD_HW | LOGD_WIFI, ++ nm_log_info (LOGD_PLATFORM | LOGD_WIFI, + "(%s): using nl80211 for WiFi device control", + nl80211->parent.iface); + +diff --git a/src/platform/wifi/wifi-utils-wext.c b/src/platform/wifi/wifi-utils-wext.c +index af285b4..66c1376 100644 +--- a/src/platform/wifi/wifi-utils-wext.c ++++ b/src/platform/wifi/wifi-utils-wext.c +@@ -105,7 +105,7 @@ wifi_wext_get_mode (WifiData *data) + + if (ioctl (wext->fd, SIOCGIWMODE, &wrq) < 0) { + if (errno != ENODEV) { +- nm_log_warn (LOGD_HW | LOGD_WIFI, ++ nm_log_warn (LOGD_PLATFORM | LOGD_WIFI, + "(%s): error %d getting card mode", + wext->parent.iface, errno); + } +@@ -154,7 +154,7 @@ wifi_wext_set_mode (WifiData *data, const NM80211Mode mode) + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); + if (ioctl (wext->fd, SIOCSIWMODE, &wrq) < 0) { + if (errno != ENODEV) { +- nm_log_err (LOGD_HW | LOGD_WIFI, "(%s): error setting mode %d", ++ nm_log_err (LOGD_PLATFORM | LOGD_WIFI, "(%s): error setting mode %d", + wext->parent.iface, mode); + } + return FALSE; +@@ -178,7 +178,7 @@ wifi_wext_set_powersave (WifiData *data, guint32 powersave) + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); + if (ioctl (wext->fd, SIOCSIWPOWER, &wrq) < 0) { + if (errno != ENODEV) { +- nm_log_err (LOGD_HW | LOGD_WIFI, "(%s): error setting powersave %" G_GUINT32_FORMAT, ++ nm_log_err (LOGD_PLATFORM | LOGD_WIFI, "(%s): error setting powersave %" G_GUINT32_FORMAT, + wext->parent.iface, powersave); + } + return FALSE; +@@ -196,7 +196,7 @@ wifi_wext_get_freq (WifiData *data) + memset (&wrq, 0, sizeof (struct iwreq)); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); + if (ioctl (wext->fd, SIOCGIWFREQ, &wrq) < 0) { +- nm_log_warn (LOGD_HW | LOGD_WIFI, ++ nm_log_warn (LOGD_PLATFORM | LOGD_WIFI, + "(%s): error getting frequency: %s", + wext->parent.iface, strerror (errno)); + return 0; +@@ -230,7 +230,7 @@ wifi_wext_get_bssid (WifiData *data, guint8 *out_bssid) + memset (&wrq, 0, sizeof (wrq)); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); + if (ioctl (wext->fd, SIOCGIWAP, &wrq) < 0) { +- nm_log_warn (LOGD_HW | LOGD_WIFI, ++ nm_log_warn (LOGD_PLATFORM | LOGD_WIFI, + "(%s): error getting associated BSSID: %s", + wext->parent.iface, strerror (errno)); + return FALSE; +@@ -360,7 +360,7 @@ wifi_wext_get_qual (WifiData *data) + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); + + if (ioctl (wext->fd, SIOCGIWSTATS, &wrq) < 0) { +- nm_log_warn (LOGD_HW | LOGD_WIFI, ++ nm_log_warn (LOGD_PLATFORM | LOGD_WIFI, + "(%s): error getting signal strength: %s", + wext->parent.iface, strerror (errno)); + return -1; +@@ -403,7 +403,7 @@ wifi_wext_set_mesh_channel (WifiData *data, guint32 channel) + } + + if (ioctl (wext->fd, SIOCSIWFREQ, &wrq) < 0) { +- nm_log_err (LOGD_HW | LOGD_WIFI | LOGD_OLPC, ++ nm_log_err (LOGD_PLATFORM | LOGD_WIFI | LOGD_OLPC, + "(%s): error setting channel to %d: %s", + wext->parent.iface, channel, strerror (errno)); + return FALSE; +@@ -431,7 +431,7 @@ wifi_wext_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len) + return TRUE; + + if (errno != ENODEV) { +- nm_log_err (LOGD_HW | LOGD_WIFI | LOGD_OLPC, ++ nm_log_err (LOGD_PLATFORM | LOGD_WIFI | LOGD_OLPC, + "(%s): error setting SSID to '%s': %s", + wext->parent.iface, + ssid ? nm_utils_escape_ssid (ssid, len) : "(null)", +@@ -482,7 +482,7 @@ wext_get_range (WifiDataWext *wext, + success = TRUE; + break; + } else if (errno != EAGAIN) { +- nm_log_err (LOGD_HW | LOGD_WIFI, ++ nm_log_err (LOGD_PLATFORM | LOGD_WIFI, + "(%s): couldn't get driver range information (%d).", + wext->parent.iface, errno); + break; +@@ -492,7 +492,7 @@ wext_get_range (WifiDataWext *wext, + } + + if (i <= 0) { +- nm_log_warn (LOGD_HW | LOGD_WIFI, ++ nm_log_warn (LOGD_PLATFORM | LOGD_WIFI, + "(%s): driver took too long to respond to IWRANGE query.", + wext->parent.iface); + } +@@ -583,13 +583,13 @@ wifi_wext_init (const char *iface, int ifindex, gboolean check_scan) + + memset (&range, 0, sizeof (struct iw_range)); + if (wext_get_range (wext, &range, &response_len) == FALSE) { +- nm_log_info (LOGD_HW | LOGD_WIFI, "(%s): driver WEXT range request failed", ++ nm_log_info (LOGD_PLATFORM | LOGD_WIFI, "(%s): driver WEXT range request failed", + wext->parent.iface); + goto error; + } + + if ((response_len < 300) || (range.we_version_compiled < 21)) { +- nm_log_info (LOGD_HW | LOGD_WIFI, ++ nm_log_info (LOGD_PLATFORM | LOGD_WIFI, + "(%s): driver WEXT version too old (got %d, expected >= 21)", + wext->parent.iface, + range.we_version_compiled); +@@ -613,7 +613,7 @@ wifi_wext_init (const char *iface, int ifindex, gboolean check_scan) + + /* Check for scanning capability; cards that can't scan are not supported */ + if (check_scan && (wext_can_scan (wext) == FALSE)) { +- nm_log_info (LOGD_HW | LOGD_WIFI, ++ nm_log_info (LOGD_PLATFORM | LOGD_WIFI, + "(%s): drivers that cannot scan are unsupported", + wext->parent.iface); + goto error; +@@ -625,12 +625,12 @@ wifi_wext_init (const char *iface, int ifindex, gboolean check_scan) + */ + scan_capa_range = (struct iw_range_with_scan_capa *) ⦥ + if (scan_capa_range->scan_capa & NM_IW_SCAN_CAPA_ESSID) { +- nm_log_info (LOGD_HW | LOGD_WIFI, ++ nm_log_info (LOGD_PLATFORM | LOGD_WIFI, + "(%s): driver supports SSID scans (scan_capa 0x%02X).", + wext->parent.iface, + scan_capa_range->scan_capa); + } else { +- nm_log_info (LOGD_HW | LOGD_WIFI, ++ nm_log_info (LOGD_PLATFORM | LOGD_WIFI, + "(%s): driver does not support SSID scans (scan_capa 0x%02X).", + wext->parent.iface, + scan_capa_range->scan_capa); +@@ -644,7 +644,7 @@ wifi_wext_init (const char *iface, int ifindex, gboolean check_scan) + if (has_5ghz) + wext->parent.caps |= NM_WIFI_DEVICE_CAP_FREQ_5GHZ; + +- nm_log_info (LOGD_HW | LOGD_WIFI, ++ nm_log_info (LOGD_PLATFORM | LOGD_WIFI, + "(%s): using WEXT for WiFi device control", + wext->parent.iface); + +-- +2.9.3 + + +From 1f57d7676330b61b8af72d87195d3ddd4da76228 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Thu, 22 Sep 2016 11:31:19 +0200 +Subject: [PATCH 02/15] device: fix NULL pointer dereference in dhcp6_start() + +Don't crash when nm_device_dhcp6_renew() calls dhcp6_start() with NULL +@reason. + +Fixes: d1295b12e9f802867edef57ee02c87495df1683e +(cherry picked from commit dbf0b343ec54ee8d34a003609a19fb74082d4afc) +(cherry picked from commit 6c4a6f2b755c6b9de1617830e2708cd1687b4dfa) +--- + src/devices/nm-device.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 96d6a7c..b182536 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -5904,7 +5904,7 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason) + } + + if (!dhcp6_start_with_link_ready (self, connection)) { +- *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED; ++ NM_SET_OUT (reason, NM_DEVICE_STATE_REASON_DHCP_START_FAILED); + return FALSE; + } + +-- +2.9.3 + + +From 61b6a9984a0f010a22270f7b14bb2dbc34dc7a50 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Tue, 13 Sep 2016 11:16:11 +0200 +Subject: [PATCH 03/15] device: cleanup _hw_addr_set() + +No change in behavior, just reorganize. + +Fixes: 32f7c1d4b9aba597a99128631f07c2985149f303 +(cherry picked from commit e7a1008b4b405a83c78f7e44fe86cc3db8f2015e) +(cherry picked from commit 66c665808f7794350036c57f7d44cadd087d8d11) +--- + src/devices/nm-device.c | 39 +++++++++++++++------------------------ + 1 file changed, 15 insertions(+), 24 deletions(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index b182536..7a47f74 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -11734,7 +11734,6 @@ _hw_addr_set (NMDevice *self, + { + NMDevicePrivate *priv; + gboolean success = FALSE; +- gboolean needs_refresh = FALSE; + NMPlatformError plerr; + guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX]; + guint hw_addr_len; +@@ -11776,24 +11775,11 @@ _hw_addr_set (NMDevice *self, + _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)", + operation, addr, detail); + } else { ++ gint64 poll_end, now; ++ + _LOGD (LOGD_DEVICE, + "set-hw-addr: new MAC address %s not successfully %s (%s) (refresh link)", + addr, operation, detail); +- needs_refresh = TRUE; +- } +- } else { +- _NMLOG (plerr == NM_PLATFORM_ERROR_NOT_FOUND ? LOGL_DEBUG : LOGL_WARN, +- LOGD_DEVICE, "set-hw-addr: failed to %s MAC address to %s (%s) (%s)", +- operation, addr, detail, +- nm_platform_error_to_string (plerr)); +- } +- +- if (needs_refresh) { +- success = TRUE; +- if (_hw_addr_matches (self, addr)) { +- /* the MAC address already changed during nm_device_bring_up() above. */ +- } else { +- gint64 poll_end, now; + + /* The platform call indicated success, however the address is not + * as expected. That is either due to a driver issue (brcmfmac, bgo#770456, +@@ -11829,16 +11815,21 @@ handle_fail: + success = FALSE; + break; + } +- } + +- if (success) { +- _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)", +- operation, addr, detail); +- } else { +- _LOGW (LOGD_DEVICE, +- "set-hw-addr: new MAC address %s not successfully %s (%s)", +- addr, operation, detail); ++ if (success) { ++ _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)", ++ operation, addr, detail); ++ } else { ++ _LOGW (LOGD_DEVICE, ++ "set-hw-addr: new MAC address %s not successfully %s (%s)", ++ addr, operation, detail); ++ } + } ++ } else { ++ _NMLOG (plerr == NM_PLATFORM_ERROR_NOT_FOUND ? LOGL_DEBUG : LOGL_WARN, ++ LOGD_DEVICE, "set-hw-addr: failed to %s MAC address to %s (%s) (%s)", ++ operation, addr, detail, ++ nm_platform_error_to_string (plerr)); + } + + if (was_up) { +-- +2.9.3 + + +From 56b845b359d83b3c685539d11389256088c1ce1e Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Sat, 15 Oct 2016 15:22:01 +0200 +Subject: [PATCH 04/15] tools: fix starting tests with D-Bus session with + NMTST_NO_VALGRIND=1 + +When running + + NMTST_NO_VALGRIND=1 make check -j + +we would not start separate D-Bus sessions, thus running tests with +valgrind enabled failed. + +(cherry picked from commit c94dac0b5d9d77ef7d60d18eb835a0dd7bba4f42) +(cherry picked from commit 7927d451fc7b6cfbd9cd3bf1078fa3cb4140789a) +--- + tools/run-test-valgrind.sh | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/run-test-valgrind.sh b/tools/run-test-valgrind.sh +index d3dd915..634ca2c 100755 +--- a/tools/run-test-valgrind.sh ++++ b/tools/run-test-valgrind.sh +@@ -91,6 +91,7 @@ if [ "$NMTST_LAUNCH_DBUS" == "yes" ]; then + fi + + if [ "$NMTST_NO_VALGRIND" != "" ]; then ++ "${NMTST_DBUS_RUN_SESSION[@]}" \ + "$TEST" "$@" + exit $? + fi +-- +2.9.3 + + +From 6d654721a1997c464deb99cd61aabb3c7b930517 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 28 Sep 2016 15:34:52 +0200 +Subject: [PATCH 05/15] shared: add nm_clear_g_free() + +(cherry picked from commit b4e66c4818cf6ff14e8b5181ec9d71fa5c9f5452) +(cherry picked from commit beeb676735d6242dd4c12de27bbc1b8fd3afaeee) +--- + libnm-core/tests/test-general.c | 2 +- + shared/nm-utils/nm-macros-internal.h | 21 +++++++++++++++++++++ + 2 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c +index 6aee252..6b54dc3 100644 +--- a/libnm-core/tests/test-general.c ++++ b/libnm-core/tests/test-general.c +@@ -2527,7 +2527,7 @@ test_setting_compare_wireless_cloned_mac_address (void) + g_assert_cmpstr ("stable-bia", ==, nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) new)); + g_object_get (new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL); + g_assert_cmpstr ("stable-bia", ==, str1); +- g_clear_pointer (&str1, g_free); ++ nm_clear_g_free (&str1); + + success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT); + g_assert (!success); +diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h +index 91970c3..9f96a4c 100644 +--- a/shared/nm-utils/nm-macros-internal.h ++++ b/shared/nm-utils/nm-macros-internal.h +@@ -410,6 +410,27 @@ nm_g_object_unref (gpointer obj) + g_object_unref (obj); + } + ++/* basically, replaces ++ * g_clear_pointer (&location, g_free) ++ * with ++ * nm_clear_g_free (&location) ++ * ++ * Another advantage is that by using a macro and typeof(), it is more ++ * typesafe and gives you for example a compiler warning when pp is a const ++ * pointer or points to a const-pointer. ++ */ ++#define nm_clear_g_free(pp) \ ++ ({ \ ++ typeof (*(pp)) *_pp = (pp); \ ++ typeof (**_pp) *_p = *_pp; \ ++ \ ++ if (_p) { \ ++ *_pp = NULL; \ ++ g_free (_p); \ ++ } \ ++ !!_p; \ ++ }) ++ + static inline gboolean + nm_clear_g_source (guint *id) + { +-- +2.9.3 + + +From e935a4cf7340cbcde24370e752e35aad736da886 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 26 Oct 2016 14:44:02 +0200 +Subject: [PATCH 06/15] shared: add nm_assert_se() macro + +We usually don't build NM with g_assert() disabled (G_DISABLE_ASSERT). +But even if we would, there is no assertion macro that always evaluates +the condition for possible side effects. + +I think that is a useful thing to have. + +(cherry picked from commit ba950cedee5c4a92d9fb7e00f58b9f97a151b9e8) +(cherry picked from commit d242fdc3193948cce078a55adec540f3489ee94a) +--- + shared/nm-utils/nm-macros-internal.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h +index 9f96a4c..2e05b2a 100644 +--- a/shared/nm-utils/nm-macros-internal.h ++++ b/shared/nm-utils/nm-macros-internal.h +@@ -344,9 +344,11 @@ nm_strdup_not_empty (const char *str) + + #if NM_MORE_ASSERTS + #define nm_assert(cond) G_STMT_START { g_assert (cond); } G_STMT_END ++#define nm_assert_se(cond) G_STMT_START { if (G_LIKELY (cond)) { ; } else { g_assert (FALSE && (cond)); } } G_STMT_END + #define nm_assert_not_reached() G_STMT_START { g_assert_not_reached (); } G_STMT_END + #else + #define nm_assert(cond) G_STMT_START { if (FALSE) { if (cond) { } } } G_STMT_END ++#define nm_assert_se(cond) G_STMT_START { if (G_LIKELY (cond)) { ; } } G_STMT_END + #define nm_assert_not_reached() G_STMT_START { ; } G_STMT_END + #endif + +-- +2.9.3 + + +From 59f0ed05eaf656c5f3846717003e22caed41e376 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Thu, 13 Oct 2016 17:51:07 +0200 +Subject: [PATCH 07/15] libnm-core/utils: update hwaddr utilities + +_nm_utils_hwaddr_length() did a validation of the string +and returned the length of the address. In all cases where +we were interested in that, we also either want to validate +the address, get the address in binary form, or canonicalize +the address. + +We can avoid these duplicate checks, by using _nm_utils_hwaddr_aton() +which both does the parsing and returning the length. + +(cherry picked from commit e5fe5a4c033875679adbea3cae50108daef43eb3) +(cherry picked from commit 977fbf70895f3a9dce3e178b5e4c03ecf4ee8fa3) +--- + libnm-core/nm-core-internal.h | 5 +- + libnm-core/nm-utils.c | 307 ++++++++++++++++++++++++------------------ + src/devices/nm-device.c | 46 ++++--- + src/nm-core-utils.c | 7 +- + 4 files changed, 205 insertions(+), 160 deletions(-) + +diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h +index e491bce..5d3c190 100644 +--- a/libnm-core/nm-core-internal.h ++++ b/libnm-core/nm-core-internal.h +@@ -123,7 +123,10 @@ guint32 _nm_setting_get_setting_priority (NMSetting *setting); + + gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value); + +-guint _nm_utils_hwaddr_length (const char *asc); ++#define NM_UTILS_HWADDR_LEN_MAX_STR (NM_UTILS_HWADDR_LEN_MAX * 3) ++ ++guint8 *_nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize buffer_length, gsize *out_length); ++const char *nm_utils_hwaddr_ntoa_buf (gconstpointer addr, gsize addr_len, gboolean upper_case, char *buf, gsize buf_len); + + char *_nm_utils_bin2str (gconstpointer addr, gsize length, gboolean upper_case); + +diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c +index df75d56..fe8a371 100644 +--- a/libnm-core/nm-utils.c ++++ b/libnm-core/nm-utils.c +@@ -2965,17 +2965,64 @@ nm_utils_wifi_strength_bars (guint8 strength) + gsize + nm_utils_hwaddr_len (int type) + { +- g_return_val_if_fail (type == ARPHRD_ETHER || type == ARPHRD_INFINIBAND, 0); +- + if (type == ARPHRD_ETHER) + return ETH_ALEN; + else if (type == ARPHRD_INFINIBAND) + return INFINIBAND_ALEN; + +- g_assert_not_reached (); ++ g_return_val_if_reached (0); + } + +-#define HEXVAL(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10) ++static guint8 * ++hwaddr_aton (const char *asc, guint8 *buffer, gsize buffer_length, gsize *out_len) ++{ ++ const char *in = asc; ++ guint8 *out = buffer; ++ guint8 delimiter = '\0'; ++ ++ nm_assert (asc); ++ nm_assert (buffer); ++ nm_assert (buffer_length); ++ nm_assert (out_len); ++ ++ while (TRUE) { ++ const guint8 d1 = in[0]; ++ guint8 d2; ++ ++ if (!g_ascii_isxdigit (d1)) ++ return NULL; ++ ++#define HEXVAL(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - ('A' - 10)) ++ ++ /* If there's no leading zero (ie "aa:b:cc") then fake it */ ++ d2 = in[1]; ++ if (d2 && g_ascii_isxdigit (d2)) { ++ *out++ = (HEXVAL (d1) << 4) + HEXVAL (d2); ++ d2 = in[2]; ++ in += 3; ++ } else { ++ /* Fake leading zero */ ++ *out++ = HEXVAL (d1); ++ in += 2; ++ } ++ ++ if (!d2) ++ break; ++ if (--buffer_length == 0) ++ return NULL; ++ ++ if (d2 != delimiter) { ++ if ( delimiter == '\0' ++ && (d2 == ':' || d2 == '-')) ++ delimiter = d2; ++ else ++ return NULL; ++ } ++ } ++ ++ *out_len = out - buffer; ++ return buffer; ++} + + /** + * nm_utils_hwaddr_atoba: +@@ -2992,18 +3039,52 @@ GByteArray * + nm_utils_hwaddr_atoba (const char *asc, gsize length) + { + GByteArray *ba; ++ gsize l; + +- g_return_val_if_fail (asc != NULL, NULL); ++ g_return_val_if_fail (asc, NULL); + g_return_val_if_fail (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX, NULL); + + ba = g_byte_array_sized_new (length); + g_byte_array_set_size (ba, length); +- if (!nm_utils_hwaddr_aton (asc, ba->data, length)) { +- g_byte_array_unref (ba); +- return NULL; +- } ++ if (!hwaddr_aton (asc, ba->data, length, &l)) ++ goto fail; ++ if (length != l) ++ goto fail; + + return ba; ++fail: ++ g_byte_array_unref (ba); ++ return NULL; ++} ++ ++/** ++ * _nm_utils_hwaddr_aton: ++ * @asc: the ASCII representation of a hardware address ++ * @buffer: buffer to store the result into. Must have ++ * at least a size of @buffer_length. ++ * @buffer_length: the length of the input buffer @buffer. ++ * The result must fit into that buffer, otherwise ++ * the function fails and returns %NULL. ++ * @out_length: the output length in case of success. ++ * ++ * Parses @asc and converts it to binary form in @buffer. ++ * Bytes in @asc can be sepatared by colons (:), or hyphens (-), but not mixed. ++ * ++ * It is like nm_utils_hwaddr_aton(), but contrary to that it ++ * can parse addresses of any length. That is, you don't need ++ * to know the length before-hand. ++ * ++ * Return value: @buffer, or %NULL if @asc couldn't be parsed. ++ */ ++guint8 * ++_nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize buffer_length, gsize *out_length) ++{ ++ g_return_val_if_fail (asc, NULL); ++ g_return_val_if_fail (buffer, NULL); ++ g_return_val_if_fail (buffer_length > 0, NULL); ++ g_return_val_if_fail (out_length, NULL); ++ ++ return hwaddr_aton (asc, buffer, buffer_length, out_length); + } + + /** +@@ -3022,72 +3103,55 @@ nm_utils_hwaddr_atoba (const char *asc, gsize length) + guint8 * + nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize length) + { +- const char *in = asc; +- guint8 *out = (guint8 *)buffer; +- char delimiter = '\0'; ++ gsize l; + +- g_return_val_if_fail (asc != NULL, NULL); +- g_return_val_if_fail (buffer != NULL, NULL); ++ g_return_val_if_fail (asc, NULL); ++ g_return_val_if_fail (buffer, NULL); + g_return_val_if_fail (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX, NULL); + +- while (length && *in) { +- guint8 d1 = in[0], d2 = in[1]; +- +- if (!g_ascii_isxdigit (d1)) +- return NULL; +- +- /* If there's no leading zero (ie "aa:b:cc") then fake it */ +- if (d2 && g_ascii_isxdigit (d2)) { +- *out++ = (HEXVAL (d1) << 4) + HEXVAL (d2); +- in += 2; +- } else { +- /* Fake leading zero */ +- *out++ = (HEXVAL ('0') << 4) + HEXVAL (d1); +- in += 1; +- } +- +- length--; +- if (*in) { +- if (delimiter == '\0') { +- if (*in == ':' || *in == '-') +- delimiter = *in; +- else +- return NULL; +- } else { +- if (*in != delimiter) +- return NULL; +- } +- in++; +- } +- } +- +- if (length == 0 && !*in) +- return buffer; +- else ++ if (!hwaddr_aton (asc, buffer, length, &l)) ++ return NULL; ++ if (length != l) + return NULL; ++ return buffer; + } + +-static char * +-_bin2str (gconstpointer addr, gsize length, gboolean upper_case) ++static void ++_bin2str_buf (gconstpointer addr, gsize length, gboolean upper_case, char *out) + { + const guint8 *in = addr; +- char *out, *result; + const char *LOOKUP = upper_case ? "0123456789ABCDEF" : "0123456789abcdef"; + +- g_return_val_if_fail (addr != NULL, g_strdup ("")); +- g_return_val_if_fail (length > 0, g_strdup ("")); ++ nm_assert (addr); ++ nm_assert (out); ++ nm_assert (length > 0); + +- result = out = g_malloc (length * 3); +- while (length--) { +- guint8 v = *in++; ++ /* @out must contain at least @length*3 bytes */ ++ ++ for (;;) { ++ const guint8 v = *in++; + + *out++ = LOOKUP[v >> 4]; + *out++ = LOOKUP[v & 0x0F]; +- if (length) +- *out++ = ':'; ++ length--; ++ if (!length) ++ break; ++ *out++ = ':'; + } + + *out = 0; ++} ++ ++static char * ++_bin2str (gconstpointer addr, gsize length, gboolean upper_case) ++{ ++ char *result; ++ ++ nm_assert (addr); ++ nm_assert (length > 0); ++ ++ result = g_malloc (length * 3); ++ _bin2str_buf (addr, length, upper_case, result); + return result; + } + +@@ -3103,9 +3167,25 @@ _bin2str (gconstpointer addr, gsize length, gboolean upper_case) + char * + nm_utils_hwaddr_ntoa (gconstpointer addr, gsize length) + { ++ g_return_val_if_fail (addr, g_strdup ("")); ++ g_return_val_if_fail (length > 0, g_strdup ("")); ++ + return _bin2str (addr, length, TRUE); + } + ++const char * ++nm_utils_hwaddr_ntoa_buf (gconstpointer addr, gsize addr_len, gboolean upper_case, char *buf, gsize buf_len) ++{ ++ g_return_val_if_fail (addr, NULL); ++ g_return_val_if_fail (addr_len > 0, NULL); ++ g_return_val_if_fail (buf, NULL); ++ if (buf_len < addr_len * 3) ++ g_return_val_if_reached (NULL); ++ ++ _bin2str_buf (addr, addr_len, TRUE, buf); ++ return buf; ++} ++ + /** + * _nm_utils_bin2str: + * @addr: (type guint8) (array length=length): a binary hardware address +@@ -3119,49 +3199,10 @@ nm_utils_hwaddr_ntoa (gconstpointer addr, gsize length) + char * + _nm_utils_bin2str (gconstpointer addr, gsize length, gboolean upper_case) + { +- return _bin2str (addr, length, upper_case); +-} +- +-static int +-hwaddr_binary_len (const char *asc) +-{ +- int octets = 1; +- +- if (!*asc) +- return 0; +- +- for (; *asc; asc++) { +- if (*asc == ':' || *asc == '-') +- octets++; +- } +- return octets; +-} +- +-/** +- * _nm_utils_hwaddr_length: +- * @asc: the ASCII representation of the hardware address +- * +- * Validates that @asc is a valid representation of a hardware +- * address up to (including) %NM_UTILS_HWADDR_LEN_MAX bytes. +- * +- * Returns: binary length of the hardware address @asc or +- * 0 on error. +- */ +-guint +-_nm_utils_hwaddr_length (const char *asc) +-{ +- int l; +- +- if (!asc) +- return 0; +- +- l = hwaddr_binary_len (asc); +- if (l <= 0 || l > NM_UTILS_HWADDR_LEN_MAX) +- return 0; ++ g_return_val_if_fail (addr, g_strdup ("")); ++ g_return_val_if_fail (length > 0, g_strdup ("")); + +- if (!nm_utils_hwaddr_valid (asc, l)) +- return 0; +- return l; ++ return _bin2str (addr, length, upper_case); + } + + /** +@@ -3180,17 +3221,18 @@ gboolean + nm_utils_hwaddr_valid (const char *asc, gssize length) + { + guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; ++ gsize l; + + g_return_val_if_fail (asc != NULL, FALSE); +- g_return_val_if_fail (length == -1 || (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX), FALSE); + +- if (length == -1) { +- length = hwaddr_binary_len (asc); +- if (length == 0 || length > NM_UTILS_HWADDR_LEN_MAX) ++ if (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX) { ++ if (!hwaddr_aton (asc, buf, length, &l)) + return FALSE; +- } +- +- return nm_utils_hwaddr_aton (asc, buf, length) != NULL; ++ return length == l; ++ } else if (length == -1) { ++ return !!hwaddr_aton (asc, buf, sizeof (buf), &l); ++ } else ++ g_return_val_if_reached (FALSE); + } + + /** +@@ -3210,20 +3252,23 @@ char * + nm_utils_hwaddr_canonical (const char *asc, gssize length) + { + guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; ++ gsize l; + +- g_return_val_if_fail (asc != NULL, NULL); ++ g_return_val_if_fail (asc, NULL); + g_return_val_if_fail (length == -1 || (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX), NULL); + +- if (length == -1) { +- length = hwaddr_binary_len (asc); +- if (length == 0 || length > NM_UTILS_HWADDR_LEN_MAX) ++ if (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX) { ++ if (!hwaddr_aton (asc, buf, length, &l)) + return NULL; +- } +- +- if (nm_utils_hwaddr_aton (asc, buf, length) == NULL) +- return NULL; ++ if (l != length) ++ return NULL; ++ } else if (length == -1) { ++ if (!hwaddr_aton (asc, buf, NM_UTILS_HWADDR_LEN_MAX, &l)) ++ return NULL; ++ } else ++ g_return_val_if_reached (NULL); + +- return nm_utils_hwaddr_ntoa (buf, length); ++ return nm_utils_hwaddr_ntoa (buf, l); + } + + /* This is used to possibly canonicalize values passed to MAC address property +@@ -3287,17 +3332,17 @@ nm_utils_hwaddr_matches (gconstpointer hwaddr1, + gssize hwaddr2_len) + { + guint8 buf1[NM_UTILS_HWADDR_LEN_MAX], buf2[NM_UTILS_HWADDR_LEN_MAX]; ++ gsize l; + + if (hwaddr1_len == -1) { + g_return_val_if_fail (hwaddr1 != NULL, FALSE); + +- hwaddr1_len = hwaddr_binary_len (hwaddr1); +- if (hwaddr1_len == 0 || hwaddr1_len > NM_UTILS_HWADDR_LEN_MAX) +- return FALSE; +- if (!nm_utils_hwaddr_aton (hwaddr1, buf1, hwaddr1_len)) ++ if (!hwaddr_aton (hwaddr1, buf1, sizeof (buf1), &l)) { ++ g_return_val_if_fail ((hwaddr2_len == -1 && hwaddr2) || (hwaddr2_len > 0 && hwaddr2_len <= NM_UTILS_HWADDR_LEN_MAX), FALSE); + return FALSE; +- ++ } + hwaddr1 = buf1; ++ hwaddr1_len = l; + } else { + g_return_val_if_fail (hwaddr1_len > 0 && hwaddr1_len <= NM_UTILS_HWADDR_LEN_MAX, FALSE); + +@@ -3310,23 +3355,24 @@ nm_utils_hwaddr_matches (gconstpointer hwaddr1, + if (hwaddr2_len == -1) { + g_return_val_if_fail (hwaddr2 != NULL, FALSE); + +- if (!nm_utils_hwaddr_aton (hwaddr2, buf2, hwaddr1_len)) ++ if (!hwaddr_aton (hwaddr2, buf2, sizeof (buf2), &l)) ++ return FALSE; ++ if (l != hwaddr1_len) + return FALSE; +- + hwaddr2 = buf2; + hwaddr2_len = hwaddr1_len; + } else { + g_return_val_if_fail (hwaddr2_len > 0 && hwaddr2_len <= NM_UTILS_HWADDR_LEN_MAX, FALSE); + ++ if (hwaddr2_len != hwaddr1_len) ++ return FALSE; ++ + if (!hwaddr2) { + memset (buf2, 0, hwaddr2_len); + hwaddr2 = buf2; + } + } + +- if (hwaddr1_len != hwaddr2_len) +- return FALSE; +- + if (hwaddr1_len == INFINIBAND_ALEN) { + hwaddr1 = (guint8 *)hwaddr1 + INFINIBAND_ALEN - 8; + hwaddr2 = (guint8 *)hwaddr2 + INFINIBAND_ALEN - 8; +@@ -3342,16 +3388,11 @@ static GVariant * + _nm_utils_hwaddr_to_dbus_impl (const char *str) + { + guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; +- int len; ++ gsize len; + + if (!str) + return NULL; +- +- len = _nm_utils_hwaddr_length (str); +- if (len == 0) +- return NULL; +- +- if (!nm_utils_hwaddr_aton (str, buf, len)) ++ if (!hwaddr_aton (str, buf, sizeof (buf), &len)) + return NULL; + + return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, buf, len, 1); +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 7a47f74..4be572c 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -11718,25 +11718,25 @@ nm_device_hw_addr_is_explict (NMDevice *self) + } + + static gboolean +-_hw_addr_matches (NMDevice *self, const char *addr) ++_hw_addr_matches (NMDevice *self, const guint8 *addr, gsize addr_len) + { + const char *cur_addr; + + cur_addr = nm_device_get_hw_address (self); +- return cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1); ++ return cur_addr && nm_utils_hwaddr_matches (addr, addr_len, cur_addr, -1); + } + + static gboolean + _hw_addr_set (NMDevice *self, +- const char *addr, +- const char *operation, +- const char *detail) ++ const char *const addr, ++ const char *const operation, ++ const char *const detail) + { + NMDevicePrivate *priv; + gboolean success = FALSE; + NMPlatformError plerr; + guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX]; +- guint hw_addr_len; ++ gsize addr_len; + gboolean was_up; + + nm_assert (NM_IS_DEVICE (self)); +@@ -11745,18 +11745,20 @@ _hw_addr_set (NMDevice *self, + + priv = NM_DEVICE_GET_PRIVATE (self); + ++ if (!_nm_utils_hwaddr_aton (addr, addr_bytes, sizeof (addr_bytes), &addr_len)) ++ g_return_val_if_reached (FALSE); ++ + /* Do nothing if current MAC is same */ +- if (_hw_addr_matches (self, addr)) { ++ if (_hw_addr_matches (self, addr_bytes, addr_len)) { + _LOGT (LOGD_DEVICE, "set-hw-addr: no MAC address change needed (%s)", addr); + return TRUE; + } + +- hw_addr_len = priv->hw_addr_len; +- if (!hw_addr_len) +- hw_addr_len = _nm_utils_hwaddr_length (addr); +- if ( !hw_addr_len +- || !nm_utils_hwaddr_aton (addr, addr_bytes, hw_addr_len)) +- g_return_val_if_reached (FALSE); ++ if (priv->hw_addr_len != addr_len) { ++ if (priv->hw_addr_len) ++ g_return_val_if_reached (FALSE); ++ priv->hw_addr_len = addr_len; ++ } + + _LOGT (LOGD_DEVICE, "set-hw-addr: setting MAC address to '%s' (%s, %s)...", addr, operation, detail); + +@@ -11766,12 +11768,12 @@ _hw_addr_set (NMDevice *self, + nm_device_take_down (self, FALSE); + } + +- plerr = nm_platform_link_set_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), addr_bytes, hw_addr_len); ++ plerr = nm_platform_link_set_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), addr_bytes, addr_len); + success = (plerr == NM_PLATFORM_ERROR_SUCCESS); + if (success) { + /* MAC address succesfully changed; update the current MAC to match */ + nm_device_update_hw_address (self); +- if (_hw_addr_matches (self, addr)) { ++ if (_hw_addr_matches (self, addr_bytes, addr_len)) { + _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)", + operation, addr, detail); + } else { +@@ -11801,7 +11803,7 @@ _hw_addr_set (NMDevice *self, + goto handle_fail; + if (!nm_device_update_hw_address (self)) + goto handle_wait; +- if (!_hw_addr_matches (self, addr)) ++ if (!_hw_addr_matches (self, addr_bytes, addr_len)) + goto handle_fail; + + break; +@@ -11928,9 +11930,8 @@ nm_device_hw_addr_set_cloned (NMDevice *self, NMConnection *connection, gboolean + addr = hw_addr_generated; + } else { + /* this must be a valid address. Otherwise, we shouldn't come here. */ +- if (_nm_utils_hwaddr_length (addr) <= 0) { ++ if (!nm_utils_hwaddr_valid (addr, -1)) + g_return_val_if_reached (FALSE); +- } + priv->hw_addr_type = HW_ADDR_TYPE_EXPLICIT; + } + +@@ -12127,13 +12128,16 @@ constructor (GType type, + } + + if (priv->hw_addr_perm) { +- priv->hw_addr_len = _nm_utils_hwaddr_length (priv->hw_addr_perm); +- if (!priv->hw_addr_len) { ++ guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; ++ gsize l; ++ ++ if (!_nm_utils_hwaddr_aton (priv->hw_addr_perm, buf, sizeof (buf), &l)) { + g_clear_pointer (&priv->hw_addr_perm, g_free); + g_return_val_if_reached (object); + } + +- priv->hw_addr = g_strdup (priv->hw_addr_perm); ++ priv->hw_addr_len = l; ++ priv->hw_addr = nm_utils_hwaddr_ntoa (buf, l); + _LOGT (LOGD_DEVICE, "hw-addr: has permanent hw-address '%s'", priv->hw_addr_perm); + } + +diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c +index 6dfbb4c..6988a12 100644 +--- a/src/nm-core-utils.c ++++ b/src/nm-core-utils.c +@@ -1272,7 +1272,7 @@ nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr) + { + const GSList *iter; + NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH; +- guint hwaddr_len = 0; ++ gsize hwaddr_len = 0; + guint8 hwaddr_bin[NM_UTILS_HWADDR_LEN_MAX]; + + nm_assert (nm_utils_hwaddr_valid (hwaddr, -1)); +@@ -1297,11 +1297,8 @@ nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr) + continue; + + if (G_UNLIKELY (hwaddr_len == 0)) { +- hwaddr_len = _nm_utils_hwaddr_length (hwaddr); +- if (!hwaddr_len) ++ if (!_nm_utils_hwaddr_aton (hwaddr, hwaddr_bin, sizeof (hwaddr_bin), &hwaddr_len)) + g_return_val_if_reached (NM_MATCH_SPEC_NO_MATCH); +- if (!nm_utils_hwaddr_aton (hwaddr, hwaddr_bin, hwaddr_len)) +- nm_assert_not_reached (); + } + + if (nm_utils_hwaddr_matches (spec_str, -1, hwaddr_bin, hwaddr_len)) { +-- +2.9.3 + + +From 8b6c03327ab5038e71f79020782e552a8192ef59 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Thu, 13 Oct 2016 15:56:13 +0200 +Subject: [PATCH 08/15] core: add nm_device_get_permanent_hw_address_full() + function + +This is a partial cherry-pick from commit 5912b2f9a170893002b789fe37a7784eefac4e34. + +(cherry picked from commit b071c91eef15d6dbbf365d2db5aaca1b4eadcce0) +--- + src/devices/nm-device.c | 32 ++++++++++++++++++++++++-------- + src/devices/nm-device.h | 2 ++ + 2 files changed, 26 insertions(+), 8 deletions(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 4be572c..5001fce 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -11609,8 +11609,10 @@ nm_device_update_permanent_hw_address (NMDevice *self) + + success_read = nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len); + if (!success_read || len != priv->hw_addr_len) { +- /* Fall back to current address. We use the fake address and keep it +- * until the device unrealizes. ++ priv->hw_addr_perm_fake = TRUE; ++ ++ /* we failed to read a permanent MAC address, thus we use a fake address, ++ * that is the current MAC address of the device. + * + * In some cases it might be necessary to know whether this is a "real" or + * a temporary address (fake). */ +@@ -11619,14 +11621,16 @@ nm_device_update_permanent_hw_address (NMDevice *self) + ? "read HW addr length of permanent MAC address differs" + : "unable to read permanent MAC address", + priv->hw_addr); +- priv->hw_addr_perm_fake = TRUE; + priv->hw_addr_perm = g_strdup (priv->hw_addr); +- } else { +- priv->hw_addr_perm_fake = FALSE; +- priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, len); +- _LOGD (LOGD_DEVICE, "hw-addr: read permanent MAC address '%s'", +- priv->hw_addr_perm); ++ goto out; + } ++ ++ priv->hw_addr_perm_fake = FALSE; ++ priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, len); ++ _LOGD (LOGD_DEVICE, "hw-addr: read permanent MAC address '%s'", ++ priv->hw_addr_perm); ++ ++out: + _notify (self, PROP_PERM_HW_ADDRESS); + } + +@@ -11963,6 +11967,18 @@ nm_device_hw_addr_reset (NMDevice *self, const char *detail) + } + + const char * ++nm_device_get_permanent_hw_address_full (NMDevice *self, gboolean *out_is_fake) ++{ ++ NMDevicePrivate *priv; ++ ++ g_return_val_if_fail (NM_IS_DEVICE (self), NULL); ++ ++ priv = NM_DEVICE_GET_PRIVATE (self); ++ NM_SET_OUT (out_is_fake, priv->hw_addr_perm && priv->hw_addr_perm_fake); ++ return priv->hw_addr_perm; ++} ++ ++const char * + nm_device_get_permanent_hw_address (NMDevice *self, gboolean fallback_fake) + { + NMDevicePrivate *priv; +diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h +index a757a37..010c9b9 100644 +--- a/src/devices/nm-device.h ++++ b/src/devices/nm-device.h +@@ -366,6 +366,8 @@ guint32 nm_device_get_ip6_route_metric (NMDevice *dev); + const char * nm_device_get_hw_address (NMDevice *dev); + const char * nm_device_get_permanent_hw_address (NMDevice *dev, + gboolean fallback_fake); ++const char * nm_device_get_permanent_hw_address_full (NMDevice *self, ++ gboolean *out_is_fake); + const char * nm_device_get_initial_hw_address (NMDevice *dev); + + NMDhcp4Config * nm_device_get_dhcp4_config (NMDevice *dev); +-- +2.9.3 + + +From c6bd879444816dbf7f2bc86b10b2b0589b4c94bf Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Tue, 11 Oct 2016 07:47:25 +0000 +Subject: [PATCH 09/15] config: allow fallback to fake permanent address for + default wired connections + +The default wired connection is already generated allowing the use of a fake +address, but for the state file and the device matching specs only non-fake +addresses are used. Let's allow fake addresses consistently, so that default +wired connections work properly in containers (where the veth address is +considered fake) as well. + +Also, it would really be a better idea to use ifnames everywhere instead, but +that would change the format of the state file. + +(cherry picked from commit bcb685c4cb2b126f4a8593083fed043aed74ed17) +(cherry picked from commit bb5ee41dc440709c3f2e0a3e498ab70fde4cea1a) +--- + src/devices/nm-device.c | 2 +- + src/nm-config.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 5001fce..a3af85a 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -12048,7 +12048,7 @@ spec_match_list (NMDevice *self, const GSList *specs) + } + } + +- hw_addr_perm = nm_device_get_permanent_hw_address (self, FALSE); ++ hw_addr_perm = nm_device_get_permanent_hw_address (self, TRUE); + if (hw_addr_perm) { + m = nm_match_spec_hwaddr (specs, hw_addr_perm); + matched = MAX (matched, m); +diff --git a/src/nm-config.c b/src/nm-config.c +index 4bc4f48..3823e34 100644 +--- a/src/nm-config.c ++++ b/src/nm-config.c +@@ -399,7 +399,7 @@ nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device) + + priv = NM_CONFIG_GET_PRIVATE (self); + +- hw_address = nm_device_get_permanent_hw_address (device, FALSE); ++ hw_address = nm_device_get_permanent_hw_address (device, TRUE); + if (!hw_address) + return; + +-- +2.9.3 + + +From 5e1e3c0e79922ac4ff9a83ce406b9ff3b559832c Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Thu, 13 Oct 2016 18:52:12 +0200 +Subject: [PATCH 10/15] device: treat fake permanent MAC address mostly like a + real one + +Now that we persist the fake permanent address across +restart of NetworkManager, we want to consider fake +addresses as good enough in most cases. + +(cherry picked from commit 416164aa29c45d8071c8767fed866e06ee0e9169) +(cherry picked from commit 7bb7b17408de2a1001c3ed77e06d2b23c1125b72) +--- + src/devices/nm-device-ethernet.c | 15 +++++++++------ + src/devices/nm-device-infiniband.c | 6 +++--- + src/devices/nm-device-macvlan.c | 2 +- + src/devices/nm-device-vlan.c | 2 +- + src/devices/nm-device.c | 25 +++++++++++-------------- + src/devices/nm-device.h | 3 +-- + src/devices/wifi/nm-device-wifi.c | 4 ++-- + src/nm-config.c | 2 +- + src/nm-manager.c | 2 +- + src/settings/nm-settings.c | 2 +- + 10 files changed, 31 insertions(+), 32 deletions(-) + +diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c +index 2f0b68a..004a4bd 100644 +--- a/src/devices/nm-device-ethernet.c ++++ b/src/devices/nm-device-ethernet.c +@@ -396,7 +396,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) + if (!match_subchans (self, s_wired, &try_mac)) + return FALSE; + +- perm_hw_addr = nm_device_get_permanent_hw_address (device, TRUE); ++ perm_hw_addr = nm_device_get_permanent_hw_address (device); + mac = nm_setting_wired_get_mac_address (s_wired); + if (perm_hw_addr) { + if (try_mac && mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1)) +@@ -1346,6 +1346,7 @@ complete_connection (NMDevice *device, + NMSettingPppoe *s_pppoe; + const char *setting_mac; + const char *perm_hw_addr; ++ gboolean perm_hw_addr_is_fake; + + s_pppoe = nm_connection_get_setting_pppoe (connection); + +@@ -1373,8 +1374,8 @@ complete_connection (NMDevice *device, + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + } + +- perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE); +- if (perm_hw_addr) { ++ perm_hw_addr = nm_device_get_permanent_hw_address_full (device, &perm_hw_addr_is_fake); ++ if (perm_hw_addr && !perm_hw_addr_is_fake) { + setting_mac = nm_setting_wired_get_mac_address (s_wired); + if (setting_mac) { + /* Make sure the setting MAC (if any) matches the device's permanent MAC */ +@@ -1410,7 +1411,7 @@ new_default_connection (NMDevice *self) + if (nm_config_get_no_auto_default_for_device (nm_config_get (), self)) + return NULL; + +- perm_hw_addr = nm_device_get_permanent_hw_address (self, TRUE); ++ perm_hw_addr = nm_device_get_permanent_hw_address (self); + if (!perm_hw_addr) + return NULL; + +@@ -1470,7 +1471,8 @@ update_connection (NMDevice *device, NMConnection *connection) + { + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE ((NMDeviceEthernet *) device); + NMSettingWired *s_wired = nm_connection_get_setting_wired (connection); +- const char *perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE); ++ gboolean perm_hw_addr_is_fake; ++ const char *perm_hw_addr; + const char *mac = nm_device_get_hw_address (device); + const char *mac_prop = NM_SETTING_WIRED_MAC_ADDRESS; + GHashTableIter iter; +@@ -1489,7 +1491,8 @@ update_connection (NMDevice *device, NMConnection *connection) + /* If the device reports a permanent address, use that for the MAC address + * and the current MAC, if different, is the cloned MAC. + */ +- if (perm_hw_addr) { ++ perm_hw_addr = nm_device_get_permanent_hw_address_full (device, &perm_hw_addr_is_fake); ++ if (perm_hw_addr && !perm_hw_addr_is_fake) { + g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, perm_hw_addr, NULL); + + mac_prop = NULL; +diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c +index 17f50ba..e2a67de 100644 +--- a/src/devices/nm-device-infiniband.c ++++ b/src/devices/nm-device-infiniband.c +@@ -151,7 +151,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) + + mac = nm_setting_infiniband_get_mac_address (s_infiniband); + if (mac) { +- hw_addr = nm_device_get_permanent_hw_address (device, TRUE); ++ hw_addr = nm_device_get_permanent_hw_address (device); + if ( !hw_addr + || !nm_utils_hwaddr_matches (mac, -1, hw_addr, -1)) + return FALSE; +@@ -188,7 +188,7 @@ complete_connection (NMDevice *device, + } + + setting_mac = nm_setting_infiniband_get_mac_address (s_infiniband); +- hw_address = nm_device_get_permanent_hw_address (device, TRUE); ++ hw_address = nm_device_get_permanent_hw_address (device); + if (setting_mac) { + /* Make sure the setting MAC (if any) matches the device's MAC */ + if (!nm_utils_hwaddr_matches (setting_mac, -1, hw_address, -1)) { +@@ -214,7 +214,7 @@ static void + update_connection (NMDevice *device, NMConnection *connection) + { + NMSettingInfiniband *s_infiniband = nm_connection_get_setting_infiniband (connection); +- const char *mac = nm_device_get_permanent_hw_address (device, TRUE); ++ const char *mac = nm_device_get_permanent_hw_address (device); + const char *transport_mode = "datagram"; + int ifindex; + +diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c +index 0a43646..c53abb6 100644 +--- a/src/devices/nm-device-macvlan.c ++++ b/src/devices/nm-device-macvlan.c +@@ -373,7 +373,7 @@ match_hwaddr (NMDevice *device, NMConnection *connection, gboolean fail_if_no_hw + if (!priv->parent) + return !fail_if_no_hwaddr; + +- parent_mac = nm_device_get_permanent_hw_address (priv->parent, FALSE); ++ parent_mac = nm_device_get_permanent_hw_address (priv->parent); + return parent_mac && nm_utils_hwaddr_matches (setting_mac, -1, parent_mac, -1); + } + +diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c +index 16edc0d..461bae6 100644 +--- a/src/devices/nm-device-vlan.c ++++ b/src/devices/nm-device-vlan.c +@@ -391,7 +391,7 @@ match_hwaddr (NMDevice *device, NMConnection *connection, gboolean fail_if_no_hw + if (!priv->parent) + return !fail_if_no_hwaddr; + +- parent_mac = nm_device_get_permanent_hw_address (priv->parent, FALSE); ++ parent_mac = nm_device_get_permanent_hw_address (priv->parent); + return parent_mac && nm_utils_hwaddr_matches (setting_mac, -1, parent_mac, -1); + } + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index a3af85a..8efd61f 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -11890,7 +11890,7 @@ nm_device_hw_addr_set_cloned (NMDevice *self, NMConnection *connection, gboolean + } + + if (nm_streq (addr, NM_CLONED_MAC_PERMANENT)) { +- addr = nm_device_get_permanent_hw_address (self, TRUE); ++ addr = nm_device_get_permanent_hw_address (self); + if (!addr) + return FALSE; + priv->hw_addr_type = HW_ADDR_TYPE_PERMANENT; +@@ -11979,19 +11979,11 @@ nm_device_get_permanent_hw_address_full (NMDevice *self, gboolean *out_is_fake) + } + + const char * +-nm_device_get_permanent_hw_address (NMDevice *self, gboolean fallback_fake) ++nm_device_get_permanent_hw_address (NMDevice *self) + { +- NMDevicePrivate *priv; +- + g_return_val_if_fail (NM_IS_DEVICE (self), NULL); + +- priv = NM_DEVICE_GET_PRIVATE (self); +- if (!priv->hw_addr_perm) +- return NULL; +- if ( priv->hw_addr_perm_fake +- && !fallback_fake) +- return NULL; +- return priv->hw_addr_perm; ++ return NM_DEVICE_GET_PRIVATE (self)->hw_addr_perm; + } + + const char * +@@ -12048,7 +12040,7 @@ spec_match_list (NMDevice *self, const GSList *specs) + } + } + +- hw_addr_perm = nm_device_get_permanent_hw_address (self, TRUE); ++ hw_addr_perm = nm_device_get_permanent_hw_address (self); + if (hw_addr_perm) { + m = nm_match_spec_hwaddr (specs, hw_addr_perm); + matched = MAX (matched, m); +@@ -12521,10 +12513,15 @@ get_property (GObject *object, guint prop_id, + case PROP_HW_ADDRESS: + g_value_set_string (value, priv->hw_addr); + break; +- case PROP_PERM_HW_ADDRESS: ++ case PROP_PERM_HW_ADDRESS: { ++ const char *perm_hw_addr; ++ gboolean perm_hw_addr_is_fake; ++ ++ perm_hw_addr = nm_device_get_permanent_hw_address_full (self, &perm_hw_addr_is_fake); + /* this property is exposed on D-Bus for NMDeviceEthernet and NMDeviceWifi. */ +- g_value_set_string (value, nm_device_get_permanent_hw_address (self, FALSE)); ++ g_value_set_string (value, perm_hw_addr && !perm_hw_addr_is_fake ? perm_hw_addr : NULL); + break; ++ } + case PROP_HAS_PENDING_ACTION: + g_value_set_boolean (value, nm_device_has_pending_action (self)); + break; +diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h +index 010c9b9..476a42b 100644 +--- a/src/devices/nm-device.h ++++ b/src/devices/nm-device.h +@@ -364,8 +364,7 @@ guint32 nm_device_get_ip4_route_metric (NMDevice *dev); + guint32 nm_device_get_ip6_route_metric (NMDevice *dev); + + const char * nm_device_get_hw_address (NMDevice *dev); +-const char * nm_device_get_permanent_hw_address (NMDevice *dev, +- gboolean fallback_fake); ++const char * nm_device_get_permanent_hw_address (NMDevice *self); + const char * nm_device_get_permanent_hw_address_full (NMDevice *self, + gboolean *out_is_fake); + const char * nm_device_get_initial_hw_address (NMDevice *dev); +diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c +index f467c81..f65b0cc 100644 +--- a/src/devices/wifi/nm-device-wifi.c ++++ b/src/devices/wifi/nm-device-wifi.c +@@ -615,7 +615,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) + if (!s_wireless) + return FALSE; + +- perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE); ++ perm_hw_addr = nm_device_get_permanent_hw_address (device); + mac = nm_setting_wireless_get_mac_address (s_wireless); + if (perm_hw_addr) { + if (mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1)) +@@ -907,7 +907,7 @@ complete_connection (NMDevice *device, + if (hidden) + g_object_set (s_wifi, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL); + +- perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE); ++ perm_hw_addr = nm_device_get_permanent_hw_address (device); + if (perm_hw_addr) { + setting_mac = nm_setting_wireless_get_mac_address (s_wifi); + if (setting_mac) { +diff --git a/src/nm-config.c b/src/nm-config.c +index 3823e34..f0f0c52 100644 +--- a/src/nm-config.c ++++ b/src/nm-config.c +@@ -399,7 +399,7 @@ nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device) + + priv = NM_CONFIG_GET_PRIVATE (self); + +- hw_address = nm_device_get_permanent_hw_address (device, TRUE); ++ hw_address = nm_device_get_permanent_hw_address (device); + if (!hw_address) + return; + +diff --git a/src/nm-manager.c b/src/nm-manager.c +index 932dafd..aadc572 100644 +--- a/src/nm-manager.c ++++ b/src/nm-manager.c +@@ -610,7 +610,7 @@ find_device_by_permanent_hw_addr (NMManager *manager, const char *hwaddr) + + if (nm_utils_hwaddr_valid (hwaddr, -1)) { + for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) { +- device_addr = nm_device_get_permanent_hw_address (NM_DEVICE (iter->data), FALSE); ++ device_addr = nm_device_get_permanent_hw_address (NM_DEVICE (iter->data)); + if (device_addr && nm_utils_hwaddr_matches (hwaddr, -1, device_addr, -1)) + return NM_DEVICE (iter->data); + } +diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c +index 1f691c0..cd54e52 100644 +--- a/src/settings/nm-settings.c ++++ b/src/settings/nm-settings.c +@@ -1874,7 +1874,7 @@ have_connection_for_device (NMSettings *self, NMDevice *device) + + g_return_val_if_fail (NM_IS_SETTINGS (self), FALSE); + +- perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE); ++ perm_hw_addr = nm_device_get_permanent_hw_address (device); + + /* Find a wired connection locked to the given MAC address, if any */ + g_hash_table_iter_init (&iter, priv->connections); +-- +2.9.3 + + +From 1d2c444c6fc819c33a91dadd6535c117854cfd65 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 26 Oct 2016 12:20:12 +0200 +Subject: [PATCH 11/15] device: don't allow mutating the device's hardware + address length + +We repeatedly call nm_device_update_hw_address() to reset the cached +MAC address of the device. However, we don't allow changing the address +length once it is set. + +Multiple entities (initial, current and permanent MAC address) are all +checked to have the same address length. Changing the length would be a +very strange thing (and probably indicate a bug somewhere else). + +Just don't allow that. + +(cherry picked from commit cbea1f9f23fac42626134b38cf94dd4ebca4091d) +(cherry picked from commit e41284b3fca21123a6808cb1d5c262f678472d3f) +--- + src/devices/nm-device.c | 53 ++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 37 insertions(+), 16 deletions(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 8efd61f..c126728 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -227,7 +227,10 @@ typedef struct _NMDevicePrivate { + char * iface; /* may change, could be renamed by user */ + int ifindex; + +- guint hw_addr_len; ++ union { ++ const guint8 hw_addr_len; /* read-only */ ++ guint8 hw_addr_len_; ++ }; + guint8 /*HwAddrType*/ hw_addr_type; + + bool real; +@@ -2475,11 +2478,6 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) + g_clear_pointer (&priv->udi, g_free); + _notify (self, PROP_UDI); + } +- if (priv->hw_addr) { +- priv->hw_addr_len = 0; +- g_clear_pointer (&priv->hw_addr, g_free); +- _notify (self, PROP_HW_ADDRESS); +- } + if (priv->physical_port_id) { + g_clear_pointer (&priv->physical_port_id, g_free); + _notify (self, PROP_PHYSICAL_PORT_ID); +@@ -2488,9 +2486,12 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) + nm_clear_g_source (&priv->stats.timeout_id); + _stats_update_counters (self, 0, 0); + ++ priv->hw_addr_len_ = 0; ++ if (nm_clear_g_free (&priv->hw_addr)) ++ _notify (self, PROP_HW_ADDRESS); + priv->hw_addr_type = HW_ADDR_TYPE_UNSET; +- g_clear_pointer (&priv->hw_addr_perm, g_free); +- _notify (self, PROP_PERM_HW_ADDRESS); ++ if (nm_clear_g_free (&priv->hw_addr_perm)) ++ _notify (self, PROP_PERM_HW_ADDRESS); + g_clear_pointer (&priv->hw_addr_initial, g_free); + + priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED; +@@ -11499,11 +11500,17 @@ const char * + nm_device_get_hw_address (NMDevice *self) + { + NMDevicePrivate *priv; ++ char buf[NM_UTILS_HWADDR_LEN_MAX]; ++ gsize l; + + g_return_val_if_fail (NM_IS_DEVICE (self), NULL); ++ + priv = NM_DEVICE_GET_PRIVATE (self); + +- nm_assert ((!priv->hw_addr) ^ (priv->hw_addr_len > 0)); ++ nm_assert ( (!priv->hw_addr && priv->hw_addr_len == 0) ++ || ( priv->hw_addr ++ && _nm_utils_hwaddr_aton (priv->hw_addr, buf, sizeof (buf), &l) ++ && l == priv->hw_addr_len)); + + return priv->hw_addr; + } +@@ -11528,9 +11535,25 @@ nm_device_update_hw_address (NMDevice *self) + hwaddrlen = 0; + + if (hwaddrlen) { +- priv->hw_addr_len = hwaddrlen; ++ if ( priv->hw_addr_len ++ && priv->hw_addr_len != hwaddrlen) { ++ char s_buf[NM_UTILS_HWADDR_LEN_MAX_STR]; ++ ++ /* we cannot change the address length of a device once it is set (except ++ * unrealizing the device). ++ * ++ * The reason is that the permanent and initial MAC addresses also must have the ++ * same address length, so it's unclear what it would mean that the length changes. */ ++ _LOGD (LOGD_PLATFORM | LOGD_DEVICE, ++ "hw-addr: read a MAC address with differing length (%s vs. %s)", ++ priv->hw_addr, ++ nm_utils_hwaddr_ntoa_buf (hwaddr, hwaddrlen, TRUE, s_buf, sizeof (s_buf))); ++ return FALSE; ++ } ++ + if (!priv->hw_addr || !nm_utils_hwaddr_matches (priv->hw_addr, -1, hwaddr, hwaddrlen)) { + g_free (priv->hw_addr); ++ priv->hw_addr_len_ = hwaddrlen; + priv->hw_addr = nm_utils_hwaddr_ntoa (hwaddr, hwaddrlen); + + _LOGD (LOGD_PLATFORM | LOGD_DEVICE, "hw-addr: hardware address now %s", priv->hw_addr); +@@ -11758,11 +11781,9 @@ _hw_addr_set (NMDevice *self, + return TRUE; + } + +- if (priv->hw_addr_len != addr_len) { +- if (priv->hw_addr_len) +- g_return_val_if_reached (FALSE); +- priv->hw_addr_len = addr_len; +- } ++ if ( priv->hw_addr_len ++ && priv->hw_addr_len != addr_len) ++ g_return_val_if_reached (FALSE); + + _LOGT (LOGD_DEVICE, "set-hw-addr: setting MAC address to '%s' (%s, %s)...", addr, operation, detail); + +@@ -12144,7 +12165,7 @@ constructor (GType type, + g_return_val_if_reached (object); + } + +- priv->hw_addr_len = l; ++ priv->hw_addr_len_ = l; + priv->hw_addr = nm_utils_hwaddr_ntoa (buf, l); + _LOGT (LOGD_DEVICE, "hw-addr: has permanent hw-address '%s'", priv->hw_addr_perm); + } +-- +2.9.3 + + +From f7af2a0a65f293809aac04faa17e469ecde5bc98 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Mon, 24 Oct 2016 12:50:17 +0200 +Subject: [PATCH 12/15] device: delay capturing permanent MAC address until + UDEV is settled + +The permanent MAC address of an NMDevice shall not change as +long as the device is realized. That is, we read it only once +and don't change it afterwards. + +There are two issues that this commit tries to mitigate: + +(1) users are advised to use UDEV to rename interfaces. As we lookup + the permenent MAC address using ethtool (which uses the interface + name), there is a race where we could read the permanent MAC + address using the wrong interface name. We should wait until + UDEV finished initializing the device and until the interface + name is stable (see rh#1388286). + This commit still cannot avoid the race of ethtool entirely. It only + tries to avoid ethtool until UDEV has done its work. That is, until we + expect the interface name no longer to change. + +(2) some device types, don't have a permanent MAC address so we fall + back to use the currently set address (fake). Again, users are advised + to use UDEV to configure the MAC addresses on such software devices. + Thus, we should not get the fake MAC address until UDEV initialized + the device. + +This patch actually doesn't solve the problem at all yet. +The reason is that a regular caller of nm_device_get_permanent_hw_address() can +not afford to wait until UDEV settled. Thus, any user who requests the +permanent MAC address before the link is initialized, runs into the +problems above. + +In a next step, we shall revisit such calls to nm_device_get_permanent_hw_address() +and delay them until the link is initialized. + +(cherry picked from commit 7b7c653c4f812f0ede676e8e0a08aa750e9e30b5) + +Conflicts: + src/devices/nm-device.c + src/nm-manager.c + +(cherry picked from commit 38b6f36edcc1d908863f66fd20dd79f1ef084f91) +--- + src/devices/nm-device-ethernet.c | 4 +- + src/devices/nm-device.c | 100 +++++++++++++++++++++++++-------------- + src/devices/nm-device.h | 3 +- + 3 files changed, 69 insertions(+), 38 deletions(-) + +diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c +index 004a4bd..75802cf 100644 +--- a/src/devices/nm-device-ethernet.c ++++ b/src/devices/nm-device-ethernet.c +@@ -1374,7 +1374,7 @@ complete_connection (NMDevice *device, + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + } + +- perm_hw_addr = nm_device_get_permanent_hw_address_full (device, &perm_hw_addr_is_fake); ++ perm_hw_addr = nm_device_get_permanent_hw_address_full (device, TRUE, &perm_hw_addr_is_fake); + if (perm_hw_addr && !perm_hw_addr_is_fake) { + setting_mac = nm_setting_wired_get_mac_address (s_wired); + if (setting_mac) { +@@ -1491,7 +1491,7 @@ update_connection (NMDevice *device, NMConnection *connection) + /* If the device reports a permanent address, use that for the MAC address + * and the current MAC, if different, is the cloned MAC. + */ +- perm_hw_addr = nm_device_get_permanent_hw_address_full (device, &perm_hw_addr_is_fake); ++ perm_hw_addr = nm_device_get_permanent_hw_address_full (device, TRUE, &perm_hw_addr_is_fake); + if (perm_hw_addr && !perm_hw_addr_is_fake) { + g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, perm_hw_addr, NULL); + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index c126728..638c37d 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -1822,7 +1822,7 @@ device_link_changed (NMDevice *self) + had_hw_addr = (priv->hw_addr != NULL); + nm_device_update_hw_address (self); + got_hw_addr = (!had_hw_addr && priv->hw_addr); +- nm_device_update_permanent_hw_address (self); ++ nm_device_update_permanent_hw_address (self, FALSE); + + if (info.name[0] && strcmp (priv->iface, info.name) != 0) { + _LOGI (LOGD_DEVICE, "interface index %d renamed iface from '%s' to '%s'", +@@ -2288,7 +2288,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) + + nm_device_update_hw_address (self); + nm_device_update_initial_hw_address (self); +- nm_device_update_permanent_hw_address (self); ++ nm_device_update_permanent_hw_address (self, FALSE); + + /* Note: initial hardware address must be read before calling get_ignore_carrier() */ + config = nm_config_get (); +@@ -11605,12 +11605,14 @@ nm_device_update_initial_hw_address (NMDevice *self) + } + + void +-nm_device_update_permanent_hw_address (NMDevice *self) ++nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze) + { + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; + size_t len = 0; + gboolean success_read; ++ int ifindex; ++ const NMPlatformLink *pllink; + + if (priv->hw_addr_perm) { + /* the permanent hardware address is only read once and not +@@ -11621,39 +11623,60 @@ nm_device_update_permanent_hw_address (NMDevice *self) + return; + } + +- if (priv->ifindex <= 0) ++ ifindex = priv->ifindex; ++ if (ifindex <= 0) + return; + +- if (!priv->hw_addr_len) { +- nm_device_update_hw_address (self); +- if (!priv->hw_addr_len) ++ /* the user is advised to configure stable MAC addresses for software devices via ++ * UDEV. Thus, check whether the link is fully initialized. */ ++ pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex); ++ if ( !pllink ++ || !pllink->initialized) { ++ if (!force_freeze) { ++ /* we can afford to wait. Back off and leave the permanent MAC address ++ * undecided for now. */ + return; +- } +- +- success_read = nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len); +- if (!success_read || len != priv->hw_addr_len) { +- priv->hw_addr_perm_fake = TRUE; ++ } ++ /* try to refresh the link just to give UDEV a bit more time... */ ++ nm_platform_link_refresh (NM_PLATFORM_GET, ifindex); ++ /* maybe the MAC address changed... */ ++ nm_device_update_hw_address (self); ++ } else if (!priv->hw_addr_len) ++ nm_device_update_hw_address (self); + +- /* we failed to read a permanent MAC address, thus we use a fake address, +- * that is the current MAC address of the device. ++ if (!priv->hw_addr_len) { ++ /* we need the current MAC address because we require the permanent MAC address ++ * to have the same length as the current address. + * +- * In some cases it might be necessary to know whether this is a "real" or +- * a temporary address (fake). */ +- _LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use current: %s)", +- success_read +- ? "read HW addr length of permanent MAC address differs" +- : "unable to read permanent MAC address", +- priv->hw_addr); +- priv->hw_addr_perm = g_strdup (priv->hw_addr); +- goto out; +- } +- +- priv->hw_addr_perm_fake = FALSE; +- priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, len); +- _LOGD (LOGD_DEVICE, "hw-addr: read permanent MAC address '%s'", +- priv->hw_addr_perm); ++ * Abort if there is no current MAC address. */ ++ return; ++ } + +-out: ++ success_read = nm_platform_link_get_permanent_address (NM_PLATFORM_GET, ifindex, buf, &len); ++ if (success_read && priv->hw_addr_len == len) { ++ priv->hw_addr_perm_fake = FALSE; ++ priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, len); ++ _LOGD (LOGD_DEVICE, "hw-addr: read permanent MAC address '%s'", ++ priv->hw_addr_perm); ++ goto notify_and_out; ++ } ++ ++ /* we failed to read a permanent MAC address, thus we use a fake address, ++ * that is the current MAC address of the device. ++ * ++ * Note that the permanet MAC address of a NMDevice instance does not change ++ * after being set once. Thus, we use now a fake address and stick to that ++ * (until we unrealize the device). */ ++ priv->hw_addr_perm_fake = TRUE; ++ ++ _LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use current: %s)", ++ success_read ++ ? "read HW addr length of permanent MAC address differs" ++ : "unable to read permanent MAC address", ++ priv->hw_addr); ++ priv->hw_addr_perm = g_strdup (priv->hw_addr); ++ ++notify_and_out: + _notify (self, PROP_PERM_HW_ADDRESS); + } + +@@ -11988,13 +12011,22 @@ nm_device_hw_addr_reset (NMDevice *self, const char *detail) + } + + const char * +-nm_device_get_permanent_hw_address_full (NMDevice *self, gboolean *out_is_fake) ++nm_device_get_permanent_hw_address_full (NMDevice *self, gboolean force_freeze, gboolean *out_is_fake) + { + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (self), NULL); + + priv = NM_DEVICE_GET_PRIVATE (self); ++ ++ if ( !priv->hw_addr_perm ++ && force_freeze) { ++ /* somebody requests a permanent MAC address, but we don't have it set ++ * yet. We cannot delay it any longer and try to get it without waiting ++ * for UDEV. */ ++ nm_device_update_permanent_hw_address (self, TRUE); ++ } ++ + NM_SET_OUT (out_is_fake, priv->hw_addr_perm && priv->hw_addr_perm_fake); + return priv->hw_addr_perm; + } +@@ -12002,9 +12034,7 @@ nm_device_get_permanent_hw_address_full (NMDevice *self, gboolean *out_is_fake) + const char * + nm_device_get_permanent_hw_address (NMDevice *self) + { +- g_return_val_if_fail (NM_IS_DEVICE (self), NULL); +- +- return NM_DEVICE_GET_PRIVATE (self)->hw_addr_perm; ++ return nm_device_get_permanent_hw_address_full (self, TRUE, NULL); + } + + const char * +@@ -12538,7 +12568,7 @@ get_property (GObject *object, guint prop_id, + const char *perm_hw_addr; + gboolean perm_hw_addr_is_fake; + +- perm_hw_addr = nm_device_get_permanent_hw_address_full (self, &perm_hw_addr_is_fake); ++ perm_hw_addr = nm_device_get_permanent_hw_address_full (self, FALSE, &perm_hw_addr_is_fake); + /* this property is exposed on D-Bus for NMDeviceEthernet and NMDeviceWifi. */ + g_value_set_string (value, perm_hw_addr && !perm_hw_addr_is_fake ? perm_hw_addr : NULL); + break; +diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h +index 476a42b..9044374 100644 +--- a/src/devices/nm-device.h ++++ b/src/devices/nm-device.h +@@ -366,6 +366,7 @@ guint32 nm_device_get_ip6_route_metric (NMDevice *dev); + const char * nm_device_get_hw_address (NMDevice *dev); + const char * nm_device_get_permanent_hw_address (NMDevice *self); + const char * nm_device_get_permanent_hw_address_full (NMDevice *self, ++ gboolean force_freeze, + gboolean *out_is_fake); + const char * nm_device_get_initial_hw_address (NMDevice *dev); + +@@ -591,7 +592,7 @@ void nm_device_reactivate_ip6_config (NMDevice *device, + + gboolean nm_device_update_hw_address (NMDevice *self); + void nm_device_update_initial_hw_address (NMDevice *self); +-void nm_device_update_permanent_hw_address (NMDevice *self); ++void nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze); + void nm_device_update_dynamic_ip_setup (NMDevice *self); + + #endif /* __NETWORKMANAGER_DEVICE_H__ */ +-- +2.9.3 + + +From 03b1d4dbdbb5914613d6d28f0fb8ee9d206bbf27 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Tue, 25 Oct 2016 15:27:57 +0200 +Subject: [PATCH 13/15] device: delay evaluating unmanaged-by-user-settings + flags until link initialized + +Before the link is initialized, that is before UDEV completed +initializing the device, we should not evaluate the user-settings +unmanaged flags. + +The reason is, that evaluating it likely involves looking at the +permanent MAC address, which might use the wrong fake MAC address +(before UDEV set the right one). Also, it might use the wrong ifname +to lookup the permanent MAC address via ethtool. + +(cherry picked from commit c0d249b733325046ca192d112d468b86aac54ba4) +(cherry picked from commit 9f51a93d973e673ff5a6ee286cef1b7347f09767) +--- + src/devices/nm-device.c | 39 ++++++++++++++++++++++++++++++++------- + src/devices/nm-device.h | 2 +- + src/nm-manager.c | 15 +++++++-------- + 3 files changed, 40 insertions(+), 16 deletions(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 638c37d..aa3bf1e 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -1834,7 +1834,7 @@ device_link_changed (NMDevice *self) + ip_ifname_changed = !priv->ip_iface; + + if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) +- nm_device_set_unmanaged_by_user_settings (self, nm_settings_get_unmanaged_specs (priv->settings)); ++ nm_device_set_unmanaged_by_user_settings (self); + else + update_unmanaged_specs = TRUE; + +@@ -1913,7 +1913,7 @@ device_link_changed (NMDevice *self) + } + + if (update_unmanaged_specs) +- nm_device_set_unmanaged_by_user_settings (self, nm_settings_get_unmanaged_specs (priv->settings)); ++ nm_device_set_unmanaged_by_user_settings (self); + + if ( got_hw_addr + && !priv->up +@@ -9868,6 +9868,21 @@ _set_unmanaged_flags (NMDevice *self, + allow_state_transition = FALSE; + was_managed = allow_state_transition && nm_device_get_managed (self, FALSE); + ++ if ( NM_FLAGS_HAS (priv->unmanaged_flags, NM_UNMANAGED_PLATFORM_INIT) ++ && NM_FLAGS_HAS (flags, NM_UNMANAGED_PLATFORM_INIT) ++ && NM_IN_SET (set_op, NM_UNMAN_FLAG_OP_SET_MANAGED)) { ++ /* we are clearing the platform-init flags. This triggers additional actions. */ ++ if (!NM_FLAGS_HAS (flags, NM_UNMANAGED_USER_SETTINGS)) { ++ gboolean unmanaged; ++ ++ unmanaged = nm_device_spec_match_list (self, ++ nm_settings_get_unmanaged_specs (NM_DEVICE_GET_PRIVATE (self)->settings)); ++ nm_device_set_unmanaged_flags (self, ++ NM_UNMANAGED_USER_SETTINGS, ++ !!unmanaged); ++ } ++ } ++ + old_flags = priv->unmanaged_flags; + old_mask = priv->unmanaged_mask; + +@@ -9982,20 +9997,30 @@ nm_device_set_unmanaged_by_flags_queue (NMDevice *self, + } + + void +-nm_device_set_unmanaged_by_user_settings (NMDevice *self, const GSList *unmanaged_specs) ++nm_device_set_unmanaged_by_user_settings (NMDevice *self) + { +- NMDevicePrivate *priv; + gboolean unmanaged; + + g_return_if_fail (NM_IS_DEVICE (self)); + +- priv = NM_DEVICE_GET_PRIVATE (self); ++ if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) { ++ /* the device is already unmanaged due to platform-init. ++ * ++ * We want to delay evaluating the device spec, because it will freeze ++ * the permanent MAC address. That should not be done, before the platform ++ * link is fully initialized (via UDEV). ++ * ++ * Note that when clearing NM_UNMANAGED_PLATFORM_INIT, we will re-evaluate ++ * whether the device is unmanaged by user-settings. */ ++ return; ++ } + +- unmanaged = nm_device_spec_match_list (self, unmanaged_specs); ++ unmanaged = nm_device_spec_match_list (self, ++ nm_settings_get_unmanaged_specs (NM_DEVICE_GET_PRIVATE (self)->settings)); + + nm_device_set_unmanaged_by_flags (self, + NM_UNMANAGED_USER_SETTINGS, +- unmanaged, ++ !!unmanaged, + unmanaged + ? NM_DEVICE_STATE_REASON_NOW_UNMANAGED + : NM_DEVICE_STATE_REASON_NOW_MANAGED); +diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h +index 9044374..f90444c 100644 +--- a/src/devices/nm-device.h ++++ b/src/devices/nm-device.h +@@ -509,7 +509,7 @@ void nm_device_set_unmanaged_by_flags_queue (NMDevice *self, + NMUnmanagedFlags flags, + NMUnmanFlagOp set_op, + NMDeviceStateReason reason); +-void nm_device_set_unmanaged_by_user_settings (NMDevice *self, const GSList *unmanaged_specs); ++void nm_device_set_unmanaged_by_user_settings (NMDevice *self); + void nm_device_set_unmanaged_by_user_udev (NMDevice *self); + void nm_device_set_unmanaged_by_quitting (NMDevice *device); + +diff --git a/src/nm-manager.c b/src/nm-manager.c +index aadc572..4680f68 100644 +--- a/src/nm-manager.c ++++ b/src/nm-manager.c +@@ -1320,11 +1320,10 @@ system_unmanaged_devices_changed_cb (NMSettings *settings, + { + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); +- const GSList *unmanaged_specs, *iter; ++ const GSList *iter; + +- unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings); + for (iter = priv->devices; iter; iter = g_slist_next (iter)) +- nm_device_set_unmanaged_by_user_settings (NM_DEVICE (iter->data), unmanaged_specs); ++ nm_device_set_unmanaged_by_user_settings (NM_DEVICE (iter->data)); + } + + static void +@@ -1991,7 +1990,7 @@ add_device (NMManager *self, NMDevice *device, GError **error) + type_desc = nm_device_get_type_desc (device); + g_assert (type_desc); + +- nm_device_set_unmanaged_by_user_settings (device, nm_settings_get_unmanaged_specs (priv->settings)); ++ nm_device_set_unmanaged_by_user_settings (device); + + nm_device_set_unmanaged_flags (device, + NM_UNMANAGED_SLEEPING, +@@ -2810,15 +2809,15 @@ unmanaged_to_disconnected (NMDevice *device) + + if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) { + nm_device_state_changed (device, +- NM_DEVICE_STATE_UNAVAILABLE, +- NM_DEVICE_STATE_REASON_USER_REQUESTED); ++ NM_DEVICE_STATE_UNAVAILABLE, ++ NM_DEVICE_STATE_REASON_USER_REQUESTED); + } + + if ( nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST) + && (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) { + nm_device_state_changed (device, +- NM_DEVICE_STATE_DISCONNECTED, +- NM_DEVICE_STATE_REASON_USER_REQUESTED); ++ NM_DEVICE_STATE_DISCONNECTED, ++ NM_DEVICE_STATE_REASON_USER_REQUESTED); + } + } + +-- +2.9.3 + + +From c464623f4049278fd3eff5551198d1fad280b519 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 26 Oct 2016 13:43:49 +0200 +Subject: [PATCH 14/15] device: don't evaluate IP config changes until device + is initialized + +The unmanaged flags PLATFORM_INIT indicates whether UDEV is done +initializing the device. We should not handle IP config changes +before that pointer. + +This avoids codepaths that require the permanent MAC address of the +device. We should not freeze the permanent MAC address before +UDEV initialized the device, for two reasons: + +- getting the permanent MAC address using ethtool is racy as + UDEV might still rename the interface. +- freezing a fake permanent MAC address should only happen after + UDEV is done configuring the MAC address of software devices. + + #0 0x000055555568bc7a in nm_device_update_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1) at src/devices/nm-device.c:11817 + #1 0x000055555568c443 in nm_device_get_permanent_hw_address_full (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1, out_is_fake=out_is_fake@entry=0x0) + at src/devices/nm-device.c:12227 + #2 0x000055555568cb06 in nm_device_get_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:12237 + #3 0x000055555568cb50 in spec_match_list (self=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12294 + #4 0x00005555556a4ee6 in spec_match_list (device=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device-ethernet.c:1461 + #5 0x00005555556978db in nm_device_spec_match_list (self=self@entry=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12277 + #6 0x000055555558e187 in _match_section_infos_lookup (match_section_infos=0x555555a5d500, keyfile=0x555555a46f80, property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth], out_value=out_value@entry=0x7fffffffe018) at src/nm-config-data.c:1169 + #7 0x00005555555922ca in nm_config_data_get_connection_default (self=0x555555a548c0 [NMConfigData], property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth]) at src/nm-config-data.c:1234 + #8 0x00005555556790cd in _get_ipx_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth], is_v4=is_v4@entry=1) at src/devices/nm-device.c:1142 + #9 0x000055555567912e in nm_device_get_ip4_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:1161 + #10 0x000055555567da6c in ip4_config_merge_and_apply (self=self@entry=0x555555f0fb70 [NMDeviceVeth], config=config@entry=0x0, commit=commit@entry=0, out_reason=out_reason@entry=0x0) + at src/devices/nm-device.c:4787 + #11 0x000055555567e0fb in update_ip4_config (self=self@entry=0x555555f0fb70 [NMDeviceVeth], initial=initial@entry=0) at src/devices/nm-device.c:9532 + #12 0x0000555555693acd in queued_ip4_config_change (user_data=0x555555f0fb70) at src/devices/nm-device.c:9651 + #13 0x00007ffff4c966ba in g_main_context_dispatch (context=0x555555a46af0) at gmain.c:3154 + #14 0x00007ffff4c966ba in g_main_context_dispatch (context=context@entry=0x555555a46af0) at gmain.c:3769 + #15 0x00007ffff4c96a70 in g_main_context_iterate (context=0x555555a46af0, block=block@entry=1, dispatch=dispatch@entry=1, self=) at gmain.c:3840 + #16 0x00007ffff4c96d92 in g_main_loop_run (loop=0x555555a47400) at gmain.c:4034 + #17 0x000055555558372a in main (argc=, argv=) at src/main.c:411 + +(cherry picked from commit 31ca7962f8f7d1993f0a363b9677c7cee89e7ee3) +(cherry picked from commit cc0a590d57d860582396a5d03b1a316c364fd9a7) +--- + src/devices/nm-device.c | 44 ++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 38 insertions(+), 6 deletions(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index aa3bf1e..119806c 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -233,7 +233,12 @@ typedef struct _NMDevicePrivate { + }; + guint8 /*HwAddrType*/ hw_addr_type; + +- bool real; ++ bool real:1; ++ ++ /* there was a IP config change, but no idle action was scheduled because device ++ * is still not platform-init */ ++ bool queued_ip4_config_pending:1; ++ bool queued_ip6_config_pending:1; + + char * ip_iface; + int ip_ifindex; +@@ -2282,9 +2287,8 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) + _notify (self, PROP_UDI); + } + +- /* trigger initial ip config change to initialize ip-config */ +- priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self); +- priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); ++ priv->queued_ip4_config_pending = TRUE; ++ priv->queued_ip6_config_pending = TRUE; + + nm_device_update_hw_address (self); + nm_device_update_initial_hw_address (self); +@@ -7626,6 +7630,7 @@ _cleanup_ip4_pre (NMDevice *self, CleanupType cleanup_type) + + if (nm_clear_g_source (&priv->queued_ip4_config_id)) + _LOGD (LOGD_DEVICE, "clearing queued IP4 config change"); ++ priv->queued_ip4_config_pending = FALSE; + + dhcp4_cleanup (self, cleanup_type, FALSE); + arp_cleanup (self); +@@ -7642,6 +7647,7 @@ _cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type) + + if (nm_clear_g_source (&priv->queued_ip6_config_id)) + _LOGD (LOGD_DEVICE, "clearing queued IP6 config change"); ++ priv->queued_ip6_config_pending = FALSE; + + g_clear_object (&priv->dad6_ip6_config); + dhcp6_cleanup (self, cleanup_type, FALSE); +@@ -9341,6 +9347,7 @@ update_ip4_config (NMDevice *self, gboolean initial) + && activation_source_is_scheduled (self, + activate_stage5_ip4_config_commit, + AF_INET)) { ++ priv->queued_ip4_config_pending = FALSE; + priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self); + _LOGT (LOGD_DEVICE, "IP4 update was postponed"); + return; +@@ -9431,6 +9438,7 @@ update_ip6_config (NMDevice *self, gboolean initial) + && activation_source_is_scheduled (self, + activate_stage5_ip6_config_commit, + AF_INET6)) { ++ priv->queued_ip6_config_pending = FALSE; + priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); + _LOGT (LOGD_DEVICE, "IP6 update was postponed"); + return; +@@ -9508,6 +9516,8 @@ queued_ip4_config_change (gpointer user_data) + + priv = NM_DEVICE_GET_PRIVATE (self); + ++ nm_assert (!priv->queued_ip4_config_pending); ++ + /* Wait for any queued state changes */ + if (priv->queued_state.id) + return TRUE; +@@ -9532,6 +9542,8 @@ queued_ip6_config_change (gpointer user_data) + + priv = NM_DEVICE_GET_PRIVATE (self); + ++ nm_assert (!priv->queued_ip4_config_pending); ++ + /* Wait for any queued state changes */ + if (priv->queued_state.id) + return TRUE; +@@ -9609,7 +9621,11 @@ device_ipx_changed (NMPlatform *platform, + switch (obj_type) { + case NMP_OBJECT_TYPE_IP4_ADDRESS: + case NMP_OBJECT_TYPE_IP4_ROUTE: +- if (!priv->queued_ip4_config_id) { ++ if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) { ++ priv->queued_ip4_config_pending = TRUE; ++ nm_assert_se (!nm_clear_g_source (&priv->queued_ip4_config_id)); ++ } else if (!priv->queued_ip4_config_id) { ++ priv->queued_ip4_config_pending = FALSE; + priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self); + _LOGD (LOGD_DEVICE, "queued IP4 config change"); + } +@@ -9626,7 +9642,11 @@ device_ipx_changed (NMPlatform *platform, + } + /* fallthrough */ + case NMP_OBJECT_TYPE_IP6_ROUTE: +- if (!priv->queued_ip6_config_id) { ++ if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) { ++ priv->queued_ip6_config_pending = TRUE; ++ nm_assert_se (!nm_clear_g_source (&priv->queued_ip6_config_id)); ++ } else if (!priv->queued_ip6_config_id) { ++ priv->queued_ip6_config_pending = FALSE; + priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); + _LOGD (LOGD_DEVICE, "queued IP6 config change"); + } +@@ -9881,6 +9901,18 @@ _set_unmanaged_flags (NMDevice *self, + NM_UNMANAGED_USER_SETTINGS, + !!unmanaged); + } ++ ++ if (priv->queued_ip4_config_pending) { ++ priv->queued_ip4_config_pending = FALSE; ++ nm_assert_se (!nm_clear_g_source (&priv->queued_ip4_config_id)); ++ priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self); ++ } ++ ++ if (priv->queued_ip6_config_pending) { ++ priv->queued_ip6_config_pending = FALSE; ++ nm_assert_se (!nm_clear_g_source (&priv->queued_ip6_config_id)); ++ priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); ++ } + } + + old_flags = priv->unmanaged_flags; +-- +2.9.3 + + +From afc74296f260bd1a590b9c54b54b1170dea2e9ee Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Fri, 28 Oct 2016 17:06:13 +0200 +Subject: [PATCH 15/15] device: suppress log message in + nm_device_update_hw_address() when no MAC address + +For example for tun devices we get a lot of + + (tun7): hw-addr: failed reading current MAC address + +warnings. Just be silent about it. We log when something +changes, we don't need to log when we fail to obtain +a MAC address. + +Thereby, refactor nm_device_update_hw_address() to return early. + +(cherry picked from commit 0e0018c8016156b9a01028f1448e7baf76e14d4a) + +Conflicts: + src/devices/nm-device.c + +(cherry picked from commit 37266b483bcaa89ae169c8e11ea9fbb42ba50d12) +--- + src/devices/nm-device.c | 79 ++++++++++++++++++++++--------------------------- + 1 file changed, 35 insertions(+), 44 deletions(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 119806c..380e663 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -11578,7 +11578,6 @@ nm_device_update_hw_address (NMDevice *self) + NMDevicePrivate *priv; + const guint8 *hwaddr; + gsize hwaddrlen = 0; +- gboolean changed = FALSE; + + priv = NM_DEVICE_GET_PRIVATE (self); + if (priv->ifindex <= 0) +@@ -11591,54 +11590,46 @@ nm_device_update_hw_address (NMDevice *self) + && nm_utils_hwaddr_matches (hwaddr, hwaddrlen, nm_ip_addr_zero.addr_eth, sizeof (nm_ip_addr_zero.addr_eth))) + hwaddrlen = 0; + +- if (hwaddrlen) { +- if ( priv->hw_addr_len +- && priv->hw_addr_len != hwaddrlen) { +- char s_buf[NM_UTILS_HWADDR_LEN_MAX_STR]; ++ if (!hwaddrlen) ++ return FALSE; + +- /* we cannot change the address length of a device once it is set (except +- * unrealizing the device). +- * +- * The reason is that the permanent and initial MAC addresses also must have the +- * same address length, so it's unclear what it would mean that the length changes. */ +- _LOGD (LOGD_PLATFORM | LOGD_DEVICE, +- "hw-addr: read a MAC address with differing length (%s vs. %s)", +- priv->hw_addr, +- nm_utils_hwaddr_ntoa_buf (hwaddr, hwaddrlen, TRUE, s_buf, sizeof (s_buf))); +- return FALSE; +- } ++ if ( priv->hw_addr_len ++ && priv->hw_addr_len != hwaddrlen) { ++ char s_buf[NM_UTILS_HWADDR_LEN_MAX_STR]; + +- if (!priv->hw_addr || !nm_utils_hwaddr_matches (priv->hw_addr, -1, hwaddr, hwaddrlen)) { +- g_free (priv->hw_addr); +- priv->hw_addr_len_ = hwaddrlen; +- priv->hw_addr = nm_utils_hwaddr_ntoa (hwaddr, hwaddrlen); ++ /* we cannot change the address length of a device once it is set (except ++ * unrealizing the device). ++ * ++ * The reason is that the permanent and initial MAC addresses also must have the ++ * same address length, so it's unclear what it would mean that the length changes. */ ++ _LOGD (LOGD_PLATFORM | LOGD_DEVICE, ++ "hw-addr: read a MAC address with differing length (%s vs. %s)", ++ priv->hw_addr, ++ nm_utils_hwaddr_ntoa_buf (hwaddr, hwaddrlen, TRUE, s_buf, sizeof (s_buf))); ++ return FALSE; ++ } + +- _LOGD (LOGD_PLATFORM | LOGD_DEVICE, "hw-addr: hardware address now %s", priv->hw_addr); +- _notify (self, PROP_HW_ADDRESS); ++ if ( priv->hw_addr ++ && nm_utils_hwaddr_matches (priv->hw_addr, -1, hwaddr, hwaddrlen)) ++ return FALSE; + +- if ( !priv->hw_addr_initial +- || ( priv->hw_addr_type == HW_ADDR_TYPE_UNSET +- && priv->state < NM_DEVICE_STATE_PREPARE +- && !nm_device_is_activating (self))) { +- /* when we get a hw_addr the first time or while the device +- * is not activated (with no explict hw address set), always +- * update our inital hw-address as well. */ +- nm_device_update_initial_hw_address (self); +- } +- changed = TRUE; +- } +- } else { +- /* Invalid or no hardware address */ +- if (priv->hw_addr_len != 0) { +- _LOGD (LOGD_PLATFORM | LOGD_DEVICE, +- "hw-addr: failed reading current MAC address (stay with %s)", +- priv->hw_addr); +- } else { +- _LOGD (LOGD_PLATFORM | LOGD_DEVICE, +- "hw-addr: failed reading current MAC address"); +- } ++ g_free (priv->hw_addr); ++ priv->hw_addr_len_ = hwaddrlen; ++ priv->hw_addr = nm_utils_hwaddr_ntoa (hwaddr, hwaddrlen); ++ ++ _LOGD (LOGD_PLATFORM | LOGD_DEVICE, "hw-addr: hardware address now %s", priv->hw_addr); ++ _notify (self, PROP_HW_ADDRESS); ++ ++ if ( !priv->hw_addr_initial ++ || ( priv->hw_addr_type == HW_ADDR_TYPE_UNSET ++ && priv->state < NM_DEVICE_STATE_PREPARE ++ && !nm_device_is_activating (self))) { ++ /* when we get a hw_addr the first time or while the device ++ * is not activated (with no explict hw address set), always ++ * update our inital hw-address as well. */ ++ nm_device_update_initial_hw_address (self); + } +- return changed; ++ return TRUE; + } + + void +-- +2.9.3 + diff --git a/SPECS/NetworkManager.spec b/SPECS/NetworkManager.spec index 118ef3d..c54302e 100644 --- a/SPECS/NetworkManager.spec +++ b/SPECS/NetworkManager.spec @@ -12,7 +12,7 @@ %global rpm_version 1.4.0 %global real_version 1.4.0 -%global release_version 13 +%global release_version 14 %global epoch_version 1 %global obsoletes_nmver 1:0.9.9.95-1 @@ -126,6 +126,7 @@ Patch19: 0019-cli-fix-autocompletion-rh1375933.patch Patch20: 0020-fix-assume-bond-and-infiniband-rh1375558.patch Patch21: 0021-assume-devices-with-slaves-rh1333983.patch Patch22: 0022-no-unmanage-on-quit-rh1371126.patch +Patch23: 0023-udev-initialized-race-rh1388286.patch Requires(post): systemd Requires(preun): systemd @@ -396,6 +397,7 @@ by nm-connection-editor and nm-applet in a non-graphical environment. %patch20 -p1 %patch21 -p1 %patch22 -p1 +%patch23 -p1 %build %if %{with regen_docs} @@ -701,6 +703,9 @@ fi %endif %changelog +* Tue Dec 13 2016 Thomas Haller - 1:1.4.0-14 +- core: avoid race reading permanent MAC address before udev initialized (rh#1388286) + * Wed Nov 2 2016 Thomas Haller - 1:1.4.0-13 - core: don't unmanage devices on shutdown (rh#1371126)