netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net] ip: frags: fix crash in ip_do_fragment()
@ 2018-09-06 17:50 Taehee Yoo
  2018-09-06 18:06 ` Eric Dumazet
  0 siblings, 1 reply; 4+ messages in thread
From: Taehee Yoo @ 2018-09-06 17:50 UTC (permalink / raw)
  To: davem, posk, netdev; +Cc: ap420073, pablo, fw, edumazet

A kernel crash occurrs when defragmented packet is fragmented
in ip_do_fragment().
In defragment routine, skb_orphan() is called and
skb->ip_defrag_offset is set. but skb->sk and
skb->ip_defrag_offset are same union member. so that
frag->sk is not NULL.
Hence crash occurrs in skb->sk check routine in ip_do_fragment() when
defragmented packet is fragmented.

test commands:
   %iptables -t nat -I POSTROUTING -j MASQUERADE
   %hping3 192.168.4.2 -s 1000 -p 2000 -d 60000

splat looks like:
[  261.069429] kernel BUG at net/ipv4/ip_output.c:636!
[  261.075753] invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN PTI
[  261.083854] CPU: 1 PID: 1349 Comm: hping3 Not tainted 4.19.0-rc2+ #3
[  261.100977] RIP: 0010:ip_do_fragment+0x1613/0x2600
[  261.106945] Code: e8 e2 38 e3 fe 4c 8b 44 24 18 48 8b 74 24 08 e9 92 f6 ff ff 80 3c 02 00 0f 85 da 07 00 00 48 8b b5 d0 00 00 00 e9 25 f6 ff ff <0f> 0b 0f 0b 44 8b 54 24 58 4c 8b 4c 24 18 4c 8b 5c 24 60 4c 8b 6c
[  261.127015] RSP: 0018:ffff8801031cf2c0 EFLAGS: 00010202
[  261.134156] RAX: 1ffff1002297537b RBX: ffffed0020639e6e RCX: 0000000000000004
[  261.142156] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff880114ba9bd8
[  261.150157] RBP: ffff880114ba8a40 R08: ffffed0022975395 R09: ffffed0022975395
[  261.158157] R10: 0000000000000001 R11: ffffed0022975394 R12: ffff880114ba9ca4
[  261.166159] R13: 0000000000000010 R14: ffff880114ba9bc0 R15: dffffc0000000000
[  261.174169] FS:  00007fbae2199700(0000) GS:ffff88011b400000(0000) knlGS:0000000000000000
[  261.183012] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  261.189013] CR2: 00005579244fe000 CR3: 0000000119bf4000 CR4: 00000000001006e0
[  261.198158] Call Trace:
[  261.199018]  ? dst_output+0x180/0x180
[  261.205011]  ? save_trace+0x300/0x300
[  261.209018]  ? ip_copy_metadata+0xb00/0xb00
[  261.213034]  ? sched_clock_local+0xd4/0x140
[  261.218158]  ? kill_l4proto+0x120/0x120 [nf_conntrack]
[  261.223014]  ? rt_cpu_seq_stop+0x10/0x10
[  261.227014]  ? find_held_lock+0x39/0x1c0
[  261.233008]  ip_finish_output+0x51d/0xb50
[  261.237006]  ? ip_fragment.constprop.56+0x220/0x220
[  261.243011]  ? nf_ct_l4proto_register_one+0x5b0/0x5b0 [nf_conntrack]
[  261.250152]  ? rcu_is_watching+0x77/0x120
[  261.255010]  ? nf_nat_ipv4_out+0x1e/0x2b0 [nf_nat_ipv4]
[  261.261033]  ? nf_hook_slow+0xb1/0x160
[  261.265007]  ip_output+0x1c7/0x710
[  261.269005]  ? ip_mc_output+0x13f0/0x13f0
[  261.273002]  ? __local_bh_enable_ip+0xe9/0x1b0
[  261.278152]  ? ip_fragment.constprop.56+0x220/0x220
[  261.282996]  ? nf_hook_slow+0xb1/0x160
[  261.287007]  raw_sendmsg+0x21f9/0x4420
[  261.291008]  ? dst_output+0x180/0x180
[  261.297003]  ? sched_clock_cpu+0x126/0x170
[  261.301003]  ? find_held_lock+0x39/0x1c0
[  261.306155]  ? stop_critical_timings+0x420/0x420
[  261.311004]  ? check_flags.part.36+0x450/0x450
[  261.315005]  ? _raw_spin_unlock_irq+0x29/0x40
[  261.320995]  ? _raw_spin_unlock_irq+0x29/0x40
[  261.326142]  ? cyc2ns_read_end+0x10/0x10
[  261.330139]  ? raw_bind+0x280/0x280
[  261.334138]  ? sched_clock_cpu+0x126/0x170
[  261.338995]  ? check_flags.part.36+0x450/0x450
[  261.342991]  ? __lock_acquire+0x4500/0x4500
[  261.348994]  ? inet_sendmsg+0x11c/0x500
[  261.352989]  ? dst_output+0x180/0x180
[  261.357012]  inet_sendmsg+0x11c/0x500
[ ... ]

Fixes: fa0f527358bd ("ip: use rb trees for IP frag queue.")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
 include/linux/skbuff.h | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 17a13e4785fc..2eb115be5bf6 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -676,16 +676,13 @@ struct sk_buff {
 				 * UDP receive path is one user.
 				 */
 				unsigned long		dev_scratch;
+				int			ip_defrag_offset;
 			};
 		};
 		struct rb_node		rbnode; /* used in netem, ip4 defrag, and tcp stack */
 		struct list_head	list;
 	};
-
-	union {
-		struct sock		*sk;
-		int			ip_defrag_offset;
-	};
+	struct sock		*sk;
 
 	union {
 		ktime_t		tstamp;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH net] ip: frags: fix crash in ip_do_fragment()
  2018-09-06 17:50 [PATCH net] ip: frags: fix crash in ip_do_fragment() Taehee Yoo
@ 2018-09-06 18:06 ` Eric Dumazet
  2018-09-06 18:23   ` Eric Dumazet
  0 siblings, 1 reply; 4+ messages in thread
From: Eric Dumazet @ 2018-09-06 18:06 UTC (permalink / raw)
  To: ap420073
  Cc: David Miller, Peter Oskolkov, netdev, Pablo Neira Ayuso,
	Florian Westphal

On Thu, Sep 6, 2018 at 10:51 AM Taehee Yoo <ap420073@gmail.com> wrote:
>
> A kernel crash occurrs when defragmented packet is fragmented
> in ip_do_fragment().
> In defragment routine, skb_orphan() is called and
> skb->ip_defrag_offset is set. but skb->sk and
> skb->ip_defrag_offset are same union member. so that
> frag->sk is not NULL.
> Hence crash occurrs in skb->sk check routine in ip_do_fragment() when
> defragmented packet is fragmented.

Have you tested this patch ?

Moving back ip_defrag_offset is conflicting with the rbnode !

A more correct fix would be to properly clear skb->sk at reassembly.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH net] ip: frags: fix crash in ip_do_fragment()
  2018-09-06 18:06 ` Eric Dumazet
