]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.4.133/dccp-fix-tasklet-usage.patch
Fixes for 5.10
[thirdparty/kernel/stable-queue.git] / releases / 4.4.133 / dccp-fix-tasklet-usage.patch
1 From foo@baz Wed May 16 16:57:32 CEST 2018
2 From: Eric Dumazet <edumazet@google.com>
3 Date: Thu, 3 May 2018 09:39:20 -0700
4 Subject: dccp: fix tasklet usage
5
6 From: Eric Dumazet <edumazet@google.com>
7
8 [ Upstream commit a8d7aa17bbc970971ccdf71988ea19230ab368b1 ]
9
10 syzbot reported a crash in tasklet_action_common() caused by dccp.
11
12 dccp needs to make sure socket wont disappear before tasklet handler
13 has completed.
14
15 This patch takes a reference on the socket when arming the tasklet,
16 and moves the sock_put() from dccp_write_xmit_timer() to dccp_write_xmitlet()
17
18 kernel BUG at kernel/softirq.c:514!
19 invalid opcode: 0000 [#1] SMP KASAN
20 Dumping ftrace buffer:
21 (ftrace buffer empty)
22 Modules linked in:
23 CPU: 1 PID: 17 Comm: ksoftirqd/1 Not tainted 4.17.0-rc3+ #30
24 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
25 RIP: 0010:tasklet_action_common.isra.19+0x6db/0x700 kernel/softirq.c:515
26 RSP: 0018:ffff8801d9b3faf8 EFLAGS: 00010246
27 dccp_close: ABORT with 65423 bytes unread
28 RAX: 1ffff1003b367f6b RBX: ffff8801daf1f3f0 RCX: 0000000000000000
29 RDX: ffff8801cf895498 RSI: 0000000000000004 RDI: 0000000000000000
30 RBP: ffff8801d9b3fc40 R08: ffffed0039f12a95 R09: ffffed0039f12a94
31 dccp_close: ABORT with 65423 bytes unread
32 R10: ffffed0039f12a94 R11: ffff8801cf8954a3 R12: 0000000000000000
33 R13: ffff8801d9b3fc18 R14: dffffc0000000000 R15: ffff8801cf895490
34 FS: 0000000000000000(0000) GS:ffff8801daf00000(0000) knlGS:0000000000000000
35 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
36 CR2: 0000001b2bc28000 CR3: 00000001a08a9000 CR4: 00000000001406e0
37 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
38 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
39 Call Trace:
40 tasklet_action+0x1d/0x20 kernel/softirq.c:533
41 __do_softirq+0x2e0/0xaf5 kernel/softirq.c:285
42 dccp_close: ABORT with 65423 bytes unread
43 run_ksoftirqd+0x86/0x100 kernel/softirq.c:646
44 smpboot_thread_fn+0x417/0x870 kernel/smpboot.c:164
45 kthread+0x345/0x410 kernel/kthread.c:238
46 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:412
47 Code: 48 8b 85 e8 fe ff ff 48 8b 95 f0 fe ff ff e9 94 fb ff ff 48 89 95 f0 fe ff ff e8 81 53 6e 00 48 8b 95 f0 fe ff ff e9 62 fb ff ff <0f> 0b 48 89 cf 48 89 8d e8 fe ff ff e8 64 53 6e 00 48 8b 8d e8
48 RIP: tasklet_action_common.isra.19+0x6db/0x700 kernel/softirq.c:515 RSP: ffff8801d9b3faf8
49
50 Fixes: dc841e30eaea ("dccp: Extend CCID packet dequeueing interface")
51 Signed-off-by: Eric Dumazet <edumazet@google.com>
52 Reported-by: syzbot <syzkaller@googlegroups.com>
53 Cc: Gerrit Renker <gerrit@erg.abdn.ac.uk>
54 Cc: dccp@vger.kernel.org
55 Signed-off-by: David S. Miller <davem@davemloft.net>
56 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
57 ---
58 net/dccp/ccids/ccid2.c | 14 ++++++++++++--
59 net/dccp/timer.c | 2 +-
60 2 files changed, 13 insertions(+), 3 deletions(-)
61
62 --- a/net/dccp/ccids/ccid2.c
63 +++ b/net/dccp/ccids/ccid2.c
64 @@ -126,6 +126,16 @@ static void ccid2_change_l_seq_window(st
65 DCCPF_SEQ_WMAX));
66 }
67
68 +static void dccp_tasklet_schedule(struct sock *sk)
69 +{
70 + struct tasklet_struct *t = &dccp_sk(sk)->dccps_xmitlet;
71 +
72 + if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
73 + sock_hold(sk);
74 + __tasklet_schedule(t);
75 + }
76 +}
77 +
78 static void ccid2_hc_tx_rto_expire(unsigned long data)
79 {
80 struct sock *sk = (struct sock *)data;
81 @@ -166,7 +176,7 @@ static void ccid2_hc_tx_rto_expire(unsig
82
83 /* if we were blocked before, we may now send cwnd=1 packet */
84 if (sender_was_blocked)
85 - tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet);
86 + dccp_tasklet_schedule(sk);
87 /* restart backed-off timer */
88 sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
89 out:
90 @@ -706,7 +716,7 @@ static void ccid2_hc_tx_packet_recv(stru
91 done:
92 /* check if incoming Acks allow pending packets to be sent */
93 if (sender_was_blocked && !ccid2_cwnd_network_limited(hc))
94 - tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet);
95 + dccp_tasklet_schedule(sk);
96 dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks);
97 }
98
99 --- a/net/dccp/timer.c
100 +++ b/net/dccp/timer.c
101 @@ -230,12 +230,12 @@ static void dccp_write_xmitlet(unsigned
102 else
103 dccp_write_xmit(sk);
104 bh_unlock_sock(sk);
105 + sock_put(sk);
106 }
107
108 static void dccp_write_xmit_timer(unsigned long data)
109 {
110 dccp_write_xmitlet(data);
111 - sock_put((struct sock *)data);
112 }
113
114 void dccp_init_xmit_timers(struct sock *sk)