1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-24 14:50:17 +03:00

Merge pull request #19631 from yuwata/network-fix-reference-counting-issues

network: fix reference counting issues
This commit is contained in:
Yu Watanabe 2021-05-19 10:29:16 +09:00 committed by GitHub
commit 734b3115d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 157 additions and 139 deletions

View File

@ -1149,6 +1149,9 @@ int request_process_address(Request *req) {
if (r < 0)
return r;
/* To prevent a double decrement on failure in after_configure(). */
req->message_counter = NULL;
if (req->after_configure) {
r = req->after_configure(req, ret);
if (r < 0)

View File

@ -401,121 +401,6 @@ static int link_update_flags(Link *link, sd_netlink_message *m, bool force_updat
return 0;
}
static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
_cleanup_(link_unrefp) Link *link = NULL;
const char *ifname, *kind = NULL;
unsigned short iftype;
int r, ifindex;
uint16_t type;
assert(manager);
assert(message);
assert(ret);
/* check for link kind */
r = sd_netlink_message_enter_container(message, IFLA_LINKINFO);
if (r == 0) {
(void) sd_netlink_message_read_string(message, IFLA_INFO_KIND, &kind);
r = sd_netlink_message_exit_container(message);
if (r < 0)
return r;
}
r = sd_netlink_message_get_type(message, &type);
if (r < 0)
return r;
else if (type != RTM_NEWLINK)
return -EINVAL;
r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
if (r < 0)
return r;
else if (ifindex <= 0)
return -EINVAL;
r = sd_rtnl_message_link_get_type(message, &iftype);
if (r < 0)
return r;
r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname);
if (r < 0)
return r;
link = new(Link, 1);
if (!link)
return -ENOMEM;
*link = (Link) {
.n_ref = 1,
.manager = manager,
.state = LINK_STATE_PENDING,
.ifindex = ifindex,
.iftype = iftype,
.n_dns = UINT_MAX,
.dns_default_route = -1,
.llmnr = _RESOLVE_SUPPORT_INVALID,
.mdns = _RESOLVE_SUPPORT_INVALID,
.dnssec_mode = _DNSSEC_MODE_INVALID,
.dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
};
link->ifname = strdup(ifname);
if (!link->ifname)
return -ENOMEM;
if (kind) {
link->kind = strdup(kind);
if (!link->kind)
return -ENOMEM;
}
r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t *)&link->master_ifindex);
if (r < 0)
log_link_debug_errno(link, r, "New device has no master, continuing without");
r = netlink_message_read_hw_addr(message, IFLA_ADDRESS, &link->hw_addr);
if (r < 0)
log_link_debug_errno(link, r, "Hardware address not found for new device, continuing without");
r = netlink_message_read_hw_addr(message, IFLA_BROADCAST, &link->bcast_addr);
if (r < 0)
log_link_debug_errno(link, r, "Broadcast address not found for new device, continuing without");
r = ethtool_get_permanent_macaddr(&manager->ethtool_fd, link->ifname, &link->permanent_mac);
if (r < 0)
log_link_debug_errno(link, r, "Permanent MAC address not found for new device, continuing without: %m");
r = ethtool_get_driver(&manager->ethtool_fd, link->ifname, &link->driver);
if (r < 0)
log_link_debug_errno(link, r, "Failed to get driver, continuing without: %m");
r = sd_netlink_message_read_strv(message, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &link->alternative_names);
if (r < 0 && r != -ENODATA)
return r;
if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0)
return -ENOMEM;
if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0)
return -ENOMEM;
if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0)
return -ENOMEM;
r = hashmap_ensure_put(&manager->links, NULL, INT_TO_PTR(link->ifindex), link);
if (r < 0)
return r;
r = link_update_flags(link, message, false);
if (r < 0)
return r;
*ret = TAKE_PTR(link);
return 0;
}
void link_ntp_settings_clear(Link *link) {
link->ntp = strv_free(link->ntp);
}
@ -1771,24 +1656,31 @@ static void link_drop_from_master(Link *link, NetDev *netdev) {
link_unref(set_remove(master->slaves, link));
}
static void link_detach_from_manager(Link *link) {
if (!link || !link->manager)
return;
static void link_drop_requests(Link *link) {
Request *req;
link_unref(set_remove(link->manager->links_requesting_uuid, link));
link_clean(link);
assert(link);
assert(link->manager);
/* The following must be called at last. */
assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link);
link_unref(link);
ORDERED_SET_FOREACH(req, link->manager->request_queue)
if (req->link == link)
request_drop(req);
}
static void link_drop(Link *link) {
if (!link || link->state == LINK_STATE_LINGER)
return;
static Link *link_drop(Link *link) {
if (!link)
return NULL;
assert(link->manager);
link_set_state(link, LINK_STATE_LINGER);
/* Drop all references from other links and manager. Note that async netlink calls may have
* references to the link, and they will be dropped when we receive replies. */
link_drop_requests(link);
link_free_carrier_maps(link);
if (link->network) {
@ -1797,10 +1689,14 @@ static void link_drop(Link *link) {
link_drop_from_master(link, link->network->bond);
}
log_link_debug(link, "Link removed");
link_unref(set_remove(link->manager->links_requesting_uuid, link));
(void) unlink(link->state_file);
link_detach_from_manager(link);
link_clean(link);
/* The following must be called at last. */
assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link);
return link_unref(link);
}
int link_activate(Link *link) {
@ -2101,17 +1997,6 @@ static int link_drop_config(Link *link) {
return r;
}
static void link_drop_requests(Link *link) {
Request *req;
assert(link);
assert(link->manager);
ORDERED_SET_FOREACH(req, link->manager->request_queue)
if (req->link == link)
request_drop(req);
}
int link_configure(Link *link) {
int r;
@ -2524,6 +2409,124 @@ static int link_initialized(Link *link, sd_device *device) {
return 0;
}
static Link *link_drop_or_unref(Link *link) {
if (!link)
return NULL;
if (!link->manager)
return link_unref(link);
return link_drop(link);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_drop_or_unref);
static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
_cleanup_(link_drop_or_unrefp) Link *link = NULL;
_cleanup_free_ char *ifname = NULL, *kind = NULL;
unsigned short iftype;
int r, ifindex;
uint16_t type;
assert(manager);
assert(message);
assert(ret);
r = sd_netlink_message_get_type(message, &type);
if (r < 0)
return r;
else if (type != RTM_NEWLINK)
return -EINVAL;
r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
if (r < 0)
return r;
else if (ifindex <= 0)
return -EINVAL;
r = sd_rtnl_message_link_get_type(message, &iftype);
if (r < 0)
return r;
r = sd_netlink_message_read_string_strdup(message, IFLA_IFNAME, &ifname);
if (r < 0)
return r;
/* check for link kind */
r = sd_netlink_message_enter_container(message, IFLA_LINKINFO);
if (r >= 0) {
(void) sd_netlink_message_read_string_strdup(message, IFLA_INFO_KIND, &kind);
r = sd_netlink_message_exit_container(message);
if (r < 0)
return r;
}
link = new(Link, 1);
if (!link)
return -ENOMEM;
*link = (Link) {
.n_ref = 1,
.state = LINK_STATE_PENDING,
.ifindex = ifindex,
.iftype = iftype,
.ifname = TAKE_PTR(ifname),
.kind = TAKE_PTR(kind),
.n_dns = UINT_MAX,
.dns_default_route = -1,
.llmnr = _RESOLVE_SUPPORT_INVALID,
.mdns = _RESOLVE_SUPPORT_INVALID,
.dnssec_mode = _DNSSEC_MODE_INVALID,
.dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
};
r = hashmap_ensure_put(&manager->links, NULL, INT_TO_PTR(link->ifindex), link);
if (r < 0)
return r;
link->manager = manager;
r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t*) &link->master_ifindex);
if (r < 0)
log_link_debug_errno(link, r, "New device has no master, continuing without");
r = netlink_message_read_hw_addr(message, IFLA_ADDRESS, &link->hw_addr);
if (r < 0)
log_link_debug_errno(link, r, "Hardware address not found for new device, continuing without");
r = netlink_message_read_hw_addr(message, IFLA_BROADCAST, &link->bcast_addr);
if (r < 0)
log_link_debug_errno(link, r, "Broadcast address not found for new device, continuing without");
r = ethtool_get_permanent_macaddr(&manager->ethtool_fd, link->ifname, &link->permanent_mac);
if (r < 0)
log_link_debug_errno(link, r, "Permanent MAC address not found for new device, continuing without: %m");
r = ethtool_get_driver(&manager->ethtool_fd, link->ifname, &link->driver);
if (r < 0)
log_link_debug_errno(link, r, "Failed to get driver, continuing without: %m");
r = sd_netlink_message_read_strv(message, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &link->alternative_names);
if (r < 0 && r != -ENODATA)
return r;
if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0)
return -ENOMEM;
if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0)
return -ENOMEM;
if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0)
return -ENOMEM;
r = link_update_flags(link, message, false);
if (r < 0)
return r;
*ret = TAKE_PTR(link);
return 0;
}
static int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
char ifindex_str[2 + DECIMAL_STR_MAX(int)];

View File

@ -479,6 +479,9 @@ int request_process_neighbor(Request *req) {
if (r < 0)
return r;
/* To prevent a double decrement on failure in after_configure(). */
req->message_counter = NULL;
if (req->after_configure) {
r = req->after_configure(req, ret);
if (r < 0)

View File

@ -751,6 +751,9 @@ int request_process_nexthop(Request *req) {
if (r < 0)
return r;
/* To prevent a double decrement on failure in after_configure(). */
req->message_counter = NULL;
if (req->after_configure) {
r = req->after_configure(req, ret);
if (r < 0)

View File

@ -1622,6 +1622,9 @@ int request_process_route(Request *req) {
if (r < 0)
return r;
/* To prevent a double decrement on failure in after_configure(). */
req->message_counter = NULL;
if (req->after_configure) {
assert(n_routes > 0);

View File

@ -814,6 +814,9 @@ int request_process_routing_policy_rule(Request *req) {
if (r < 0)
return r;
/* To prevent a double decrement on failure in after_configure(). */
req->message_counter = NULL;
if (req->after_configure) {
r = req->after_configure(req, ret);
if (r < 0)