]>
Commit | Line | Data |
---|---|---|
9783ad81 GKH |
1 | From foo@baz Tue May 22 21:07:28 CEST 2018 |
2 | From: Eric Dumazet <edumazet@google.com> | |
3 | Date: Mon, 14 May 2018 21:14:26 -0700 | |
4 | Subject: tcp: purge write queue in tcp_connect_init() | |
5 | ||
6 | From: Eric Dumazet <edumazet@google.com> | |
7 | ||
8 | [ Upstream commit 7f582b248d0a86bae5788c548d7bb5bca6f7691a ] | |
9 | ||
10 | syzkaller found a reliable way to crash the host, hitting a BUG() | |
11 | in __tcp_retransmit_skb() | |
12 | ||
13 | Malicous MSG_FASTOPEN is the root cause. We need to purge write queue | |
14 | in tcp_connect_init() at the point we init snd_una/write_seq. | |
15 | ||
16 | This patch also replaces the BUG() by a less intrusive WARN_ON_ONCE() | |
17 | ||
18 | kernel BUG at net/ipv4/tcp_output.c:2837! | |
19 | invalid opcode: 0000 [#1] SMP KASAN | |
20 | Dumping ftrace buffer: | |
21 | (ftrace buffer empty) | |
22 | Modules linked in: | |
23 | CPU: 0 PID: 5276 Comm: syz-executor0 Not tainted 4.17.0-rc3+ #51 | |
24 | Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 | |
25 | RIP: 0010:__tcp_retransmit_skb+0x2992/0x2eb0 net/ipv4/tcp_output.c:2837 | |
26 | RSP: 0000:ffff8801dae06ff8 EFLAGS: 00010206 | |
27 | RAX: ffff8801b9fe61c0 RBX: 00000000ffc18a16 RCX: ffffffff864e1a49 | |
28 | RDX: 0000000000000100 RSI: ffffffff864e2e12 RDI: 0000000000000005 | |
29 | RBP: ffff8801dae073a0 R08: ffff8801b9fe61c0 R09: ffffed0039c40dd2 | |
30 | R10: ffffed0039c40dd2 R11: ffff8801ce206e93 R12: 00000000421eeaad | |
31 | R13: ffff8801ce206d4e R14: ffff8801ce206cc0 R15: ffff8801cd4f4a80 | |
32 | FS: 0000000000000000(0000) GS:ffff8801dae00000(0063) knlGS:00000000096bc900 | |
33 | CS: 0010 DS: 002b ES: 002b CR0: 0000000080050033 | |
34 | CR2: 0000000020000000 CR3: 00000001c47b6000 CR4: 00000000001406f0 | |
35 | DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 | |
36 | DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 | |
37 | Call Trace: | |
38 | <IRQ> | |
39 | tcp_retransmit_skb+0x2e/0x250 net/ipv4/tcp_output.c:2923 | |
40 | tcp_retransmit_timer+0xc50/0x3060 net/ipv4/tcp_timer.c:488 | |
41 | tcp_write_timer_handler+0x339/0x960 net/ipv4/tcp_timer.c:573 | |
42 | tcp_write_timer+0x111/0x1d0 net/ipv4/tcp_timer.c:593 | |
43 | call_timer_fn+0x230/0x940 kernel/time/timer.c:1326 | |
44 | expire_timers kernel/time/timer.c:1363 [inline] | |
45 | __run_timers+0x79e/0xc50 kernel/time/timer.c:1666 | |
46 | run_timer_softirq+0x4c/0x70 kernel/time/timer.c:1692 | |
47 | __do_softirq+0x2e0/0xaf5 kernel/softirq.c:285 | |
48 | invoke_softirq kernel/softirq.c:365 [inline] | |
49 | irq_exit+0x1d1/0x200 kernel/softirq.c:405 | |
50 | exiting_irq arch/x86/include/asm/apic.h:525 [inline] | |
51 | smp_apic_timer_interrupt+0x17e/0x710 arch/x86/kernel/apic/apic.c:1052 | |
52 | apic_timer_interrupt+0xf/0x20 arch/x86/entry/entry_64.S:863 | |
53 | ||
54 | Fixes: cf60af03ca4e ("net-tcp: Fast Open client - sendmsg(MSG_FASTOPEN)") | |
55 | Signed-off-by: Eric Dumazet <edumazet@google.com> | |
56 | Cc: Yuchung Cheng <ycheng@google.com> | |
57 | Cc: Neal Cardwell <ncardwell@google.com> | |
58 | Reported-by: syzbot <syzkaller@googlegroups.com> | |
59 | Acked-by: Neal Cardwell <ncardwell@google.com> | |
60 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
61 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
62 | --- | |
63 | net/ipv4/tcp_output.c | 7 +++++-- | |
64 | 1 file changed, 5 insertions(+), 2 deletions(-) | |
65 | ||
66 | --- a/net/ipv4/tcp_output.c | |
67 | +++ b/net/ipv4/tcp_output.c | |
68 | @@ -2587,8 +2587,10 @@ int __tcp_retransmit_skb(struct sock *sk | |
69 | return -EBUSY; | |
70 | ||
71 | if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) { | |
72 | - if (before(TCP_SKB_CB(skb)->end_seq, tp->snd_una)) | |
73 | - BUG(); | |
74 | + if (unlikely(before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))) { | |
75 | + WARN_ON_ONCE(1); | |
76 | + return -EINVAL; | |
77 | + } | |
78 | if (tcp_trim_head(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq)) | |
79 | return -ENOMEM; | |
80 | } | |
81 | @@ -3117,6 +3119,7 @@ static void tcp_connect_init(struct sock | |
82 | sock_reset_flag(sk, SOCK_DONE); | |
83 | tp->snd_wnd = 0; | |
84 | tcp_init_wl(tp, 0); | |
85 | + tcp_write_queue_purge(sk); | |
86 | tp->snd_una = tp->write_seq; | |
87 | tp->snd_sml = tp->write_seq; | |
88 | tp->snd_up = tp->write_seq; |