diff options
| author | Jiri Benc <jbenc@redhat.com> | 2012-07-26 22:58:22 -0400 |
|---|---|---|
| committer | Luis Henriques <luis.henriques@canonical.com> | 2012-08-13 09:10:38 -0400 |
| commit | e458e003982ad8608e5f1434da444fb87a4890bd (patch) | |
| tree | 7a7ed54002bd9af372bb3b564c0486a6952a0752 /net/core | |
| parent | de7aa474ef77d08e7bf939f8477308905d60a4ba (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.c | 8 |
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 | ||
| 650 | static 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 | |||
| 650 | static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, | 656 | static 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 | } |
