aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorJiri Benc <jbenc@redhat.com>2012-07-26 22:58:22 -0400
committerLuis Henriques <luis.henriques@canonical.com>2012-08-13 09:10:38 -0400
commite458e003982ad8608e5f1434da444fb87a4890bd (patch)
tree7a7ed54002bd9af372bb3b564c0486a6952a0752 /net/core
parentde7aa474ef77d08e7bf939f8477308905d60a4ba (diff)
net: fix rtnetlink IFF_PROMISC and IFF_ALLMULTI handling
BugLink: http://bugs.launchpad.net/bugs/1034988 [ Upstream commit b1beb681cba5358f62e6187340660ade226a5fcc ] 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/rtnetlink.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index abd936d8a71..861d53f5f13 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -647,6 +647,12 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
647 } 647 }
648} 648}
649 649
650static unsigned int rtnl_dev_get_flags(const struct net_device *dev)
651{
652 return (dev->flags & ~(IFF_PROMISC | IFF_ALLMULTI)) |
653 (dev->gflags & (IFF_PROMISC | IFF_ALLMULTI));
654}
655
650static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, 656static unsigned int rtnl_dev_combine_flags(const struct net_device *dev,
651 const struct ifinfomsg *ifm) 657 const struct ifinfomsg *ifm)
652{ 658{
@@ -655,7 +661,7 @@ static unsigned int rtnl_dev_combine_flags(const struct net_device *dev,
655 /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ 661 /* bugwards compatibility: ifi_change == 0 is treated as ~0 */
656 if (ifm->ifi_change) 662 if (ifm->ifi_change)
657 flags = (flags & ifm->ifi_change) | 663 flags = (flags & ifm->ifi_change) |
658 (dev->flags & ~ifm->ifi_change); 664 (rtnl_dev_get_flags(dev) & ~ifm->ifi_change);
659 665
660 return flags; 666 return flags;
661} 667}