]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: fix segfault in link_update_hardware_address() 20083/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 1 Jul 2021 05:52:05 +0000 (14:52 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 1 Jul 2021 07:24:07 +0000 (16:24 +0900)
This fixes a bug introduced by fe321d457c118be5d1640b586135a69d1db9270a.

When we want to update a value (in the case of this commit, it is a hardware
address) which is used as a hashmap key, we need to do the following steps:
1. remove the old hashmap entry,
2. update the value,
3. create a new hashmap entry with the new value.

src/network/networkd-link.c

index 4efe74ad4121631cd605d70b18c003d17d2e4463..a939f55731e1a636c3b9d45ca7ff739a788ead74 100644 (file)
@@ -1998,7 +1998,7 @@ static int link_update_master(Link *link, sd_netlink_message *message) {
 }
 
 static int link_update_hardware_address(Link *link, sd_netlink_message *message) {
-        struct hw_addr_data old;
+        struct hw_addr_data addr;
         int r;
 
         assert(link);
@@ -2008,26 +2008,27 @@ static int link_update_hardware_address(Link *link, sd_netlink_message *message)
         if (r < 0 && r != -ENODATA)
                 return log_link_debug_errno(link, r, "rtnl: failed to read broadcast address: %m");
 
-        old = link->hw_addr;
-        r = netlink_message_read_hw_addr(message, IFLA_ADDRESS, &link->hw_addr);
+        r = netlink_message_read_hw_addr(message, IFLA_ADDRESS, &addr);
         if (r == -ENODATA)
                 return 0;
         if (r < 0)
                 return log_link_debug_errno(link, r, "rtnl: failed to read hardware address: %m");
 
-        if (hw_addr_equal(&link->hw_addr, &old))
+        if (hw_addr_equal(&link->hw_addr, &addr))
                 return 0;
 
-        if (hw_addr_is_null(&old))
-                log_link_debug(link, "Saved hardware address: %s", HW_ADDR_TO_STR(&link->hw_addr));
+        if (hw_addr_is_null(&link->hw_addr))
+                log_link_debug(link, "Saved hardware address: %s", HW_ADDR_TO_STR(&addr));
         else {
                 log_link_debug(link, "Hardware address is changed: %s → %s",
-                               HW_ADDR_TO_STR(&old), HW_ADDR_TO_STR(&link->hw_addr));
+                               HW_ADDR_TO_STR(&link->hw_addr), HW_ADDR_TO_STR(&addr));
 
-                if (hashmap_get(link->manager->links_by_hw_addr, &old) == link)
-                        hashmap_remove(link->manager->links_by_hw_addr, &old);
+                if (hashmap_get(link->manager->links_by_hw_addr, &link->hw_addr) == link)
+                        hashmap_remove(link->manager->links_by_hw_addr, &link->hw_addr);
         }
 
+        link->hw_addr = addr;
+
         if (!hw_addr_is_null(&link->hw_addr)) {
                 r = hashmap_ensure_put(&link->manager->links_by_hw_addr, &hw_addr_hash_ops, &link->hw_addr, link);
                 if (r == -EEXIST && streq_ptr(link->kind, "bond"))