net: fix rtnetlink IFF_PROMISC and IFF_ALLMULTI handling
When device flags are set using rtnetlink, IFF_PROMISC and IFF_ALLMULTI flags are handled specially. Function dev_change_flags sets IFF_PROMISC and IFF_ALLMULTI bits in dev->gflags according to the passed value but do_setlink passes a result of rtnl_dev_combine_flags which takes those bits from dev->flags. This can be easily trigerred by doing: tcpdump -i eth0 & ip l s up eth0 ip sets IFF_UP flag in ifi_flags and ifi_change, which is combined with IFF_PROMISC by rtnl_dev_combine_flags, causing __dev_change_flags to set IFF_PROMISC in gflags. Reported-by: Max Matveev <makc@redhat.com> Signed-off-by: Jiri Benc <jbenc@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e4c7f259c5
commit
b1beb681cb
@ -659,6 +659,12 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int rtnl_dev_get_flags(const struct net_device *dev)
|
||||||
|
{
|
||||||
|
return (dev->flags & ~(IFF_PROMISC | IFF_ALLMULTI)) |
|
||||||
|
(dev->gflags & (IFF_PROMISC | IFF_ALLMULTI));
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int rtnl_dev_combine_flags(const struct net_device *dev,
|
static unsigned int rtnl_dev_combine_flags(const struct net_device *dev,
|
||||||
const struct ifinfomsg *ifm)
|
const struct ifinfomsg *ifm)
|
||||||
{
|
{
|
||||||
@ -667,7 +673,7 @@ static unsigned int rtnl_dev_combine_flags(const struct net_device *dev,
|
|||||||
/* bugwards compatibility: ifi_change == 0 is treated as ~0 */
|
/* bugwards compatibility: ifi_change == 0 is treated as ~0 */
|
||||||
if (ifm->ifi_change)
|
if (ifm->ifi_change)
|
||||||
flags = (flags & ifm->ifi_change) |
|
flags = (flags & ifm->ifi_change) |
|
||||||
(dev->flags & ~ifm->ifi_change);
|
(rtnl_dev_get_flags(dev) & ~ifm->ifi_change);
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user