From: Yu Watanabe Date: Thu, 1 Jul 2021 05:52:05 +0000 (+0900) Subject: network: fix segfault in link_update_hardware_address() X-Git-Tag: v249-rc3~6^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e2bacccd069c7f8429b84a7d9c44a9710850def1;p=thirdparty%2Fsystemd.git network: fix segfault in link_update_hardware_address() 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. --- diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 4efe74ad412..a939f55731e 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -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"))