diff options
author | Alexei Starovoitov <ast@plumgrid.com> | 2013-10-23 19:02:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-25 19:03:45 -0400 |
commit | 7f29405403d7c17f539c099987972b862e7e5255 (patch) | |
tree | 22c5a8a78b275b6da6bbc5f31fa3273b441d85ab /net/core/rtnetlink.c | |
parent | 66415cf8a1b99d101317f5aa08574b1ec8832672 (diff) |
net: fix rtnl notification in atomic context
commit 991fb3f74c "dev: always advertise rx_flags changes via netlink"
introduced rtnl notification from __dev_set_promiscuity(),
which can be called in atomic context.
Steps to reproduce:
ip tuntap add dev tap1 mode tap
ifconfig tap1 up
tcpdump -nei tap1 &
ip tuntap del dev tap1 mode tap
[ 271.627994] device tap1 left promiscuous mode
[ 271.639897] BUG: sleeping function called from invalid context at mm/slub.c:940
[ 271.664491] in_atomic(): 1, irqs_disabled(): 0, pid: 3394, name: ip
[ 271.677525] INFO: lockdep is turned off.
[ 271.690503] CPU: 0 PID: 3394 Comm: ip Tainted: G W 3.12.0-rc3+ #73
[ 271.703996] Hardware name: System manufacturer System Product Name/P8Z77 WS, BIOS 3007 07/26/2012
[ 271.731254] ffffffff81a58506 ffff8807f0d57a58 ffffffff817544e5 ffff88082fa0f428
[ 271.760261] ffff8808071f5f40 ffff8807f0d57a88 ffffffff8108bad1 ffffffff81110ff8
[ 271.790683] 0000000000000010 00000000000000d0 00000000000000d0 ffff8807f0d57af8
[ 271.822332] Call Trace:
[ 271.838234] [<ffffffff817544e5>] dump_stack+0x55/0x76
[ 271.854446] [<ffffffff8108bad1>] __might_sleep+0x181/0x240
[ 271.870836] [<ffffffff81110ff8>] ? rcu_irq_exit+0x68/0xb0
[ 271.887076] [<ffffffff811a80be>] kmem_cache_alloc_node+0x4e/0x2a0
[ 271.903368] [<ffffffff810b4ddc>] ? vprintk_emit+0x1dc/0x5a0
[ 271.919716] [<ffffffff81614d67>] ? __alloc_skb+0x57/0x2a0
[ 271.936088] [<ffffffff810b4de0>] ? vprintk_emit+0x1e0/0x5a0
[ 271.952504] [<ffffffff81614d67>] __alloc_skb+0x57/0x2a0
[ 271.968902] [<ffffffff8163a0b2>] rtmsg_ifinfo+0x52/0x100
[ 271.985302] [<ffffffff8162ac6d>] __dev_notify_flags+0xad/0xc0
[ 272.001642] [<ffffffff8162ad0c>] __dev_set_promiscuity+0x8c/0x1c0
[ 272.017917] [<ffffffff81731ea5>] ? packet_notifier+0x5/0x380
[ 272.033961] [<ffffffff8162b109>] dev_set_promiscuity+0x29/0x50
[ 272.049855] [<ffffffff8172e937>] packet_dev_mc+0x87/0xc0
[ 272.065494] [<ffffffff81732052>] packet_notifier+0x1b2/0x380
[ 272.080915] [<ffffffff81731ea5>] ? packet_notifier+0x5/0x380
[ 272.096009] [<ffffffff81761c66>] notifier_call_chain+0x66/0x150
[ 272.110803] [<ffffffff8108503e>] __raw_notifier_call_chain+0xe/0x10
[ 272.125468] [<ffffffff81085056>] raw_notifier_call_chain+0x16/0x20
[ 272.139984] [<ffffffff81620190>] call_netdevice_notifiers_info+0x40/0x70
[ 272.154523] [<ffffffff816201d6>] call_netdevice_notifiers+0x16/0x20
[ 272.168552] [<ffffffff816224c5>] rollback_registered_many+0x145/0x240
[ 272.182263] [<ffffffff81622641>] rollback_registered+0x31/0x40
[ 272.195369] [<ffffffff816229c8>] unregister_netdevice_queue+0x58/0x90
[ 272.208230] [<ffffffff81547ca0>] __tun_detach+0x140/0x340
[ 272.220686] [<ffffffff81547ed6>] tun_chr_close+0x36/0x60
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 4aedf03da052..cf67144d3e3c 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1984,14 +1984,15 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) | |||
1984 | return skb->len; | 1984 | return skb->len; |
1985 | } | 1985 | } |
1986 | 1986 | ||
1987 | void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change) | 1987 | void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change, |
1988 | gfp_t flags) | ||
1988 | { | 1989 | { |
1989 | struct net *net = dev_net(dev); | 1990 | struct net *net = dev_net(dev); |
1990 | struct sk_buff *skb; | 1991 | struct sk_buff *skb; |
1991 | int err = -ENOBUFS; | 1992 | int err = -ENOBUFS; |
1992 | size_t if_info_size; | 1993 | size_t if_info_size; |
1993 | 1994 | ||
1994 | skb = nlmsg_new((if_info_size = if_nlmsg_size(dev, 0)), GFP_KERNEL); | 1995 | skb = nlmsg_new((if_info_size = if_nlmsg_size(dev, 0)), flags); |
1995 | if (skb == NULL) | 1996 | if (skb == NULL) |
1996 | goto errout; | 1997 | goto errout; |
1997 | 1998 | ||
@@ -2002,7 +2003,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change) | |||
2002 | kfree_skb(skb); | 2003 | kfree_skb(skb); |
2003 | goto errout; | 2004 | goto errout; |
2004 | } | 2005 | } |
2005 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); | 2006 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, flags); |
2006 | return; | 2007 | return; |
2007 | errout: | 2008 | errout: |
2008 | if (err < 0) | 2009 | if (err < 0) |
@@ -2716,7 +2717,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi | |||
2716 | case NETDEV_JOIN: | 2717 | case NETDEV_JOIN: |
2717 | break; | 2718 | break; |
2718 | default: | 2719 | default: |
2719 | rtmsg_ifinfo(RTM_NEWLINK, dev, 0); | 2720 | rtmsg_ifinfo(RTM_NEWLINK, dev, 0, GFP_KERNEL); |
2720 | break; | 2721 | break; |
2721 | } | 2722 | } |
2722 | return NOTIFY_DONE; | 2723 | return NOTIFY_DONE; |