net: delete stale packet_mclist entries
When an interface is deleted from a net namespace the ifindex in the corresponding entries in PF_PACKET sockets' mclists becomes stale. This can create inconsistencies if later an interface with the same ifindex is moved from a different namespace (not that unlikely since ifindexes are per-namespace). In particular we saw problems with dev->promiscuity, resulting in "promiscuity touches roof, set promiscuity failed. promiscuity feature of device might be broken" warnings and EOVERFLOW failures of setsockopt(PACKET_ADD_MEMBERSHIP). This patch deletes the mclist entries for interfaces that are deleted. Since this now causes setsockopt(PACKET_DROP_MEMBERSHIP) to fail with EADDRNOTAVAIL if called after the interface is deleted, also make packet_mc_drop not fail. Signed-off-by: Francesco Ruggeri <fruggeri@arista.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0b2eb3e9bc
commit
82f17091e6
|
@ -3123,11 +3123,18 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void packet_dev_mclist(struct net_device *dev, struct packet_mclist *i, int what)
|
||||
static void packet_dev_mclist_delete(struct net_device *dev,
|
||||
struct packet_mclist **mlp)
|
||||
{
|
||||
for ( ; i; i = i->next) {
|
||||
if (i->ifindex == dev->ifindex)
|
||||
packet_dev_mc(dev, i, what);
|
||||
struct packet_mclist *ml;
|
||||
|
||||
while ((ml = *mlp) != NULL) {
|
||||
if (ml->ifindex == dev->ifindex) {
|
||||
packet_dev_mc(dev, ml, -1);
|
||||
*mlp = ml->next;
|
||||
kfree(ml);
|
||||
} else
|
||||
mlp = &ml->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3204,12 +3211,11 @@ static int packet_mc_drop(struct sock *sk, struct packet_mreq_max *mreq)
|
|||
packet_dev_mc(dev, ml, -1);
|
||||
kfree(ml);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
rtnl_unlock();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
rtnl_unlock();
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
static void packet_flush_mclist(struct sock *sk)
|
||||
|
@ -3559,7 +3565,7 @@ static int packet_notifier(struct notifier_block *this,
|
|||
switch (msg) {
|
||||
case NETDEV_UNREGISTER:
|
||||
if (po->mclist)
|
||||
packet_dev_mclist(dev, po->mclist, -1);
|
||||
packet_dev_mclist_delete(dev, &po->mclist);
|
||||
/* fallthrough */
|
||||
|
||||
case NETDEV_DOWN:
|
||||
|
|
Loading…
Reference in New Issue