From b90e5794c5bdef91d26c623e992257947c506e35 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 28 Nov 2011 11:16:50 +0000 Subject: net: dont call jump_label_dec from irq context Igor Maravic reported an error caused by jump_label_dec() being called from IRQ context : BUG: sleeping function called from invalid context at kernel/mutex.c:271 in_atomic(): 1, irqs_disabled(): 0, pid: 0, name: swapper 1 lock held by swapper/0: #0: (&n->timer){+.-...}, at: [] call_timer_fn+0x0/0x340 Pid: 0, comm: swapper Not tainted 3.2.0-rc2-net-next-mpls+ #1 Call Trace: [] __might_sleep+0x137/0x1f0 [] mutex_lock_nested+0x2f/0x370 [] ? trace_hardirqs_off+0xd/0x10 [] ? local_clock+0x6f/0x80 [] ? lock_release_holdtime.part.22+0x15/0x1a0 [] ? sock_def_write_space+0x59/0x160 [] ? arp_error_report+0x3e/0x90 [] atomic_dec_and_mutex_lock+0x5d/0x80 [] jump_label_dec+0x1d/0x50 [] net_disable_timestamp+0x15/0x20 [] sock_disable_timestamp+0x45/0x50 [] __sk_free+0x80/0x200 [] ? sk_send_sigurg+0x70/0x70 [] ? arp_error_report+0x3e/0x90 [] sock_wfree+0x3a/0x70 [] skb_release_head_state+0x70/0x120 [] __kfree_skb+0x16/0x30 [] kfree_skb+0x49/0x170 [] arp_error_report+0x3e/0x90 [] neigh_invalidate+0x89/0xc0 [] neigh_timer_handler+0x9e/0x2a0 [] ? neigh_update+0x640/0x640 [] __do_softirq+0xc8/0x3a0 Since jump_label_{inc|dec} must be called from process context only, we must defer jump_label_dec() if net_disable_timestamp() is called from interrupt context. Reported-by: Igor Maravic Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv6/netfilter/ip6_queue.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/ipv6/netfilter') diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index e63c3972a739..fb80a23c6640 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -405,6 +405,7 @@ __ipq_rcv_skb(struct sk_buff *skb) int status, type, pid, flags; unsigned int nlmsglen, skblen; struct nlmsghdr *nlh; + bool enable_timestamp = false; skblen = skb->len; if (skblen < sizeof(*nlh)) @@ -442,11 +443,13 @@ __ipq_rcv_skb(struct sk_buff *skb) RCV_SKB_FAIL(-EBUSY); } } else { - net_enable_timestamp(); + enable_timestamp = true; peer_pid = pid; } spin_unlock_bh(&queue_lock); + if (enable_timestamp) + net_enable_timestamp(); status = ipq_receive_peer(NLMSG_DATA(nlh), type, nlmsglen - NLMSG_LENGTH(0)); -- cgit v1.2.3-55-g7522