Commit 7282ea08 authored by Mathieu Anquetin's avatar Mathieu Anquetin Committed by Benjamin Cabé
Browse files

net: dhcpv4: fix deadlock issue

There is a deadlock issue when calling stop using address conflict
detection. This is due to the fact that some net_mgmt events are fired
and trigger the dhcpv4_acd_event_handler() with lock held even if they
are of no interest for this callback.

Therefore, before acquiring the lock, make sure the event we received
is one we are expecting.

Also, do the same for dhcpv4_iface_event_handler().

Signed-off-by: default avatarMathieu Anquetin <mathieu.anquetin@groupe-cahors.com>
parent 3342ef3f
Loading
Loading
Loading
Loading
+15 −11
Changes for subsys/net/lib/dhcpv4/dhcpv4.c: 15 added lines, 11 removed lines.
Original line number Diff line number Diff line
@@ -1555,6 +1555,11 @@ static void dhcpv4_iface_event_handler(struct net_mgmt_event_callback *cb,
{
	sys_snode_t *node = NULL;

	if (mgmt_event != NET_EVENT_IF_UP &&
	    mgmt_event != NET_EVENT_IF_DOWN) {
		return;
	}

	k_mutex_lock(&lock, K_FOREVER);

	SYS_SLIST_FOR_EACH_NODE(&dhcpv4_ifaces, node) {
@@ -1602,6 +1607,16 @@ static void dhcpv4_acd_event_handler(struct net_mgmt_event_callback *cb,
	sys_snode_t *node = NULL;
	struct in_addr *addr;

	if (mgmt_event != NET_EVENT_IPV4_ACD_FAILED &&
	    mgmt_event != NET_EVENT_IPV4_ACD_CONFLICT) {
		return;
	}

	if (cb->info_length != sizeof(struct in_addr)) {
		return;
	}

	addr = (struct in_addr *)cb->info;

	k_mutex_lock(&lock, K_FOREVER);

@@ -1615,17 +1630,6 @@ static void dhcpv4_acd_event_handler(struct net_mgmt_event_callback *cb,
		goto out;
	}

	if (mgmt_event != NET_EVENT_IPV4_ACD_FAILED &&
	    mgmt_event != NET_EVENT_IPV4_ACD_CONFLICT) {
		goto out;
	}

	if (cb->info_length != sizeof(struct in_addr)) {
		goto out;
	}

	addr = (struct in_addr *)cb->info;

	if (!net_ipv4_addr_cmp(&iface->config.dhcpv4.requested_ip, addr)) {
		goto out;
	}