From: Joe Stringer Date: Fri, 22 Jan 2016 23:49:12 +0000 (-0800) Subject: inet: frag: Always orphan skbs inside ip_defrag() X-Git-Tag: v4.4.14-KARO~1377 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=649dc6c32e516972128502ad6a45a16b96098567;p=karo-tx-linux.git inet: frag: Always orphan skbs inside ip_defrag() [ Upstream commit 8282f27449bf15548cb82c77b6e04ee0ab827bdc ] Later parts of the stack (including fragmentation) expect that there is never a socket attached to frag in a frag_list, however this invariant was not enforced on all defrag paths. This could lead to the BUG_ON(skb->sk) during ip_do_fragment(), as per the call stack at the end of this commit message. While the call could be added to openvswitch to fix this particular error, the head and tail of the frags list are already orphaned indirectly inside ip_defrag(), so it seems like the remaining fragments should all be orphaned in all circumstances. kernel BUG at net/ipv4/ip_output.c:586! [...] Call Trace: [] ? do_output.isra.29+0x1b0/0x1b0 [openvswitch] [] ovs_fragment+0xcc/0x214 [openvswitch] [] ? dst_discard_out+0x20/0x20 [] ? dst_ifdown+0x80/0x80 [] ? find_bucket.isra.2+0x62/0x70 [openvswitch] [] ? mod_timer_pending+0x65/0x210 [] ? __lock_acquire+0x3db/0x1b90 [] ? nf_conntrack_in+0x252/0x500 [nf_conntrack] [] ? __lock_is_held+0x54/0x70 [] do_output.isra.29+0xe3/0x1b0 [openvswitch] [] do_execute_actions+0xe11/0x11f0 [openvswitch] [] ? __lock_is_held+0x54/0x70 [] ovs_execute_actions+0x32/0xd0 [openvswitch] [] ovs_dp_process_packet+0x85/0x140 [openvswitch] [] ? __lock_is_held+0x54/0x70 [] ovs_execute_actions+0xb2/0xd0 [openvswitch] [] ovs_dp_process_packet+0x85/0x140 [openvswitch] [] ? ovs_ct_get_labels+0x49/0x80 [openvswitch] [] ovs_vport_receive+0x5d/0xa0 [openvswitch] [] ? __lock_acquire+0x3db/0x1b90 [] ? __lock_acquire+0x3db/0x1b90 [] ? __lock_acquire+0x3db/0x1b90 [] ? internal_dev_xmit+0x5/0x140 [openvswitch] [] internal_dev_xmit+0x6c/0x140 [openvswitch] [] ? internal_dev_xmit+0x5/0x140 [openvswitch] [] dev_hard_start_xmit+0x2b9/0x5e0 [] ? netif_skb_features+0xd1/0x1f0 [] __dev_queue_xmit+0x800/0x930 [] ? __dev_queue_xmit+0x50/0x930 [] ? mark_held_locks+0x71/0x90 [] ? neigh_resolve_output+0x106/0x220 [] dev_queue_xmit+0x10/0x20 [] neigh_resolve_output+0x178/0x220 [] ? ip_finish_output2+0x1ff/0x590 [] ip_finish_output2+0x1ff/0x590 [] ? ip_finish_output2+0x7e/0x590 [] ip_do_fragment+0x831/0x8a0 [] ? ip_copy_metadata+0x1b0/0x1b0 [] ip_fragment.constprop.49+0x43/0x80 [] ip_finish_output+0x17c/0x340 [] ? nf_hook_slow+0xe4/0x190 [] ip_output+0x70/0x110 [] ? ip_fragment.constprop.49+0x80/0x80 [] ip_local_out+0x39/0x70 [] ip_send_skb+0x19/0x40 [] ip_push_pending_frames+0x33/0x40 [] icmp_push_reply+0xea/0x120 [] icmp_reply.constprop.23+0x1ed/0x230 [] icmp_echo.part.21+0x4e/0x50 [] ? __lock_is_held+0x54/0x70 [] ? rcu_read_lock_held+0x5e/0x70 [] icmp_echo+0x36/0x70 [] icmp_rcv+0x271/0x450 [] ip_local_deliver_finish+0x127/0x3a0 [] ? ip_local_deliver_finish+0x41/0x3a0 [] ip_local_deliver+0x60/0xd0 [] ? ip_rcv_finish+0x560/0x560 [] ip_rcv_finish+0xdd/0x560 [] ip_rcv+0x283/0x3e0 [] ? match_held_lock+0x192/0x200 [] ? inet_del_offload+0x40/0x40 [] __netif_receive_skb_core+0x392/0xae0 [] ? process_backlog+0x8e/0x230 [] ? mark_held_locks+0x71/0x90 [] __netif_receive_skb+0x18/0x60 [] process_backlog+0x78/0x230 [] ? process_backlog+0xdd/0x230 [] net_rx_action+0x155/0x400 [] __do_softirq+0xcc/0x420 [] ? ip_finish_output2+0x217/0x590 [] do_softirq_own_stack+0x1c/0x30 [] do_softirq+0x4e/0x60 [] __local_bh_enable_ip+0xa8/0xb0 [] ip_finish_output2+0x240/0x590 [] ? ip_do_fragment+0x831/0x8a0 [] ip_do_fragment+0x831/0x8a0 [] ? ip_copy_metadata+0x1b0/0x1b0 [] ip_fragment.constprop.49+0x43/0x80 [] ip_finish_output+0x17c/0x340 [] ? nf_hook_slow+0xe4/0x190 [] ip_output+0x70/0x110 [] ? ip_fragment.constprop.49+0x80/0x80 [] ip_local_out+0x39/0x70 [] ip_send_skb+0x19/0x40 [] ip_push_pending_frames+0x33/0x40 [] raw_sendmsg+0x7d3/0xc30 [] ? __lock_acquire+0x3db/0x1b90 [] ? inet_sendmsg+0xc7/0x1d0 [] ? __lock_is_held+0x54/0x70 [] inet_sendmsg+0x10a/0x1d0 [] ? inet_sendmsg+0x5/0x1d0 [] sock_sendmsg+0x38/0x50 [] ___sys_sendmsg+0x25f/0x270 [] ? handle_mm_fault+0x8dd/0x1320 [] ? _raw_spin_unlock+0x27/0x40 [] ? __do_page_fault+0x1e2/0x460 [] ? __fget_light+0x66/0x90 [] __sys_sendmsg+0x42/0x80 [] SyS_sendmsg+0x12/0x20 [] entry_SYSCALL_64_fastpath+0x12/0x6f Code: 00 00 44 89 e0 e9 7c fb ff ff 4c 89 ff e8 e7 e7 ff ff 41 8b 9d 80 00 00 00 2b 5d d4 89 d8 c1 f8 03 0f b7 c0 e9 33 ff ff f 66 66 66 2e 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 RIP [] ip_do_fragment+0x892/0x8a0 RSP Fixes: 7f8a436eaa2c ("openvswitch: Add conntrack action") Signed-off-by: Joe Stringer Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 1fe55ae81781..b8a0607dab96 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -661,6 +661,7 @@ int ip_defrag(struct net *net, struct sk_buff *skb, u32 user) struct ipq *qp; IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); + skb_orphan(skb); /* Lookup (or create) queue header */ qp = ip_find(net, ip_hdr(skb), user, vif); diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index 6fb869f646bf..a04dee536b8e 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c @@ -27,8 +27,6 @@ static int nf_ct_ipv4_gather_frags(struct net *net, struct sk_buff *skb, { int err; - skb_orphan(skb); - local_bh_disable(); err = ip_defrag(net, skb, user); local_bh_enable();