Skip to contentSkip to conversation

Possible deadlock in ipv6?

DISCUSSION Vladimir Davydov 3 participants 8 messages Jun 6, 2012 – Jun 21, 2012

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

I'm not familiar with the linux net subsystem, so I would appreciate if someone could clarify if the following call chain is possible:

addrconf_ifdown() calls neigh_ifdown(nd_tbl) which locks nd_tbl.lock for writing and calls

    pneigh_ifdown
    pndisc_destructor
    ipv6_dev_mc_dec
    __ipv6_dev_mc_dec
    igmp6_group_dropped
    igmp6_leave_group
    igmp6_send
    icmp6_dst_alloc
    ip6_neigh_lookup
    neigh_create

and neigh_create() locks nd_tbl.lock for writing again resulting in a deadlock.

Thank you.

#1 lore raw
Quoted 17 lines · Vladimir Davydov

I'm not familiar with the linux net subsystem, so I would appreciate if someone could clarify if the following call chain is possible:

addrconf_ifdown() calls neigh_ifdown(nd_tbl) which locks nd_tbl.lock for writing and calls

     pneigh_ifdown
     pndisc_destructor
     ipv6_dev_mc_dec
     __ipv6_dev_mc_dec
     igmp6_group_dropped
     igmp6_leave_group
     igmp6_send
     icmp6_dst_alloc
     ip6_neigh_lookup
     neigh_create
Quoted 2 lines

and neigh_create() locks nd_tbl.lock for writing again resulting in a deadlock.

It seems a deadlock is possible indeed, good catch !

#2 lore raw
Quoted 18 lines · Eric Dumazet
Quoted 17 lines · Vladimir Davydov

I'm not familiar with the linux net subsystem, so I would appreciate if someone could clarify if the following call chain is possible:

addrconf_ifdown() calls neigh_ifdown(nd_tbl) which locks nd_tbl.lock for writing and calls

     pneigh_ifdown
     pndisc_destructor
     ipv6_dev_mc_dec
     __ipv6_dev_mc_dec
     igmp6_group_dropped
     igmp6_leave_group
     igmp6_send
     icmp6_dst_alloc
     ip6_neigh_lookup
     neigh_create
Quoted 6 lines
Quoted 2 lines

and neigh_create() locks nd_tbl.lock for writing again resulting in a deadlock.

It seems a deadlock is possible indeed, good catch !

And it seems this neigh_down() can be removed, its called later (after dev->ip6_ptr is cleared)

net/ipv6/addrconf.c +0 -1
index 8f6411c..62c4c00 100644
@@ -2750,7 +2750,6 @@ static int addrconf_ifdown(struct net_device *dev, int how)
 	ASSERT_RTNL();
 
 	rt6_ifdown(net, dev);
-	neigh_ifdown(&nd_tbl, dev);
 
 	idev = __in6_dev_get(dev);
 	if (idev == NULL)
#3 lore raw
Quoted 22 lines · Eric Dumazet
Quoted 21 lines · Eric Dumazet
Quoted 19 lines · Vladimir Davydov

I'm not familiar with the linux net subsystem, so I would appreciate if someone could clarify if the following call chain is possible:

addrconf_ifdown() calls neigh_ifdown(nd_tbl) which locks nd_tbl.lock for writing and calls

    pneigh_ifdown
    pndisc_destructor
    ipv6_dev_mc_dec
    __ipv6_dev_mc_dec
    igmp6_group_dropped
    igmp6_leave_group
    igmp6_send
    icmp6_dst_alloc
    ip6_neigh_lookup
    neigh_create

and neigh_create() locks nd_tbl.lock for writing again resulting in a deadlock.

Quoted 7 lines
Quoted 3 lines

It seems a deadlock is possible indeed, good catch !

And it seems this neigh_down() can be removed, its called later (after dev->ip6_ptr is cleared)

BTW, commit d1ed113f1669390da9898da3beddcc058d938587 did exactly the same, but it was reverted along with a bundle of other commits by 73a8bd74e2618990dbb218c3d82f53e60acd9af0.

Quoted 14 lines
net/ipv6/addrconf.c +0 -1
index 8f6411c..62c4c00 100644
@@ -2750,7 +2750,6 @@ static int addrconf_ifdown(struct net_device *dev, int how)
 	ASSERT_RTNL();
 
 	rt6_ifdown(net, dev);
-	neigh_ifdown(&nd_tbl, dev);
 
 	idev = __in6_dev_get(dev);
 	if (idev == NULL)
#4 lore raw
Quoted 28 lines · Vladimir Davydov
Quoted 26 lines · Eric Dumazet
Quoted 24 lines · Eric Dumazet
Quoted 17 lines · Vladimir Davydov

I'm not familiar with the linux net subsystem, so I would appreciate if someone could clarify if the following call chain is possible:

addrconf_ifdown() calls neigh_ifdown(nd_tbl) which locks nd_tbl.lock for writing and calls

    pneigh_ifdown
    pndisc_destructor
    ipv6_dev_mc_dec
    __ipv6_dev_mc_dec
    igmp6_group_dropped
    igmp6_leave_group
    igmp6_send
    icmp6_dst_alloc
    ip6_neigh_lookup
    neigh_create
Quoted 2 lines

and neigh_create() locks nd_tbl.lock for writing again resulting in a deadlock.

It seems a deadlock is possible indeed, good catch !

Quoted 5 lines
Quoted 3 lines

And it seems this neigh_down() can be removed, its called later (after dev->ip6_ptr is cleared)

BTW, commit d1ed113f1669390da9898da3beddcc058d938587 did exactly the same, but it was reverted along with a bundle of other commits by 73a8bd74e2618990dbb218c3d82f53e60acd9af0.

Yes, but the revert was a 'revert a serie', while this particular patch seems fine, especially if fixing a deadlock ;)

maintainer
#5 lore raw
In reply to Eric Dumazet

From: Eric Dumazet <[email protected]>
Date: Wed, 06 Jun 2012 17:58:34 +0200

Quoted 2 lines

And it seems this neigh_down() can be removed, its called later (after dev->ip6_ptr is cleared)

It is unclear whether we need to do the the neigh_down() in both the 'how' and '!how' cases. If so then we can't make this change.

#6 lore raw
Quoted 9 lines · David Miller

From: Eric Dumazet <[email protected]>
Date: Wed, 06 Jun 2012 17:58:34 +0200

Quoted 2 lines

And it seems this neigh_down() can be removed, its called later (after dev->ip6_ptr is cleared)

It is unclear whether we need to do the the neigh_down() in both the 'how' and '!how' cases. If so then we can't make this change.

Hmm...

Is it expected we send traffic on device dismantle ?

If no, we could do :

net/core/neighbour.c +0 -2
index d81d026..16e0ddb 100644
@@ -681,8 +681,6 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
 		while ((n = *np) != NULL) {
 			if (!dev || n->dev == dev) {
 				*np = n->next;
-				if (tbl->pdestructor)
-					tbl->pdestructor(n);
 				if (n->dev)
 					dev_put(n->dev);
 				release_net(pneigh_net(n));
maintainer
#7 lore raw

From: Eric Dumazet <[email protected]>
Date: Tue, 12 Jun 2012 11:09:44 +0200

Quoted 1 line

Is it expected we send traffic on device dismantle ?

If we are subscribed to multicast groups we could, to announce our leaving those groups.