diff options
author | Jiri Benc <jbenc@redhat.com> | 2012-07-26 22:58:22 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-27 16:45:50 -0400 |
commit | b1beb681cba5358f62e6187340660ade226a5fcc (patch) | |
tree | 72dfe8df581bee6b804847794fa77af207327aea /net/core | |
parent | e4c7f259c5be99dcfc3d98f913590663b0305bf8 (diff) |
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>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/rtnetlink.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 334b930e0de3..bc9e380f0abf 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -659,6 +659,12 @@ static void set_operstate(struct net_device *dev, unsigned char transition) | |||
659 | } | 659 | } |
660 | } | 660 | } |
661 | 661 | ||
662 | static unsigned int rtnl_dev_get_flags(const struct net_device *dev) | ||
663 | { | ||
664 | return (dev->flags & ~(IFF_PROMISC | IFF_ALLMULTI)) | | ||
665 | (dev->gflags & (IFF_PROMISC | IFF_ALLMULTI)); | ||
666 | } | ||
667 | |||
662 | static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, | 668 | static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, |
663 | const struct ifinfomsg *ifm) | 669 | const struct ifinfomsg *ifm) |
664 | { | 670 | { |
@@ -667,7 +673,7 @@ static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, | |||
667 | /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ | 673 | /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ |
668 | if (ifm->ifi_change) | 674 | if (ifm->ifi_change) |
669 | flags = (flags & ifm->ifi_change) | | 675 | flags = (flags & ifm->ifi_change) | |
670 | (dev->flags & ~ifm->ifi_change); | 676 | (rtnl_dev_get_flags(dev) & ~ifm->ifi_change); |
671 | 677 | ||
672 | return flags; | 678 | return flags; |
673 | } | 679 | } |