@ 2018-09-06 18:23   ` Eric Dumazet
  2018-09-06 18:48     ` Taehee Yoo
  0 siblings, 1 reply; 4+ messages in thread
From: Eric Dumazet @ 2018-09-06 18:23 UTC (permalink / raw)
  To: ap420073
  Cc: David Miller, Peter Oskolkov, netdev, Pablo Neira Ayuso,
	Florian Westphal

On Thu, Sep 6, 2018 at 11:06 AM Eric Dumazet <edumazet@google.com> wrote:
>
> On Thu, Sep 6, 2018 at 10:51 AM Taehee Yoo <ap420073@gmail.com> wrote:
> >
> > A kernel crash occurrs when defragmented packet is fragmented
> > in ip_do_fragment().
> > In defragment routine, skb_orphan() is called and
> > skb->ip_defrag_offset is set. but skb->sk and
> > skb->ip_defrag_offset are same union member. so that
> > frag->sk is not NULL.
> > Hence crash occurrs in skb->sk check routine in ip_do_fragment() when
> > defragmented packet is fragmented.
>
> Have you tested this patch ?
>
> Moving back ip_defrag_offset is conflicting with the rbnode !
>
> A more correct fix would be to properly clear skb->sk at reassembly.

Something like that :

diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 88281fbce88ce8f1062b99594665766c2a5f5b74..e7227128df2c8fd54727c234f76043133809bd1e
100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -599,6 +599,7 @@ static int ip_frag_reasm(struct ipq *qp, struct
sk_buff *skb,
                        nextp = &fp->next;
                        fp->prev = NULL;
                        memset(&fp->rbnode, 0, sizeof(fp->rbnode));
+                       fp->sk = NULL;
                        head->data_len += fp->len;
                        head->len += fp->len;
                        if (head->ip_summed != fp->ip_summed)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH net] ip: frags: fix crash in ip_do_fragment()
  2018-09-06 18:23   ` Eric Dumazet
@ 2018-09-06 18:48     ` Taehee Yoo
  0 siblings, 0 replies; 4+ messages in thread
From: Taehee Yoo @ 2018-09-06 18:48 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David Miller, Peter Oskolkov, netdev, Pablo Neira Ayuso,
	Florian Westphal

2018-09-07 3:23 GMT+09:00 Eric Dumazet <edumazet@google.com>:
> On Thu, Sep 6, 2018 at 11:06 AM Eric Dumazet <edumazet@google.com> wrote:
>>
>> On Thu, Sep 6, 2018 at 10:51 AM Taehee Yoo <ap420073@gmail.com> wrote:
>> >
>> > A kernel crash occurrs when defragmented packet is fragmented
>> > in ip_do_fragment().
>> > In defragment routine, skb_orphan() is called and
>> > skb->ip_defrag_offset is set. but skb->sk and
>> > skb->ip_defrag_offset are same union member. so that
>> > frag->sk is not NULL.
>> > Hence crash occurrs in skb->sk check routine in ip_do_fragment() when
>> > defragmented packet is fragmented.
>>
>> Have you tested this patch ?
>>
>> Moving back ip_defrag_offset is conflicting with the rbnode !
>>
>> A more correct fix would be to properly clear skb->sk at reassembly.
>
> Something like that :
>
> diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
> index 88281fbce88ce8f1062b99594665766c2a5f5b74..e7227128df2c8fd54727c234f76043133809bd1e
> 100644
> --- a/net/ipv4/ip_fragment.c
> +++ b/net/ipv4/ip_fragment.c
> @@ -599,6 +599,7 @@ static int ip_frag_reasm(struct ipq *qp, struct
> sk_buff *skb,
>                         nextp = &fp->next;
>                         fp->prev = NULL;
>                         memset(&fp->rbnode, 0, sizeof(fp->rbnode));
> +                       fp->sk = NULL;
>                         head->data_len += fp->len;
>                         head->len += fp->len;
>                         if (head->ip_summed != fp->ip_summed)

Hi Eric!

Oh I'm sorry, I realized that ip_defrag_offset would be conflicting
with the rbnode just now
So, this patch should be dropped.
And I will make v2 patch regard you suggested!

Thank you for review and suggestion!

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-09-06 23:25 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-09-06 17:50 [PATCH net] ip: frags: fix crash in ip_do_fragment() Taehee Yoo
2018-09-06 18:06 ` Eric Dumazet
2018-09-06 18:23   ` Eric Dumazet
2018-09-06 18:48     ` Taehee Yoo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).